From 9fb78a3908324290b6d7738e3816dc0d7c52854b Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Wed, 3 Apr 2024 14:06:54 -0700 Subject: [PATCH 1/6] Some improvments around building common shapes --- .../Drivers/ContentOptionsDisplayDriver.cs | 5 +- .../Drivers/ContentsDriver.cs | 81 +++++++++---------- .../Drivers/DateEditorDriver.cs | 3 +- .../AdminTemplatesShapeBindingResolver.cs | 13 +-- .../Services/TemplatesShapeBindingResolver.cs | 13 +-- .../AdminAttribute.cs | 3 +- .../ContentFieldDisplayDriver.cs | 31 ++++--- .../ContentItemDisplayCoordinator.cs | 27 ++++--- .../Descriptors/ShapeAlterationBuilder.cs | 2 + .../Implementation/DefaultHtmlDisplay.cs | 32 ++++---- .../Views/ShapeViewModel.cs | 4 +- 11 files changed, 105 insertions(+), 109 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentOptionsDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentOptionsDisplayDriver.cs index 4316c44f399..53eed647f85 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentOptionsDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentOptionsDisplayDriver.cs @@ -8,7 +8,7 @@ namespace OrchardCore.Contents.Drivers { public class ContentOptionsDisplayDriver : DisplayDriver { - // Maintain the Options prefix for compatability with binding. + // Maintain the Options prefix for compatibility with binding. protected override void BuildPrefix(ContentOptionsViewModel model, string htmlFieldPrefix) { Prefix = "Options"; @@ -36,7 +36,6 @@ public override IDisplayResult Edit(ContentOptionsViewModel model) Initialize("ContentsAdminListSummary", m => BuildContentOptionsViewModel(m, model)).Location("Summary:10"), Initialize("ContentsAdminListFilters", m => BuildContentOptionsViewModel(m, model)).Location("Actions:10.1"), Initialize("ContentsAdminList_Fields_BulkActions", m => BuildContentOptionsViewModel(m, model)).Location("Actions:10.1") - ); } @@ -45,7 +44,7 @@ public override Task UpdateAsync(ContentOptionsViewModel model, // Map the incoming values from a form post to the filter result. model.FilterResult.MapFrom(model); - return Task.FromResult(Edit(model)); + return Task.FromResult(Edit(model)); } private static void BuildContentOptionsViewModel(ContentOptionsViewModel m, ContentOptionsViewModel model) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs index 36bdb9d5d4e..6adefe997c4 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs @@ -34,15 +34,21 @@ public override async Task DisplayAsync(ContentItem contentItem, // We add custom alternates. This could be done generically to all shapes coming from ContentDisplayDriver but right now it's // only necessary on this shape. Otherwise c.f. ContentPartDisplayDriver - var context = _httpContextAccessor.HttpContext; - var results = new List(); + var contentItemViewModel = new ContentItemViewModel(contentItem); + + var results = new List() + { + Shape("ContentsTags_SummaryAdmin", contentItemViewModel).Location("SummaryAdmin", "Tags:10"), + Shape("ContentsMeta_SummaryAdmin", contentItemViewModel).Location("SummaryAdmin", "Meta:20"), + }; + var contentTypeDefinition = await _contentDefinitionManager.GetTypeDefinitionAsync(contentItem.ContentType); - var contentsMetadataShape = Shape("ContentsMetadata", - new ContentItemViewModel(contentItem)) - .Location("Detail", "Content:before"); if (contentTypeDefinition != null) { + var contentsMetadataShape = Shape("ContentsMetadata", contentItemViewModel) + .Location("Detail", "Content:before"); + contentsMetadataShape.Displaying(ctx => { var hasStereotype = contentTypeDefinition.TryGetStereotype(out var stereotype); @@ -65,60 +71,51 @@ public override async Task DisplayAsync(ContentItem contentItem, } }); - results.Add(contentsMetadataShape); - results.Add(Shape("ContentsButtonEdit_SummaryAdmin", new ContentItemViewModel(contentItem)).Location("SummaryAdmin", "Actions:10")); - results.Add(Shape("ContentsButtonActions_SummaryAdmin", new ContentItemViewModel(contentItem)).Location("SummaryAdmin", "ActionsMenu:10") - .RenderWhen(async () => - { - var hasPublishPermission = await _authorizationService.AuthorizeAsync(context.User, CommonPermissions.PublishContent, contentItem); - var hasDeletePermission = await _authorizationService.AuthorizeAsync(context.User, CommonPermissions.DeleteContent, contentItem); - var hasPreviewPermission = await _authorizationService.AuthorizeAsync(context.User, CommonPermissions.PreviewContent, contentItem); - var hasClonePermission = await _authorizationService.AuthorizeAsync(context.User, CommonPermissions.CloneContent, contentItem); + var user = _httpContextAccessor.HttpContext.User; - if (hasPublishPermission || hasDeletePermission || hasPreviewPermission || hasClonePermission) + results.AddRange( + [ + contentsMetadataShape, + Shape("ContentsButtonEdit_SummaryAdmin", contentItemViewModel) + .Location("SummaryAdmin", "Actions:10"), + Shape("ContentsButtonActions_SummaryAdmin", contentItemViewModel) + .Location("SummaryAdmin", "ActionsMenu:10") + .RenderWhen(async () => { - return true; - } - - return false; - }) - ); + var hasPublishPermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.PublishContent, contentItem); + var hasDeletePermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.DeleteContent, contentItem); + var hasPreviewPermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.PreviewContent, contentItem); + var hasClonePermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.CloneContent, contentItem); + + return hasPublishPermission || hasDeletePermission || hasPreviewPermission || hasClonePermission; + }), + ]); } - results.Add(Shape("ContentsTags_SummaryAdmin", new ContentItemViewModel(contentItem)).Location("SummaryAdmin", "Tags:10")); - results.Add(Shape("ContentsMeta_SummaryAdmin", new ContentItemViewModel(contentItem)).Location("SummaryAdmin", "Meta:20")); - - return Combine(results.ToArray()); + return Combine(results); } public override async Task EditAsync(ContentItem contentItem, IUpdateModel updater) { - var context = _httpContextAccessor.HttpContext; var contentTypeDefinition = await _contentDefinitionManager.GetTypeDefinitionAsync(contentItem.ContentType); - var results = new List(); if (contentTypeDefinition == null) { return null; } - results.Add(Dynamic("Content_PublishButton").Location("Actions:10") - .RenderWhen(() => _authorizationService.AuthorizeAsync(context.User, CommonPermissions.PublishContent, contentItem))); + var context = _httpContextAccessor.HttpContext; - results.Add(Dynamic("Content_SaveDraftButton").Location("Actions:20") - .RenderWhen(async () => - { - if (contentTypeDefinition.IsDraftable() && - await _authorizationService.AuthorizeAsync(context.User, CommonPermissions.EditContent, contentItem)) + return Combine( + Dynamic("Content_PublishButton").Location("Actions:10") + .RenderWhen(() => _authorizationService.AuthorizeAsync(context.User, CommonPermissions.PublishContent, contentItem)), + Dynamic("Content_SaveDraftButton").Location("Actions:20") + .RenderWhen(async () => { - return true; - } - - return false; - }) - ); - - return Combine(results.ToArray()); + return contentTypeDefinition.IsDraftable() + && await _authorizationService.AuthorizeAsync(context.User, CommonPermissions.EditContent, contentItem); + }) + ); } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/DateEditorDriver.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/DateEditorDriver.cs index b4c761ee04c..f1fcb4c2b68 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/DateEditorDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/DateEditorDriver.cs @@ -1,4 +1,3 @@ -using System; using System.Threading.Tasks; using OrchardCore.ContentManagement.Display.ContentDisplay; using OrchardCore.ContentManagement.Display.Models; @@ -28,7 +27,7 @@ public override IDisplayResult Edit(CommonPart part, BuildPartEditorContext cont return Initialize("CommonPart_Edit__Date", async model => { model.LocalDateTime = part.ContentItem.CreatedUtc.HasValue - ? (DateTime?)(await _localClock.ConvertToLocalAsync(part.ContentItem.CreatedUtc.Value)).DateTime + ? (await _localClock.ConvertToLocalAsync(part.ContentItem.CreatedUtc.Value)).DateTime : null; }); } diff --git a/src/OrchardCore.Modules/OrchardCore.Templates/Services/AdminTemplatesShapeBindingResolver.cs b/src/OrchardCore.Modules/OrchardCore.Templates/Services/AdminTemplatesShapeBindingResolver.cs index b04c6690c07..067fdc200b2 100644 --- a/src/OrchardCore.Modules/OrchardCore.Templates/Services/AdminTemplatesShapeBindingResolver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Templates/Services/AdminTemplatesShapeBindingResolver.cs @@ -41,12 +41,9 @@ public async Task GetShapeBindingAsync(string shapeType) var localTemplates = _previewTemplatesProvider.GetTemplates(); - if (localTemplates != null) + if (localTemplates != null && localTemplates.Templates.TryGetValue(shapeType, out var localTemplate)) { - if (localTemplates.Templates.TryGetValue(shapeType, out var localTemplate)) - { - return BuildShapeBinding(shapeType, localTemplate); - } + return BuildShapeBinding(shapeType, localTemplate); } _templatesDocument ??= await _templatesManager.GetTemplatesDocumentAsync(); @@ -55,10 +52,8 @@ public async Task GetShapeBindingAsync(string shapeType) { return BuildShapeBinding(shapeType, template); } - else - { - return null; - } + + return null; } private ShapeBinding BuildShapeBinding(string shapeType, Template template) diff --git a/src/OrchardCore.Modules/OrchardCore.Templates/Services/TemplatesShapeBindingResolver.cs b/src/OrchardCore.Modules/OrchardCore.Templates/Services/TemplatesShapeBindingResolver.cs index d4788f2009f..58be7015a5f 100644 --- a/src/OrchardCore.Modules/OrchardCore.Templates/Services/TemplatesShapeBindingResolver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Templates/Services/TemplatesShapeBindingResolver.cs @@ -41,12 +41,9 @@ public async Task GetShapeBindingAsync(string shapeType) var localTemplates = _previewTemplatesProvider.GetTemplates(); - if (localTemplates != null) + if (localTemplates != null && localTemplates.Templates.TryGetValue(shapeType, out var localTemplate)) { - if (localTemplates.Templates.TryGetValue(shapeType, out var localTemplate)) - { - return BuildShapeBinding(shapeType, localTemplate); - } + return BuildShapeBinding(shapeType, localTemplate); } _templatesDocument ??= await _templatesManager.GetTemplatesDocumentAsync(); @@ -55,10 +52,8 @@ public async Task GetShapeBindingAsync(string shapeType) { return BuildShapeBinding(shapeType, template); } - else - { - return null; - } + + return null; } private ShapeBinding BuildShapeBinding(string shapeType, Template template) diff --git a/src/OrchardCore/OrchardCore.Admin.Abstractions/AdminAttribute.cs b/src/OrchardCore/OrchardCore.Admin.Abstractions/AdminAttribute.cs index 5dfe1b170db..4cdee6c6332 100644 --- a/src/OrchardCore/OrchardCore.Admin.Abstractions/AdminAttribute.cs +++ b/src/OrchardCore/OrchardCore.Admin.Abstractions/AdminAttribute.cs @@ -56,6 +56,7 @@ public static void Apply(HttpContext context) context.Items[typeof(AdminAttribute)] = null; } - public static bool IsApplied(HttpContext context) => context.Items.TryGetValue(typeof(AdminAttribute), out _); + public static bool IsApplied(HttpContext context) + => context.Items.ContainsKey(typeof(AdminAttribute)); } } diff --git a/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs b/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs index 396d2a8de69..9ad3ccd481b 100644 --- a/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs +++ b/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs @@ -63,7 +63,7 @@ public override ShapeResult Factory(string shapeType, Func { - var displayTypes = new[] { "", "_" + ctx.Shape.Metadata.DisplayType }; + var displayTypes = new[] { string.Empty, "_" + ctx.Shape.Metadata.DisplayType }; // [ShapeType]_[DisplayType], e.g. TextField.Summary ctx.Shape.Metadata.Alternates.Add($"{shapeType}_{ctx.Shape.Metadata.DisplayType}"); @@ -74,14 +74,17 @@ public override ShapeResult Factory(string shapeType, Func { - // ContentPart_Edit__[PartType] - // eg ContentPart-ServicePart.Edit - ctx.Shape.Metadata.Alternates.Add($"{shapeType}__{partTypeName}"); - // ContentPart_Edit__[ContentType]__[PartType] - // e.g. ContentPart-LandingPage-ServicePart.Edit - ctx.Shape.Metadata.Alternates.Add($"{shapeType}__{contentType}__{partTypeName}"); + ctx.Shape.Metadata.Alternates.AddRange([ + // ContentPart_Edit__[PartType] + // eg ContentPart-ServicePart.Edit + $"{shapeType}__{partTypeName}", + + // ContentPart_Edit__[ContentType]__[PartType] + // e.g. ContentPart-LandingPage-ServicePart.Edit + $"{shapeType}__{contentType}__{partTypeName}", + ]); var isNamedPart = typePartDefinition.PartDefinition.IsReusable() && partName != partTypeName; diff --git a/src/OrchardCore/OrchardCore.DisplayManagement/Descriptors/ShapeAlterationBuilder.cs b/src/OrchardCore/OrchardCore.DisplayManagement/Descriptors/ShapeAlterationBuilder.cs index b047751b09d..18cb69c1976 100644 --- a/src/OrchardCore/OrchardCore.DisplayManagement/Descriptors/ShapeAlterationBuilder.cs +++ b/src/OrchardCore/OrchardCore.DisplayManagement/Descriptors/ShapeAlterationBuilder.cs @@ -45,6 +45,8 @@ public ShapeAlterationBuilder Configure(Action action) public ShapeAlterationBuilder BoundAs(string bindingSource, Func> bindingDelegate) { + ArgumentException.ThrowIfNullOrEmpty(bindingSource); + // Schedule the configuration. return Configure(descriptor => { diff --git a/src/OrchardCore/OrchardCore.DisplayManagement/Implementation/DefaultHtmlDisplay.cs b/src/OrchardCore/OrchardCore.DisplayManagement/Implementation/DefaultHtmlDisplay.cs index 85f3e19c9f6..d150f757152 100644 --- a/src/OrchardCore/OrchardCore.DisplayManagement/Implementation/DefaultHtmlDisplay.cs +++ b/src/OrchardCore/OrchardCore.DisplayManagement/Implementation/DefaultHtmlDisplay.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Html; using Microsoft.Extensions.Logging; @@ -14,6 +13,8 @@ namespace OrchardCore.DisplayManagement.Implementation { public class DefaultHtmlDisplay : IHtmlDisplay { + private const string _separator = "__"; + private readonly IShapeTableManager _shapeTableManager; private readonly IEnumerable _shapeDisplayEvents; private readonly IEnumerable _shapeBindingResolvers; @@ -48,7 +49,7 @@ public async Task ExecuteAsync(DisplayContext context) } // Check if the shape is Position Wrapper - if(shape is PositionWrapper wrapper) + if (shape is PositionWrapper wrapper) { return PositionWrapper.UnWrap(wrapper); } @@ -62,7 +63,7 @@ public async Task ExecuteAsync(DisplayContext context) var shapeMetadata = shape.Metadata; // Can't really cope with a shape that has no type information. - if (shapeMetadata == null || string.IsNullOrEmpty(shapeMetadata.Type)) + if (string.IsNullOrEmpty(shapeMetadata?.Type)) { return new HtmlContentString(context.Value.ToString()); } @@ -71,7 +72,7 @@ public async Task ExecuteAsync(DisplayContext context) // for instance to change the HtmlFieldPrefix. var localContext = new DisplayContext(context) { - HtmlFieldPrefix = shapeMetadata.Prefix ?? "", + HtmlFieldPrefix = shapeMetadata.Prefix ?? string.Empty, }; var displayContext = new ShapeDisplayContext @@ -97,8 +98,8 @@ public async Task ExecuteAsync(DisplayContext context) await shapeDescriptor.DisplayingAsync.InvokeAsync((action, displayContext) => action(displayContext), displayContext, _logger); // Copy all binding sources (all templates for this shape) in order to use them as Localization scopes. - shapeMetadata.BindingSources = shapeDescriptor.BindingSources.Where(x => x != null).ToList(); - if (!shapeMetadata.BindingSources.Any()) + shapeMetadata.BindingSources = shapeDescriptor.BindingSources; + if (shapeMetadata.BindingSources.Count == 0) { shapeMetadata.BindingSources.Add(shapeDescriptor.BindingSource); } @@ -122,17 +123,12 @@ public async Task ExecuteAsync(DisplayContext context) } // Now find the actual binding to render, taking alternates into account. - var actualBinding = await GetShapeBindingAsync(shapeMetadata.Type, shapeMetadata.Alternates, shapeTable); - if (actualBinding != null) - { - await shapeMetadata.ProcessingAsync.InvokeAsync((action, displayContext) => action(displayContext.Shape), displayContext, _logger); + var actualBinding = await GetShapeBindingAsync(shapeMetadata.Type, shapeMetadata.Alternates, shapeTable) + ?? throw new Exception($"The shape type '{shapeMetadata.Type}' is not found"); - shape.Metadata.ChildContent = await ProcessAsync(actualBinding, shape, localContext); - } - else - { - throw new Exception($"Shape type '{shapeMetadata.Type}' not found"); - } + await shapeMetadata.ProcessingAsync.InvokeAsync((action, displayContext) => action(displayContext.Shape), displayContext, _logger); + + shape.Metadata.ChildContent = await ProcessAsync(actualBinding, shape, localContext); } // Process wrappers. @@ -201,7 +197,7 @@ private static ShapeDescriptor GetShapeDescriptor(string shapeType, ShapeTable s if (!shapeTable.Descriptors.TryGetValue(shapeType, out var shapeDescriptor)) { // Check if not a fundamental type. - var index = shapeType.IndexOf("__", StringComparison.Ordinal); + var index = shapeType.IndexOf(_separator, StringComparison.Ordinal); if (index > 0) { @@ -268,7 +264,7 @@ private async Task GetShapeBindingAsync(string shapeType, Alternat private static bool TryGetParentShapeTypeName(ref string shapeTypeScan) { - var delimiterIndex = shapeTypeScan.LastIndexOf("__", StringComparison.Ordinal); + var delimiterIndex = shapeTypeScan.LastIndexOf(_separator, StringComparison.Ordinal); if (delimiterIndex > 0) { shapeTypeScan = shapeTypeScan[..delimiterIndex]; diff --git a/src/OrchardCore/OrchardCore.DisplayManagement/Views/ShapeViewModel.cs b/src/OrchardCore/OrchardCore.DisplayManagement/Views/ShapeViewModel.cs index 33305412241..0036c50b116 100644 --- a/src/OrchardCore/OrchardCore.DisplayManagement/Views/ShapeViewModel.cs +++ b/src/OrchardCore/OrchardCore.DisplayManagement/Views/ShapeViewModel.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Html; using OrchardCore.DisplayManagement.Shapes; using OrchardCore.DisplayManagement.Zones; @@ -83,7 +82,10 @@ public ValueTask AddAsync(object item, string position) var wrapped = PositionWrapper.TryWrap(item, position); if (wrapped is not null) + { _items.Add(wrapped); + } + return new ValueTask(this); } } From adf821b11a1d7f6e68d28cbc0007586fdf0825b4 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Wed, 3 Apr 2024 14:10:32 -0700 Subject: [PATCH 2/6] cleanup --- .../ContentDisplay/ContentFieldDisplayDriver.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs b/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs index 9ad3ccd481b..cb33e4f72a7 100644 --- a/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs +++ b/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs @@ -76,14 +76,14 @@ public override ShapeResult Factory(string shapeType, Func Date: Wed, 3 Apr 2024 14:36:02 -0700 Subject: [PATCH 3/6] undo some changes --- .../Drivers/ContentsDriver.cs | 30 ++++++++---------- .../ContentFieldDisplayDriver.cs | 31 +++++++++---------- .../ContentItemDisplayCoordinator.cs | 27 +++++++--------- 3 files changed, 38 insertions(+), 50 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs index 6adefe997c4..e97f801158a 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs @@ -73,23 +73,19 @@ public override async Task DisplayAsync(ContentItem contentItem, var user = _httpContextAccessor.HttpContext.User; - results.AddRange( - [ - contentsMetadataShape, - Shape("ContentsButtonEdit_SummaryAdmin", contentItemViewModel) - .Location("SummaryAdmin", "Actions:10"), - Shape("ContentsButtonActions_SummaryAdmin", contentItemViewModel) - .Location("SummaryAdmin", "ActionsMenu:10") - .RenderWhen(async () => - { - var hasPublishPermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.PublishContent, contentItem); - var hasDeletePermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.DeleteContent, contentItem); - var hasPreviewPermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.PreviewContent, contentItem); - var hasClonePermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.CloneContent, contentItem); - - return hasPublishPermission || hasDeletePermission || hasPreviewPermission || hasClonePermission; - }), - ]); + results.Add(contentsMetadataShape); + results.Add(Shape("ContentsButtonEdit_SummaryAdmin", new ContentItemViewModel(contentItem)).Location("SummaryAdmin", "Actions:10")); + results.Add(Shape("ContentsButtonActions_SummaryAdmin", new ContentItemViewModel(contentItem)).Location("SummaryAdmin", "ActionsMenu:10") + .RenderWhen(async () => + { + var hasPublishPermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.PublishContent, contentItem); + var hasDeletePermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.DeleteContent, contentItem); + var hasPreviewPermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.PreviewContent, contentItem); + var hasClonePermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.CloneContent, contentItem); + + return hasPublishPermission || hasDeletePermission || hasPreviewPermission || hasClonePermission; + }) + ); } return Combine(results); diff --git a/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs b/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs index cb33e4f72a7..350c2840109 100644 --- a/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs +++ b/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs @@ -74,17 +74,17 @@ public override ShapeResult Factory(string shapeType, Func { + // ContentPart_Edit__[PartType] + // eg ContentPart-ServicePart.Edit + ctx.Shape.Metadata.Alternates.Add($"{shapeType}__{partTypeName}"); - ctx.Shape.Metadata.Alternates.AddRange([ - // ContentPart_Edit__[PartType] - // eg ContentPart-ServicePart.Edit - $"{shapeType}__{partTypeName}", - - // ContentPart_Edit__[ContentType]__[PartType] - // e.g. ContentPart-LandingPage-ServicePart.Edit - $"{shapeType}__{contentType}__{partTypeName}", - ]); + // ContentPart_Edit__[ContentType]__[PartType] + // e.g. ContentPart-LandingPage-ServicePart.Edit + ctx.Shape.Metadata.Alternates.Add($"{shapeType}__{contentType}__{partTypeName}"); var isNamedPart = typePartDefinition.PartDefinition.IsReusable() && partName != partTypeName; From 79accf59c855e407b03131b09ae4df28c0c805f2 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Wed, 3 Apr 2024 14:37:06 -0700 Subject: [PATCH 4/6] Fix error --- .../ContentDisplay/ContentFieldDisplayDriver.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs b/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs index 350c2840109..67c8e1b6df1 100644 --- a/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs +++ b/src/OrchardCore/OrchardCore.ContentManagement.Display/ContentDisplay/ContentFieldDisplayDriver.cs @@ -74,17 +74,14 @@ public override ShapeResult Factory(string shapeType, Func Date: Wed, 3 Apr 2024 14:56:35 -0700 Subject: [PATCH 5/6] fix undo error --- .../OrchardCore.Contents/Drivers/ContentsDriver.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs index e97f801158a..385d611ccbb 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Drivers/ContentsDriver.cs @@ -74,8 +74,8 @@ public override async Task DisplayAsync(ContentItem contentItem, var user = _httpContextAccessor.HttpContext.User; results.Add(contentsMetadataShape); - results.Add(Shape("ContentsButtonEdit_SummaryAdmin", new ContentItemViewModel(contentItem)).Location("SummaryAdmin", "Actions:10")); - results.Add(Shape("ContentsButtonActions_SummaryAdmin", new ContentItemViewModel(contentItem)).Location("SummaryAdmin", "ActionsMenu:10") + results.Add(Shape("ContentsButtonEdit_SummaryAdmin", contentItemViewModel).Location("SummaryAdmin", "Actions:10")); + results.Add(Shape("ContentsButtonActions_SummaryAdmin", contentItemViewModel).Location("SummaryAdmin", "ActionsMenu:10") .RenderWhen(async () => { var hasPublishPermission = await _authorizationService.AuthorizeAsync(user, CommonPermissions.PublishContent, contentItem); From e1e76e2c28c46730897be43f2f61dae9bb6d2092 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Wed, 3 Apr 2024 15:19:14 -0700 Subject: [PATCH 6/6] spelling --- .../Implementation/DefaultHtmlDisplay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OrchardCore/OrchardCore.DisplayManagement/Implementation/DefaultHtmlDisplay.cs b/src/OrchardCore/OrchardCore.DisplayManagement/Implementation/DefaultHtmlDisplay.cs index d150f757152..50ebf9b876e 100644 --- a/src/OrchardCore/OrchardCore.DisplayManagement/Implementation/DefaultHtmlDisplay.cs +++ b/src/OrchardCore/OrchardCore.DisplayManagement/Implementation/DefaultHtmlDisplay.cs @@ -236,8 +236,8 @@ private async Task GetShapeBindingAsync(string shapeType, Alternat } // When no alternates matches, the shapeType is used to find the longest matching binding, - // the shapetype name can break itself into shorter fallbacks at double-underscore marks, - // so the shapetype itself may contain a longer alternate forms that falls back to a shorter one. + // the shape-type name can break itself into shorter fallbacks at double-underscore marks, + // so the shape-type itself may contain a longer alternate forms that falls back to a shorter one. var shapeTypeScan = shapeType; do