diff --git a/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs b/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs index 788310d7a1..e0b63d1069 100644 --- a/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs +++ b/src/Umbraco.Core/Manifest/ManifestContentAppFactory.cs @@ -62,6 +62,10 @@ namespace Umbraco.Core.Manifest partA = "member"; partB = member.ContentType.Alias; break; + case IContentType contentType: + partA = "contentType"; + partB = contentType.Alias; + break; default: return null; diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index 42dba5f580..ad042842f5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -38,7 +38,7 @@ vm.page.loading = false; vm.page.saveButtonState = "init"; vm.page.navigation = []; - + var labelKeys = [ "general_design", "general_listView", @@ -92,33 +92,6 @@ vm.labels.addTemplate = values[13]; vm.labels.allowCultureVariants = values[14]; - var buttons = [ - { - "name": vm.labels.design, - "alias": "design", - "icon": "icon-document-dashed-line", - "view": "views/documenttypes/views/design/design.html" - }, - { - "name": vm.labels.listview, - "alias": "listView", - "icon": "icon-list", - "view": "views/documenttypes/views/listview/listview.html" - }, - { - "name": vm.labels.permissions, - "alias": "permissions", - "icon": "icon-keychain", - "view": "views/documenttypes/views/permissions/permissions.html" - }, - { - "name": vm.labels.templates, - "alias": "templates", - "icon": "icon-layout", - "view": "views/documenttypes/views/templates/templates.html" - } - ]; - vm.page.keyboardShortcutsOverview = [ { "name": vm.labels.sections, @@ -187,9 +160,6 @@ ] } ]; - - loadButtons(buttons); - }); contentTypeHelper.checkModelsBuilderStatus().then(function (result) { @@ -279,25 +249,25 @@ contentTypeResource.getById(documentTypeId).then(function (dt) { init(dt); // we don't need to sync the tree in infinite mode - if(!infiniteMode) { + if (!infiniteMode) { syncTreeNode(vm.contentType, dt.path, true); } vm.page.loading = false; }); } - function loadButtons(buttons) { + function loadButtons() { + vm.page.navigation = vm.contentType.apps; - angular.forEach(buttons, - function (val, index) { + if (disableTemplates === true) { + Utilities.forEach(vm.contentType.apps, + (app, index) => { + if (app.alias === "templates") { + vm.page.navigation.splice(index, 1); + } + }); + } - if (disableTemplates === true && val.alias === "templates") { - buttons.splice(index, 1); - } - - }); - - vm.page.navigation = buttons; initializeActiveNavigationPanel(); } @@ -307,16 +277,14 @@ var initialViewSetFromRouteParams = false; var view = $routeParams.view; if (view) { - var viewPath = "views/documenttypes/views/" + view + "/" + view + ".html"; for (var i = 0; i < vm.page.navigation.length; i++) { - if (vm.page.navigation[i].view === viewPath) { + if (vm.page.navigation[i].alias.localeCompare(view, undefined, { sensitivity: 'accent' }) === 0) { vm.page.navigation[i].active = true; initialViewSetFromRouteParams = true; break; } } } - if (initialViewSetFromRouteParams === false) { vm.page.navigation[0].active = true; } @@ -379,17 +347,17 @@ }).then(function (data) { //success // we don't need to sync the tree in infinite mode - if(!infiniteMode) { + if (!infiniteMode) { syncTreeNode(vm.contentType, data.path); } // emit event var args = { documentType: vm.contentType }; eventsService.emit("editors.documentType.saved", args); - + vm.page.saveButtonState = "success"; - if(infiniteMode && $scope.model.submit) { + if (infiniteMode && $scope.model.submit) { $scope.model.documentTypeAlias = vm.contentType.alias; $scope.model.submit($scope.model); } @@ -446,10 +414,12 @@ // convert icons for content type convertLegacyIcons(contentType); - //set a shared state - editorState.set(contentType); - vm.contentType = contentType; + + //set a shared state + editorState.set(vm.contentType); + + loadButtons(); } /** Syncs the template alias for new doc types before saving if a template is to be created */ @@ -525,11 +495,10 @@ if (treeExists) { navigationService.syncTree({ tree: "templates", path: [], forceReload: true }) .then(function (syncArgs) { - navigationService.reloadNode(syncArgs.node) - } - ); + navigationService.reloadNode(syncArgs.node); + }); } - }); + }); } })); diff --git a/src/Umbraco.Web/ContentApps/ContentEditorContentAppFactory.cs b/src/Umbraco.Web/ContentApps/ContentEditorContentAppFactory.cs index add7e2f16a..9f6924cd54 100644 --- a/src/Umbraco.Web/ContentApps/ContentEditorContentAppFactory.cs +++ b/src/Umbraco.Web/ContentApps/ContentEditorContentAppFactory.cs @@ -30,9 +30,6 @@ namespace Umbraco.Web.ContentApps Weight = Weight }); - case IContent _: - return null; - case IMedia media when !media.ContentType.IsContainer || media.Properties.Count > 0: return _mediaApp ?? (_mediaApp = new ContentApp { @@ -43,9 +40,6 @@ namespace Umbraco.Web.ContentApps Weight = Weight }); - case IMedia _: - return null; - case IMember _: return _memberApp ?? (_memberApp = new ContentApp { @@ -57,7 +51,7 @@ namespace Umbraco.Web.ContentApps }); default: - throw new NotSupportedException($"Object type {o.GetType()} is not supported here."); + return null; } } } diff --git a/src/Umbraco.Web/ContentApps/ContentInfoContentAppFactory.cs b/src/Umbraco.Web/ContentApps/ContentInfoContentAppFactory.cs index fac03c43d0..abad7f4bf8 100644 --- a/src/Umbraco.Web/ContentApps/ContentInfoContentAppFactory.cs +++ b/src/Umbraco.Web/ContentApps/ContentInfoContentAppFactory.cs @@ -49,7 +49,7 @@ namespace Umbraco.Web.ContentApps }); default: - throw new NotSupportedException($"Object type {o.GetType()} is not supported here."); + return null; } } } diff --git a/src/Umbraco.Web/ContentApps/ContentTypeDesignContentAppFactory.cs b/src/Umbraco.Web/ContentApps/ContentTypeDesignContentAppFactory.cs new file mode 100644 index 0000000000..1aa0770aeb --- /dev/null +++ b/src/Umbraco.Web/ContentApps/ContentTypeDesignContentAppFactory.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Models.Membership; + +namespace Umbraco.Web.ContentApps +{ + internal class ContentTypeDesignContentAppFactory : IContentAppFactory + { + private const int Weight = -200; + + private ContentApp _contentTypeApp; + + public ContentApp GetContentAppFor(object source, IEnumerable userGroups) + { + switch (source) + { + case IContentType _: + return _contentTypeApp ?? (_contentTypeApp = new ContentApp() + { + Alias = "design", + Name = "Design", + Icon = "icon-document-dashed-line", + View = "views/documenttypes/views/design/design.html", + Weight = Weight + }); + default: + return null; + } + } + } +} diff --git a/src/Umbraco.Web/ContentApps/ContentTypeListViewContentAppFactory.cs b/src/Umbraco.Web/ContentApps/ContentTypeListViewContentAppFactory.cs new file mode 100644 index 0000000000..3b618c64f7 --- /dev/null +++ b/src/Umbraco.Web/ContentApps/ContentTypeListViewContentAppFactory.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Models.Membership; + +namespace Umbraco.Web.ContentApps +{ + internal class ContentTypeListViewContentAppFactory : IContentAppFactory + { + private const int Weight = -180; + + private ContentApp _contentTypeApp; + + public ContentApp GetContentAppFor(object source, IEnumerable userGroups) + { + switch (source) + { + case IContentType _: + return _contentTypeApp ?? (_contentTypeApp = new ContentApp() + { + Alias = "listView", + Name = "List view", + Icon = "icon-list", + View = "views/documenttypes/views/listview/listview.html", + Weight = Weight + }); + default: + return null; + } + } + } +} diff --git a/src/Umbraco.Web/ContentApps/ContentTypePermissionsContentAppFactory.cs b/src/Umbraco.Web/ContentApps/ContentTypePermissionsContentAppFactory.cs new file mode 100644 index 0000000000..0b07515068 --- /dev/null +++ b/src/Umbraco.Web/ContentApps/ContentTypePermissionsContentAppFactory.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Models.Membership; + +namespace Umbraco.Web.ContentApps +{ + internal class ContentTypePermissionsContentAppFactory : IContentAppFactory + { + private const int Weight = -160; + + private ContentApp _contentTypeApp; + + public ContentApp GetContentAppFor(object source, IEnumerable userGroups) + { + switch (source) + { + case IContentType _: + return _contentTypeApp ?? (_contentTypeApp = new ContentApp() + { + Alias = "permissions", + Name = "Permissions", + Icon = "icon-keychain", + View = "views/documenttypes/views/permissions/permissions.html", + Weight = Weight + }); + default: + return null; + } + } + } +} diff --git a/src/Umbraco.Web/ContentApps/ContentTypeTemplatesContentAppFactory.cs b/src/Umbraco.Web/ContentApps/ContentTypeTemplatesContentAppFactory.cs new file mode 100644 index 0000000000..0b656518d8 --- /dev/null +++ b/src/Umbraco.Web/ContentApps/ContentTypeTemplatesContentAppFactory.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models; +using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Models.Membership; + +namespace Umbraco.Web.ContentApps +{ + internal class ContentTypeTemplatesContentAppFactory : IContentAppFactory + { + private const int Weight = -140; + + private ContentApp _contentTypeApp; + + public ContentApp GetContentAppFor(object source, IEnumerable userGroups) + { + switch (source) + { + case IContentType _: + return _contentTypeApp ?? (_contentTypeApp = new ContentApp() + { + Alias = "templates", + Name = "Templates", + Icon = "icon-layout", + View = "views/documenttypes/views/templates/templates.html", + Weight = Weight + }); + default: + return null; + } + } + } +} diff --git a/src/Umbraco.Web/ContentApps/ListViewContentAppFactory.cs b/src/Umbraco.Web/ContentApps/ListViewContentAppFactory.cs index bf6184197f..7d9ab43ac9 100644 --- a/src/Umbraco.Web/ContentApps/ListViewContentAppFactory.cs +++ b/src/Umbraco.Web/ContentApps/ListViewContentAppFactory.cs @@ -45,10 +45,8 @@ namespace Umbraco.Web.ContentApps entityType = "media"; dtdId = Core.Constants.DataTypes.DefaultMediaListView; break; - case IMember member: - return null; default: - throw new NotSupportedException($"Object type {o.GetType()} is not supported here."); + return null; } return CreateContentApp(_dataTypeService, _propertyEditors, entityType, contentTypeAlias, dtdId); diff --git a/src/Umbraco.Web/Models/ContentEditing/DocumentTypeDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/DocumentTypeDisplay.cs index 9467033aec..8aaa5c8af1 100644 --- a/src/Umbraco.Web/Models/ContentEditing/DocumentTypeDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/DocumentTypeDisplay.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Runtime.Serialization; +using Umbraco.Core.Models.ContentEditing; namespace Umbraco.Web.Models.ContentEditing { @@ -27,5 +28,8 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "allowSegmentVariant")] public bool AllowSegmentVariant { get; set; } + [DataMember(Name = "apps")] + public IEnumerable ContentApps { get; set; } + } } diff --git a/src/Umbraco.Web/Models/Mapping/CommonMapper.cs b/src/Umbraco.Web/Models/Mapping/CommonMapper.cs index 7bf4a94b1c..1276a2a405 100644 --- a/src/Umbraco.Web/Models/Mapping/CommonMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/CommonMapper.cs @@ -7,6 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.ContentApps; @@ -81,7 +82,7 @@ namespace Umbraco.Web.Models.Mapping return urlHelper.GetUmbracoApiService(controller => controller.GetTreeNode(source.Key.ToString("N"), null)); } - public IEnumerable GetContentApps(IContentBase source) + public IEnumerable GetContentApps(IUmbracoEntity source) { var apps = _contentAppDefinitions.GetContentAppsFor(source).ToArray(); diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs index c767e9aaf3..35b844ce95 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeMapDefinition.cs @@ -17,6 +17,7 @@ namespace Umbraco.Web.Models.Mapping /// internal class ContentTypeMapDefinition : IMapDefinition { + private readonly CommonMapper _commonMapper; private readonly PropertyEditorCollection _propertyEditors; private readonly IDataTypeService _dataTypeService; private readonly IFileService _fileService; @@ -25,10 +26,11 @@ namespace Umbraco.Web.Models.Mapping private readonly IMemberTypeService _memberTypeService; private readonly ILogger _logger; - public ContentTypeMapDefinition(PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IFileService fileService, + public ContentTypeMapDefinition(CommonMapper commonMapper, PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IFileService fileService, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, ILogger logger) { + _commonMapper = commonMapper; _propertyEditors = propertyEditors; _dataTypeService = dataTypeService; _fileService = fileService; @@ -122,6 +124,7 @@ namespace Umbraco.Web.Models.Mapping target.AllowCultureVariant = source.VariesByCulture(); target.AllowSegmentVariant = source.VariesBySegment(); + target.ContentApps = _commonMapper.GetContentApps(source); //sync templates target.AllowedTemplates = context.MapEnumerable(source.AllowedTemplates); diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index c631aac5e3..60521e6d90 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -238,7 +238,11 @@ namespace Umbraco.Web.Runtime composition.ContentApps() .Append() .Append() - .Append(); + .Append() + .Append() + .Append() + .Append() + .Append(); // register back office sections in the order we want them rendered composition.Sections() diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index c06ec574c5..b1cbff0fef 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -135,6 +135,10 @@ + + + +