diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js
index 5ce3eac8a0..6183151c2a 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js
@@ -154,8 +154,16 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se
}
navigationService.hideSearch();
- navigationService.showTree(section.alias);
- $location.path("/" + section.alias);
+ navigationService.showTree(section.alias);
+
+ //in some cases the section will have a custom route path specified, if there is one we'll use it
+ if (section.routePath) {
+ $location.path(section.routePath);
+ }
+ else {
+ $location.path(section.alias);
+ }
+
};
scope.sectionDblClick = function(section){
diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js
index 69e6779a15..7eafd7106d 100644
--- a/src/Umbraco.Web.UI.Client/src/routes.js
+++ b/src/Umbraco.Web.UI.Client/src/routes.js
@@ -98,14 +98,25 @@ app.config(function ($routeProvider) {
resolve: doLogout()
})
.when('/:section', {
- templateUrl: function (rp) {
- if (rp.section.toLowerCase() === "default" || rp.section.toLowerCase() === "umbraco" || rp.section === "")
- {
- rp.section = "content";
+ //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
+ template: "
",
+ //This controller will execute for this route, then we can execute some code in order to set the template Url
+ controller: function ($scope, $route, $routeParams, $location) {
+ if ($routeParams.section.toLowerCase() === "default" || $routeParams.section.toLowerCase() === "umbraco" || $routeParams.section === "") {
+ $routeParams.section = "content";
}
+
+ //TODO: Here we could run some extra logic to check if the dashboard we are navigating
+ //to has any content to show and if not it could redirect to the first tree root path.
+ //BUT! this would mean that we'd need a server side call to check this data....
+ //Instead we already have this data in the sections returned from the sectionResource but we
+ //don't want to cache data in a resource so we'd have to create a sectionService which would rely
+ //on the userService, then we update the umbsections.directive to use the sectionService and when the
+ //sectionService requests the sections, it caches the result against the current user. Then we can
+ //use the sectionService here to do the redirection.
- rp.url = "dashboard.aspx?app=" + rp.section;
- return 'views/common/dashboard.html';
+ $routeParams.url = "dashboard.aspx?app=" + $routeParams.section;
+ $scope.templateUrl = 'views/common/dashboard.html';
},
resolve: canRoute(true)
})
@@ -121,15 +132,11 @@ app.config(function ($routeProvider) {
})
.when('/:section/:tree/:method', {
templateUrl: function (rp) {
+
+ //if there is no method registered for this then show the dashboard
if (!rp.method)
return "views/common/dashboard.html";
-
- //NOTE: This current isn't utilized by anything but does open up some cool opportunities for
- // us since we'll be able to have specialized views for individual sections which is something
- // we've never had before. So could utilize this for a new dashboard model when we get native
- // 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');
},
resolve: canRoute(true)
diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs
index e4c94965b7..55286d99b4 100644
--- a/src/Umbraco.Web/Editors/DashboardController.cs
+++ b/src/Umbraco.Web/Editors/DashboardController.cs
@@ -19,7 +19,6 @@ using Umbraco.Core.Logging;
namespace Umbraco.Web.Editors
{
-
//we need to fire up the controller like this to enable loading of remote css directly from this controller
[PluginController("UmbracoApi")]
[ValidationFilter]
@@ -124,54 +123,8 @@ namespace Umbraco.Web.Editors
[ValidateAngularAntiForgeryToken]
public IEnumerable> GetDashboard(string section)
{
- var tabs = new List>();
- var i = 1;
-
- // The dashboard config can contain more than one area inserted by a package.
- foreach( var dashboardSection in UmbracoConfig.For.DashboardSettings().Sections.Where(x => x.Areas.Contains(section)))
- {
- //we need to validate access to this section
- if (DashboardSecurity.AuthorizeAccess(dashboardSection, Security.CurrentUser, Services.SectionService) == false)
- continue;
-
- //User is authorized
- foreach (var tab in dashboardSection.Tabs)
- {
- //we need to validate access to this tab
- if (DashboardSecurity.AuthorizeAccess(tab, Security.CurrentUser, Services.SectionService) == false)
- continue;
-
- var dashboardControls = new List();
-
- foreach (var control in tab.Controls)
- {
- if (DashboardSecurity.AuthorizeAccess(control, Security.CurrentUser, Services.SectionService) == false)
- continue;
-
- var dashboardControl = new DashboardControl();
- var controlPath = control.ControlPath.Trim();
- dashboardControl.Path = IOHelper.FindFile(controlPath);
- if (controlPath.ToLowerInvariant().EndsWith(".ascx".ToLowerInvariant()))
- dashboardControl.ServerSide = true;
-
- dashboardControls.Add(dashboardControl);
- }
-
- tabs.Add(new Tab
- {
- Id = i,
- Alias = tab.Caption.ToSafeAlias(),
- IsActive = i == 1,
- Label = tab.Caption,
- Properties = dashboardControls
- });
-
- i++;
- }
- }
-
- //In case there are no tabs or a user doesn't have access the empty tabs list is returned
- return tabs;
+ var dashboardHelper = new DashboardHelper(Services.SectionService);
+ return dashboardHelper.GetDashboard(section, Security.CurrentUser);
}
}
}
diff --git a/src/Umbraco.Web/Editors/DashboardHelper.cs b/src/Umbraco.Web/Editors/DashboardHelper.cs
new file mode 100644
index 0000000000..8b43335ebe
--- /dev/null
+++ b/src/Umbraco.Web/Editors/DashboardHelper.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.IO;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Core.Services;
+using Umbraco.Web.Models.ContentEditing;
+
+namespace Umbraco.Web.Editors
+{
+ internal class DashboardHelper
+ {
+ private readonly ISectionService _sectionService;
+
+ public DashboardHelper(ISectionService sectionService)
+ {
+ if (sectionService == null) throw new ArgumentNullException("sectionService");
+ _sectionService = sectionService;
+ }
+
+ ///
+ /// Returns the dashboard models per section for the current user and it's access
+ ///
+ ///
+ ///
+ public IDictionary>> GetDashboards(IUser currentUser)
+ {
+ var result = new Dictionary>>();
+ foreach (var section in _sectionService.GetSections())
+ {
+ result[section.Alias] = GetDashboard(section.Alias, currentUser);
+ }
+ return result;
+ }
+
+ ///
+ /// Returns the dashboard model for the given section based on the current user and it's access
+ ///
+ ///
+ ///
+ ///
+ public IEnumerable> GetDashboard(string section, IUser currentUser)
+ {
+ var tabs = new List>();
+ var i = 1;
+
+ // The dashboard config can contain more than one area inserted by a package.
+ foreach (var dashboardSection in UmbracoConfig.For.DashboardSettings().Sections.Where(x => x.Areas.Contains(section)))
+ {
+ //we need to validate access to this section
+ if (DashboardSecurity.AuthorizeAccess(dashboardSection, currentUser, _sectionService) == false)
+ continue;
+
+ //User is authorized
+ foreach (var tab in dashboardSection.Tabs)
+ {
+ //we need to validate access to this tab
+ if (DashboardSecurity.AuthorizeAccess(tab, currentUser, _sectionService) == false)
+ continue;
+
+ var dashboardControls = new List();
+
+ foreach (var control in tab.Controls)
+ {
+ if (DashboardSecurity.AuthorizeAccess(control, currentUser, _sectionService) == false)
+ continue;
+
+ var dashboardControl = new DashboardControl();
+ var controlPath = control.ControlPath.Trim();
+ dashboardControl.Path = IOHelper.FindFile(controlPath);
+ if (controlPath.ToLowerInvariant().EndsWith(".ascx".ToLowerInvariant()))
+ dashboardControl.ServerSide = true;
+
+ dashboardControls.Add(dashboardControl);
+ }
+
+ tabs.Add(new Tab
+ {
+ Id = i,
+ Alias = tab.Caption.ToSafeAlias(),
+ IsActive = i == 1,
+ Label = tab.Caption,
+ Properties = dashboardControls
+ });
+
+ i++;
+ }
+ }
+
+ //In case there are no tabs or a user doesn't have access the empty tabs list is returned
+ return tabs;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Editors/SectionController.cs b/src/Umbraco.Web/Editors/SectionController.cs
index cdb5b29b7b..6563e18b17 100644
--- a/src/Umbraco.Web/Editors/SectionController.cs
+++ b/src/Umbraco.Web/Editors/SectionController.cs
@@ -5,6 +5,8 @@ using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
using System.Linq;
+using System.Net.Http.Formatting;
+using Umbraco.Web.Trees;
namespace Umbraco.Web.Editors
{
@@ -15,9 +17,45 @@ namespace Umbraco.Web.Editors
public class SectionController : UmbracoAuthorizedJsonController
{
public IEnumerable GetSections()
- {
- var sections = Services.SectionService.GetAllowedSections(UmbracoUser.Id);
- return sections.Select(Mapper.Map);
+ {
+
+ var sections = Services.SectionService.GetAllowedSections(Security.GetUserId());
+
+ var sectionModels = sections.Select(Mapper.Map).ToArray();
+
+ //Check if there are empty dashboards or dashboards that will end up empty based on the current user's access
+ //and add the meta data about them
+ var dashboardHelper = new DashboardHelper(Services.SectionService);
+ //this is a bit nasty since we'll be proxying via the app tree controller but we sort of have to do that
+ //since tree's by nature are controllers and require request contextual data.
+ var appTreeController = new ApplicationTreeController
+ {
+ ControllerContext = ControllerContext
+ };
+ var dashboards = dashboardHelper.GetDashboards(Security.CurrentUser);
+ //now we can add metadata for each section so that the UI knows if there's actually anything at all to render for
+ //a dashboard for a given section, then the UI can deal with it accordingly (i.e. redirect to the first tree)
+ foreach (var section in sectionModels)
+ {
+ var hasDashboards = false;
+ IEnumerable> dashboardsForSection;
+ if (dashboards.TryGetValue(section.Alias, out dashboardsForSection))
+ {
+ if (dashboardsForSection.Any())
+ hasDashboards = true;
+ }
+
+ if (hasDashboards == false)
+ {
+ //get the first tree in the section and get it's root node route path
+ var sectionTrees = appTreeController.GetApplicationTrees(section.Alias, null, null).Result;
+ section.RoutePath = sectionTrees.IsContainer == false
+ ? sectionTrees.RoutePath
+ : sectionTrees.Children[0].RoutePath;
+ }
+ }
+
+ return sectionModels;
}
public IEnumerable GetAllSections()
diff --git a/src/Umbraco.Web/Models/ContentEditing/Section.cs b/src/Umbraco.Web/Models/ContentEditing/Section.cs
index b0c1839297..06ece10ddf 100644
--- a/src/Umbraco.Web/Models/ContentEditing/Section.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/Section.cs
@@ -23,6 +23,13 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "alias")]
public string Alias { get; set; }
+
+ ///
+ /// In some cases a custom route path can be specified so that when clicking on a section it goes to this
+ /// path instead of the normal dashboard path
+ ///
+ [DataMember(Name = "routePath")]
+ public string RoutePath { get; set; }
}
}
diff --git a/src/Umbraco.Web/Trees/ApplicationTreeController.cs b/src/Umbraco.Web/Trees/ApplicationTreeController.cs
index c66cb1d22c..dcec993dfe 100644
--- a/src/Umbraco.Web/Trees/ApplicationTreeController.cs
+++ b/src/Umbraco.Web/Trees/ApplicationTreeController.cs
@@ -40,7 +40,7 @@ namespace Umbraco.Web.Trees
var rootId = Constants.System.Root.ToString(CultureInfo.InvariantCulture);
//find all tree definitions that have the current application alias
- var appTrees = ApplicationContext.Current.Services.ApplicationTreeService.GetApplicationTrees(application, onlyInitialized).ToArray();
+ var appTrees = Services.ApplicationTreeService.GetApplicationTrees(application, onlyInitialized).ToArray();
if (string.IsNullOrEmpty(tree) == false || appTrees.Length == 1)
{
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 14ba427bbb..9046c92f48 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -320,6 +320,7 @@
+