Skip to content

Commit

Permalink
Add "Display Header" property to ListPartSettings (#12525)
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeAlhayek authored Oct 20, 2022
1 parent 97abb2e commit b45c84c
Show file tree
Hide file tree
Showing 18 changed files with 431 additions and 105 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1 class="fs-5">@Model.ContentItem</h1>
Original file line number Diff line number Diff line change
@@ -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;
}

Expand All @@ -33,13 +37,15 @@ public override async Task<IDisplayResult> 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<ContainedPart>();

if (model.As<ContainedPart>() != null)
if (containedPart != null)
{
return BuildViewModel(model.As<ContainedPart>().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
Expand All @@ -48,23 +54,12 @@ public override async Task<IDisplayResult> 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<EditContainedPartViewModel>("ListPart_ContainerId", m =>
{
m.ContainerId = containerId;
m.EnableOrdering = enableOrdering;
m.ContentType = contentType;
})
.Location("Content");
}

public override async Task<IDisplayResult> UpdateAsync(ContentItem model, IUpdateModel updater)
{
var viewModel = new EditContainedPartViewModel();
Expand All @@ -73,7 +68,12 @@ public override async Task<IDisplayResult> 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<ContainedPart>(x => x.ListContentItemId = viewModel.ContainerId);
model.Alter<ContainedPart>(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)
{
Expand All @@ -84,5 +84,78 @@ public override async Task<IDisplayResult> 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<IDisplayResult>()
{
Initialize<EditContainedPartViewModel>("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<ListPartSettings>();

if (settings != null)
{
// Add list part navigation
results.Add(Initialize<ListPartNavigationAdminViewModel>("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<ListPartHeaderAdminViewModel>("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<ContentTypeDefinition> GetContainedContentTypes(ListPartSettings settings)
{
var contentTypes = settings.ContainedContentTypes ?? Enumerable.Empty<string>();

return contentTypes.Select(contentType => _contentDefinitionManager.GetTypeDefinition(contentType));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand Down Expand Up @@ -32,57 +33,136 @@ IUpdateModelAccessor updateModelAccessor
_updateModelAccessor = updateModelAccessor;
}

public override IDisplayResult Edit(ListPart part, BuildPartEditorContext context)
{
var settings = context.TypePartDefinition.GetSettings<ListPartSettings>();

return
Combine(
InitilizeEditListPartNavigationAdmin(part, context, settings),
InitilizeEditListPartHeaderAdmin(part, context, settings)
);
}

public override IDisplayResult Display(ListPart listPart, BuildPartDisplayContext context)
{
var settings = context.TypePartDefinition.GetSettings<ListPartSettings>();

return
Combine(
Initialize<ListPartViewModel>(GetDisplayShapeType(context), async model =>
{
var pager = await GetPagerSlimAsync(context);
var settings = context.TypePartDefinition.GetSettings<ListPartSettings>();
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<ListPartViewModel>("ListPartDetailAdmin", async model =>
{
var pager = await GetPagerSlimAsync(context);
var settings = context.TypePartDefinition.GetSettings<ListPartSettings>();
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<ContentItemViewModel>("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<PagerSlim> GetPagerSlimAsync(BuildPartDisplayContext context)
private ShapeResult InitilizeEditListPartHeaderAdmin(ListPart part, BuildPartEditorContext context, ListPartSettings settings)
{
return Initialize("ListPartHeaderAdmin", (Action<ListPartHeaderAdminViewModel>)(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<ListPartNavigationAdminViewModel>("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<ContentItemViewModel>)(model => model.ContentItem = listPart.ContentItem))
.Location("SummaryAdmin", "Actions:4");
}

private ShapeResult InitilizeDisplayListPartHeaderAdminShape(ListPart listPart, ListPartSettings settings)
{
return Initialize("ListPartHeaderAdmin", (Action<ListPartHeaderAdminViewModel>)(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<ListPartNavigationAdminViewModel>)(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<ListPartViewModel, ValueTask>)(async model =>
{
var pager = await GetPagerSlimAsync(context);
var settings = context.TypePartDefinition.GetSettings<ListPartSettings>();
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<ListPartViewModel>(GetDisplayShapeType(context), async model =>
{
var pager = await GetPagerSlimAsync(context);
var settings = context.TypePartDefinition.GetSettings<ListPartSettings>();
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<PagerSlim> GetPagerSlimAsync(BuildPartDisplayContext context)
{
var settings = context.TypePartDefinition.GetSettings<ListPartSettings>();
var pagerParameters = new PagerSlimParameters();
Expand All @@ -93,10 +173,10 @@ private async Task<PagerSlim> GetPagerSlimAsync(BuildPartDisplayContext context)
return pager;
}

private IEnumerable<ContentTypeDefinition> GetContainedContentTypes(BuildPartDisplayContext context)
private IEnumerable<ContentTypeDefinition> GetContainedContentTypes(ListPartSettings settings)
{
var settings = context.TypePartDefinition.GetSettings<ListPartSettings>();
var contentTypes = settings.ContainedContentTypes ?? Enumerable.Empty<string>();

return contentTypes.Select(contentType => _contentDefinitionManager.GetTypeDefinition(contentType));
}
}
Expand Down
Loading

0 comments on commit b45c84c

Please sign in to comment.