diff --git a/CHANGELOG.md b/CHANGELOG.md index cab8990e4..5f20c4de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Added `-SkipUrlValidation` to `Get-PnPSiteCollectionAppCatalog` which allows for skipping the URL validation when retrieving the site collection app catalog making it faster but potentially returning URLs that have been renamed [#2305](https://github.com/pnp/powershell/pull/3025) - Added `Get-PnPLargeListOperationStatus` cmdlet to retrieve the status of a large list operation. [#3033](https://github.com/pnp/powershell/pull/3033) - Added `-BlockDownloadPolicy`, `-ExcludeBlockDownloadPolicySiteOwners` and `ExcludedBlockDownloadGroupIds` parameters to `Set-PnPTenantSite` and `Set-PnPSite` cmdlets. [#3084](https://github.com/pnp/powershell/pull/3084) +- Added `-OpenInNewTab` parameter to `Add-PnPNavigationNode` cmdlet to allow links to be opened in a new tab. [#3094](https://github.com/pnp/powershell/pull/3094) - Added `-ArchiveRedirectUrl` to `Set-PnPTenant` allowing the configuration of a custom page to be shown when navigating to an archived SharePoint Online site [#3100](https://github.com/pnp/powershell/pull/3100) - Added `-BlockSendLabelMismatchEmail` to `Set-PnPTenant` allowing the warning e-mail being sent when uploading a file with a higher sensitivity label than the site it is being uploaded to to be disabled. [#3113](https://github.com/pnp/powershell/pull/3113) - Added `Move-PnPTerm` and `Move-PnPTermSet` cmdlets to allow moving the terms and termsets. [#2989](https://github.com/pnp/powershell/pull/2989) diff --git a/documentation/Add-PnPNavigationNode.md b/documentation/Add-PnPNavigationNode.md index 890499a18..dc33c340f 100644 --- a/documentation/Add-PnPNavigationNode.md +++ b/documentation/Add-PnPNavigationNode.md @@ -17,13 +17,13 @@ Adds an item to a navigation element ### Default ```powershell -Add-PnPNavigationNode -Location -Title [-Url ] [-Parent ] [-First] [-External] [-AudienceIds ] [-Connection ] +Add-PnPNavigationNode -Location -Title [-Url ] [-Parent ] [-First] [-External] [-AudienceIds [-OpenInNewTab ] [-Connection ] ``` ### Provide PreviousNode ```powershell -Add-PnPNavigationNode -Location -Title -PreviousNode [-Url ] [-Parent ] [-External] [-AudienceIds ] [-Connection ] +Add-PnPNavigationNode -Location -Title -PreviousNode [-Url ] [-Parent ] [-External] [-AudienceIds ] [-OpenInNewTab ] [-Connection ] ``` ## DESCRIPTION @@ -86,6 +86,13 @@ Add-PnPNavigationNode -Title "Marketing" -Url "https://contoso.sharepoint.com/si ``` Adds the Marketing navigation node to the top navigation bar on the root site. NOTE that the `-External` switch is mandatory as the connection is made to the root site. This is currently a CSOM issue but once fixed, it will be fixed in PnP PowerShell automatically. +### EXAMPLE 9 +```powershell +Add-PnPNavigationNode -Title "Contoso" -Url "http://contoso.sharepoint.com/sites/contoso/" -Location "QuickLaunch" -OpenInNewTab +``` + +Adds a navigation node to the quicklaunch. The navigation node will have the title "Contoso" and will link to the url "http://contoso.sharepoint.com/sites/contoso/". It will also open the link in a new tab. + ## PARAMETERS ### -Connection @@ -215,6 +222,20 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -OpenInNewTab +Indicates that the link will be opened in a new browser tab. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ## RELATED LINKS [Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp) diff --git a/src/Commands/Model/SharePoint/NavigationNode.cs b/src/Commands/Model/SharePoint/NavigationNode.cs new file mode 100644 index 000000000..622bdc29a --- /dev/null +++ b/src/Commands/Model/SharePoint/NavigationNode.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PnP.PowerShell.Commands.Model.SharePoint +{ + public sealed class NavigationNode + { + public List AudienceIds { get; set; } + public int CurrentLCID { get; set; } + public List CustomProperties { get; set; } + public string FriendlyUrlSegment { get; set; } + public bool IsDeleted { get; set; } + public bool IsHidden { get; set; } + public bool IsTitleForExistingLanguage { get; set; } + public string Key { get; set; } + public List Nodes { get; set; } + public int NodeType { get; set; } + public bool? OpenInNewWindow { get; set; } + public string SimpleUrl { get; set; } + public string Title { get; set; } + public List Translations { get; set; } + } +} diff --git a/src/Commands/Model/SharePoint/NavigationNodeCollection.cs b/src/Commands/Model/SharePoint/NavigationNodeCollection.cs new file mode 100644 index 000000000..c0eedbdd8 --- /dev/null +++ b/src/Commands/Model/SharePoint/NavigationNodeCollection.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; + +namespace PnP.PowerShell.Commands.Model.SharePoint +{ + public sealed class NavigationNodeCollection + { + public List AudienceIds { get; set; } + public string FriendlyUrlPrefix { get; set; } + public bool IsAudienceTargetEnabledForGlobalNav { get; set; } + public List Nodes { get; set; } + public string SimpleUrl { get; set; } + public string SPSitePrefix { get; set; } + public string SPWebPrefix { get; set; } + public string StartingNodeKey { get; set; } + public string StartingNodeTitle { get; set; } + public DateTime Version { get; set; } + } +} diff --git a/src/Commands/Navigation/AddNavigationNode.cs b/src/Commands/Navigation/AddNavigationNode.cs index 8a83bf687..fcaf58438 100644 --- a/src/Commands/Navigation/AddNavigationNode.cs +++ b/src/Commands/Navigation/AddNavigationNode.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Management.Automation; +using System.Text.Json; using Microsoft.SharePoint.Client; using PnP.Framework.Enums; using PnP.PowerShell.Commands.Base.PipeBinds; @@ -48,6 +50,11 @@ public class AddNavigationNode : PnPWebCmdlet [Parameter(Mandatory = false)] public List AudienceIds; + [Parameter(ParameterSetName = ParameterSet_Default)] + [Parameter(ParameterSetName = ParameterSet_PreviousNode)] + [Parameter(Mandatory = false)] + public SwitchParameter OpenInNewTab; + [Parameter(Mandatory = true, ParameterSetName = ParameterSet_PreviousNode)] public NavigationNodePipeBind PreviousNode; @@ -115,8 +122,25 @@ protected override void ExecuteCmdlet() { // Retrieve the menu definition and save it back again. This step is needed to enforce some properties of the menu to be shown, such as the audience targeting. CurrentWeb.EnsureProperties(w => w.Url); - var menuState = Utilities.REST.RestHelper.GetAsync(Connection.HttpClient, $"{CurrentWeb.Url}/_api/navigation/MenuState", ClientContext, "application/json;odata=nometadata").GetAwaiter().GetResult(); - Utilities.REST.RestHelper.PostAsync(Connection.HttpClient, $"{CurrentWeb.Url}/_api/navigation/SaveMenuState", ClientContext, @"{ ""menuState"": " + menuState + "}", "application/json", "application/json;odata=nometadata").GetAwaiter().GetResult(); + var menuState = Utilities.REST.RestHelper.GetAsync(Connection.HttpClient, $"{CurrentWeb.Url}/_api/navigation/MenuState", ClientContext.GetAccessToken(), false).GetAwaiter().GetResult(); + + var currentItem = menuState?.Nodes?.Where(t => t.Key == addedNode.Id.ToString()).FirstOrDefault(); + if (currentItem != null) + { + currentItem.OpenInNewWindow = OpenInNewTab.ToBool(); + + if (ParameterSpecified(nameof(AudienceIds))) + { + currentItem.AudienceIds = AudienceIds; + } + + var payload = JsonSerializer.Serialize(menuState); + Utilities.REST.RestHelper.PostAsync(Connection.HttpClient, $"{CurrentWeb.Url}/_api/navigation/SaveMenuState", ClientContext, @"{ ""menuState"": " + payload + "}", "application/json", "application/json;odata=nometadata").GetAwaiter().GetResult(); + } + else + { + WriteWarning("Something went wrong while trying to set AudienceIDs or Open in new tab property"); + } } WriteObject(addedNode);