diff --git a/Commands/Base/PipeBinds/ClientSideComponentPipeBind.cs b/Commands/Base/PipeBinds/ClientSideComponentPipeBind.cs new file mode 100644 index 000000000..785fbc921 --- /dev/null +++ b/Commands/Base/PipeBinds/ClientSideComponentPipeBind.cs @@ -0,0 +1,74 @@ +using Microsoft.SharePoint.Client; +using OfficeDevPnP.Core.Pages; +using SharePointPnP.PowerShell.Commands.ClientSidePages; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharePointPnP.PowerShell.Commands.Base.PipeBinds +{ + public sealed class ClientSideComponentPipeBind + { + private readonly ClientSideComponent _component; + private string _name; + private Guid _id; + + public ClientSideComponentPipeBind(ClientSideComponent component) + { + _component = component; + _id = Guid.Parse(_component.Id); + _name = _component.Name; + } + + public ClientSideComponentPipeBind(string nameOrId) + { + _component = null; + if (!Guid.TryParse(nameOrId, out _id)) + { + _name = nameOrId; + } + } + + public ClientSideComponentPipeBind(Guid id) + { + _id = id; + _name = null; + _component = null; + } + + public ClientSideComponent Component => _component; + + public string Name => _component?.Name; + + public string Id => _component == null ? Guid.Empty.ToString() : _component.Id; + + public override string ToString() => Name; + + internal ClientSideComponent GetComponent(ClientSidePage page) + { + if (_component != null) + { + return _component; + } + else if (!string.IsNullOrEmpty(_name)) + { + ClientSideComponent com = page.AvailableClientSideComponents(_name).FirstOrDefault(); + return com; + } + else if (_id != Guid.Empty) + { + string idAsString = _id.ToString(); + var comQuery = from c in page.AvailableClientSideComponents(_name) + where c.Id == idAsString + select c; + return comQuery.FirstOrDefault(); + } + else + { + return null; + } + } + } +} diff --git a/Commands/Base/PipeBinds/ClientSidePagePipeBind.cs b/Commands/Base/PipeBinds/ClientSidePagePipeBind.cs new file mode 100644 index 000000000..e20a8e4c1 --- /dev/null +++ b/Commands/Base/PipeBinds/ClientSidePagePipeBind.cs @@ -0,0 +1,58 @@ +using Microsoft.SharePoint.Client; +using OfficeDevPnP.Core.Pages; +using SharePointPnP.PowerShell.Commands.ClientSidePages; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharePointPnP.PowerShell.Commands.Base.PipeBinds +{ + public sealed class ClientSidePagePipeBind + { + private readonly ClientSidePage _page; + private string _name; + + public ClientSidePagePipeBind(ClientSidePage page) + { + _page = page; + _name = page.PageTitle; + } + + public ClientSidePagePipeBind(string name) + { + _page = null; + _name = name; + } + + public ClientSidePage Page => _page; + + public string Name => ClientSidePageUtilities.EnsureCorrectPageName(_name); + + public override string ToString() => Name; + + internal ClientSidePage GetPage(ClientContext ctx) + { + if (_page != null) + { + return _page; + } + else if (!string.IsNullOrEmpty(_name)) + { + try + { + return ClientSidePage.Load(ctx, Name); + } + catch (ArgumentException ex) + { + return null; + } + } + else + { + return null; + } + } + } +} diff --git a/Commands/Base/PipeBinds/GenericPropertiesPipeBind.cs b/Commands/Base/PipeBinds/GenericPropertiesPipeBind.cs new file mode 100644 index 000000000..733fecb7e --- /dev/null +++ b/Commands/Base/PipeBinds/GenericPropertiesPipeBind.cs @@ -0,0 +1,67 @@ +using Microsoft.SharePoint.Client; +using Newtonsoft.Json.Linq; +using OfficeDevPnP.Core.Pages; +using SharePointPnP.PowerShell.Commands.ClientSidePages; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; +using System.Text; +using System.Threading.Tasks; + +namespace SharePointPnP.PowerShell.Commands.Base.PipeBinds +{ + public sealed class PropertyBagPipeBind + { + private readonly Hashtable _hashtable; + private string _jsonString; + private JObject _jsonObject; + + public PropertyBagPipeBind(Hashtable hashtable) + { + _hashtable = hashtable; + _jsonString = null; + _jsonObject = null; + } + + public PropertyBagPipeBind(string json) + { + _hashtable = null; + _jsonString = json; + _jsonObject = JObject.Parse(json); + } + + public string Json => _jsonString; + + public JObject JsonObject => _jsonObject ?? HashtableToJsonObject(_hashtable); + + public Hashtable Properties => _hashtable; + + public override string ToString() => Json ?? HashtableToJsonString(_hashtable); + + private string HashtableToJsonString(Hashtable hashtable) + { + return HashtableToJsonObject(hashtable).ToString(); + } + + private JObject HashtableToJsonObject(Hashtable hashtable) + { + var obj = new JObject(); + + foreach (var key in hashtable.Keys) + { + var rawValue = hashtable[key]; + + // To ensure the value is not serialized as PSObject + object value = rawValue is PSObject + ? ((PSObject)rawValue).BaseObject + : rawValue; + + obj[key] = JToken.FromObject(value); + } + return obj; + } + + } +} diff --git a/Commands/ClientSidePages/AddClientSidePage.cs b/Commands/ClientSidePages/AddClientSidePage.cs new file mode 100644 index 000000000..b920831ea --- /dev/null +++ b/Commands/ClientSidePages/AddClientSidePage.cs @@ -0,0 +1,99 @@ +#if !ONPREMISES +using Microsoft.SharePoint.Client; +using OfficeDevPnP.Core.Pages; +using SharePointPnP.PowerShell.CmdletHelpAttributes; +using System; +using System.Management.Automation; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + [Cmdlet(VerbsCommon.Add, "PnPClientSidePage")] + [CmdletHelp("Adds a Client-Side Page", + Category = CmdletHelpCategory.ClientSidePages, SupportedPlatform = CmdletSupportedPlatform.Online)] + [CmdletExample( + Code = @"PS:> Add-PnPClientSidePage -PageName ""OurNewPage""", + Remarks = "Creates a new Client-Side page called 'OurNewPage'", + SortOrder = 1)] + public class AddClientSidePage : PnPWebCmdlet + { + [Parameter(Mandatory = true, HelpMessage = "Specifies the name of the page.")] + public string Name = null; + + [Parameter(Mandatory = false, HelpMessage = "Specifies the layout type of the page.")] + public ClientSidePageLayoutType LayoutType = ClientSidePageLayoutType.Article; + + [Parameter(Mandatory = false, HelpMessage = "Allows to promote the page for a specific purpose (HomePage | NewsPage)")] + public ClientSidePagePromoteType PromoteAs = ClientSidePagePromoteType.None; + + [Parameter(Mandatory = false, HelpMessage = "Enables or Disables the comments on the page")] + public bool? CommentsEnabled = null; + + [Parameter(Mandatory = false, HelpMessage = "Publishes the page once it is saved. Applicable to libraries set to create major and minor versions.")] + public SwitchParameter Publish; + + [Parameter(Mandatory = false, HelpMessage = "Sets the message for publishing the page.")] + public string PublishMessage = string.Empty; + + protected override void ExecuteCmdlet() + { + + ClientSidePage clientSidePage = null; + + // Check if the page exists + + string name = ClientSidePageUtilities.EnsureCorrectPageName(Name); + + bool pageExists = false; + try + { + ClientSidePage.Load(ClientContext, name); + pageExists = true; + } + catch { } + + if(pageExists) + { + throw new Exception($"Page {name} already exists"); + } + + // Create a page that persists immediately + clientSidePage = SelectedWeb.AddClientSidePage(name); + clientSidePage.LayoutType = LayoutType; + clientSidePage.Save(name); + + // If a specific promote type is specified, promote the page as Home or Article or ... + switch (PromoteAs) + { + case ClientSidePagePromoteType.HomePage: + clientSidePage.PromoteAsHomePage(); + break; + case ClientSidePagePromoteType.NewsArticle: + clientSidePage.PromoteAsNewsArticle(); + break; + case ClientSidePagePromoteType.None: + default: + break; + } + + if (CommentsEnabled.HasValue) + { + if (CommentsEnabled.Value) + { + clientSidePage.EnableComments(); + } + else + { + clientSidePage.DisableComments(); + } + } + + if (Publish) + { + clientSidePage.Publish(PublishMessage); + } + + WriteObject(clientSidePage); + } + } +} +#endif \ No newline at end of file diff --git a/Commands/ClientSidePages/AddClientSidePageSection.cs b/Commands/ClientSidePages/AddClientSidePageSection.cs new file mode 100644 index 000000000..c633efa2c --- /dev/null +++ b/Commands/ClientSidePages/AddClientSidePageSection.cs @@ -0,0 +1,56 @@ +#if !ONPREMISES +using OfficeDevPnP.Core.Pages; +using SharePointPnP.PowerShell.CmdletHelpAttributes; +using SharePointPnP.PowerShell.Commands.Base.PipeBinds; +using System; +using System.Management.Automation; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + [Cmdlet(VerbsCommon.Add, "PnPClientSidePageSection")] + [CmdletHelp("Adds a new section to a Client-Side page", + Category = CmdletHelpCategory.ClientSidePages, SupportedPlatform = CmdletSupportedPlatform.Online)] + [CmdletExample( + Code = @"PS:> Add-PnPClientSidePageSection -Page ""MyPage"" -SectionTemplate OneColumn", + Remarks = "Adds a new one-column section to the Client-Side page 'MyPage'", + SortOrder = 1)] + [CmdletExample( + Code = @"PS:> Add-PnPClientSidePageSection -Page ""MyPage"" -SectionTemplate ThreeColumn -Order 10", + Remarks = "Adds a new Three columns section to the Client-Side page 'MyPage' with an order index of 10", + SortOrder = 2)] + [CmdletExample( + Code = @"PS:> $page = Add-PnPClientSidePage -Name ""MyPage"" +PS> Add-PnPClientSidePageSection -Page $page -SectionTemplate OneColumn", + Remarks = "Adds a new one column section to the Client-Side page 'MyPage'", + SortOrder = 2)] + public class AddClientSidePageSection : PnPWebCmdlet + { + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page")] + public ClientSidePagePipeBind Page; + + [Parameter(Mandatory = true, HelpMessage = "Specifies the columns template to use for the section.")] + public CanvasSectionTemplate SectionTemplate; + + [Parameter(Mandatory = false, HelpMessage = "Sets the order of the section. (Default = 1)")] + public int Order = 1; + + + protected override void ExecuteCmdlet() + { + var clientSidePage = Page?.GetPage(ClientContext); + + if (clientSidePage != null) + { + clientSidePage.AddSection(SectionTemplate, Order); + clientSidePage.Save(); + } + else + { + // If the client side page object cannot be found + throw new Exception($"Page {Page} cannot be found."); + } + + } + } +} +#endif diff --git a/Commands/ClientSidePages/AddClientSideText.cs b/Commands/ClientSidePages/AddClientSideText.cs new file mode 100644 index 000000000..b256798d6 --- /dev/null +++ b/Commands/ClientSidePages/AddClientSideText.cs @@ -0,0 +1,78 @@ +#if !ONPREMISES +using OfficeDevPnP.Core.Pages; +using SharePointPnP.PowerShell.CmdletHelpAttributes; +using SharePointPnP.PowerShell.Commands.Base.PipeBinds; +using System; +using System.Management.Automation; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + [Cmdlet(VerbsCommon.Add, "PnPClientSideText")] + [CmdletHelp("Adds a Client-Side Page", + Category = CmdletHelpCategory.ClientSidePages, SupportedPlatform = CmdletSupportedPlatform.Online)] + [CmdletExample( + Code = @"PS:> Add-PnPClientSideText -Page ""OurNewPage"" -Text ""Hello World!""", + Remarks = "Adds the text 'Hello World!' to the Client-Side Page 'OurNewPage'", + SortOrder = 1)] + public class AddClientSideText : PnPWebCmdlet + { + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page.", ParameterSetName = "Default")] + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page.", ParameterSetName = "Positioned")] + public ClientSidePagePipeBind Page; + + [Parameter(Mandatory = true, HelpMessage = "Specifies the text to display in the text area.", ParameterSetName = "Default")] + [Parameter(Mandatory = true, HelpMessage = "Specifies the text to display in the text area.", ParameterSetName = "Positioned")] + public string Text; + + [Parameter(Mandatory = false, HelpMessage = "Sets the order of the text control. (Default = 1)", ParameterSetName = "Default")] + [Parameter(Mandatory = false, HelpMessage = "Sets the order of the text control. (Default = 1)", ParameterSetName = "Positioned")] + public int Order = 1; + + [Parameter(Mandatory = true, HelpMessage = "Sets the section where to insert the text control.", ParameterSetName = "Positioned")] + public int Section; + + [Parameter(Mandatory = true, HelpMessage = "Sets the column where to insert the text control.", ParameterSetName = "Positioned")] + public int Column; + + protected override void ExecuteCmdlet() + { + if (MyInvocation.BoundParameters.ContainsKey("Section") && Section == 0) + { + throw new Exception("Section value should be at least 1 or higher"); + } + + if (MyInvocation.BoundParameters.ContainsKey("Column") && Column == 0) + { + throw new Exception("Column value should be at least 1 or higher"); + } + + var clientSidePage = Page.GetPage(ClientContext); + + if (clientSidePage == null) + // If the client side page object cannot be found + throw new Exception($"Page {Page} cannot be found."); + + var text = new ClientSideText() { Text = Text }; + if (MyInvocation.BoundParameters.ContainsKey("Section")) + { + if (MyInvocation.BoundParameters.ContainsKey("Section")) + { + clientSidePage.AddControl(text, + clientSidePage.Sections[Section - 1].Columns[Column - 1], Order); + } + else + { + clientSidePage.AddControl(text, clientSidePage.Sections[Section - 1], Order); + } + } + else + { + clientSidePage.AddControl(text, Order); + } + + // Save the page + clientSidePage.Save(); + } + } +} +#endif \ No newline at end of file diff --git a/Commands/ClientSidePages/AddClientSideWebPart.cs b/Commands/ClientSidePages/AddClientSideWebPart.cs new file mode 100644 index 000000000..0bde29d7b --- /dev/null +++ b/Commands/ClientSidePages/AddClientSideWebPart.cs @@ -0,0 +1,123 @@ +#if !ONPREMISES +using OfficeDevPnP.Core.Pages; +using SharePointPnP.PowerShell.CmdletHelpAttributes; +using SharePointPnP.PowerShell.Commands.Base.PipeBinds; +using System; +using System.Management.Automation; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + [Cmdlet(VerbsCommon.Add, "PnPClientSideWebPart")] + [CmdletHelp("Adds a Client-Side Component to a page", + Category = CmdletHelpCategory.ClientSidePages, SupportedPlatform = CmdletSupportedPlatform.Online)] + [CmdletExample( + Code = @"PS:> Add-PnPClientSideWebPart -Page ""OurNewPage"" -DefaultWebPartType BingMap", + Remarks = "Adds a built-in Client-Side component 'BingMap' to the page called 'OurNewPage'", + SortOrder = 2)] + [CmdletExample( + Code = @"PS:> Add-PnPClientSideWebPart -Page ""OurNewPage"" -Component ""HelloWorld""", + Remarks = "Adds a Client-Side component 'HelloWorld' to the page called 'OurNewPage'", + SortOrder = 2)] + [CmdletExample( + Code = @"PS:> Add-PnPClientSideWebPart -Page ""OurNewPage"" -Component ""HelloWorld"" -Section 1 -Column 2", + Remarks = "Adds a Client-Side component 'HelloWorld' to the page called 'OurNewPage' in section 1 and column 2", + SortOrder = 3)] + public class AddClientSideWebPart : PnPWebCmdlet + { + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page.", ParameterSetName = "DefaultBuiltIn")] + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page.", ParameterSetName = "Default3rdParty")] + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page.", ParameterSetName = "PositionedBuiltIn")] + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page.", ParameterSetName = "Positioned3rdParty")] + public ClientSidePagePipeBind Page; + + [Parameter(Mandatory = true, HelpMessage = "Defines a default WebPart type to insert.", ParameterSetName = "DefaultBuiltIn")] + [Parameter(Mandatory = true, HelpMessage = "Defines a default WebPart type to insert.", ParameterSetName = "PositionedBuiltIn")] + public DefaultClientSideWebParts DefaultWebPartType; + + [Parameter(Mandatory = true, HelpMessage = "Specifies the component instance or Id to add.", ParameterSetName = "Default3rdParty")] + [Parameter(Mandatory = true, HelpMessage = "Specifies the component instance or Id to add.", ParameterSetName = "Positioned3rdParty")] + public ClientSideComponentPipeBind Component; + + [Parameter(Mandatory = false, HelpMessage = @"The properties of the WebPart", ParameterSetName = "DefaultBuiltIn")] + [Parameter(Mandatory = false, HelpMessage = @"The properties of the WebPart", ParameterSetName = "Default3rdParty")] + [Parameter(Mandatory = false, HelpMessage = @"The properties of the WebPart", ParameterSetName = "PositionedBuiltIn")] + [Parameter(Mandatory = false, HelpMessage = @"The properties of the WebPart", ParameterSetName = "Positioned3rdParty")] + public PropertyBagPipeBind WebPartProperties; + + [Parameter(Mandatory = false, HelpMessage = "Sets the order of the WebPart control. (Default = 1)", ParameterSetName = "DefaultBuiltIn")] + [Parameter(Mandatory = false, HelpMessage = "Sets the order of the WebPart control. (Default = 1)", ParameterSetName = "Default3rdParty")] + [Parameter(Mandatory = false, HelpMessage = "Sets the order of the WebPart control. (Default = 1)", ParameterSetName = "PositionedBuiltIn")] + [Parameter(Mandatory = false, HelpMessage = "Sets the order of the WebPart control. (Default = 1)", ParameterSetName = "Positioned3rdParty")] + public int Order = 1; + + [Parameter(Mandatory = true, HelpMessage = "Sets the section where to insert the WebPart control.", ParameterSetName = "PositionedBuiltIn")] + [Parameter(Mandatory = true, HelpMessage = "Sets the section where to insert the WebPart control.", ParameterSetName = "Positioned3rdParty")] + public int Section; + + [Parameter(Mandatory = true, HelpMessage = "Sets the column where to insert the WebPart control.", ParameterSetName = "PositionedBuiltIn")] + [Parameter(Mandatory = true, HelpMessage = "Sets the column where to insert the WebPart control.", ParameterSetName = "Positioned3rdParty")] + public int Column; + + protected override void ExecuteCmdlet() + { + if (MyInvocation.BoundParameters.ContainsKey("Section") && Section == 0) + { + throw new Exception("Section value should be at least 1 or higher"); + } + + if (MyInvocation.BoundParameters.ContainsKey("Column") && Column == 0) + { + throw new Exception("Column value should be at least 1 or higher"); + } + + var clientSidePage = Page.GetPage(ClientContext); + // If the client side page object cannot be found + if (clientSidePage == null) + { + throw new Exception($"Page {Page} cannot be found."); + } + + ClientSideWebPart webpart = null; + if (MyInvocation.BoundParameters.ContainsKey("DefaultWebPartType")) + { + webpart = clientSidePage.InstantiateDefaultWebPart(DefaultWebPartType); + } + else + { + webpart = new ClientSideWebPart(Component.GetComponent(clientSidePage)); + } + + if (WebPartProperties != null) + { + if (WebPartProperties.Properties != null) + { + webpart.Properties.Merge(WebPartProperties.JsonObject); + } + else if (!string.IsNullOrEmpty(WebPartProperties.Json)) + { + webpart.PropertiesJson = WebPartProperties.Json; + } + } + + if (MyInvocation.BoundParameters.ContainsKey("Section")) + { + if (MyInvocation.BoundParameters.ContainsKey("Column")) + { + clientSidePage.AddControl(webpart, + clientSidePage.Sections[Section - 1].Columns[Column - 1], Order); + } + else + { + clientSidePage.AddControl(webpart, clientSidePage.Sections[Section - 1], Order); + } + } + else + { + clientSidePage.AddControl(webpart, Order); + } + + clientSidePage.Save(); + } + } +} +#endif \ No newline at end of file diff --git a/Commands/ClientSidePages/ClientSidePageUtilities.cs b/Commands/ClientSidePages/ClientSidePageUtilities.cs new file mode 100644 index 000000000..22568b850 --- /dev/null +++ b/Commands/ClientSidePages/ClientSidePageUtilities.cs @@ -0,0 +1,16 @@ +#if !ONPREMISES + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + internal static class ClientSidePageUtilities + { + public static string EnsureCorrectPageName(string pageName) + { + if (pageName != null && !pageName.EndsWith(".aspx")) + pageName += ".aspx"; + + return pageName; + } + } +} +#endif diff --git a/Commands/ClientSidePages/GetAvailableClientSideComponents.cs b/Commands/ClientSidePages/GetAvailableClientSideComponents.cs new file mode 100644 index 000000000..61a4a85f8 --- /dev/null +++ b/Commands/ClientSidePages/GetAvailableClientSideComponents.cs @@ -0,0 +1,48 @@ +#if !ONPREMISES +using SharePointPnP.PowerShell.CmdletHelpAttributes; +using SharePointPnP.PowerShell.Commands.Base.PipeBinds; +using System.Linq; +using System.Management.Automation; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + [Cmdlet(VerbsCommon.Get, "PnPAvailableClientSideComponents")] + [CmdletHelp("Gets the available client side components on a particular page", + Category = CmdletHelpCategory.ClientSidePages, SupportedPlatform = CmdletSupportedPlatform.Online)] + [CmdletExample( + Code = @"PS:> Get-PnPAvailableClientSideComponents -Identity ""MyPage.aspx""", + Remarks = "Gets the list of available client side components on the page 'MyPage.aspx'", + SortOrder = 1)] + [CmdletExample( + Code = @"PS:> Get-PnPAvailableClientSideComponents $page", + Remarks = "Gets the list of available client side components on the page contained in the $page variable", + SortOrder = 2)] + [CmdletExample( + Code = @"PS:> Get-PnPAvailableClientSideComponents -Identity ""MyPage.aspx"" -ComponentName ""HelloWorld""", + Remarks = "Gets the client side component 'HelloWorld' if available on the page 'MyPage.aspx'", + SortOrder = 3)] + public class GetAvailableClientSideComponents : PnPWebCmdlet + { + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page.")] + public ClientSidePagePipeBind Page; + + [Parameter(Mandatory = false, HelpMessage = "Specifies the component instance or Id to look for.")] + public ClientSideComponentPipeBind Component; + + protected override void ExecuteCmdlet() + { + var clientSidePage = Page.GetPage(ClientContext); + + if (Component == null) + { + var allComponents = clientSidePage.AvailableClientSideComponents().Where(c => c.ComponentType == 1); + WriteObject(allComponents, true); + } + else + { + WriteObject(Component.GetComponent(clientSidePage)); + } + } + } +} +#endif diff --git a/Commands/ClientSidePages/GetClientSidePage.cs b/Commands/ClientSidePages/GetClientSidePage.cs new file mode 100644 index 000000000..f6400e89e --- /dev/null +++ b/Commands/ClientSidePages/GetClientSidePage.cs @@ -0,0 +1,36 @@ +#if !ONPREMISES +using SharePointPnP.PowerShell.CmdletHelpAttributes; +using SharePointPnP.PowerShell.Commands.Base.PipeBinds; +using System; +using System.Management.Automation; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + [Cmdlet(VerbsCommon.Get, "PnPClientSidePage")] + [CmdletHelp("Gets a Client-Side Page", + Category = CmdletHelpCategory.ClientSidePages, SupportedPlatform = CmdletSupportedPlatform.Online)] + [CmdletExample( + Code = @"PS:> Get-PnPClientSidePage -Identity ""MyPage.aspx""", + Remarks = "Gets the Modern Page (Client-Side) called 'MyPage.aspx' in the current SharePoint site", + SortOrder = 2)] + [CmdletExample( + Code = @"PS:> Get-PnPClientSidePage ""MyPage""", + Remarks = "Gets the Modern Page (Client-Side) called 'MyPage.aspx' in the current SharePoint site", + SortOrder = 2)] + public class GetClientSidePage : PnPWebCmdlet + { + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page")] + public ClientSidePagePipeBind Identity; + + protected override void ExecuteCmdlet() + { + var clientSidePage = Identity.GetPage(ClientContext); + + if (clientSidePage == null) + throw new Exception($"Page '{Identity?.Name}' does not exist"); + + WriteObject(clientSidePage); + } + } +} +#endif \ No newline at end of file diff --git a/Commands/ClientSidePages/RemoveClientSidePage.cs b/Commands/ClientSidePages/RemoveClientSidePage.cs new file mode 100644 index 000000000..ce90b7b7d --- /dev/null +++ b/Commands/ClientSidePages/RemoveClientSidePage.cs @@ -0,0 +1,42 @@ +#if !ONPREMISES +using SharePointPnP.PowerShell.CmdletHelpAttributes; +using SharePointPnP.PowerShell.Commands.Base.PipeBinds; +using SharePointPnP.PowerShell.Commands.Properties; +using System; +using System.Management.Automation; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + [Cmdlet(VerbsCommon.Remove, "PnPClientSidePage")] + [CmdletHelp("Removes a Client-Side Page", + Category = CmdletHelpCategory.ClientSidePages, SupportedPlatform = CmdletSupportedPlatform.Online)] + [CmdletExample( + Code = @"PS:> Remove-PnPClientSidePage -Identity ""MyPage""", + Remarks = "Removes the Client-Side page called 'MyPage.aspx'", + SortOrder = 1)] + [CmdletExample( + Code = @"PS:> Remove-PnPClientSidePage $page", + Remarks = "Removes the specified Client-Side page which is contained in the $page variable.", + SortOrder = 2)] + public class RemoveClientSidePage : PnPWebCmdlet + { + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name of the page")] + public ClientSidePagePipeBind Identity; + + [Parameter(Mandatory = false, HelpMessage = "Specifying the Force parameter will skip the confirmation question.")] + public SwitchParameter Force; + + protected override void ExecuteCmdlet() + { + if (Force || ShouldContinue(Resources.RemoveClientSidePage, Resources.Confirm)) + { + var clientSidePage = Identity.GetPage(ClientContext); + if (clientSidePage == null) + throw new Exception($"Page '{Identity?.Name}' does not exist"); + + clientSidePage.Delete(); + } + } + } +} +#endif \ No newline at end of file diff --git a/Commands/ClientSidePages/SetClientSidePage.cs b/Commands/ClientSidePages/SetClientSidePage.cs new file mode 100644 index 000000000..126f11771 --- /dev/null +++ b/Commands/ClientSidePages/SetClientSidePage.cs @@ -0,0 +1,92 @@ +#if !ONPREMISES +using OfficeDevPnP.Core.Pages; +using SharePointPnP.PowerShell.CmdletHelpAttributes; +using SharePointPnP.PowerShell.Commands.Base.PipeBinds; +using System; +using System.Management.Automation; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + [Cmdlet(VerbsCommon.Set, "PnPClientSidePage")] + [CmdletHelp("Sets parameters of a Client-Side Page", + Category = CmdletHelpCategory.ClientSidePages, SupportedPlatform = CmdletSupportedPlatform.Online)] + [CmdletExample( + Code = @"PS:> Set-PnPClientSidePage -Identity ""MyPage"" -LayoutType Home", + Remarks = "Updates the properties of the Client-Side page called 'MyPage'", + SortOrder = 1)] + public class SetClientSidePage : PnPWebCmdlet + { + [Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0, HelpMessage = "The name/identity of the page")] + public ClientSidePagePipeBind Identity; + + [Parameter(Mandatory = false, HelpMessage = "Sets the name of the page.")] + public string Name = null; + + [Parameter(Mandatory = false, HelpMessage = "Sets the layout type of the page. (Default = Article)")] + public ClientSidePageLayoutType LayoutType = ClientSidePageLayoutType.Article; + + [Parameter(Mandatory = false, HelpMessage = "Allows to promote the page for a specific purpose (HomePage | NewsPage)")] + public ClientSidePagePromoteType PromoteAs = ClientSidePagePromoteType.None; + + [Parameter(Mandatory = false, HelpMessage = "Enables or Disables the comments on the page")] + public bool? CommentsEnabled = null; + + [Parameter(Mandatory = false, HelpMessage = "Publishes the page once it is saved.")] + public SwitchParameter Publish; + + [Parameter(Mandatory = false, HelpMessage = "Sets the message for publishing the page.")] + public string PublishMessage = string.Empty; + + protected override void ExecuteCmdlet() + { + + ClientSidePage clientSidePage = Identity?.GetPage(ClientContext); + + if (clientSidePage == null) + // If the client side page object cannot be found + throw new Exception($"Page {Identity?.Name} cannot be found."); + + // We need to have the page name, if not found, raise an error + string name = ClientSidePageUtilities.EnsureCorrectPageName(Name ?? Identity?.Name); + if (name == null) + throw new Exception("Insufficient arguments to add a client side page"); + + clientSidePage.LayoutType = LayoutType; + clientSidePage.Save(name); + + // If a specific promote type is specified, promote the page as Home or Article or ... + switch (PromoteAs) + { + case ClientSidePagePromoteType.HomePage: + clientSidePage.PromoteAsHomePage(); + break; + case ClientSidePagePromoteType.NewsArticle: + clientSidePage.PromoteAsNewsArticle(); + break; + case ClientSidePagePromoteType.None: + default: + break; + } + + if (CommentsEnabled.HasValue) + { + if (CommentsEnabled.Value) + { + clientSidePage.EnableComments(); + } + else + { + clientSidePage.DisableComments(); + } + } + + if (Publish) + { + clientSidePage.Publish(PublishMessage); + } + + WriteObject(clientSidePage); + } + } +} +#endif \ No newline at end of file diff --git a/Commands/Enums/ClientSidePagePromoteType.cs b/Commands/Enums/ClientSidePagePromoteType.cs new file mode 100644 index 000000000..b9137b3c3 --- /dev/null +++ b/Commands/Enums/ClientSidePagePromoteType.cs @@ -0,0 +1,17 @@ +#if !ONPREMISES +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SharePointPnP.PowerShell.Commands.ClientSidePages +{ + public enum ClientSidePagePromoteType + { + None = 0, + HomePage = 1, + NewsArticle = 2, + } +} +#endif diff --git a/Commands/ModuleFiles/SharePointPnP.PowerShell.Online.Commands.Format.ps1xml b/Commands/ModuleFiles/SharePointPnP.PowerShell.Online.Commands.Format.ps1xml index bb2cb6e98..534544dd3 100644 --- a/Commands/ModuleFiles/SharePointPnP.PowerShell.Online.Commands.Format.ps1xml +++ b/Commands/ModuleFiles/SharePointPnP.PowerShell.Online.Commands.Format.ps1xml @@ -1270,5 +1270,42 @@ + + ClientSideComponent + + OfficeDevPnP.Core.Pages.ClientSideComponent + + + + + + left + + + + left + + + + left + + + + + + + Id + + + Name + + + (ConvertFrom-Json $_.Manifest).alias + + + + + + \ No newline at end of file diff --git a/Commands/Properties/Resources.Designer.cs b/Commands/Properties/Resources.Designer.cs index c4e19c603..3019863f4 100644 --- a/Commands/Properties/Resources.Designer.cs +++ b/Commands/Properties/Resources.Designer.cs @@ -341,6 +341,15 @@ internal class Resources { } } + /// + /// Looks up a localized string similar to Remove Client-Side Page?. + /// + internal static string RemoveClientSidePage { + get { + return ResourceManager.GetString("RemoveClientSidePage", resourceCulture); + } + } + /// /// Looks up a localized string similar to Remove content type?. /// diff --git a/Commands/Properties/Resources.resx b/Commands/Properties/Resources.resx index bc0c741fc..a13f33bb5 100644 --- a/Commands/Properties/Resources.resx +++ b/Commands/Properties/Resources.resx @@ -289,6 +289,9 @@ Remove Webhook Subscription '{0}' from {1} '{2}' ? + + Remove Client-Side Page? + Remove User with Id {0}, LoginName '{1}', Email '{2}' from the User Information List? diff --git a/Commands/SharePointPnP.PowerShell.Commands.csproj b/Commands/SharePointPnP.PowerShell.Commands.csproj index 0b0a2a153..cfc6f0d29 100644 --- a/Commands/SharePointPnP.PowerShell.Commands.csproj +++ b/Commands/SharePointPnP.PowerShell.Commands.csproj @@ -406,6 +406,9 @@ + + + @@ -482,6 +485,16 @@ + + + + + + + + + + diff --git a/Documentation/AddPnPClientSidePage.md b/Documentation/AddPnPClientSidePage.md new file mode 100644 index 000000000..3fa67eb62 --- /dev/null +++ b/Documentation/AddPnPClientSidePage.md @@ -0,0 +1,32 @@ +# Add-PnPClientSidePage +Adds a Client-Side Page +>*Only available for SharePoint Online* +## Syntax +```powershell +Add-PnPClientSidePage -Name + [-LayoutType ] + [-PromoteAs ] + [-CommentsEnabled ] + [-Publish []] + [-PublishMessage ] + [-Web ] +``` + + +## Parameters +Parameter|Type|Required|Description +---------|----|--------|----------- +|Name|String|True|Specifies the name of the page.| +|CommentsEnabled|Nullable`1|False|Enables or Disables the comments on the page| +|LayoutType|ClientSidePageLayoutType|False|Specifies the layout type of the page.| +|PromoteAs|ClientSidePagePromoteType|False|Allows to promote the page for a specific purpose (HomePage | NewsPage)| +|Publish|SwitchParameter|False|Publishes the page once it is saved. Applicable to libraries set to create major and minor versions.| +|PublishMessage|String|False|Sets the message for publishing the page.| +|Web|WebPipeBind|False|The web to apply the command to. Omit this parameter to use the current web.| +## Examples + +### Example 1 +```powershell +PS:> Add-PnPClientSidePage -PageName "OurNewPage" +``` +Creates a new Client-Side page called 'OurNewPage' diff --git a/Documentation/AddPnPClientSidePageSection.md b/Documentation/AddPnPClientSidePageSection.md new file mode 100644 index 000000000..882be7f8a --- /dev/null +++ b/Documentation/AddPnPClientSidePageSection.md @@ -0,0 +1,39 @@ +# Add-PnPClientSidePageSection +Adds a new section to a Client-Side page +>*Only available for SharePoint Online* +## Syntax +```powershell +Add-PnPClientSidePageSection -SectionTemplate + -Page + [-Order ] + [-Web ] +``` + + +## Parameters +Parameter|Type|Required|Description +---------|----|--------|----------- +|Page|ClientSidePagePipeBind|True|The name of the page| +|SectionTemplate|CanvasSectionTemplate|True|Specifies the columns template to use for the section.| +|Order|Int|False|Sets the order of the section. (Default = 1)| +|Web|WebPipeBind|False|The web to apply the command to. Omit this parameter to use the current web.| +## Examples + +### Example 1 +```powershell +PS:> Add-PnPClientSidePageSection -Page "MyPage" -SectionTemplate OneColumn +``` +Adds a new one-column section to the Client-Side page 'MyPage' + +### Example 2 +```powershell +PS:> Add-PnPClientSidePageSection -Page "MyPage" -SectionTemplate ThreeColumn -Order 10 +``` +Adds a new Three columns section to the Client-Side page 'MyPage' with an order index of 10 + +### Example 3 +```powershell +PS:> $page = Add-PnPClientSidePage -Name "MyPage" +PS> Add-PnPClientSidePageSection -Page $page -SectionTemplate OneColumn +``` +Adds a new one column section to the Client-Side page 'MyPage' diff --git a/Documentation/AddPnPClientSideText.md b/Documentation/AddPnPClientSideText.md new file mode 100644 index 000000000..8dcc0b687 --- /dev/null +++ b/Documentation/AddPnPClientSideText.md @@ -0,0 +1,38 @@ +# Add-PnPClientSideText +Adds a Client-Side Page +>*Only available for SharePoint Online* +## Syntax +```powershell +Add-PnPClientSideText -Text + -Page + [-Order ] + [-Web ] +``` + + +```powershell +Add-PnPClientSideText -Text + -Section + -Column + -Page + [-Order ] + [-Web ] +``` + + +## Parameters +Parameter|Type|Required|Description +---------|----|--------|----------- +|Column|Int|True|Sets the column where to insert the text control.| +|Page|ClientSidePagePipeBind|True|The name of the page.| +|Section|Int|True|Sets the section where to insert the text control.| +|Text|String|True|Specifies the text to display in the text area.| +|Order|Int|False|Sets the order of the text control. (Default = 1)| +|Web|WebPipeBind|False|The web to apply the command to. Omit this parameter to use the current web.| +## Examples + +### Example 1 +```powershell +PS:> Add-PnPClientSideText -Page "OurNewPage" -Text "Hello World!" +``` +Adds the text 'Hello World!' to the Client-Side Page 'OurNewPage' diff --git a/Documentation/AddPnPClientSideWebPart.md b/Documentation/AddPnPClientSideWebPart.md new file mode 100644 index 000000000..1c9f10c3d --- /dev/null +++ b/Documentation/AddPnPClientSideWebPart.md @@ -0,0 +1,74 @@ +# Add-PnPClientSideWebPart +Adds a Client-Side Component to a page +>*Only available for SharePoint Online* +## Syntax +```powershell +Add-PnPClientSideWebPart -DefaultWebPartType + -Page + [-WebPartProperties ] + [-Order ] + [-Web ] +``` + + +```powershell +Add-PnPClientSideWebPart -Component + -Page + [-WebPartProperties ] + [-Order ] + [-Web ] +``` + + +```powershell +Add-PnPClientSideWebPart -DefaultWebPartType + -Section + -Column + -Page + [-WebPartProperties ] + [-Order ] + [-Web ] +``` + + +```powershell +Add-PnPClientSideWebPart -Component + -Section + -Column + -Page + [-WebPartProperties ] + [-Order ] + [-Web ] +``` + + +## Parameters +Parameter|Type|Required|Description +---------|----|--------|----------- +|Column|Int|True|Sets the column where to insert the WebPart control.| +|Component|ClientSideComponentPipeBind|True|Specifies the component instance or Id to add.| +|DefaultWebPartType|DefaultClientSideWebParts|True|Defines a default WebPart type to insert.| +|Page|ClientSidePagePipeBind|True|The name of the page.| +|Section|Int|True|Sets the section where to insert the WebPart control.| +|Order|Int|False|Sets the order of the WebPart control. (Default = 1)| +|Web|WebPipeBind|False|The web to apply the command to. Omit this parameter to use the current web.| +|WebPartProperties|PropertyBagPipeBind|False|The properties of the WebPart| +## Examples + +### Example 1 +```powershell +PS:> Add-PnPClientSideWebPart -Page "OurNewPage" -DefaultWebPartType BingMap +``` +Adds a built-in Client-Side component 'BingMap' to the page called 'OurNewPage' + +### Example 2 +```powershell +PS:> Add-PnPClientSideWebPart -Page "OurNewPage" -Component "HelloWorld" +``` +Adds a Client-Side component 'HelloWorld' to the page called 'OurNewPage' + +### Example 3 +```powershell +PS:> Add-PnPClientSideWebPart -Page "OurNewPage" -Component "HelloWorld" -Section 1 -Column 2 +``` +Adds a Client-Side component 'HelloWorld' to the page called 'OurNewPage' in section 1 and column 2 diff --git a/Documentation/GetPnPAvailableClientSideComponents.md b/Documentation/GetPnPAvailableClientSideComponents.md new file mode 100644 index 000000000..ea450318b --- /dev/null +++ b/Documentation/GetPnPAvailableClientSideComponents.md @@ -0,0 +1,36 @@ +# Get-PnPAvailableClientSideComponents +Gets the available client side components on a particular page +>*Only available for SharePoint Online* +## Syntax +```powershell +Get-PnPAvailableClientSideComponents -Page + [-Component ] + [-Web ] +``` + + +## Parameters +Parameter|Type|Required|Description +---------|----|--------|----------- +|Page|ClientSidePagePipeBind|True|The name of the page.| +|Component|ClientSideComponentPipeBind|False|Specifies the component instance or Id to look for.| +|Web|WebPipeBind|False|The web to apply the command to. Omit this parameter to use the current web.| +## Examples + +### Example 1 +```powershell +PS:> Get-PnPAvailableClientSideComponents -Identity "MyPage.aspx" +``` +Gets the list of available client side components on the page 'MyPage.aspx' + +### Example 2 +```powershell +PS:> Get-PnPAvailableClientSideComponents $page +``` +Gets the list of available client side components on the page contained in the $page variable + +### Example 3 +```powershell +PS:> Get-PnPAvailableClientSideComponents -Identity "MyPage.aspx" -ComponentName "HelloWorld" +``` +Gets the client side component 'HelloWorld' if available on the page 'MyPage.aspx' diff --git a/Documentation/GetPnPClientSidePage.md b/Documentation/GetPnPClientSidePage.md new file mode 100644 index 000000000..f2479752b --- /dev/null +++ b/Documentation/GetPnPClientSidePage.md @@ -0,0 +1,28 @@ +# Get-PnPClientSidePage +Gets a Client-Side Page +>*Only available for SharePoint Online* +## Syntax +```powershell +Get-PnPClientSidePage -Identity + [-Web ] +``` + + +## Parameters +Parameter|Type|Required|Description +---------|----|--------|----------- +|Identity|ClientSidePagePipeBind|True|The name of the page| +|Web|WebPipeBind|False|The web to apply the command to. Omit this parameter to use the current web.| +## Examples + +### Example 1 +```powershell +PS:> Get-PnPClientSidePage -Identity "MyPage.aspx" +``` +Gets the Modern Page (Client-Side) called 'MyPage.aspx' in the current SharePoint site + +### Example 2 +```powershell +PS:> Get-PnPClientSidePage "MyPage" +``` +Gets the Modern Page (Client-Side) called 'MyPage.aspx' in the current SharePoint site diff --git a/Documentation/MSDN/Client-SidePages-category.md b/Documentation/MSDN/Client-SidePages-category.md new file mode 100644 index 000000000..5f56553ac --- /dev/null +++ b/Documentation/MSDN/Client-SidePages-category.md @@ -0,0 +1,11 @@ +# Client-Side Pages +Cmdlet|Description|Platform +:-----|:----------|:------- +**[Get‑PnPAvailableClientSideComponents](GetPnPAvailableClientSideComponents.md)** |Gets the available client side components on a particular page|SharePoint Online +**[Add‑PnPClientSidePage](AddPnPClientSidePage.md)** |Adds a Client-Side Page|SharePoint Online +**[Get‑PnPClientSidePage](GetPnPClientSidePage.md)** |Gets a Client-Side Page|SharePoint Online +**[Remove‑PnPClientSidePage](RemovePnPClientSidePage.md)** |Removes a Client-Side Page|SharePoint Online +**[Set‑PnPClientSidePage](SetPnPClientSidePage.md)** |Sets parameters of a Client-Side Page|SharePoint Online +**[Add‑PnPClientSidePageSection](AddPnPClientSidePageSection.md)** |Adds a new section to a Client-Side page|SharePoint Online +**[Add‑PnPClientSideText](AddPnPClientSideText.md)** |Adds a Client-Side Page|SharePoint Online +**[Add‑PnPClientSideWebPart](AddPnPClientSideWebPart.md)** |Adds a Client-Side Component to a page|SharePoint Online diff --git a/Documentation/MSDN/PnP-PowerShell-Overview.md b/Documentation/MSDN/PnP-PowerShell-Overview.md index 1031b8269..43a62bca6 100644 --- a/Documentation/MSDN/PnP-PowerShell-Overview.md +++ b/Documentation/MSDN/PnP-PowerShell-Overview.md @@ -127,6 +127,19 @@ Cmdlet|Description|Platform **[Set‑PnPTheme](SetPnPTheme.md)** |Sets the theme of the current web.|All +### Client-Side Pages +Cmdlet|Description|Platform +:-----|:----------|:------- +**[Get‑PnPAvailableClientSideComponents](GetPnPAvailableClientSideComponents.md)** |Gets the available client side components on a particular page|SharePoint Online +**[Add‑PnPClientSidePage](AddPnPClientSidePage.md)** |Adds a Client-Side Page|SharePoint Online +**[Get‑PnPClientSidePage](GetPnPClientSidePage.md)** |Gets a Client-Side Page|SharePoint Online +**[Remove‑PnPClientSidePage](RemovePnPClientSidePage.md)** |Removes a Client-Side Page|SharePoint Online +**[Set‑PnPClientSidePage](SetPnPClientSidePage.md)** |Sets parameters of a Client-Side Page|SharePoint Online +**[Add‑PnPClientSidePageSection](AddPnPClientSidePageSection.md)** |Adds a new section to a Client-Side page|SharePoint Online +**[Add‑PnPClientSideText](AddPnPClientSideText.md)** |Adds a Client-Side Page|SharePoint Online +**[Add‑PnPClientSideWebPart](AddPnPClientSideWebPart.md)** |Adds a Client-Side Component to a page|SharePoint Online + + ### Content Types Cmdlet|Description|Platform :-----|:----------|:------- diff --git a/Documentation/MSDN/TOC.md b/Documentation/MSDN/TOC.md index 177f04f04..db7fc9e42 100644 --- a/Documentation/MSDN/TOC.md +++ b/Documentation/MSDN/TOC.md @@ -35,6 +35,15 @@ ### [Enable-PnPResponsiveUI](EnablePnPResponsiveUI.md) ### [Get-PnPTheme](GetPnPTheme.md) ### [Set-PnPTheme](SetPnPTheme.md) +## [Client-Side Pages](Client-SidePages-category.md) +### [Get-PnPAvailableClientSideComponents](GetPnPAvailableClientSideComponents.md) +### [Add-PnPClientSidePage](AddPnPClientSidePage.md) +### [Get-PnPClientSidePage](GetPnPClientSidePage.md) +### [Remove-PnPClientSidePage](RemovePnPClientSidePage.md) +### [Set-PnPClientSidePage](SetPnPClientSidePage.md) +### [Add-PnPClientSidePageSection](AddPnPClientSidePageSection.md) +### [Add-PnPClientSideText](AddPnPClientSideText.md) +### [Add-PnPClientSideWebPart](AddPnPClientSideWebPart.md) ## [Content Types](ContentTypes-category.md) ### [Add-PnPContentType](AddPnPContentType.md) ### [Get-PnPContentType](GetPnPContentType.md) diff --git a/Documentation/RemovePnPClientSidePage.md b/Documentation/RemovePnPClientSidePage.md new file mode 100644 index 000000000..fb197f896 --- /dev/null +++ b/Documentation/RemovePnPClientSidePage.md @@ -0,0 +1,30 @@ +# Remove-PnPClientSidePage +Removes a Client-Side Page +>*Only available for SharePoint Online* +## Syntax +```powershell +Remove-PnPClientSidePage -Identity + [-Force []] + [-Web ] +``` + + +## Parameters +Parameter|Type|Required|Description +---------|----|--------|----------- +|Identity|ClientSidePagePipeBind|True|The name of the page| +|Force|SwitchParameter|False|Specifying the Force parameter will skip the confirmation question.| +|Web|WebPipeBind|False|The web to apply the command to. Omit this parameter to use the current web.| +## Examples + +### Example 1 +```powershell +PS:> Remove-PnPClientSidePage -Identity "MyPage" +``` +Removes the Client-Side page called 'MyPage.aspx' + +### Example 2 +```powershell +PS:> Remove-PnPClientSidePage $page +``` +Removes the specified Client-Side page which is contained in the $page variable. diff --git a/Documentation/SetPnPClientSidePage.md b/Documentation/SetPnPClientSidePage.md new file mode 100644 index 000000000..cbdcbfc98 --- /dev/null +++ b/Documentation/SetPnPClientSidePage.md @@ -0,0 +1,34 @@ +# Set-PnPClientSidePage +Sets parameters of a Client-Side Page +>*Only available for SharePoint Online* +## Syntax +```powershell +Set-PnPClientSidePage -Identity + [-Name ] + [-LayoutType ] + [-PromoteAs ] + [-CommentsEnabled ] + [-Publish []] + [-PublishMessage ] + [-Web ] +``` + + +## Parameters +Parameter|Type|Required|Description +---------|----|--------|----------- +|Identity|ClientSidePagePipeBind|True|The name/identity of the page| +|CommentsEnabled|Nullable`1|False|Enables or Disables the comments on the page| +|LayoutType|ClientSidePageLayoutType|False|Sets the layout type of the page. (Default = Article)| +|Name|String|False|Sets the name of the page.| +|PromoteAs|ClientSidePagePromoteType|False|Allows to promote the page for a specific purpose (HomePage | NewsPage)| +|Publish|SwitchParameter|False|Publishes the page once it is saved.| +|PublishMessage|String|False|Sets the message for publishing the page.| +|Web|WebPipeBind|False|The web to apply the command to. Omit this parameter to use the current web.| +## Examples + +### Example 1 +```powershell +PS:> Set-PnPClientSidePage -Identity "MyPage" -LayoutType Home +``` +Updates the properties of the Client-Side page called 'MyPage' diff --git a/Documentation/readme.md b/Documentation/readme.md index 2e6e3cf09..212e843f0 100644 --- a/Documentation/readme.md +++ b/Documentation/readme.md @@ -47,6 +47,17 @@ Cmdlet|Description|Platforms **[Enable‑PnPResponsiveUI](EnablePnPResponsiveUI.md)** |Enables the PnP Responsive UI implementation on a classic SharePoint Site|All **[Get‑PnPTheme](GetPnPTheme.md)** |Returns the current theme/composed look of the current web.|All **[Set‑PnPTheme](SetPnPTheme.md)** |Sets the theme of the current web.|All +## Client-Side Pages +Cmdlet|Description|Platforms +:-----|:----------|:-------- +**[Get‑PnPAvailableClientSideComponents](GetPnPAvailableClientSideComponents.md)** |Gets the available client side components on a particular page|SharePoint Online +**[Add‑PnPClientSidePage](AddPnPClientSidePage.md)** |Adds a Client-Side Page|SharePoint Online +**[Get‑PnPClientSidePage](GetPnPClientSidePage.md)** |Gets a Client-Side Page|SharePoint Online +**[Remove‑PnPClientSidePage](RemovePnPClientSidePage.md)** |Removes a Client-Side Page|SharePoint Online +**[Set‑PnPClientSidePage](SetPnPClientSidePage.md)** |Sets parameters of a Client-Side Page|SharePoint Online +**[Add‑PnPClientSidePageSection](AddPnPClientSidePageSection.md)** |Adds a new section to a Client-Side page|SharePoint Online +**[Add‑PnPClientSideText](AddPnPClientSideText.md)** |Adds a Client-Side Page|SharePoint Online +**[Add‑PnPClientSideWebPart](AddPnPClientSideWebPart.md)** |Adds a Client-Side Component to a page|SharePoint Online ## Content Types Cmdlet|Description|Platforms :-----|:----------|:-------- diff --git a/HelpAttributes/CmdletHelpCategory.cs b/HelpAttributes/CmdletHelpCategory.cs index 3e82aa3d3..db261496f 100644 --- a/HelpAttributes/CmdletHelpCategory.cs +++ b/HelpAttributes/CmdletHelpCategory.cs @@ -44,6 +44,8 @@ public enum CmdletHelpCategory [EnumMember(Value = "SharePoint WebHooks")] Webhooks = 25, [EnumMember(Value = "Records Management")] - RecordsManagement = 26 + RecordsManagement = 26, + [EnumMember(Value = "Client-Side Pages")] + ClientSidePages = 27 } } diff --git a/Tests/ModernPagesTests.cs b/Tests/ModernPagesTests.cs new file mode 100644 index 000000000..1ef903a1b --- /dev/null +++ b/Tests/ModernPagesTests.cs @@ -0,0 +1,250 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Management.Automation.Runspaces; +using Microsoft.SharePoint.Client; +using System.Linq; +using OfficeDevPnP.Core.Pages; +using System.Collections; + +namespace SharePointPnP.PowerShell.Tests +{ + [TestClass] + public class ModernPagesTests + { + + public const string PageTestNewDefaultName = "Page 1.aspx"; + public const string PageTestNewName = "NewPage.aspx"; + public const string PageTestWithoutExtensionName = "PageWithoutExtensionTest"; + public const string PageTestWithExtensionName = "PageWithExtensionTest.aspx"; + public const string PagePipedTestName = "PagePipedTest.aspx"; + public const string PageGetTestName = "PageGetTest.aspx"; + public const string PageRemoveTestName = "PageRemoveTest.aspx"; + public const string PageSetTestName = "PageSetTest.aspx"; + public const string PageSet2TestName = "PageSet2Test.aspx"; + public const string PageNotExistingTestName = "PageNotExisting.aspx"; + public const string PageAddSectionTestName = "PageAddSection.aspx"; + public const string PageAddWebPartTestName = "PageAddWebPart.aspx"; + + private void CleanupPageIfExists(ClientContext ctx, string pageName) + { + try + { + pageName = pageName.EndsWith(".aspx") ? pageName : pageName + ".aspx"; + var p = ClientSidePage.Load(ctx, pageName); + p.Delete(); + } + catch (Exception) { } + } + + [TestCleanup] + public void Cleanup() + { + using (var ctx = TestCommon.CreateClientContext()) + { + // Delete all the test pages if they exist + CleanupPageIfExists(ctx, PageTestNewDefaultName); + CleanupPageIfExists(ctx, PageTestNewName); + CleanupPageIfExists(ctx, PageTestWithoutExtensionName); + CleanupPageIfExists(ctx, PageTestWithExtensionName); + CleanupPageIfExists(ctx, PagePipedTestName); + CleanupPageIfExists(ctx, PageGetTestName); + CleanupPageIfExists(ctx, PageRemoveTestName); + CleanupPageIfExists(ctx, PageSetTestName); + CleanupPageIfExists(ctx, PageSet2TestName); + CleanupPageIfExists(ctx, PageAddSectionTestName); + CleanupPageIfExists(ctx, PageAddWebPartTestName); + } + } + + [TestMethod] + public void NewClientSidePageTest() + { + using (var scope = new PSTestScope(true)) + { + var results = scope.ExecuteCommand("New-PnPClientSidePage"); + var page = results[0].BaseObject as ClientSidePage; + Assert.IsNotNull(page); + } + } + + [TestMethod] + public void NewClientSidePageWithNameTest() + { + using (var scope = new PSTestScope(true)) + { + var results = scope.ExecuteCommand("New-PnPClientSidePage", + new CommandParameter("Name", PageTestNewName)); + + var page = results[0].BaseObject as ClientSidePage; + Assert.IsNotNull(page); + } + } + + [TestMethod] + public void AddClientSidePageWithNameWithoutExtensionTest() + { + using (var scope = new PSTestScope(true)) + { + var results = scope.ExecuteCommand("Add-PnPClientSidePage", + new CommandParameter("Name", PageTestWithoutExtensionName)); + + var page = results[0].BaseObject as ClientSidePage; + string pageName = page.PageListItem["FileLeafRef"] as string; + Assert.IsTrue(page != null && pageName == PageTestWithoutExtensionName + ".aspx"); + } + } + + [TestMethod] + public void AddClientSidePageWithNameWithExtensionTest() + { + using (var scope = new PSTestScope(true)) + { + var results = scope.ExecuteCommand("Add-PnPClientSidePage", + new CommandParameter("Name", PageTestWithExtensionName)); + + var page = results[0].BaseObject as ClientSidePage; + string pageName = page.PageListItem["FileLeafRef"] as string; + Assert.IsTrue(page != null && pageName == PageTestWithExtensionName); + } + } + + + [TestMethod] + public void GetClientSidePageTest() + { + using (var scope = new PSTestScope(true)) + { + using (var ctx = TestCommon.CreateClientContext()) + { + ctx.Web.AddClientSidePage(PageGetTestName, true); + } + + var results = scope.ExecuteCommand("Get-PnPClientSidePage", + new CommandParameter("Identity", PageGetTestName)); + + var page = results[0].BaseObject as ClientSidePage; + string pageName = page.PageListItem["FileLeafRef"] as string; + Assert.IsTrue(page != null && pageName == PageGetTestName); + } + } + + + [TestMethod] + public void GetClientSidePageNotExistingTest() + { + using (var scope = new PSTestScope(true)) + { + try + { + scope.ExecuteCommand("Get-PnPClientSidePage", + new CommandParameter("Identity", PageNotExistingTestName)); + Assert.Fail(); + } + catch (Exception) + { + // An exception should be thrown + Assert.IsTrue(true); + } + + } + } + + [TestMethod] + public void SetClientSidePageTest() + { + using (var scope = new PSTestScope(true)) + { + using (var ctx = TestCommon.CreateClientContext()) + { + ctx.Web.AddClientSidePage(PageSetTestName, true); + + + var results = scope.ExecuteCommand("Set-PnPClientSidePage", + new CommandParameter("Identity", PageSetTestName), + new CommandParameter("LayoutType", ClientSidePageLayoutType.Home), + new CommandParameter("Name", PageSet2TestName)); + + var page = ClientSidePage.Load(ctx, PageSet2TestName); + + Assert.IsTrue(page.LayoutType == ClientSidePageLayoutType.Home); + } + } + } + + // TODO Add more test cases + + [TestMethod] + [ExpectedException(typeof(ArgumentException), + "The page does not exist.")] + public void RemoveClientSidePageTest() + { + using (var scope = new PSTestScope(true)) + { + using (var ctx = TestCommon.CreateClientContext()) + { + ctx.Web.AddClientSidePage(PageRemoveTestName, true); + + scope.ExecuteCommand("Remove-PnPClientSidePage", + new CommandParameter("Identity", PageRemoveTestName), + new CommandParameter("Force")); + + + var p = ClientSidePage.Load(ctx, PageRemoveTestName); + } + } + } + + [TestMethod] + public void AddClientSidePageSectionTest() + { + using (var scope = new PSTestScope(true)) + { + using (var ctx = TestCommon.CreateClientContext()) + { + ctx.Web.AddClientSidePage(PageAddSectionTestName, true); + + + var results = scope.ExecuteCommand("Add-PnPClientSidePageSection", + new CommandParameter("Page", PageAddSectionTestName), + new CommandParameter("SectionTemplate", CanvasSectionTemplate.ThreeColumn), + new CommandParameter("Order", 10)); + + var page = ClientSidePage.Load(ctx, PageAddSectionTestName); + + Assert.IsTrue(page.Sections[0].Columns.Count == 3); + } + } + } + + [TestMethod] + public void AddClientSideWebPartTest() + { + using (var scope = new PSTestScope(true)) + { + using (var ctx = TestCommon.CreateClientContext()) + { + ctx.Web.AddClientSidePage(PageAddWebPartTestName, true); + + var results = scope.ExecuteCommand("Add-PnPClientSideWebPart", + new CommandParameter("Page", PageAddWebPartTestName), + new CommandParameter("DefaultWebPartType", DefaultClientSideWebParts.Image), + new CommandParameter("WebPartProperties", new Hashtable() + { + {"imageSourceType", 2}, + {"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", 500 }, + {"imgHeight", 235 } + } + )); + + var page = ClientSidePage.Load(ctx, PageAddWebPartTestName); + + Assert.AreEqual(page.Controls.Count , 1); + } + } + } + } +} diff --git a/Tests/SharePointPnP.PowerShell.Tests.csproj b/Tests/SharePointPnP.PowerShell.Tests.csproj index b42b56bb7..8b14f168f 100644 --- a/Tests/SharePointPnP.PowerShell.Tests.csproj +++ b/Tests/SharePointPnP.PowerShell.Tests.csproj @@ -272,6 +272,7 @@ +