U4-10227 Users section should start in the user tree
This commit is contained in:
@@ -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){
|
||||
|
||||
@@ -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: "<div ng-include='templateUrl'></div>",
|
||||
//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)
|
||||
|
||||
@@ -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<Tab<DashboardControl>> GetDashboard(string section)
|
||||
{
|
||||
var tabs = new List<Tab<DashboardControl>>();
|
||||
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<DashboardControl>();
|
||||
|
||||
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<DashboardControl>
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
src/Umbraco.Web/Editors/DashboardHelper.cs
Normal file
96
src/Umbraco.Web/Editors/DashboardHelper.cs
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dashboard models per section for the current user and it's access
|
||||
/// </summary>
|
||||
/// <param name="currentUser"></param>
|
||||
/// <returns></returns>
|
||||
public IDictionary<string, IEnumerable<Tab<DashboardControl>>> GetDashboards(IUser currentUser)
|
||||
{
|
||||
var result = new Dictionary<string, IEnumerable<Tab<DashboardControl>>>();
|
||||
foreach (var section in _sectionService.GetSections())
|
||||
{
|
||||
result[section.Alias] = GetDashboard(section.Alias, currentUser);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the dashboard model for the given section based on the current user and it's access
|
||||
/// </summary>
|
||||
/// <param name="section"></param>
|
||||
/// <param name="currentUser"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Tab<DashboardControl>> GetDashboard(string section, IUser currentUser)
|
||||
{
|
||||
var tabs = new List<Tab<DashboardControl>>();
|
||||
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<DashboardControl>();
|
||||
|
||||
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<DashboardControl>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Section> GetSections()
|
||||
{
|
||||
var sections = Services.SectionService.GetAllowedSections(UmbracoUser.Id);
|
||||
return sections.Select(Mapper.Map<Core.Models.Section, Section>);
|
||||
{
|
||||
|
||||
var sections = Services.SectionService.GetAllowedSections(Security.GetUserId());
|
||||
|
||||
var sectionModels = sections.Select(Mapper.Map<Core.Models.Section, Section>).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<Tab<DashboardControl>> 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<Section> GetAllSections()
|
||||
|
||||
@@ -23,6 +23,13 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
|
||||
[DataMember(Name = "alias")]
|
||||
public string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
[DataMember(Name = "routePath")]
|
||||
public string RoutePath { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -320,6 +320,7 @@
|
||||
<Compile Include="Cache\UserCacheRefresher.cs" />
|
||||
<Compile Include="Editors\BackOfficeNotificationsController.cs" />
|
||||
<Compile Include="Editors\BackOfficeServerVariables.cs" />
|
||||
<Compile Include="Editors\DashboardHelper.cs" />
|
||||
<Compile Include="Editors\EditorValidationResolver.cs" />
|
||||
<Compile Include="Editors\EditorValidator.cs" />
|
||||
<Compile Include="Editors\FromJsonPathAttribute.cs" />
|
||||
|
||||
Reference in New Issue
Block a user