public static void AddSectionAndAddWebpart() { OfficeDevPnP.Core.AuthenticationManager authenticationManager = new OfficeDevPnP.Core.AuthenticationManager(); using (binderSiteClientContext = authenticationManager.GetSharePointOnlineAuthenticatedContextTenant(binderSiteUrl, userName, passWord)) { //Create a page or get the existing page string pageName = "POCSiteProvisioning.aspx"; ClientSidePage page = ClientSidePage.Load(binderSiteClientContext, pageName); //var page = binderSiteClientContext.Web.AddClientSidePage("POCAppProvisioning.aspx", true); // Add Section page.AddSection(CanvasSectionTemplate.ThreeColumn, 5); // get the available web parts - this collection will include OOTB and custom SPFx web parts.. page.Save(); // Get all the available webparts var components = page.AvailableClientSideComponents(); // add the named web part.. var webPartToAdd = components.Where(wp => wp.ComponentType == 1 && wp.Name == "HeroControl").FirstOrDefault(); if (webPartToAdd != null) { ClientSideWebPart clientWp = new ClientSideWebPart(webPartToAdd) { Order = 1 }; //Add the WebPart to the page with appropriate section page.AddControl(clientWp, page.Sections[1].Columns[1]); } // the save method creates the page if one doesn't exist with that name in this site.. page.Save(); } }
private static void AddDefaultWebPart(ClientContext siteContext, string pageName) { // add video embed web part.. ClientSidePage page = new ClientSidePage(siteContext); ClientSideWebPart videoEmbedWp = page.InstantiateDefaultWebPart(DefaultClientSideWebParts.VideoEmbed); videoEmbedWp.Properties["videoSource"] = "[specify-url-here]"; videoEmbedWp.Properties["captionText"] = "[specify-title-here]"; videoEmbedWp.Properties["showInfo"] = false; videoEmbedWp.Properties["embedCode"] = "<iframe width=853 height=480 src='[specify-url-here]' allowfullscreen></iframe>"; videoEmbedWp.Title = "Associated video"; page.AddControl(videoEmbedWp); // add Yammer embed web part.. ClientSideWebPart yammerEmbedWp = page.InstantiateDefaultWebPart(DefaultClientSideWebParts.YammerEmbed); yammerEmbedWp.Properties["yammerFeedURL"] = "[specify-url-here]"; yammerEmbedWp.Title = "Associated Yammer group"; page.AddControl(yammerEmbedWp); page.Save(pageName); Console.WriteLine("Default Web Part added."); }
private static void CreatePage(ClientContext siteContext, string pageName) { ClientSidePage page = new ClientSidePage(siteContext); ClientSideText txt1 = new ClientSideText() { Text = "Hello world!" }; page.AddControl(txt1, 0); page.Save(pageName); Console.WriteLine("Page successfully created."); }
private static void ModifyPage(ClientContext siteContext, string pageName) { ClientSidePage page = ClientSidePage.Load(siteContext, pageName); ClientSideText txt1 = new ClientSideText() { Text = "Hello world 2!" }; page.AddControl(txt1, 0); page.Save(pageName); Console.WriteLine("Page successfully modified."); }
/// <summary> /// Adds the controls. /// </summary> /// <param name="sourceContext">The source context.</param> /// <param name="newModernPage">The new modern page.</param> /// <param name="pageName">Name of the page.</param> private void AddControls(ClientContext sourceContext, ClientSidePage newModernPage, string pageName) { try { var sourcePage = ClientSidePage.Load(sourceContext, pageName); //newModernPage.Controls; var controlsCollection = sourcePage.Controls; foreach (var control in controlsCollection) { newModernPage.AddControl(control); //var webparttoadd = newmodernpage.instantiatedefaultwebpart(defaultclientsidewebparts.) } newModernPage.Save(); } catch (Exception ex) { ConsoleOperations.WriteToConsole("Problem with adding controls to page", ConsoleColor.Yellow); } }
private static void AddCustomSPFxWebPart(ClientContext siteContext, string wpName, string pageName, int wpOrder) { ClientSidePage page = new ClientSidePage(siteContext); var components = page.AvailableClientSideComponents(); var webPartToAdd = components.Where(wp => wp.ComponentType == 1 && wp.Name == wpName).FirstOrDefault(); if (webPartToAdd != null) { ClientSideWebPart clientWp = new ClientSideWebPart(webPartToAdd) { Order = wpOrder }; page.AddControl(clientWp); } page.Save(pageName); }
/// <summary> /// Transforms the passed web parts into the loaded client side page /// </summary> /// <param name="webParts">List of web parts that need to be transformed</param> public void Transform(List <WebPartEntity> webParts) { if (webParts == null || webParts.Count == 0) { // nothing to transform return; } // find the default mapping, will be used for webparts for which the model does not contain a mapping var defaultMapping = pageTransformation.BaseWebPart.Mappings.Mapping.Where(p => p.Default == true).FirstOrDefault(); if (defaultMapping == null) { throw new Exception("No default mapping was found int the provided mapping file"); } // Load existing available controls var componentsToAdd = page.AvailableClientSideComponents().ToList(); // Normalize row numbers as there can be gaps if the analyzed page contained wiki tables int newRowOrder = 0; int lastExistingRowOrder = -1; foreach (var webPart in webParts.OrderBy(p => p.Row)) { if (lastExistingRowOrder < webPart.Row) { newRowOrder++; lastExistingRowOrder = webPart.Row; } webPart.Row = newRowOrder; } // Iterate over the web parts, important to order them by row, column and zoneindex foreach (var webPart in webParts.OrderBy(p => p.Row).ThenBy(p => p.Column).ThenBy(p => p.Order)) { // Title bar will never be migrated if (webPart.Type == WebParts.TitleBar) { continue; } Mapping mapping = defaultMapping; // Does the web part have a mapping defined? var webPartData = pageTransformation.WebParts.Where(p => p.Type == webPart.Type).FirstOrDefault(); if (webPartData != null && webPartData.Mappings != null) { // Add site level (e.g. site) tokens to the web part properties and model so they can be used in the same manner as a web part property UpdateWebPartDataProperties(webPart, webPartData, this.siteTokens); // The mapping can have a selector function defined, is so it will be executed. If a selector was executed the selectorResult will contain the name of the mapping to use var selectorResult = functionProcessor.Process(ref webPartData, webPart); Mapping webPartMapping = null; // Get the needed mapping: // - use the mapping returned by the selector // - if no selector then take the default mapping // - if no mapping found we'll fall back to the default web part mapping if (!string.IsNullOrEmpty(selectorResult)) { webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Name.Equals(selectorResult, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); } else { // If there's only one mapping let's take that one, even if not specified as default if (webPartData.Mappings.Mapping.Length == 1) { webPartMapping = webPartData.Mappings.Mapping[0]; } else { webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Default == true).FirstOrDefault(); } } if (webPartMapping != null) { mapping = webPartMapping; } } // Use the mapping data => make one list of Text and WebParts to allow for correct ordering combinedMappinglist = new List <CombinedMapping>(); if (mapping.ClientSideText != null) { foreach (var map in mapping.ClientSideText.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = map, ClientSideWebPart = null, Order = mapOrder }); } } if (mapping.ClientSideWebPart != null) { foreach (var map in mapping.ClientSideWebPart.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = null, ClientSideWebPart = map, Order = mapOrder }); } } // Get the order of the last inserted control in this column int order = LastColumnOrder(webPart.Row - 1, webPart.Column - 1); // Interate the controls for this mapping using their order foreach (var map in combinedMappinglist.OrderBy(p => p.Order)) { order++; if (map.ClientSideText != null) { // Insert a Text control OfficeDevPnP.Core.Pages.ClientSideText text = new OfficeDevPnP.Core.Pages.ClientSideText() { Text = TokenParser.ReplaceTokens(map.ClientSideText.Text, webPart) }; page.AddControl(text, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); } else if (map.ClientSideWebPart != null) { // Insert a web part ClientSideComponent baseControl = null; if (map.ClientSideWebPart.Type == ClientSideWebPartType.Custom) { // Parse the control ID to support generic web part placement scenarios map.ClientSideWebPart.ControlId = TokenParser.ReplaceTokens(map.ClientSideWebPart.ControlId, webPart); // Check if this web part belongs to the list of "usable" web parts for this site baseControl = componentsToAdd.FirstOrDefault(p => p.Id.Equals($"{{{map.ClientSideWebPart.ControlId}}}", StringComparison.InvariantCultureIgnoreCase)); } else { string webPartName = ""; switch (map.ClientSideWebPart.Type) { case ClientSideWebPartType.List: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.List); break; } case ClientSideWebPartType.Image: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Image); break; } case ClientSideWebPartType.ContentRollup: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ContentRollup); break; } case ClientSideWebPartType.BingMap: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.BingMap); break; } case ClientSideWebPartType.ContentEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ContentEmbed); break; } case ClientSideWebPartType.DocumentEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.DocumentEmbed); break; } case ClientSideWebPartType.ImageGallery: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ImageGallery); break; } case ClientSideWebPartType.LinkPreview: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.LinkPreview); break; } case ClientSideWebPartType.NewsFeed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.NewsFeed); break; } case ClientSideWebPartType.NewsReel: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.NewsReel); break; } case ClientSideWebPartType.PowerBIReportEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.PowerBIReportEmbed); break; } case ClientSideWebPartType.QuickChart: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.QuickChart); break; } case ClientSideWebPartType.SiteActivity: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.SiteActivity); break; } case ClientSideWebPartType.VideoEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.VideoEmbed); break; } case ClientSideWebPartType.YammerEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.YammerEmbed); break; } case ClientSideWebPartType.Events: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Events); break; } case ClientSideWebPartType.GroupCalendar: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.GroupCalendar); break; } case ClientSideWebPartType.Hero: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Hero); break; } case ClientSideWebPartType.PageTitle: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.PageTitle); break; } case ClientSideWebPartType.People: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.People); break; } case ClientSideWebPartType.QuickLinks: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.QuickLinks); break; } case ClientSideWebPartType.Divider: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Divider); break; } case ClientSideWebPartType.MicrosoftForms: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.MicrosoftForms); break; } case ClientSideWebPartType.Spacer: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Spacer); break; } case ClientSideWebPartType.ClientWebPart: { //TODO: replace with call once we've released the May PnP nuget webPartName = "243166f5-4dc3-4fe2-9df2-a7971b546a0a"; break; } default: { break; } } // SharePoint add-ins can be added on client side pages...all add-ins are added via the client web part, so we need additional logic to find the one we need if (map.ClientSideWebPart.Type == ClientSideWebPartType.ClientWebPart) { var addinComponents = componentsToAdd.Where(p => p.Name.Equals(webPartName, StringComparison.InvariantCultureIgnoreCase)); foreach (var addin in addinComponents) { // Find the right add-in web part via title matching...maybe not bullet proof but did find anything better for now JObject wpJObject = JObject.Parse(addin.Manifest); if (wpJObject["preconfiguredEntries"][0]["title"]["default"].Value <string>() == webPart.Title) { baseControl = addin; var jsonProperties = wpJObject["preconfiguredEntries"][0]; // Fill custom web part properties in this json. Custom properties are listed as child elements under clientWebPartProperties, // replace their "default" value with the value we got from the web part's properties jsonProperties = PopulateAddInProperties(jsonProperties, webPart); // Override the JSON data we read from the model as this is fully dynamic due to the nature of the add-in client part map.ClientSideWebPart.JsonControlData = jsonProperties.ToString(Newtonsoft.Json.Formatting.None); break; } } } else { baseControl = componentsToAdd.FirstOrDefault(p => p.Name.Equals(webPartName, StringComparison.InvariantCultureIgnoreCase)); } } // If we found the web part as a possible candidate to use then add it if (baseControl != null) { var jsonDecoded = WebUtility.HtmlDecode(TokenParser.ReplaceTokens(map.ClientSideWebPart.JsonControlData, webPart)); OfficeDevPnP.Core.Pages.ClientSideWebPart myWebPart = new OfficeDevPnP.Core.Pages.ClientSideWebPart(baseControl) { Order = map.Order, PropertiesJson = jsonDecoded }; page.AddControl(myWebPart, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); } else { //TODO: Log warning as web part was not found } } } } }
public static void PageSectionDivision() { OfficeDevPnP.Core.AuthenticationManager authenticationManager = new OfficeDevPnP.Core.AuthenticationManager(); using(ClientContext currentSiteContext = authenticationManager.GetSharePointOnlineAuthenticatedContextTenant(binderSiteUrl, userName, passWord)) { string pageName = "POCSiteProvisioning.aspx"; ClientSidePage page = ClientSidePage.Load(currentSiteContext, pageName); var appManager = new AppManager(currentSiteContext); var apps = appManager.GetAvailable(); ClientSideComponent clientSideComponent = null; var chartsApp = apps.Where(a => a.Title == "hero-control-client-side-solution-ProductionEnv").FirstOrDefault(); bool controlPresent = false; bool done = false; int count = 0; do { try { ClientSideComponent[] clientSideComponents = (ClientSideComponent[])page.AvailableClientSideComponents(); clientSideComponent = clientSideComponents.Where(c => c.Id.ToLower() == chartsApp.Id.ToString().ToLower()).FirstOrDefault(); foreach (ClientSideComponent csc in clientSideComponents) { if (csc.Id.ToString().ToLower().Contains(chartsApp.Id.ToString().ToLower())) { clientSideComponent = csc; continue; } } //ClientSideWebPart webPart = page.Controls.Where(wP => wP != null) foreach (var control in page.Controls) { ClientSideWebPart cpWP = control as ClientSideWebPart; if (cpWP != null && cpWP.SpControlData.WebPartId.ToString() == chartsApp.Id.ToString()) { controlPresent = true; done = true; } } if (!controlPresent) { ClientSideWebPart WebPart = new ClientSideWebPart(clientSideComponent); JToken activeValueToken = true; // Find the web part configuration string from the web part file or code debugging //string propertyJSONString = String.Format("[{{<WP Configuration string>}}]", < parameters >); //JToken propertyTermToken = JToken.Parse(propertyJSONString); WebPart.Properties.Add("showOnlyActive", activeValueToken); CanvasSection section = new CanvasSection(page, CanvasSectionTemplate.ThreeColumnVerticalSection, page.Sections.Count + 1); page.Sections.Add(section); page.Save(); page.AddControl(WebPart, section.Columns[0]); page.Save(); page.Publish(); done = true; controlPresent = true; } } catch (Exception ex) { //Log.Info("Catched exception while adding Capex web part.. Trying again" + ex.Message); Console.WriteLine(ex); Console.ReadLine(); count++; } } while (!done && count <= 5); } }
/// <summary> /// Transforms the passed web parts into the loaded client side page /// </summary> /// <param name="webParts">List of web parts that need to be transformed</param> public void Transform(List <WebPartEntity> webParts) { LogInfo(LogStrings.ContentTransformingWebParts, LogStrings.Heading_ContentTransform); if (webParts == null || webParts.Count == 0) { // nothing to transform LogWarning(LogStrings.NothingToTransform, LogStrings.Heading_ContentTransform); return; } // find the default mapping, will be used for webparts for which the model does not contain a mapping var defaultMapping = pageTransformation.BaseWebPart.Mappings.Mapping.Where(p => p.Default == true).FirstOrDefault(); if (defaultMapping == null) { LogError(LogStrings.Error_NoDefaultMappingFound, LogStrings.Heading_ContentTransform); throw new Exception(LogStrings.Error_NoDefaultMappingFound); } // Load existing available controls var componentsToAdd = CacheManager.Instance.GetClientSideComponents(page); // Normalize row numbers as there can be gaps if the analyzed page contained wiki tables int newRowOrder = 0; int lastExistingRowOrder = -1; foreach (var webPart in webParts.OrderBy(p => p.Row)) { if (lastExistingRowOrder < webPart.Row) { newRowOrder++; lastExistingRowOrder = webPart.Row; } webPart.Row = newRowOrder; } // Iterate over the web parts, important to order them by row, column and zoneindex foreach (var webPart in webParts.OrderBy(p => p.Row).ThenBy(p => p.Column).ThenBy(p => p.Order)) { LogInfo(string.Format(LogStrings.ContentWebPartBeingTransformed, webPart.Title, webPart.TypeShort()), LogStrings.Heading_MappingWebParts); // Title bar will never be migrated if (webPart.Type == WebParts.TitleBar) { LogInfo(LogStrings.NotTransformingTitleBar, LogStrings.Heading_MappingWebParts); continue; } // Assign the default mapping, if we're a more specific mapping than that will overwrite this mapping Mapping mapping = defaultMapping; // Does the web part have a mapping defined? // Older version of SharePoint var webPartData = pageTransformation.WebParts.Where(p => p.Type.GetTypeShort() == webPart.Type.GetTypeShort()).FirstOrDefault(); // Check for cross site transfer support if (webPartData != null && this.isCrossSiteTransfer) { if (!webPartData.CrossSiteTransformationSupported) { LogWarning(LogStrings.CrossSiteNotSupported, LogStrings.Heading_MappingWebParts); continue; } } if (webPartData != null && webPartData.Mappings != null) { // Add site level (e.g. site) tokens to the web part properties and model so they can be used in the same manner as a web part property UpdateWebPartDataProperties(webPart, webPartData, this.globalTokens); string selectorResult = null; try { // The mapping can have a selector function defined, is so it will be executed. If a selector was executed the selectorResult will contain the name of the mapping to use LogDebug(LogStrings.ProcessingSelectorFunctions, LogStrings.Heading_MappingWebParts); selectorResult = functionProcessor.Process(ref webPartData, webPart); } catch (Exception ex) { // NotAvailableAtTargetException is used to "skip" a web part since it's not valid for the target site collection (only applies to cross site collection transfers) if (ex.InnerException is NotAvailableAtTargetException) { LogError(LogStrings.Error_NotValidForTargetSiteCollection, LogStrings.Heading_MappingWebParts, ex, true); continue; } LogError($"{LogStrings.Error_AnErrorOccurredFunctions} - {ex.Message}", LogStrings.Heading_MappingWebParts, ex); throw; } Mapping webPartMapping = null; // Get the needed mapping: // - use the mapping returned by the selector // - if no selector then take the default mapping // - if no mapping found we'll fall back to the default web part mapping if (!string.IsNullOrEmpty(selectorResult)) { webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Name.Equals(selectorResult, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); } else { // If there's only one mapping let's take that one, even if not specified as default if (webPartData.Mappings.Mapping.Length == 1) { webPartMapping = webPartData.Mappings.Mapping[0]; } else { webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Default == true).FirstOrDefault(); } } if (webPartMapping != null) { mapping = webPartMapping; } else { LogWarning(LogStrings.ContentWebPartMappingNotFound, LogStrings.Heading_MappingWebParts); } // Process mapping specific functions (if any) if (!String.IsNullOrEmpty(mapping.Functions)) { try { LogInfo(LogStrings.ProcessingMappingFunctions, LogStrings.Heading_MappingWebParts); functionProcessor.ProcessMappingFunctions(ref webPartData, webPart, mapping); } catch (Exception ex) { // NotAvailableAtTargetException is used to "skip" a web part since it's not valid for the target site collection (only applies to cross site collection transfers) if (ex.InnerException is NotAvailableAtTargetException) { LogError(LogStrings.Error_NotValidForTargetSiteCollection, LogStrings.Heading_MappingWebParts, ex, true); continue; } LogError($"{LogStrings.Error_AnErrorOccurredFunctions} - {ex.Message}", LogStrings.Heading_MappingWebParts, ex); throw; } } } // Use the mapping data => make one list of Text and WebParts to allow for correct ordering LogDebug("Combining mapping data", LogStrings.Heading_MappingWebParts); combinedMappinglist = new List <CombinedMapping>(); if (mapping.ClientSideText != null) { foreach (var map in mapping.ClientSideText.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = map, ClientSideWebPart = null, Order = mapOrder }); } } if (mapping.ClientSideWebPart != null) { foreach (var map in mapping.ClientSideWebPart.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = null, ClientSideWebPart = map, Order = mapOrder }); } } // Get the order of the last inserted control in this column int order = LastColumnOrder(webPart.Row - 1, webPart.Column - 1); // Interate the controls for this mapping using their order foreach (var map in combinedMappinglist.OrderBy(p => p.Order)) { order++; if (map.ClientSideText != null) { // Insert a Text control OfficeDevPnP.Core.Pages.ClientSideText text = new OfficeDevPnP.Core.Pages.ClientSideText() { Text = TokenParser.ReplaceTokens(map.ClientSideText.Text, webPart) }; page.AddControl(text, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); LogInfo(LogStrings.AddedClientSideTextWebPart, LogStrings.Heading_AddingWebPartsToPage); } else if (map.ClientSideWebPart != null) { // Insert a web part ClientSideComponent baseControl = null; if (map.ClientSideWebPart.Type == ClientSideWebPartType.Custom) { // Parse the control ID to support generic web part placement scenarios map.ClientSideWebPart.ControlId = TokenParser.ReplaceTokens(map.ClientSideWebPart.ControlId, webPart); // Check if this web part belongs to the list of "usable" web parts for this site baseControl = componentsToAdd.FirstOrDefault(p => p.Id.Equals($"{{{map.ClientSideWebPart.ControlId}}}", StringComparison.InvariantCultureIgnoreCase)); LogInfo(LogStrings.UsingCustomModernWebPart, LogStrings.Heading_AddingWebPartsToPage); } else { string webPartName = ""; switch (map.ClientSideWebPart.Type) { case ClientSideWebPartType.List: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.List); break; } case ClientSideWebPartType.Image: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Image); break; } case ClientSideWebPartType.ContentRollup: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ContentRollup); break; } case ClientSideWebPartType.BingMap: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.BingMap); break; } case ClientSideWebPartType.ContentEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ContentEmbed); break; } case ClientSideWebPartType.DocumentEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.DocumentEmbed); break; } case ClientSideWebPartType.ImageGallery: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ImageGallery); break; } case ClientSideWebPartType.LinkPreview: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.LinkPreview); break; } case ClientSideWebPartType.NewsFeed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.NewsFeed); break; } case ClientSideWebPartType.NewsReel: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.NewsReel); break; } case ClientSideWebPartType.PowerBIReportEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.PowerBIReportEmbed); break; } case ClientSideWebPartType.QuickChart: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.QuickChart); break; } case ClientSideWebPartType.SiteActivity: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.SiteActivity); break; } case ClientSideWebPartType.VideoEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.VideoEmbed); break; } case ClientSideWebPartType.YammerEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.YammerEmbed); break; } case ClientSideWebPartType.Events: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Events); break; } case ClientSideWebPartType.GroupCalendar: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.GroupCalendar); break; } case ClientSideWebPartType.Hero: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Hero); break; } case ClientSideWebPartType.PageTitle: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.PageTitle); break; } case ClientSideWebPartType.People: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.People); break; } case ClientSideWebPartType.QuickLinks: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.QuickLinks); break; } case ClientSideWebPartType.Divider: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Divider); break; } case ClientSideWebPartType.MicrosoftForms: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.MicrosoftForms); break; } case ClientSideWebPartType.Spacer: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Spacer); break; } case ClientSideWebPartType.ClientWebPart: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ClientWebPart); break; } case ClientSideWebPartType.PowerApps: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.PowerApps); break; } case ClientSideWebPartType.CodeSnippet: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.CodeSnippet); break; } case ClientSideWebPartType.PageFields: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.PageFields); break; } case ClientSideWebPartType.Weather: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Weather); break; } case ClientSideWebPartType.YouTube: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.YouTube); break; } case ClientSideWebPartType.MyDocuments: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.MyDocuments); break; } case ClientSideWebPartType.YammerFullFeed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.YammerFullFeed); break; } case ClientSideWebPartType.CountDown: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.CountDown); break; } case ClientSideWebPartType.ListProperties: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ListProperties); break; } case ClientSideWebPartType.MarkDown: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.MarkDown); break; } case ClientSideWebPartType.Planner: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Planner); break; } default: { break; } } // SharePoint add-ins can be added on client side pages...all add-ins are added via the client web part, so we need additional logic to find the one we need if (map.ClientSideWebPart.Type == ClientSideWebPartType.ClientWebPart) { var addinComponents = componentsToAdd.Where(p => p.Name.Equals(webPartName, StringComparison.InvariantCultureIgnoreCase)); foreach (var addin in addinComponents) { // Find the right add-in web part via title matching...maybe not bullet proof but did find anything better for now JObject wpJObject = JObject.Parse(addin.Manifest); // As there can be multiple classic web parts (via provider hosted add ins or SharePoint hosted add ins) we're looping to find the first one with a matching title foreach (var addinEntry in wpJObject["preconfiguredEntries"]) { if (addinEntry["title"]["default"].Value <string>() == webPart.Title) { baseControl = addin; var jsonProperties = addinEntry; // Fill custom web part properties in this json. Custom properties are listed as child elements under clientWebPartProperties, // replace their "default" value with the value we got from the web part's properties jsonProperties = PopulateAddInProperties(jsonProperties, webPart); // Override the JSON data we read from the model as this is fully dynamic due to the nature of the add-in client part map.ClientSideWebPart.JsonControlData = jsonProperties.ToString(Newtonsoft.Json.Formatting.None); LogInfo($"{LogStrings.ContentUsingAddinWebPart} '{baseControl.Name}' ", LogStrings.Heading_AddingWebPartsToPage); break; } } } } else { baseControl = componentsToAdd.FirstOrDefault(p => p.Name.Equals(webPartName, StringComparison.InvariantCultureIgnoreCase)); LogInfo($"{LogStrings.ContentUsing} '{ map.ClientSideWebPart.Type.ToString() }' {LogStrings.ContentModernWebPart}", LogStrings.Heading_AddingWebPartsToPage); } } // If we found the web part as a possible candidate to use then add it if (baseControl != null) { var jsonDecoded = WebUtility.HtmlDecode(TokenParser.ReplaceTokens(map.ClientSideWebPart.JsonControlData, webPart)); OfficeDevPnP.Core.Pages.ClientSideWebPart myWebPart = new OfficeDevPnP.Core.Pages.ClientSideWebPart(baseControl) { Order = map.Order, PropertiesJson = jsonDecoded }; page.AddControl(myWebPart, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); LogInfo($"{LogStrings.ContentAdded} '{ myWebPart.Title }' {LogStrings.ContentClientToTargetPage}", LogStrings.Heading_AddingWebPartsToPage); } else { LogWarning(LogStrings.ContentWarnModernNotFound, LogStrings.Heading_AddingWebPartsToPage); } } } } LogInfo(LogStrings.ContentTransformationComplete, LogStrings.Heading_ContentTransform); }
static void Main(string[] args) { // Update the below variables to use your tenant and account information //string siteUrl = "https://contoso.sharepoint.com/sites/modernpagedemo"; //string userName = "******"; string siteUrl = "https://bertonline.sharepoint.com/sites/bert1"; string userName = "******"; SecureString password = GetSecureString("Password"); AuthenticationManager am = new AuthenticationManager(); using (var cc = am.GetSharePointOnlineAuthenticatedContextTenant(siteUrl, userName, password)) { #region Previous demos /* * // Demo 1: Add empty page * var page = cc.Web.AddClientSidePage("PnPRocks.aspx", true); * * // Demo 2: Read existing page and Text control + custom web part. * // Important: manually create a sample modern page called "Templatepage" in your demo site first * ClientSidePage p = ClientSidePage.Load(cc, "Demo.aspx"); * // Add text control on top * ClientSideText txt1 = new ClientSideText() { Text = "PnP Rocks" }; * p.AddControl(txt1, -1); * // Find custom component and add as last control * // Important: this assumes you've a custom client side web part with name "HelloWorld" deployed to the test site collection. * var components = p.AvailableClientSideComponents(); * var myWebPart = components.Where(s => s.Name == "HelloWorld").FirstOrDefault(); * if (myWebPart != null) * { * ClientSideWebPart helloWp = new ClientSideWebPart(myWebPart) { Order = 10 }; * p.AddControl(helloWp); * } * // Save the page under a new name * p.Save("pagewithcontrols.aspx"); * * //Demo 3: Add OOB web part (Image) * // Important: if you don't update the web part properties your client side impage web part will not be able to load the image * ClientSidePage page5 = new ClientSidePage(cc); * var imageWebPart = page5.InstantiateDefaultWebPart(DefaultClientSideWebParts.Image); * imageWebPart.Properties["imageSourceType"] = 2; * imageWebPart.Properties["siteId"] = "c827cb03-d059-4956-83d0-cd60e02e3b41"; * imageWebPart.Properties["webId"] = "9fafd7c0-e8c3-4a3c-9e87-4232c481ca26"; * imageWebPart.Properties["listId"] = "78d1b1ac-7590-49e7-b812-55f37c018c4b"; * imageWebPart.Properties["uniqueId"] = "3C27A419-66D0-4C36-BF24-BD6147719052"; * imageWebPart.Properties["imgWidth"] = 1002; * imageWebPart.Properties["imgHeight"] = 469; * //imageWebPart.PropertiesJson = "{\"imageSourceType\":2,\"altText\":\"\",\"fileName\":\"\",\"siteId\":\"c827cb03-d059-4956-83d0-cd60e02e3b41\",\"webId\":\"9fafd7c0-e8c3-4a3c-9e87-4232c481ca26\",\"listId\":\"78d1b1ac-7590-49e7-b812-55f37c018c4b\",\"uniqueId\":\"{3C27A419-66D0-4C36-BF24-BD6147719052}\",\"imgWidth\":1002,\"imgHeight\":469}"; * page5.AddControl(imageWebPart); * page5.Save("pagewithimage.aspx"); * * //Demo 4: delete page * ClientSidePage p2 = ClientSidePage.Load(cc, "pagewithcontrols.aspx"); * p2.Delete(); * * //Demo 5: delete control * ClientSidePage deleteDemoPage = ClientSidePage.Load(cc, "pagewithimage.aspx"); * deleteDemoPage.Controls[0].Delete(); * deleteDemoPage.Save(); */ #endregion //Demo 6: create a page with a flexible page layout var page2 = cc.Web.AddClientSidePage("PageWithSections.aspx", true); page2.AddZone(CanvasZoneTemplate.ThreeColumn, 5); page2.AddZone(CanvasZoneTemplate.TwoColumn, 10); var componentsToAdd = page2.AvailableClientSideComponents(); var myHellowWorldWebPart = componentsToAdd.Where(s => s.Name == "HelloWorld").FirstOrDefault(); if (myHellowWorldWebPart != null) { ClientSideText text = new ClientSideText() { Text = "Text control in first zone, left column" }; page2.AddControl(text, page2.Zones[0]); ClientSideWebPart helloWp = new ClientSideWebPart(myHellowWorldWebPart) { Order = 10 }; helloWp.Properties["description"] = "Hello world from control 1!!"; helloWp.Properties["test3"] = false; helloWp.Properties["test2"] = "1"; //description":"HelloWorld","test":"Multi-line text field","test1":true,"test2":"2","test3":true page2.AddControl(helloWp, page2.Zones[0].Sections[2]); ClientSideWebPart helloWp2 = new ClientSideWebPart(myHellowWorldWebPart) { Order = 10 }; helloWp2.Properties["description"] = "Hello world from control 2!!"; helloWp2.Properties["test3"] = true; helloWp2.Properties["test2"] = "3"; //description":"HelloWorld","test":"Multi-line text field","test1":true,"test2":"2","test3":true page2.AddControl(helloWp2, page2.Zones[1]); } page2.Save(); // Demo 7: read created page and flip the order of the sections, move web parts around and turn off commenting var page3 = cc.Web.LoadClientSidePage("PageWithSections.aspx"); // Move web part page3.Zones[0].Sections[0].Controls[0].Move(page3.Zones[0].Sections[2], 20); // Move zones page3.Zones[0].Order = 10; page3.Zones[1].Order = 5; ClientSideText text2 = new ClientSideText() { Text = "Text control in first zone, middle column" }; page3.AddControl(text2, page3.Zones[0].Sections[1]); page3.Save(); // Disable comments for this page page3.DisableComments(); // Demo 8: create a news page ClientSidePage page4 = new ClientSidePage(cc); page4.AddZone(CanvasZoneTemplate.TwoColumn, 10); ClientSideText text4 = new ClientSideText() { Text = "Hello all, this is our first news page." }; page4.AddControl(text4); var imageWebPart4 = page4.InstantiateDefaultWebPart(DefaultClientSideWebParts.Image); imageWebPart4.Properties["imageSourceType"] = 2; imageWebPart4.Properties["siteId"] = "c827cb03-d059-4956-83d0-cd60e02e3b41"; imageWebPart4.Properties["webId"] = "9fafd7c0-e8c3-4a3c-9e87-4232c481ca26"; imageWebPart4.Properties["listId"] = "78d1b1ac-7590-49e7-b812-55f37c018c4b"; imageWebPart4.Properties["uniqueId"] = "3C27A419-66D0-4C36-BF24-BD6147719052"; imageWebPart4.Properties["imgWidth"] = 500; imageWebPart4.Properties["imgHeight"] = 235; //imageWebPart.PropertiesJson = "{\"imageSourceType\":2,\"altText\":\"\",\"fileName\":\"\",\"siteId\":\"c827cb03-d059-4956-83d0-cd60e02e3b41\",\"webId\":\"9fafd7c0-e8c3-4a3c-9e87-4232c481ca26\",\"listId\":\"78d1b1ac-7590-49e7-b812-55f37c018c4b\",\"uniqueId\":\"{3C27A419-66D0-4C36-BF24-BD6147719052}\",\"imgWidth\":1002,\"imgHeight\":469}"; page4.AddControl(imageWebPart4, page4.DefaultZone.Sections[1]); page4.Save("newspage.aspx"); // promote as news page4.PromoteAsNewsArticle(); // Demo 9: give the site a new home page var newHomePage = cc.Web.AddClientSidePage(); newHomePage.LayoutType = ClientSidePageLayoutType.Home; newHomePage.AddZone(CanvasZoneTemplate.ThreeColumn, 10); newHomePage.AddControl(new ClientSideText() { Text = "Having a custom home page" }, newHomePage.DefaultZone); newHomePage.AddControl(new ClientSideText() { Text = "with multiple columns" }, newHomePage.DefaultZone.Sections[1]); newHomePage.AddControl(new ClientSideText() { Text = "is possible :-)" }, newHomePage.DefaultZone.Sections[2]); newHomePage.Save("Home_2.aspx"); newHomePage.PromoteAsHomePage(); // Demo 10: restore original home page cc.Web.LoadClientSidePage("Home.aspx").PromoteAsHomePage(); } }
static void Main(string[] args) { // Update the below variables to use your tenant and account information string siteUrl = "https://contoso.sharepoint.com/sites/modernpagedemo"; string userName = "******"; SecureString password = GetSecureString("Password"); AuthenticationManager am = new AuthenticationManager(); using (var cc = am.GetSharePointOnlineAuthenticatedContextTenant(siteUrl, userName, password)) { // Demo 1: Add empty page var page = cc.Web.AddClientSidePage("PnPRocks.aspx", true); // Demo 2: Read existing page and Text control + custom web part. // Important: manually create a sample modern page called "Templatepage" in your demo site first ClientSidePage p = ClientSidePage.Load(cc, "Templatepage.aspx"); // Add text control on top ClientSideText txt1 = new ClientSideText() { Text = "PnP Rocks" }; p.AddControl(txt1, -1); // Find custom component and add as last control // Important: this assumes you've a custom client side web part with name "HelloWorld" deployed to the test site collection. var components = p.AvailableClientSideComponents(); var myWebPart = components.Where(s => s.Name == "HelloWorld").FirstOrDefault(); if (myWebPart != null) { ClientSideWebPart helloWp = new ClientSideWebPart(myWebPart) { Order = 10 }; p.AddControl(helloWp); } // Save the page under a new name p.Save("pagewithcontrols.aspx"); //Demo 3: Add OOB web part (Image) // Important: if you don't update the web part properties your client side impage web part will not be able to load the image ClientSidePage page5 = new ClientSidePage(cc); var imageWebPart = page5.InstantiateDefaultWebPart(DefaultClientSideWebParts.Image); imageWebPart.Properties["imageSourceType"] = 2; imageWebPart.Properties["siteId"] = "c827cb03-d059-4956-83d0-cd60e02e3b41"; imageWebPart.Properties["webId"] = "9fafd7c0-e8c3-4a3c-9e87-4232c481ca26"; imageWebPart.Properties["listId"] = "78d1b1ac-7590-49e7-b812-55f37c018c4b"; imageWebPart.Properties["uniqueId"] = "3C27A419-66D0-4C36-BF24-BD6147719052"; imageWebPart.Properties["imgWidth"] = 1002; imageWebPart.Properties["imgHeight"] = 469; //imageWebPart.PropertiesJson = "{\"imageSourceType\":2,\"altText\":\"\",\"fileName\":\"\",\"siteId\":\"c827cb03-d059-4956-83d0-cd60e02e3b41\",\"webId\":\"9fafd7c0-e8c3-4a3c-9e87-4232c481ca26\",\"listId\":\"78d1b1ac-7590-49e7-b812-55f37c018c4b\",\"uniqueId\":\"{3C27A419-66D0-4C36-BF24-BD6147719052}\",\"imgWidth\":1002,\"imgHeight\":469}"; page5.AddControl(imageWebPart); page5.Save("pagewithimage.aspx"); //Demo 4: delete page ClientSidePage p2 = ClientSidePage.Load(cc, "pagewithcontrols.aspx"); p2.Delete(); //Demo 5: delete control ClientSidePage deleteDemoPage = ClientSidePage.Load(cc, "pagewithimage.aspx"); deleteDemoPage.Controls[0].Delete(); deleteDemoPage.Save(); } }
public void Transform(List <WebPartEntity> webParts) { if (webParts == null || webParts.Count == 0) { // nothing to transform return; } var defaultMapping = pageTransformation.BaseWebPart.Mappings.Mapping.Where(p => p.Default == true).FirstOrDefault(); if (defaultMapping == null) { throw new Exception("No default mapping was found int the provided mapping file"); } // Load existing available controls var componentsToAdd = page.AvailableClientSideComponents().ToList(); // Iterate over the web parts, important to order them by row, column and zoneindex foreach (var webPart in webParts.OrderBy(p => p.Row).OrderBy(p => p.Column).OrderBy(p => p.ZoneIndex)) { if (webPart.Type == WebParts.TitleBar) { continue; } // Add site tokens to the web part foreach (var token in this.siteTokens) { webPart.Properties.Add(token.Key, token.Value); } Mapping mapping = defaultMapping; // Does the web part have a mapping defined? var webPartData = pageTransformation.WebParts.Where(p => p.Type == webPart.Type).FirstOrDefault(); if (webPartData != null && webPartData.Mappings != null) { // Process the functions inside the mapping definition var selectorResult = functionProcessor.Process(ref webPartData, webPart); Mapping webPartMapping = null; if (!string.IsNullOrEmpty(selectorResult)) { webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Name.Equals(selectorResult, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); } else { webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Default == true).FirstOrDefault(); } if (webPartMapping != null) { mapping = webPartMapping; } } // Use the mapping data => make one list of Text and WebParts to allow for correct ordering combinedMappinglist = new List <CombinedMapping>(); if (mapping.ClientSideText != null) { foreach (var map in mapping.ClientSideText.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = map, ClientSideWebPart = null, Order = mapOrder }); } } if (mapping.ClientSideWebPart != null) { foreach (var map in mapping.ClientSideWebPart.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = null, ClientSideWebPart = map, Order = mapOrder }); } } // Get the order of the last inserted control in this column int order = LastColumnOrder(webPart.Row - 1, webPart.Column - 1); // Interate the controls for this mapping using their order foreach (var map in combinedMappinglist.OrderBy(p => p.Order)) { order++; if (map.ClientSideText != null) { // Insert a Text control OfficeDevPnP.Core.Pages.ClientSideText text = new OfficeDevPnP.Core.Pages.ClientSideText() { Text = TokenParser.ReplaceTokens(map.ClientSideText.Text, webPart) }; page.AddControl(text, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); } else if (map.ClientSideWebPart != null) { ClientSideComponent baseControl = null; // Insert a web part if (map.ClientSideWebPart.Type == ClientSideWebPartType.Custom) { // TODO } else { string webPartName = ""; switch (map.ClientSideWebPart.Type) { case ClientSideWebPartType.List: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.List); break; } default: { break; } } baseControl = componentsToAdd.FirstOrDefault(p => p.Name.Equals(webPartName, StringComparison.InvariantCultureIgnoreCase)); } if (baseControl != null) { OfficeDevPnP.Core.Pages.ClientSideWebPart myWebPart = new OfficeDevPnP.Core.Pages.ClientSideWebPart(baseControl) { Order = map.Order, PropertiesJson = TokenParser.ReplaceTokens(map.ClientSideWebPart.JsonControlData, webPart) }; page.AddControl(myWebPart, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); } } } } }
public void Transform(List <WebPartEntity> webParts) { if (webParts == null || webParts.Count == 0) { // nothing to transform return; } var defaultMapping = pageTransformation.BaseWebPart.Mappings.Where(p => p.Default == true).FirstOrDefault(); if (defaultMapping == null) { throw new Exception("No default mapping was found int the provided mapping file"); } // Iterate over the web parts, important to order them by row, column and zoneindex foreach (var webPart in webParts.OrderBy(p => p.Row).OrderBy(p => p.Column).OrderBy(p => p.ZoneIndex)) { if (webPart.Type == WebParts.TitleBar) { continue; } // Find the mapping information we're going to use Mapping mapping = defaultMapping; // Does the web part have a mapping defined? var webPartData = pageTransformation.WebParts.Where(p => p.Type == webPart.Type).FirstOrDefault(); if (webPartData != null && webPartData.Mappings != null) { var webPartMapping = webPartData.Mappings.Where(p => p.Default == true).FirstOrDefault(); if (webPartMapping != null) { mapping = webPartMapping; } } // Use the mapping data => make one list of Text and WebParts to allow for correct ordering combinedMappinglist = new List <CombinedMapping>(); if (mapping.ClientSideText != null) { foreach (var map in mapping.ClientSideText.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = map, ClientSideWebPart = null, Order = mapOrder }); } } if (mapping.ClientSideWebPart != null) { foreach (var map in mapping.ClientSideWebPart.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = null, ClientSideWebPart = map, Order = 0 }); } } // Get the order of the last inserted control in this column int order = LastColumnOrder(webPart.Row - 1, webPart.Column - 1); // Interate the controls for this mapping using their order foreach (var map in combinedMappinglist.OrderBy(p => p.Order)) { order++; if (map.ClientSideText != null) { // Insert a Text control OfficeDevPnP.Core.Pages.ClientSideText text = new OfficeDevPnP.Core.Pages.ClientSideText() { Text = TokenParser.ReplaceTokens(map.ClientSideText.Text, webPart) }; page.AddControl(text, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); } else if (map.ClientSideWebPart != null) { // Insert a web part } } } }
/// <summary> /// Transforms the passed web parts into the loaded client side page /// </summary> /// <param name="webParts">List of web parts that need to be transformed</param> public void Transform(List <WebPartEntity> webParts) { if (webParts == null || webParts.Count == 0) { // nothing to transform return; } // find the default mapping, will be used for webparts for which the model does not contain a mapping var defaultMapping = pageTransformation.BaseWebPart.Mappings.Mapping.Where(p => p.Default == true).FirstOrDefault(); if (defaultMapping == null) { throw new Exception("No default mapping was found int the provided mapping file"); } // Load existing available controls var componentsToAdd = page.AvailableClientSideComponents().ToList(); // Iterate over the web parts, important to order them by row, column and zoneindex foreach (var webPart in webParts.OrderBy(p => p.Row).OrderBy(p => p.Column).OrderBy(p => p.Order)) { // Title bar will never be migrated if (webPart.Type == WebParts.TitleBar) { continue; } // Add site level (e.g. site) tokens to the web part properties so they can be used in the same manner as a web part property foreach (var token in this.siteTokens) { webPart.Properties.Add(token.Key, token.Value); } Mapping mapping = defaultMapping; // Does the web part have a mapping defined? var webPartData = pageTransformation.WebParts.Where(p => p.Type == webPart.Type).FirstOrDefault(); if (webPartData != null && webPartData.Mappings != null) { // The mapping can have a selector function defined, is so it will be executed. If a selector was executed the selectorResult will contain the name of the mapping to use var selectorResult = functionProcessor.Process(ref webPartData, webPart); Mapping webPartMapping = null; // Get the needed mapping: // - use the mapping returned by the selector // - if no selector then take the default mapping // - if no mapping found we'll fall back to the default web part mapping if (!string.IsNullOrEmpty(selectorResult)) { webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Name.Equals(selectorResult, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); } else { webPartMapping = webPartData.Mappings.Mapping.Where(p => p.Default == true).FirstOrDefault(); } if (webPartMapping != null) { mapping = webPartMapping; } } // Use the mapping data => make one list of Text and WebParts to allow for correct ordering combinedMappinglist = new List <CombinedMapping>(); if (mapping.ClientSideText != null) { foreach (var map in mapping.ClientSideText.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = map, ClientSideWebPart = null, Order = mapOrder }); } } if (mapping.ClientSideWebPart != null) { foreach (var map in mapping.ClientSideWebPart.OrderBy(p => p.Order)) { if (!Int32.TryParse(map.Order, out Int32 mapOrder)) { mapOrder = 0; } combinedMappinglist.Add(new CombinedMapping { ClientSideText = null, ClientSideWebPart = map, Order = mapOrder }); } } // Get the order of the last inserted control in this column int order = LastColumnOrder(webPart.Row - 1, webPart.Column - 1); // Interate the controls for this mapping using their order foreach (var map in combinedMappinglist.OrderBy(p => p.Order)) { order++; if (map.ClientSideText != null) { // Insert a Text control OfficeDevPnP.Core.Pages.ClientSideText text = new OfficeDevPnP.Core.Pages.ClientSideText() { Text = TokenParser.ReplaceTokens(map.ClientSideText.Text, webPart) }; page.AddControl(text, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); } else if (map.ClientSideWebPart != null) { // Insert a web part ClientSideComponent baseControl = null; if (map.ClientSideWebPart.Type == ClientSideWebPartType.Custom) { baseControl = componentsToAdd.FirstOrDefault(p => p.Id.Equals(map.ClientSideWebPart.ControlId, StringComparison.InvariantCultureIgnoreCase)); } else { string webPartName = ""; switch (map.ClientSideWebPart.Type) { case ClientSideWebPartType.List: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.List); break; } case ClientSideWebPartType.Image: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Image); break; } case ClientSideWebPartType.ContentRollup: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ContentRollup); break; } case ClientSideWebPartType.BingMap: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.BingMap); break; } case ClientSideWebPartType.ContentEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ContentEmbed); break; } case ClientSideWebPartType.DocumentEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.DocumentEmbed); break; } case ClientSideWebPartType.ImageGallery: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.ImageGallery); break; } case ClientSideWebPartType.LinkPreview: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.LinkPreview); break; } case ClientSideWebPartType.NewsFeed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.NewsFeed); break; } case ClientSideWebPartType.NewsReel: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.NewsReel); break; } case ClientSideWebPartType.PowerBIReportEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.PowerBIReportEmbed); break; } case ClientSideWebPartType.QuickChart: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.QuickChart); break; } case ClientSideWebPartType.SiteActivity: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.SiteActivity); break; } case ClientSideWebPartType.VideoEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.VideoEmbed); break; } case ClientSideWebPartType.YammerEmbed: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.YammerEmbed); break; } case ClientSideWebPartType.Events: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Events); break; } case ClientSideWebPartType.GroupCalendar: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.GroupCalendar); break; } case ClientSideWebPartType.Hero: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Hero); break; } case ClientSideWebPartType.PageTitle: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.PageTitle); break; } case ClientSideWebPartType.People: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.People); break; } case ClientSideWebPartType.QuickLinks: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.QuickLinks); break; } case ClientSideWebPartType.Divider: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Divider); break; } case ClientSideWebPartType.MicrosoftForms: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.MicrosoftForms); break; } case ClientSideWebPartType.Spacer: { webPartName = ClientSidePage.ClientSideWebPartEnumToName(DefaultClientSideWebParts.Spacer); break; } default: { break; } } baseControl = componentsToAdd.FirstOrDefault(p => p.Name.Equals(webPartName, StringComparison.InvariantCultureIgnoreCase)); } // If we found the web part as a possible candidate to use then add it if (baseControl != null) { var jsonDecoded = WebUtility.HtmlDecode(TokenParser.ReplaceTokens(map.ClientSideWebPart.JsonControlData, webPart)); OfficeDevPnP.Core.Pages.ClientSideWebPart myWebPart = new OfficeDevPnP.Core.Pages.ClientSideWebPart(baseControl) { Order = map.Order, PropertiesJson = jsonDecoded }; page.AddControl(myWebPart, page.Sections[webPart.Row - 1].Columns[webPart.Column - 1], order); } else { //Log warning: web part was not found } } } } }