From b45c84c7add0dd5a6ddf6ff84408fcd877f19aaa Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Thu, 20 Oct 2022 11:03:25 -0700 Subject: [PATCH] Add "Display Header" property to ListPartSettings (#12525) --- .../Views/Content.HeaderAdmin.cshtml | 1 + .../Drivers/ContainedPartDisplayDriver.cs | 111 +++++++++-- .../Drivers/ListPartDisplayDriver.cs | 172 +++++++++++++----- .../Indexes/ContainedPartIndex.cs | 25 ++- .../OrchardCore.Lists/Migrations.cs | 65 ++++++- .../OrchardCore.Lists/Models/ContainedPart.cs | 5 + .../Models/ListPartSettings.cs | 1 + .../Services/ContainerService.cs | 8 +- .../Settings/ListPartSettingsDisplayDriver.cs | 6 +- .../ViewModels/EditContainedPartViewModel.cs | 1 + .../ListPartHeaderAdminViewModel.cs | 14 ++ .../ListPartNavigationAdminViewModel.cs | 16 ++ .../ViewModels/ListPartSettingsViewModel.cs | 1 + .../Views/ListPart.ContainerId.cshtml | 3 +- .../Views/ListPartDetailAdmin.cshtml | 28 +-- .../Views/ListPartHeaderAdmin.cshtml | 9 + .../Views/ListPartNavigationAdmin.cshtml | 62 +++++++ .../Views/ListPartSettings.Edit.cshtml | 8 + 18 files changed, 431 insertions(+), 105 deletions(-) create mode 100644 src/OrchardCore.Modules/OrchardCore.Contents/Views/Content.HeaderAdmin.cshtml create mode 100644 src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartHeaderAdminViewModel.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartNavigationAdminViewModel.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartHeaderAdmin.cshtml create mode 100644 src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartNavigationAdmin.cshtml diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Views/Content.HeaderAdmin.cshtml b/src/OrchardCore.Modules/OrchardCore.Contents/Views/Content.HeaderAdmin.cshtml new file mode 100644 index 00000000000..1d9207cfb88 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Views/Content.HeaderAdmin.cshtml @@ -0,0 +1 @@ +

@Model.ContentItem

diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Drivers/ContainedPartDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Lists/Drivers/ContainedPartDisplayDriver.cs index 72f55f147b7..1091776ce98 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Drivers/ContainedPartDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Drivers/ContainedPartDisplayDriver.cs @@ -1,29 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Display.ContentDisplay; +using OrchardCore.ContentManagement.Metadata; +using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.DisplayManagement.Views; using OrchardCore.Lists.Models; using OrchardCore.Lists.Services; using OrchardCore.Lists.ViewModels; -using YesSql; namespace OrchardCore.Lists.Drivers { public class ContainedPartDisplayDriver : ContentDisplayDriver { private readonly IContentManager _contentManager; - private readonly ISession _session; + private readonly IContentDefinitionManager _contentDefinitionManager; private readonly IContainerService _containerService; public ContainedPartDisplayDriver( IContentManager contentManager, - ISession session, + IContentDefinitionManager contentDefinitionManager, IContainerService containerService ) { - _session = session; _contentManager = contentManager; + _contentDefinitionManager = contentDefinitionManager; _containerService = containerService; } @@ -33,13 +37,15 @@ public override async Task EditAsync(ContentItem model, IUpdateM // the query string contains a ListPart.ContainerId value, or when an // existing content item has ContainedPart value. In both cases the hidden field // needs to be rendered in the edit form to maintain the relationship with the parent. + var containedPart = model.As(); - if (model.As() != null) + if (containedPart != null) { - return BuildViewModel(model.As().ListContentItemId, model.ContentType); + return BuildViewModel(containedPart.ListContentItemId, containedPart.ListContentType, model.ContentType); } var viewModel = new EditContainedPartViewModel(); + if (await updater.TryUpdateModelAsync(viewModel, nameof(ListPart)) && viewModel.ContainerId != null && viewModel.ContentType == model.ContentType) { // We are creating a content item that needs to be added to a container @@ -48,23 +54,12 @@ public override async Task EditAsync(ContentItem model, IUpdateM // The content type must be included to prevent any contained items, // such as widgets, from also having a ContainedPart shape built for them. - return BuildViewModel(viewModel.ContainerId, model.ContentType, viewModel.EnableOrdering); + return BuildViewModel(viewModel.ContainerId, viewModel.ContainerContentType, model.ContentType, viewModel.EnableOrdering); } return null; } - private IDisplayResult BuildViewModel(string containerId, string contentType, bool enableOrdering = false) - { - return Initialize("ListPart_ContainerId", m => - { - m.ContainerId = containerId; - m.EnableOrdering = enableOrdering; - m.ContentType = contentType; - }) - .Location("Content"); - } - public override async Task UpdateAsync(ContentItem model, IUpdateModel updater) { var viewModel = new EditContainedPartViewModel(); @@ -73,7 +68,12 @@ public override async Task UpdateAsync(ContentItem model, IUpdat // in order for the ContainedPart to be included on the Content Item. if (await updater.TryUpdateModelAsync(viewModel, nameof(ListPart)) && viewModel.ContainerId != null && viewModel.ContentType == model.ContentType) { - model.Alter(x => x.ListContentItemId = viewModel.ContainerId); + model.Alter(x => + { + x.ListContentItemId = viewModel.ContainerId; + x.ListContentType = viewModel.ContainerContentType; + }); + // If creating get next order number so item is added to the end of the list if (viewModel.EnableOrdering) { @@ -84,5 +84,78 @@ public override async Task UpdateAsync(ContentItem model, IUpdat return await EditAsync(model, updater); } + + private IDisplayResult BuildViewModel(string containerId, string containerContentType, string contentType, bool enableOrdering = false) + { + var results = new List() + { + Initialize("ListPart_ContainerId", m => + { + m.ContainerId = containerId; + m.ContainerContentType = containerContentType; + m.EnableOrdering = enableOrdering; + m.ContentType = contentType; + }) + .Location("Content") + }; + + if (!String.IsNullOrEmpty(containerContentType)) + { + var definition = _contentDefinitionManager.GetTypeDefinition(containerContentType); + + if (definition != null) + { + var listPart = definition.Parts.FirstOrDefault(x => x.PartDefinition.Name == nameof(ListPart)); + var settings = listPart?.GetSettings(); + + if (settings != null) + { + // Add list part navigation + results.Add(Initialize("ListPartNavigationAdmin", async model => + { + model.ContainedContentTypeDefinitions = GetContainedContentTypes(settings).ToArray(); + model.Container = await _contentManager.GetAsync(containerId); + model.EnableOrdering = settings.EnableOrdering; + model.ContainerContentTypeDefinition = definition; + }).Location("Content:1.5")); + + if (settings.ShowHeader) + { + results.Add(GetListPartHeader(containerId, settings)); + } + } + } + } + + return Combine(results); + } + + private IDisplayResult GetListPartHeader(string containerId, ListPartSettings listPartSettings) + { + return Initialize("ListPartHeaderAdmin", async model => + { + var container = await _contentManager.GetAsync(containerId); + + if (container == null) + { + return; + } + + model.ContainerContentItem = container; + + if (listPartSettings != null) + { + model.ContainedContentTypeDefinitions = GetContainedContentTypes(listPartSettings).ToArray(); + model.EnableOrdering = listPartSettings.EnableOrdering; + } + }).Location("Content:1"); + } + + private IEnumerable GetContainedContentTypes(ListPartSettings settings) + { + var contentTypes = settings.ContainedContentTypes ?? Enumerable.Empty(); + + return contentTypes.Select(contentType => _contentDefinitionManager.GetTypeDefinition(contentType)); + } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Drivers/ListPartDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Lists/Drivers/ListPartDisplayDriver.cs index 9a0baaa7394..e1763a8e3ed 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Drivers/ListPartDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Drivers/ListPartDisplayDriver.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -32,57 +33,136 @@ IUpdateModelAccessor updateModelAccessor _updateModelAccessor = updateModelAccessor; } + public override IDisplayResult Edit(ListPart part, BuildPartEditorContext context) + { + var settings = context.TypePartDefinition.GetSettings(); + + return + Combine( + InitilizeEditListPartNavigationAdmin(part, context, settings), + InitilizeEditListPartHeaderAdmin(part, context, settings) + ); + } + public override IDisplayResult Display(ListPart listPart, BuildPartDisplayContext context) { + var settings = context.TypePartDefinition.GetSettings(); + return Combine( - Initialize(GetDisplayShapeType(context), async model => - { - var pager = await GetPagerSlimAsync(context); - var settings = context.TypePartDefinition.GetSettings(); - var containedItemOptions = new ContainedItemOptions(); - model.ContentItems = (await _containerService.QueryContainedItemsAsync( - listPart.ContentItem.ContentItemId, - settings.EnableOrdering, - pager, - containedItemOptions)).ToArray(); - - model.ContainedContentTypeDefinitions = GetContainedContentTypes(context); - model.Context = context; - model.Pager = await context.New.PagerSlim(pager); - }) - .Location("Detail", "Content:10"), - Initialize("ListPartDetailAdmin", async model => - { - var pager = await GetPagerSlimAsync(context); - var settings = context.TypePartDefinition.GetSettings(); - var listPartFilterViewModel = new ListPartFilterViewModel(); - var containedItemOptions = new ContainedItemOptions(); - - await _updateModelAccessor.ModelUpdater.TryUpdateModelAsync(listPartFilterViewModel, Prefix); - model.ListPart = listPart; - containedItemOptions.DisplayText = listPartFilterViewModel.DisplayText; - containedItemOptions.Status = listPartFilterViewModel.Status; - model.ListPartFilterViewModel = listPartFilterViewModel; - - model.ContentItems = (await _containerService.QueryContainedItemsAsync( - listPart.ContentItem.ContentItemId, - settings.EnableOrdering, - pager, - containedItemOptions)).ToArray(); - - model.ContainedContentTypeDefinitions = GetContainedContentTypes(context); - model.Context = context; - model.EnableOrdering = settings.EnableOrdering; - model.Pager = await context.New.PagerSlim(pager); - }) - .Location("DetailAdmin", "Content:10"), - Initialize("ListPartSummaryAdmin", model => model.ContentItem = listPart.ContentItem) - .Location("SummaryAdmin", "Actions:4") + InitilizeDisplayListPartDisplayShape(listPart, context), + InitilizeDisplayListPartDetailAdminShape(listPart, context), + InitilizeDisplayListPartNavigationAdminShape(listPart, context, settings), + InitilizeDisplayListPartHeaderAdminShape(listPart, settings), + InitilizeDisplayListPartSummaryAdmin(listPart) ); } - private async Task GetPagerSlimAsync(BuildPartDisplayContext context) + private ShapeResult InitilizeEditListPartHeaderAdmin(ListPart part, BuildPartEditorContext context, ListPartSettings settings) + { + return Initialize("ListPartHeaderAdmin", (Action)(model => + { + model.ContainerContentItem = part.ContentItem; + model.ContainedContentTypeDefinitions = GetContainedContentTypes(settings).ToArray(); + model.EnableOrdering = settings.EnableOrdering; + })) + .Location("Content:1") + .RenderWhen(() => Task.FromResult(!context.IsNew && settings.ShowHeader)); + } + + private ShapeResult InitilizeEditListPartNavigationAdmin(ListPart part, BuildPartEditorContext context, ListPartSettings settings) + { + return Initialize("ListPartNavigationAdmin", model => + { + model.Container = part.ContentItem; + model.ContainedContentTypeDefinitions = GetContainedContentTypes(settings).ToArray(); + model.EnableOrdering = settings.EnableOrdering; + model.ContainerContentTypeDefinition = context.TypePartDefinition.ContentTypeDefinition; + }) + .Location("Content:1.5") + .RenderWhen(() => Task.FromResult(!context.IsNew)); + } + + private ShapeResult InitilizeDisplayListPartSummaryAdmin(ListPart listPart) + { + return Initialize("ListPartSummaryAdmin", (Action)(model => model.ContentItem = listPart.ContentItem)) + .Location("SummaryAdmin", "Actions:4"); + } + + private ShapeResult InitilizeDisplayListPartHeaderAdminShape(ListPart listPart, ListPartSettings settings) + { + return Initialize("ListPartHeaderAdmin", (Action)(model => + { + model.ContainerContentItem = listPart.ContentItem; + model.ContainedContentTypeDefinitions = GetContainedContentTypes(settings).ToArray(); + model.EnableOrdering = settings.EnableOrdering; + })) + .Location("DetailAdmin", "Content:1") + .RenderWhen(() => Task.FromResult(settings.ShowHeader)); + } + + private ShapeResult InitilizeDisplayListPartNavigationAdminShape(ListPart listPart, BuildPartDisplayContext context, ListPartSettings settings) + { + return Initialize("ListPartNavigationAdmin", (Action)(model => + { + model.ContainedContentTypeDefinitions = GetContainedContentTypes(settings).ToArray(); + model.Container = listPart.ContentItem; + model.EnableOrdering = settings.EnableOrdering; + model.ContainerContentTypeDefinition = context.TypePartDefinition.ContentTypeDefinition; + })) + .Location("DetailAdmin", "Content:1.5"); + } + + private ShapeResult InitilizeDisplayListPartDetailAdminShape(ListPart listPart, BuildPartDisplayContext context) + { + return Initialize("ListPartDetailAdmin", (Func)(async model => + { + var pager = await GetPagerSlimAsync(context); + var settings = context.TypePartDefinition.GetSettings(); + var listPartFilterViewModel = new ListPartFilterViewModel(); + var containedItemOptions = new ContainedItemOptions(); + + await _updateModelAccessor.ModelUpdater.TryUpdateModelAsync(listPartFilterViewModel, Prefix); + model.ListPart = listPart; + containedItemOptions.DisplayText = listPartFilterViewModel.DisplayText; + containedItemOptions.Status = listPartFilterViewModel.Status; + model.ListPartFilterViewModel = listPartFilterViewModel; + + model.ContentItems = (await _containerService.QueryContainedItemsAsync( + listPart.ContentItem.ContentItemId, + settings.EnableOrdering, + pager, + containedItemOptions)).ToArray(); + + model.ContainedContentTypeDefinitions = GetContainedContentTypes(settings); + model.Context = context; + model.EnableOrdering = settings.EnableOrdering; + model.Pager = await context.New.PagerSlim(pager); + })) + .Location("DetailAdmin", "Content:10"); + } + + private ShapeResult InitilizeDisplayListPartDisplayShape(ListPart listPart, BuildPartDisplayContext context) + { + return Initialize(GetDisplayShapeType(context), async model => + { + var pager = await GetPagerSlimAsync(context); + var settings = context.TypePartDefinition.GetSettings(); + var containedItemOptions = new ContainedItemOptions(); + model.ContentItems = (await _containerService.QueryContainedItemsAsync( + listPart.ContentItem.ContentItemId, + settings.EnableOrdering, + pager, + containedItemOptions)).ToArray(); + + model.ContainedContentTypeDefinitions = GetContainedContentTypes(settings); + model.Context = context; + model.Pager = await context.New.PagerSlim(pager); + }) + .Location("Detail", "Content:10"); + } + + private static async Task GetPagerSlimAsync(BuildPartDisplayContext context) { var settings = context.TypePartDefinition.GetSettings(); var pagerParameters = new PagerSlimParameters(); @@ -93,10 +173,10 @@ private async Task GetPagerSlimAsync(BuildPartDisplayContext context) return pager; } - private IEnumerable GetContainedContentTypes(BuildPartDisplayContext context) + private IEnumerable GetContainedContentTypes(ListPartSettings settings) { - var settings = context.TypePartDefinition.GetSettings(); var contentTypes = settings.ContainedContentTypes ?? Enumerable.Empty(); + return contentTypes.Select(contentType => _contentDefinitionManager.GetTypeDefinition(contentType)); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Indexes/ContainedPartIndex.cs b/src/OrchardCore.Modules/OrchardCore.Lists/Indexes/ContainedPartIndex.cs index 9962f8a438b..a48a95b8237 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Indexes/ContainedPartIndex.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Indexes/ContainedPartIndex.cs @@ -7,7 +7,18 @@ namespace OrchardCore.Lists.Indexes public class ContainedPartIndex : MapIndex { public string ListContentItemId { get; set; } + public int Order { get; set; } + + public string ContentItemId { get; set; } + + public string ListContentType { get; set; } + + public bool Published { get; set; } + + public bool Latest { get; set; } + + public string DisplayText { get; set; } } public class ContainedPartIndexProvider : IndexProvider @@ -15,10 +26,15 @@ public class ContainedPartIndexProvider : IndexProvider public override void Describe(DescribeContext context) { context.For() - .When(contentItem => contentItem.Has()) .Map(contentItem => { + if (!contentItem.Latest && !contentItem.Published) + { + return null; + } + var containedPart = contentItem.As(); + if (containedPart == null) { return null; @@ -26,8 +42,13 @@ public override void Describe(DescribeContext context) return new ContainedPartIndex { + ContentItemId = contentItem.ContentItemId, + ListContentType = containedPart.ListContentType, ListContentItemId = containedPart.ListContentItemId, - Order = containedPart.Order + Order = containedPart.Order, + Published = contentItem.Published, + Latest = contentItem.Latest, + DisplayText = contentItem.DisplayText, }; }); } diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Migrations.cs b/src/OrchardCore.Modules/OrchardCore.Lists/Migrations.cs index 7c1886e48ce..4aa7a1bcd3e 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Migrations.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Migrations.cs @@ -9,7 +9,7 @@ namespace OrchardCore.Lists { public class Migrations : DataMigration { - private IContentDefinitionManager _contentDefinitionManager; + private readonly IContentDefinitionManager _contentDefinitionManager; public Migrations(IContentDefinitionManager contentDefinitionManager) { @@ -23,16 +23,31 @@ public int Create() .WithDescription("Add a list behavior.")); SchemaBuilder.CreateMapIndexTable(table => table - .Column("ListContentItemId", c => c.WithLength(26)) + .Column("ContentItemId", column => column.WithLength(26)) + .Column("ListContentItemId", column => column.WithLength(26)) + .Column("DisplayText") .Column("Order") + .Column("ListContentType") + .Column("Published") + .Column("Latest") + ); SchemaBuilder.AlterIndexTable(table => table - .CreateIndex("IDX_ContainedPartIndex_DocumentId", "DocumentId", "ListContentItemId", "Order") + .CreateIndex("IDX_ContainedPartIndex_DocumentId", + "Id", + "DocumentId", + "ContentItemId", + "ListContentItemId", + "DisplayText", + "Order", + "ListContentType", + "Published", + "Latest") ); // Shortcut other migration steps on new content definition schemas. - return 3; + return 4; } // Migrate PartSettings. This only needs to run on old content definition schemas. @@ -53,5 +68,47 @@ public int UpdateFrom2() return 3; } + + // This code can be removed in a later version. + public int UpdateFrom3() + { + SchemaBuilder.AlterIndexTable(table => table + .AddColumn("ContentItemId", column => column.WithLength(26)) + ); + + SchemaBuilder.AlterIndexTable(table => table + .AddColumn("ListContentType") + ); + + SchemaBuilder.AlterIndexTable(table => table + .AddColumn("DisplayText") + ); + + SchemaBuilder.AlterIndexTable(table => table + .AddColumn("Published") + ); + + SchemaBuilder.AlterIndexTable(table => table + .AddColumn("Latest") + ); + SchemaBuilder.AlterIndexTable(table => table + .DropIndex("IDX_ContainedPartIndex_DocumentId") + ); + + SchemaBuilder.AlterIndexTable(table => table + .CreateIndex("IDX_ContainedPartIndex_DocumentId", + "Id", + "DocumentId", + "ContentItemId", + "ListContentItemId", + "DisplayText", + "Order", + "ListContentType", + "Published", + "Latest") + ); + + return 4; + } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Models/ContainedPart.cs b/src/OrchardCore.Modules/OrchardCore.Lists/Models/ContainedPart.cs index 9be0482eddf..5a62fa2ab9e 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Models/ContainedPart.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Models/ContainedPart.cs @@ -12,6 +12,11 @@ public class ContainedPart : ContentPart /// public string ListContentItemId { get; set; } + /// + /// The content type of the list owning this content item. + /// + public string ListContentType { get; set; } + /// /// The order of this content item in the list. /// diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Models/ListPartSettings.cs b/src/OrchardCore.Modules/OrchardCore.Lists/Models/ListPartSettings.cs index c96f052c435..d9089e2382c 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Models/ListPartSettings.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Models/ListPartSettings.cs @@ -5,5 +5,6 @@ public class ListPartSettings public int PageSize { get; set; } = 10; public string[] ContainedContentTypes { get; set; } public bool EnableOrdering { get; set; } + public bool ShowHeader { get; set; } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Services/ContainerService.cs b/src/OrchardCore.Modules/OrchardCore.Lists/Services/ContainerService.cs index c6b1c937ee2..43f93360f62 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Services/ContainerService.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Services/ContainerService.cs @@ -174,7 +174,7 @@ public async Task> QueryContainedItemsAsync( } else { - var beforeValue = new DateTime(long.Parse(pager.Before)); + var beforeValue = new DateTime(Int64.Parse(pager.Before)); query = _session.Query() .With(x => x.ListContentItemId == contentItemId); @@ -226,7 +226,7 @@ public async Task> QueryContainedItemsAsync( { if (enableOrdering) { - var afterValue = int.Parse(pager.After); + var afterValue = Int32.Parse(pager.After); query = _session.Query() .With(CreateOrderedContainedPartIndexFilter(null, afterValue, contentItemId)) .OrderBy(x => x.Order); @@ -352,7 +352,7 @@ private static void ApplyPagingContentIndexFilter(DateTime? before, DateTime? af private void ApplyContainedItemOptionsFilter(ContainedItemOptions containedItemOptions, IQuery query) { - if (!string.IsNullOrEmpty(containedItemOptions.DisplayText)) + if (!String.IsNullOrEmpty(containedItemOptions.DisplayText)) { query.With(i => i.DisplayText.Contains(containedItemOptions.DisplayText)); } @@ -373,7 +373,7 @@ private void ApplyContainedItemOptionsFilter(ContainedItemOptions containedItemO if (currentUserName != null) { - query.With(i => i.Owner == currentUserName); + query.With(i => (i.Published || i.Latest) && i.Owner == currentUserName); } break; diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Settings/ListPartSettingsDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Lists/Settings/ListPartSettingsDisplayDriver.cs index 9eec227071f..ea40d0083ec 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Settings/ListPartSettingsDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Settings/ListPartSettingsDisplayDriver.cs @@ -36,6 +36,7 @@ public override IDisplayResult Edit(ContentTypePartDefinition contentTypePartDef model.PageSize = model.ListPartSettings.PageSize; model.EnableOrdering = model.ListPartSettings.EnableOrdering; model.ContainedContentTypes = model.ListPartSettings.ContainedContentTypes; + model.ShowHeader = model.ListPartSettings.ShowHeader; model.ContentTypes = new NameValueCollection(); foreach (var contentTypeDefinition in _contentDefinitionManager.ListTypeDefinitions()) @@ -51,7 +52,7 @@ public override async Task UpdateAsync(ContentTypePartDefinition var model = new ListPartSettingsViewModel(); - await context.Updater.TryUpdateModelAsync(model, Prefix, m => m.ContainedContentTypes, m => m.PageSize, m => m.EnableOrdering); + await context.Updater.TryUpdateModelAsync(model, Prefix, m => m.ContainedContentTypes, m => m.PageSize, m => m.EnableOrdering, m => m.ShowHeader); if (model.ContainedContentTypes == null || model.ContainedContentTypes.Length == 0) { @@ -63,7 +64,8 @@ public override async Task UpdateAsync(ContentTypePartDefinition { PageSize = model.PageSize, EnableOrdering = model.EnableOrdering, - ContainedContentTypes = model.ContainedContentTypes + ContainedContentTypes = model.ContainedContentTypes, + ShowHeader = model.ShowHeader, }); // Update order of existing content if enable ordering has been turned on diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/EditContainedPartViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/EditContainedPartViewModel.cs index 26e59b6b054..2c850fca05b 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/EditContainedPartViewModel.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/EditContainedPartViewModel.cs @@ -3,6 +3,7 @@ namespace OrchardCore.Lists.ViewModels public class EditContainedPartViewModel { public string ContainerId { get; set; } + public string ContainerContentType { get; set; } public string ContentType { get; set; } public bool EnableOrdering { get; set; } } diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartHeaderAdminViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartHeaderAdminViewModel.cs new file mode 100644 index 00000000000..de1a62554a1 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartHeaderAdminViewModel.cs @@ -0,0 +1,14 @@ +using System; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; + +namespace OrchardCore.Lists.ViewModels; + +public class ListPartHeaderAdminViewModel +{ + public ContentItem ContainerContentItem { get; set; } + + public ContentTypeDefinition[] ContainedContentTypeDefinitions { get; set; } = Array.Empty(); + + public bool EnableOrdering { get; set; } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartNavigationAdminViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartNavigationAdminViewModel.cs new file mode 100644 index 00000000000..23ab894a4d2 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartNavigationAdminViewModel.cs @@ -0,0 +1,16 @@ +using System; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; + +namespace OrchardCore.Lists.ViewModels; + +public class ListPartNavigationAdminViewModel +{ + public ContentItem Container { get; set; } + + public ContentTypeDefinition ContainerContentTypeDefinition { get; set; } + + public bool EnableOrdering { get; set; } + + public ContentTypeDefinition[] ContainedContentTypeDefinitions { get; set; } = Array.Empty(); +} diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartSettingsViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartSettingsViewModel.cs index 4f084d8d495..da07ba8482d 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartSettingsViewModel.cs +++ b/src/OrchardCore.Modules/OrchardCore.Lists/ViewModels/ListPartSettingsViewModel.cs @@ -10,5 +10,6 @@ public class ListPartSettingsViewModel public string[] ContainedContentTypes { get; set; } public int PageSize { get; set; } public bool EnableOrdering { get; set; } + public bool ShowHeader { get; set; } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPart.ContainerId.cshtml b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPart.ContainerId.cshtml index 675220318c8..8c73b9f7366 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPart.ContainerId.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPart.ContainerId.cshtml @@ -1,4 +1,5 @@ @model OrchardCore.Lists.ViewModels.EditContainedPartViewModel - + + diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartDetailAdmin.cshtml b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartDetailAdmin.cshtml index 4f6628f6d83..27d6602a104 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartDetailAdmin.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartDetailAdmin.cshtml @@ -54,7 +54,7 @@ else
-
+
-
- - @T["Edit {0}", @Model.ListPart.ContentItem.DisplayText] - - @if (authorizedContentTypeDefinitions.Count == 1) - { - var contentTypeDefinition = authorizedContentTypeDefinitions.FirstOrDefault(); - - @T["Create {0}", contentTypeDefinition.DisplayName] - - } - else if (authorizedContentTypeDefinitions.Count > 1) - { - - - } -
diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartHeaderAdmin.cshtml b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartHeaderAdmin.cshtml new file mode 100644 index 00000000000..d7c71018eb7 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartHeaderAdmin.cshtml @@ -0,0 +1,9 @@ +@model OrchardCore.Lists.ViewModels.ListPartHeaderAdminViewModel +@inject OrchardCore.ContentManagement.Display.IContentItemDisplayManager ContentItemDisplayManager +@inject OrchardCore.DisplayManagement.ModelBinding.IUpdateModelAccessor UpdateModelAccessor + +
+
+ @await DisplayAsync(await ContentItemDisplayManager.BuildDisplayAsync(Model.ContainerContentItem, UpdateModelAccessor.ModelUpdater, "HeaderAdmin")) +
+
diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartNavigationAdmin.cshtml b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartNavigationAdmin.cshtml new file mode 100644 index 00000000000..bed0ad530df --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartNavigationAdmin.cshtml @@ -0,0 +1,62 @@ +@using Microsoft.AspNetCore.Authorization +@using OrchardCore.Contents +@model OrchardCore.Lists.ViewModels.ListPartNavigationAdminViewModel +@inject OrchardCore.ContentManagement.IContentManager ContentManager +@inject Microsoft.AspNetCore.Authorization.IAuthorizationService AuthorizationService + +
+
+
+ + @if (await AuthorizationService.AuthorizeContentTypeDefinitionsAsync(User, CommonPermissions.ViewContent, Model.ContainedContentTypeDefinitions, ContentManager)) + { + @T["List Items"] + } + + @if (await AuthorizationService.AuthorizeAsync(User, CommonPermissions.EditContent, Model.Container)) + { + + @T["Edit {0}", Model.ContainerContentTypeDefinition?.DisplayName] + + } + + @if (Model.ContainedContentTypeDefinitions.Length == 1) + { + var contentTypeDefinition = Model.ContainedContentTypeDefinitions[0]; + + var dummyContent = await ContentManager.NewAsync(contentTypeDefinition.Name); + dummyContent.Owner = User.Identity.Name; + + if (await AuthorizationService.AuthorizeAsync(User, CommonPermissions.EditContent, dummyContent)) + { + + @T["Create {0}", contentTypeDefinition.DisplayName] + + } + } + else if (Model.ContainedContentTypeDefinitions.Length > 1) + { + + + } +
+
+
diff --git a/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartSettings.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartSettings.Edit.cshtml index b334909bc23..8889e239c3c 100644 --- a/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartSettings.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Lists/Views/ListPartSettings.Edit.cshtml @@ -20,3 +20,11 @@ @T["The content types that this list can contain, e.g. Blog Post for a Blog."] @await Component.InvokeAsync("SelectContentTypes", new { selectedContentTypes = Model.ContainedContentTypes, htmlName = Html.NameFor(m => m.ContainedContentTypes) })
+ +
+
+ + + @T["Check this option to show a header for the owning content."] +
+