diff --git a/src/Umbraco.Core/Services/ApplicationTreeService.cs b/src/Umbraco.Core/Services/ApplicationTreeService.cs index c9ce839450..a0a5d8cb82 100644 --- a/src/Umbraco.Core/Services/ApplicationTreeService.cs +++ b/src/Umbraco.Core/Services/ApplicationTreeService.cs @@ -8,7 +8,6 @@ using Umbraco.Core.Events; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Cache; using File = System.IO.File; namespace Umbraco.Core.Services @@ -84,7 +83,7 @@ namespace Umbraco.Core.Services // based on the ApplicationTreeRegistrar - and as noted there this is not an ideal way to do things but were stuck like this // currently because of the legacy assemblies and types not in the Core. - //Get all the trees not registered in the config + //Get all the trees not registered in the config (those not matching by alias casing will be detected as "unregistered") var unregistered = _allAvailableTrees .Where(x => list.Any(l => l.Alias == x.Alias) == false) .ToArray(); @@ -93,19 +92,46 @@ namespace Umbraco.Core.Services if (hasChanges == false) return false; - //add the unregistered ones to the list and re-save the file if any changes were found + //add or edit the unregistered ones and re-save the file if any changes were found var count = 0; foreach (var tree in unregistered) { - doc.Root.Add(new XElement("add", - new XAttribute("initialize", tree.Initialize), - new XAttribute("sortOrder", tree.SortOrder), - new XAttribute("alias", tree.Alias), - new XAttribute("application", tree.ApplicationAlias), - new XAttribute("title", tree.Title), - new XAttribute("iconClosed", tree.IconClosed), - new XAttribute("iconOpen", tree.IconOpened), - new XAttribute("type", tree.Type))); + var existingElement = doc.Root.Elements("add").SingleOrDefault(x => + string.Equals(x.Attribute("alias").Value, tree.Alias, + StringComparison.InvariantCultureIgnoreCase) && + string.Equals(x.Attribute("application").Value, tree.ApplicationAlias, + StringComparison.InvariantCultureIgnoreCase)); + if (existingElement != null) + { + existingElement.SetAttributeValue("alias", tree.Alias); + } + else + { + if (tree.Title.IsNullOrWhiteSpace()) + { + doc.Root.Add(new XElement("add", + new XAttribute("initialize", tree.Initialize), + new XAttribute("sortOrder", tree.SortOrder), + new XAttribute("alias", tree.Alias), + new XAttribute("application", tree.ApplicationAlias), + new XAttribute("iconClosed", tree.IconClosed), + new XAttribute("iconOpen", tree.IconOpened), + new XAttribute("type", tree.Type))); + } + else + { + doc.Root.Add(new XElement("add", + new XAttribute("initialize", tree.Initialize), + new XAttribute("sortOrder", tree.SortOrder), + new XAttribute("alias", tree.Alias), + new XAttribute("application", tree.ApplicationAlias), + new XAttribute("title", tree.Title), + new XAttribute("iconClosed", tree.IconClosed), + new XAttribute("iconOpen", tree.IconOpened), + new XAttribute("type", tree.Type))); + } + + } count++; } @@ -124,11 +150,7 @@ namespace Umbraco.Core.Services } } } - - return list; - - }, new TimeSpan(0, 10, 0)); } @@ -351,13 +373,15 @@ namespace Umbraco.Core.Services { list.Add(new ApplicationTree( addElement.Attribute("initialize") == null || Convert.ToBoolean(addElement.Attribute("initialize").Value), - addElement.Attribute("sortOrder") != null ? Convert.ToByte(addElement.Attribute("sortOrder").Value) : (byte)0, - addElement.Attribute("application").Value, - addElement.Attribute("alias").Value, - addElement.Attribute("title").Value, - addElement.Attribute("iconClosed").Value, - addElement.Attribute("iconOpen").Value, - addElement.Attribute("type").Value)); + addElement.Attribute("sortOrder") != null + ? Convert.ToByte(addElement.Attribute("sortOrder").Value) + : (byte)0, + (string)addElement.Attribute("application"), + (string)addElement.Attribute("alias"), + (string)addElement.Attribute("title"), + (string)addElement.Attribute("iconClosed"), + (string)addElement.Attribute("iconOpen"), + (string)addElement.Attribute("type"))); } } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js index 7bc069ef44..9687e5c40d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js @@ -108,7 +108,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo * @param {String} source The URL to load into the iframe */ loadLegacyIFrame: function (source) { - $location.path("/" + appState.getSectionState("currentSection").toLowerCase() + "/framed/" + encodeURIComponent(source)); + $location.path("/" + appState.getSectionState("currentSection") + "/framed/" + encodeURIComponent(source)); }, /** @@ -132,7 +132,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo appState.setSectionState("currentSection", sectionAlias); this.showTree(sectionAlias); - $location.path(sectionAlias.toLowerCase()); + $location.path(sectionAlias); }, /** @@ -214,7 +214,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo //this reacts to tree items themselves being clicked //the tree directive should not contain any handling, simply just bubble events - mainTreeEventHandler.bind("treeNodeSelect", function(ev, args) { + mainTreeEventHandler.bind("treeNodeSelect", function (ev, args) { var n = args.node; ev.stopPropagation(); ev.preventDefault(); @@ -250,10 +250,10 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo appState.setMenuState("currentNode", args.node); //not legacy, lets just set the route value and clear the query string if there is one. - $location.path(n.routePath.toLowerCase()).search(""); + $location.path(n.routePath).search(""); } else if (args.element.section) { - $location.path(args.element.section.toLowerCase()).search(""); + $location.path(args.element.section).search(""); } service.hideNavigation(); @@ -446,7 +446,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo if (action.metaData && action.metaData["actionRoute"] && angular.isString(action.metaData["actionRoute"])) { //first check if the menu item simply navigates to a route var parts = action.metaData["actionRoute"].split("?"); - $location.path(parts[0].toLowerCase()).search(parts.length > 1 ? parts[1] : ""); + $location.path(parts[0]).search(parts.length > 1 ? parts[1] : ""); this.hideNavigation(); return; } diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index bd122a6c7c..5d641fcb6c 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -130,7 +130,7 @@ app.config(function ($routeProvider) { // angular dashboards working. Perhaps a normal section dashboard would list out the registered // dashboards (as tabs if we wanted) and each tab could actually be a route link to one of these views? - return ('views/' + rp.tree + '/' + rp.method + '.html').toLowerCase(); + return ('views/' + rp.tree + '/' + rp.method + '.html'); }, resolve: canRoute(true) }) @@ -156,10 +156,10 @@ app.config(function ($routeProvider) { if (packageTreeFolder) { $scope.templateUrl = (Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + "/" + packageTreeFolder + - "/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html").toLowerCase(); + "/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html"); } else { - $scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html').toLowerCase(); + $scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html'); } },