Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 64 additions & 76 deletions src/Commands/Navigation/AddNavigationNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ public class AddNavigationNode : PnPWebCmdlet
[Parameter(Mandatory = false)]
public SwitchParameter First;

[Parameter(ParameterSetName = ParameterSet_Default)]
[Parameter(ParameterSetName = ParameterSet_PreviousNode)]
[Parameter(Mandatory = false)]
public SwitchParameter External;

[Parameter(ParameterSetName = ParameterSet_Default)]
[Parameter(ParameterSetName = ParameterSet_PreviousNode)]
[Parameter(Mandatory = false)]
Expand All @@ -67,24 +62,6 @@ protected override void ExecuteCmdlet()
Url = CurrentWeb.Url;
}

var navigationNodeCreationInformation = new NavigationNodeCreationInformation
{
Title = Title,
Url = Url,
IsExternal = External.IsPresent,
};

if (ParameterSpecified(nameof(PreviousNode)))
{
navigationNodeCreationInformation.PreviousNode = PreviousNode.GetNavigationNode(CurrentWeb);
}
else
{
navigationNodeCreationInformation.AsLastNode = !First.IsPresent;
}

NavigationNodeCollection nodeCollection = null;

string menuNodeKey = string.Empty;
switch (Location)
{
Expand All @@ -104,74 +81,84 @@ protected override void ExecuteCmdlet()
throw new ArgumentOutOfRangeException("Location");
}

if (ParameterSpecified(nameof(Parent)))
{
var parentNode = Parent.GetNavigationNode(CurrentWeb);
nodeCollection = parentNode.Children;
CurrentWeb.Context.Load(nodeCollection);
CurrentWeb.Context.ExecuteQueryRetry();
}
else if (Location == NavigationType.SearchNav)
{
nodeCollection = CurrentWeb.LoadSearchNavigation();
}
else if (Location == NavigationType.Footer)
{
nodeCollection = CurrentWeb.LoadFooterNavigation();
}
else if (Location == NavigationType.QuickLaunch)
{
nodeCollection = CurrentWeb.Navigation.QuickLaunch;
ClientContext.Load(nodeCollection);
}
else
{
nodeCollection = CurrentWeb.Navigation.TopNavigationBar;
ClientContext.Load(nodeCollection);
}

// Get the current menu state
CurrentWeb.EnsureProperties(w => w.Url);
var menuState = Utilities.REST.RestHelper.Get<Model.SharePoint.NavigationNodeCollection>(
Connection.HttpClient,
$"{CurrentWeb.Url}/_api/navigation/MenuState?menuNodeKey='{menuNodeKey}'",
ClientContext.GetAccessToken(),
false);

if (nodeCollection == null)
if (menuState == null)
{
throw new Exception("Unable to define Navigation Node collection to add the node to");
throw new Exception("Unable to retrieve current menu state.");
}

var addedNode = nodeCollection.Add(navigationNodeCreationInformation);
// Build the new node
var newNode = new Model.SharePoint.NavigationNode
{
NodeType = 0,
Title = Title,
SimpleUrl = Url,
FriendlyUrlSegment = "",
IsTitleForExistingLanguage = true,
AudienceIds = AudienceIds ?? new List<Guid>(),
CustomProperties = new List<object>(),
Translations = new List<object>(),
OpenInNewWindow = OpenInNewTab.IsPresent ? true : null,
Nodes = new List<Model.SharePoint.NavigationNode>()
};

if (ParameterSpecified(nameof(AudienceIds)))
// Find where to insert the node
List<Model.SharePoint.NavigationNode> targetNodes = menuState.Nodes;
if (ParameterSpecified(nameof(Parent)))
{
addedNode.AudienceIds = AudienceIds;
addedNode.Update();
var parentNode = menuState.Nodes.Select(node => SearchNodeById(node, Parent.GetNavigationNode(CurrentWeb)?.Id ?? 0))
.FirstOrDefault(result => result != null);
if (parentNode == null)
{
throw new Exception("Parent node not found in menu state.");
}
if (parentNode.Nodes == null)
parentNode.Nodes = new List<Model.SharePoint.NavigationNode>();
targetNodes = parentNode.Nodes;
}

ClientContext.Load(addedNode);
ClientContext.ExecuteQueryRetry();

// 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.Get<Model.SharePoint.NavigationNodeCollection>(Connection.HttpClient, $"{CurrentWeb.Url}/_api/navigation/MenuState?menuNodeKey='{menuNodeKey}'", ClientContext.GetAccessToken(), false);

var currentItem = menuState?.Nodes?.Select(node => SearchNodeById(node, addedNode.Id))
.FirstOrDefault(result => result != null);
if (currentItem != null)
int insertIndex = -1;
if (ParameterSpecified(nameof(PreviousNode)))
{
currentItem.OpenInNewWindow = OpenInNewTab.ToBool();
currentItem.SimpleUrl = Url;
if (ParameterSpecified(nameof(AudienceIds)))
var prevNode = targetNodes.Select(node => SearchNodeById(node, PreviousNode.GetNavigationNode(CurrentWeb)?.Id ?? 0))
.FirstOrDefault(result => result != null);
if (prevNode != null)
{
currentItem.AudienceIds = AudienceIds;
insertIndex = targetNodes.IndexOf(prevNode) + 1;
}

var payload = JsonSerializer.Serialize(menuState);
Utilities.REST.RestHelper.Post(Connection.HttpClient, $"{CurrentWeb.Url}/_api/navigation/SaveMenuState", ClientContext, @"{ ""menuState"": " + payload + "}", "application/json", "application/json;odata=nometadata");
}
else
else if (First.IsPresent)
{
LogWarning("Something went wrong while trying to set AudienceIDs or Open in new tab property");
insertIndex = 0;
}


WriteObject(addedNode);
if (insertIndex >= 0 && insertIndex <= targetNodes.Count)
targetNodes.Insert(insertIndex, newNode);
else
targetNodes.Add(newNode);

// Prepare the payload
var payload = JsonSerializer.Serialize(new { menuState });

// Save the new menu state
Utilities.REST.RestHelper.Post(
Connection.HttpClient,
$"{CurrentWeb.Url}/_api/navigation/SaveMenuState",
ClientContext,
payload,
"application/json",
"application/json;odata=nometadata"
);

// Output the new node (for consistency with previous behavior)
WriteObject(newNode);
}

private static Model.SharePoint.NavigationNode SearchNodeById(Model.SharePoint.NavigationNode root, int id)
Expand All @@ -183,6 +170,7 @@ private static Model.SharePoint.NavigationNode SearchNodeById(Model.SharePoint.N

return root.Nodes.Select(child => SearchNodeById(child, id)).FirstOrDefault(result => result != null);
}
// LogWarning("Something went wrong while trying to set AudienceIDs or Open in new tab property");

}
}
Loading