/// <summary> /// Get the tree root node of a tree. /// </summary> private async Task <TreeRootNode> GetTreeRootNode(Tree tree, int id, FormDataCollection querystring) { if (tree == null) { throw new ArgumentNullException(nameof(tree)); } var children = await GetChildren(tree, id, querystring); var rootNode = await GetRootNode(tree, querystring); var sectionRoot = TreeRootNode.CreateSingleTreeRoot( Constants.System.RootString, rootNode.ChildNodesUrl, rootNode.MenuUrl, rootNode.Name, children, tree.IsSingleNodeTree); // assign the route path based on the root node, this means it will route there when the // section is navigated to and no dashboards will be available for this section sectionRoot.RoutePath = rootNode.RoutePath; sectionRoot.Path = rootNode.Path; foreach (var d in rootNode.AdditionalData) { sectionRoot.AdditionalData[d.Key] = d.Value; } return(sectionRoot); }
/// <summary> /// Get the tree root node of a tree. /// </summary> private async Task <ActionResult <TreeRootNode> > GetTreeRootNode(Tree tree, int id, FormCollection?querystring) { if (tree == null) { throw new ArgumentNullException(nameof(tree)); } ActionResult <TreeNodeCollection?>?childrenResult = await GetChildren(tree, id, querystring); if (!(childrenResult?.Result is null)) { return(new ActionResult <TreeRootNode>(childrenResult.Result)); } TreeNodeCollection? children = childrenResult?.Value; ActionResult <TreeNode?>?rootNodeResult = await GetRootNode(tree, querystring); if (!(rootNodeResult?.Result is null)) { return(rootNodeResult.Result); } TreeNode?rootNode = rootNodeResult?.Value; var sectionRoot = TreeRootNode.CreateSingleTreeRoot( Constants.System.RootString, rootNode !.ChildNodesUrl, rootNode.MenuUrl, rootNode.Name, children, tree.IsSingleNodeTree); // assign the route path based on the root node, this means it will route there when the // section is navigated to and no dashboards will be available for this section sectionRoot.RoutePath = rootNode.RoutePath; sectionRoot.Path = rootNode.Path; foreach (KeyValuePair <string, object?> d in rootNode.AdditionalData) { sectionRoot.AdditionalData[d.Key] = d.Value; } return(sectionRoot); }
/// <summary> /// Get the root node for an application with one tree /// </summary> /// <param name="configTree"></param> /// <param name="id"></param> /// <param name="queryStrings"></param> /// <param name="application"></param> /// <returns></returns> private async Task <TreeRootNode> GetRootForSingleAppTree(ApplicationTree configTree, string id, FormDataCollection queryStrings, string application) { var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); if (configTree == null) { throw new ArgumentNullException(nameof(configTree)); } var byControllerAttempt = configTree.TryLoadFromControllerTree(id, queryStrings, ControllerContext); if (byControllerAttempt.Success) { var rootNode = await configTree.TryGetRootNodeFromControllerTree(queryStrings, ControllerContext); if (rootNode.Success == false) { //This should really never happen if we've successfully got the children above. throw new InvalidOperationException("Could not create root node for tree " + configTree.Alias); } var treeAttribute = configTree.GetTreeAttribute(); var sectionRoot = TreeRootNode.CreateSingleTreeRoot( rootId, rootNode.Result.ChildNodesUrl, rootNode.Result.MenuUrl, rootNode.Result.Name, byControllerAttempt.Result, treeAttribute.IsSingleNodeTree); //assign the route path based on the root node, this means it will route there when the section is navigated to //and no dashboards will be available for this section sectionRoot.RoutePath = rootNode.Result.RoutePath; foreach (var d in rootNode.Result.AdditionalData) { sectionRoot.AdditionalData[d.Key] = d.Value; } return(sectionRoot); } throw new ApplicationException("Could not render a tree for type " + configTree.Alias); }
/// <summary> /// Returns the tree nodes for an application /// </summary> /// <param name="application">The application to load tree for</param> /// <param name="tree">An optional single tree alias, if specified will only load the single tree for the request app</param> /// <param name="queryStrings">The query strings</param> /// <param name="use">Tree use.</param> public async Task <ActionResult <TreeRootNode> > GetApplicationTrees(string application, string tree, [ModelBinder(typeof(HttpQueryStringModelBinder))] FormCollection queryStrings, TreeUse use = TreeUse.Main) { application = application.CleanForXss(); if (string.IsNullOrEmpty(application)) { return(NotFound()); } var section = _sectionService.GetByAlias(application); if (section == null) { return(NotFound()); } // find all tree definitions that have the current application alias var groupedTrees = _treeService.GetBySectionGrouped(application, use); var allTrees = groupedTrees.Values.SelectMany(x => x).ToList(); if (allTrees.Count == 0) { // if there are no trees defined for this section but the section is defined then we can have a simple // full screen section without trees var name = _localizedTextService.Localize("sections", application); return(TreeRootNode.CreateSingleTreeRoot(Constants.System.RootString, null, null, name, TreeNodeCollection.Empty, true)); } // handle request for a specific tree / or when there is only one tree if (!tree.IsNullOrWhiteSpace() || allTrees.Count == 1) { var t = tree.IsNullOrWhiteSpace() ? allTrees[0] : allTrees.FirstOrDefault(x => x.TreeAlias == tree); if (t == null) { return(NotFound()); } var treeRootNode = await GetTreeRootNode(t, Constants.System.Root, queryStrings); if (treeRootNode != null) { return(treeRootNode); } return(NotFound()); } // handle requests for all trees // for only 1 group if (groupedTrees.Count == 1) { var nodes = new TreeNodeCollection(); foreach (var t in allTrees) { var nodeResult = await TryGetRootNode(t, queryStrings); if (!(nodeResult.Result is null)) { return(nodeResult.Result); } var node = nodeResult.Value; if (node != null) { nodes.Add(node); } } var name = _localizedTextService.Localize("sections", application); if (nodes.Count > 0) { var treeRootNode = TreeRootNode.CreateMultiTreeRoot(nodes); treeRootNode.Name = name; return(treeRootNode); } // otherwise it's a section with all empty trees, aka a fullscreen section // todo is this true? what if we just failed to TryGetRootNode on all of them? SD: Yes it's true but we should check the result of TryGetRootNode and throw? return(TreeRootNode.CreateSingleTreeRoot(Constants.System.RootString, null, null, name, TreeNodeCollection.Empty, true)); } // for many groups var treeRootNodes = new List <TreeRootNode>(); foreach (var(groupName, trees) in groupedTrees) { var nodes = new TreeNodeCollection(); foreach (var t in trees) { var nodeResult = await TryGetRootNode(t, queryStrings); if (nodeResult != null && nodeResult.Result is not null) { return(nodeResult.Result); } var node = nodeResult?.Value; if (node != null) { nodes.Add(node); } } if (nodes.Count == 0) { continue; } // no name => third party // use localization key treeHeaders/thirdPartyGroup // todo this is an odd convention var name = groupName.IsNullOrWhiteSpace() ? "thirdPartyGroup" : groupName; var groupRootNode = TreeRootNode.CreateGroupNode(nodes, application); groupRootNode.Name = _localizedTextService.Localize("treeHeaders", name); treeRootNodes.Add(groupRootNode); } return(TreeRootNode.CreateGroupedMultiTreeRoot(new TreeNodeCollection(treeRootNodes.OrderBy(x => x.Name)))); }
public async Task <TreeRootNode> GetApplicationTrees(string application, string tree, FormDataCollection queryStrings, bool onlyInitialized = true) { application = application.CleanForXss(); if (string.IsNullOrEmpty(application)) { throw new HttpResponseException(HttpStatusCode.NotFound); } //find all tree definitions that have the current application alias var groupedTrees = Services.ApplicationTreeService.GetGroupedApplicationTrees(application, onlyInitialized); var allTrees = groupedTrees.Values.SelectMany(x => x).ToList(); if (string.IsNullOrEmpty(tree) == false || allTrees.Count == 1) { var apptree = !tree.IsNullOrWhiteSpace() ? allTrees.FirstOrDefault(x => x.Alias == tree) : allTrees.FirstOrDefault(); if (apptree == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } var result = await GetRootForSingleAppTree( apptree, Constants.System.Root.ToString(CultureInfo.InvariantCulture), queryStrings, application); //this will be null if it cannot convert to a single root section if (result != null) { return(result); } } //Don't apply fancy grouping logic futher down, if we only have one group of items var hasGroups = groupedTrees.Count > 1; if (!hasGroups) { var collection = new TreeNodeCollection(); foreach (var apptree in allTrees) { //return the root nodes for each tree in the app var rootNode = await GetRootForMultipleAppTree(apptree, queryStrings); //This could be null if the tree decides not to return it's root (i.e. the member type tree does this when not in umbraco membership mode) if (rootNode != null) { collection.Add(rootNode); } } if (collection.Count > 0) { var multiTree = TreeRootNode.CreateMultiTreeRoot(collection); multiTree.Name = Services.TextService.Localize("sections/" + application); return(multiTree); } //Otherwise its a application/section with no trees (aka a full screen app) //For example we do not have a Forms tree definied in C# & can not attribute with [Tree(isSingleNodeTree:true0] var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture); var section = Services.TextService.Localize("sections/" + application); return(TreeRootNode.CreateSingleTreeRoot(rootId, null, null, section, TreeNodeCollection.Empty, true)); } var rootNodeGroups = new List <TreeRootNode>(); //Group trees by [CoreTree] attribute with a TreeGroup property foreach (var treeSectionGroup in groupedTrees) { var treeGroupName = treeSectionGroup.Key; var groupNodeCollection = new TreeNodeCollection(); foreach (var appTree in treeSectionGroup.Value) { var rootNode = await GetRootForMultipleAppTree(appTree, queryStrings); if (rootNode != null) { //Add to a new list/collection groupNodeCollection.Add(rootNode); } } //If treeGroupName == null then its third party if (treeGroupName.IsNullOrWhiteSpace()) { //This is used for the localisation key //treeHeaders/thirdPartyGroup treeGroupName = "thirdPartyGroup"; } if (groupNodeCollection.Count > 0) { var groupRoot = TreeRootNode.CreateGroupNode(groupNodeCollection, application); groupRoot.Name = Services.TextService.Localize("treeHeaders/" + treeGroupName); rootNodeGroups.Add(groupRoot); } } return(TreeRootNode.CreateGroupedMultiTreeRoot(new TreeNodeCollection(rootNodeGroups.OrderBy(x => x.Name)))); }