Added content apps for document types (#8187)

* Added content apps for document types

* PR Feedback updates

* Updated the javascript code to use Utilities

* Replace tolowercase comparison with localeCompare
This commit is contained in:
patrickdemooij9
2020-06-19 19:10:16 +02:00
committed by GitHub
parent 0886ada39c
commit 591575b47d
14 changed files with 182 additions and 69 deletions
@@ -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;
@@ -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);
});
}
});
});
}
}));
@@ -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;
}
}
}
@@ -49,7 +49,7 @@ namespace Umbraco.Web.ContentApps
});
default:
throw new NotSupportedException($"Object type {o.GetType()} is not supported here.");
return null;
}
}
}
@@ -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<IReadOnlyUserGroup> 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;
}
}
}
}
@@ -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<IReadOnlyUserGroup> 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;
}
}
}
}
@@ -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<IReadOnlyUserGroup> 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;
}
}
}
}
@@ -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<IReadOnlyUserGroup> 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;
}
}
}
}
@@ -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);
@@ -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<ContentApp> ContentApps { get; set; }
}
}
@@ -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<MemberTreeController>(controller => controller.GetTreeNode(source.Key.ToString("N"), null));
}
public IEnumerable<ContentApp> GetContentApps(IContentBase source)
public IEnumerable<ContentApp> GetContentApps(IUmbracoEntity source)
{
var apps = _contentAppDefinitions.GetContentAppsFor(source).ToArray();
@@ -17,6 +17,7 @@ namespace Umbraco.Web.Models.Mapping
/// </summary>
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<ITemplate, EntityBasic>(source.AllowedTemplates);
@@ -238,7 +238,11 @@ namespace Umbraco.Web.Runtime
composition.ContentApps()
.Append<ListViewContentAppFactory>()
.Append<ContentEditorContentAppFactory>()
.Append<ContentInfoContentAppFactory>();
.Append<ContentInfoContentAppFactory>()
.Append<ContentTypeDesignContentAppFactory>()
.Append<ContentTypeListViewContentAppFactory>()
.Append<ContentTypePermissionsContentAppFactory>()
.Append<ContentTypeTemplatesContentAppFactory>();
// register back office sections in the order we want them rendered
composition.Sections()
+4
View File
@@ -135,6 +135,10 @@
<Compile Include="Composing\CompositionExtensions\Installer.cs" />
<Compile Include="Composing\LightInject\LightInjectContainer.cs" />
<Compile Include="Compose\BackOfficeUserAuditEventsComponent.cs" />
<Compile Include="ContentApps\ContentTypeTemplatesContentAppFactory.cs" />
<Compile Include="ContentApps\ContentTypePermissionsContentAppFactory.cs" />
<Compile Include="ContentApps\ContentTypeListViewContentAppFactory.cs" />
<Compile Include="ContentApps\ContentTypeDesignContentAppFactory.cs" />
<Compile Include="ContentApps\ListViewContentAppFactory.cs" />
<Compile Include="Dashboards\ContentDashboard.cs" />
<Compile Include="Dashboards\DashboardCollection.cs" />