Skip to content

Commit

Permalink
Add ContainedStereotypes BagPartSettings to allow a user to include c…
Browse files Browse the repository at this point in the history
…ontent-types by steryotype (#11978)
  • Loading branch information
MikeAlhayek authored Aug 18, 2022
1 parent 40afd55 commit c13ef60
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,19 @@ private static bool IsSecurable(IContentDefinitionManager contentDefinitionManag
private async Task<IEnumerable<ContentTypeDefinition>> GetContainedContentTypesAsync(IContentDefinitionManager contentDefinitionManager, ContentTypePartDefinition typePartDefinition)
{
var settings = typePartDefinition.GetSettings<BagPartSettings>();
var contentTypes = Enumerable.Empty<ContentTypeDefinition>();

var contentTypes = settings.ContainedContentTypes
.Select(contentType => _contentDefinitionManager.GetTypeDefinition(contentType))
.Where(contentType => contentType != null);
if (settings.ContainedStereotypes != null && settings.ContainedStereotypes.Length > 0)
{
contentTypes = _contentDefinitionManager.ListTypeDefinitions()
.Where(contentType => contentType.HasStereotype() && settings.ContainedStereotypes.Contains(contentType.GetStereotypeOrDefault(), StringComparer.OrdinalIgnoreCase));
}
else if (settings.ContainedContentTypes != null && settings.ContainedContentTypes.Length > 0)
{
contentTypes = settings.ContainedContentTypes
.Select(contentType => _contentDefinitionManager.GetTypeDefinition(contentType))
.Where(contentType => contentType != null);
}

var accessibleContentTypes = new List<ContentTypeDefinition>();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace OrchardCore.Flows.Models;

public enum BagPartSettingType
{
None,
ContentTypes,
Stereotypes
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ namespace OrchardCore.Flows.Models
public class BagPartSettings
{
public string[] ContainedContentTypes { get; set; } = Array.Empty<string>();

public string[] ContainedStereotypes { get; set; } = Array.Empty<string>();

public string DisplayType { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Specialized;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
Expand All @@ -8,6 +9,7 @@
using OrchardCore.DisplayManagement.Views;
using OrchardCore.Flows.Models;
using OrchardCore.Flows.ViewModels;
using OrchardCore.Mvc.ModelBinding;

namespace OrchardCore.Flows.Settings
{
Expand All @@ -28,11 +30,14 @@ public override IDisplayResult Edit(ContentTypePartDefinition contentTypePartDef
{
return Initialize<BagPartSettingsViewModel>("BagPartSettings_Edit", model =>
{
model.BagPartSettings = contentTypePartDefinition.GetSettings<BagPartSettings>();
var settings = contentTypePartDefinition.GetSettings<BagPartSettings>();
model.BagPartSettings = settings;
model.ContainedContentTypes = model.BagPartSettings.ContainedContentTypes;
model.DisplayType = model.BagPartSettings.DisplayType;
model.ContentTypes = new NameValueCollection();
model.Source = settings.ContainedStereotypes != null && settings.ContainedStereotypes.Length > 0 ? BagPartSettingType.Stereotypes : BagPartSettingType.ContentTypes;
model.Stereotypes = String.Join(',', settings.ContainedStereotypes ?? Array.Empty<string>());
foreach (var contentTypeDefinition in _contentDefinitionManager.ListTypeDefinitions())
{
model.ContentTypes.Add(contentTypeDefinition.Name, contentTypeDefinition.DisplayName);
Expand All @@ -44,22 +49,56 @@ public override async Task<IDisplayResult> UpdateAsync(ContentTypePartDefinition
{
var model = new BagPartSettingsViewModel();

await context.Updater.TryUpdateModelAsync(model, Prefix, m => m.ContainedContentTypes, m => m.DisplayType);
await context.Updater.TryUpdateModelAsync(model, Prefix, m => m.ContainedContentTypes, m => m.DisplayType, m => m.Source, m => m.Stereotypes);

if (model.ContainedContentTypes == null || model.ContainedContentTypes.Length == 0)
switch (model.Source)
{
context.Updater.ModelState.AddModelError(nameof(model.ContainedContentTypes), S["At least one content type must be selected."]);
case BagPartSettingType.ContentTypes:
SetContentTypes(context, model);
break;
case BagPartSettingType.Stereotypes:
SetStereoTypes(context, model);
break;
default:
context.Updater.ModelState.AddModelError(Prefix, nameof(model.Source), S["Content type source must be set with a valid value."]);
break;
}
else

return Edit(contentTypePartDefinition, context.Updater);
}

private void SetStereoTypes(UpdateTypePartEditorContext context, BagPartSettingsViewModel model)
{
if (String.IsNullOrEmpty(model.Stereotypes))
{
context.Builder.WithSettings(new BagPartSettings
{
ContainedContentTypes = model.ContainedContentTypes,
DisplayType = model.DisplayType
});
context.Updater.ModelState.AddModelError(Prefix, nameof(model.Stereotypes), S["Please provide a Stereotype."]);

return;
}

return Edit(contentTypePartDefinition, context.Updater);
context.Builder.WithSettings(new BagPartSettings
{
ContainedContentTypes = Array.Empty<string>(),
ContainedStereotypes = model.Stereotypes.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries),
DisplayType = model.DisplayType
});
}

private void SetContentTypes(UpdateTypePartEditorContext context, BagPartSettingsViewModel model)
{
if (model.ContainedContentTypes == null || model.ContainedContentTypes.Length == 0)
{
context.Updater.ModelState.AddModelError(Prefix, nameof(model.ContainedContentTypes), S["At least one content type must be selected."]);

return;
}

context.Builder.WithSettings(new BagPartSettings
{
ContainedContentTypes = model.ContainedContentTypes,
ContainedStereotypes = Array.Empty<string>(),
DisplayType = model.DisplayType
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ public class BagPartSettingsViewModel
public NameValueCollection ContentTypes { get; set; }
public string DisplayType { get; set; }
public string[] ContainedContentTypes { get; set; } = Array.Empty<string>();
public BagPartSettingType Source { get; set; }
public string Stereotypes { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,66 @@
@model OrchardCore.Flows.ViewModels.BagPartSettingsViewModel

@using OrchardCore.Flows.Settings
@using OrchardCore.Flows.Models
<div class="mb-3">
<label asp-for="Source">@T["Contained Content Types"]</label>
<div class="w-sm-50" id="@Html.IdFor(x => x.Source)">
<div class="form-check">
<input class="form-check-input" type="radio" asp-for="Source" id="SourceContentTypes" value="@(BagPartSettingType.ContentTypes)" checked="@(Model.Source == BagPartSettingType.ContentTypes))">
<label for="SourceContentTypes">
@T["Content Types"]
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" asp-for="Source" id="SourceStereotype" value="@(BagPartSettingType.Stereotypes)" checked="@(Model.Source == BagPartSettingType.Stereotypes)">
<label for="SourceStereotype">
@T["Stereotype"] <span class="hint">@T["All content types of these Stereotypes"]</span>
</label>
</div>
</div>
</div>

<div class="mb-3" id="ContentTypesContainer">
<label asp-for="ContainedContentTypes">@T["Contained Content Types"]</label>
<span class="hint">@T["The content types that this bag can contain, e.g. Slide for a Slide Show."]</span>
@await Component.InvokeAsync("SelectContentTypes", new { selectedContentTypes = Model.ContainedContentTypes, htmlName = Html.NameFor(m => m.ContainedContentTypes) })
</div>

<div class="mb-3" id="StereotypesContainer">
<div class="w-sm-50" id="@Html.IdFor(x => x.Source)">
<label asp-for="Stereotypes">@T["Stereotypes"]</label>
<input asp-for="Stereotypes" class="form-control medium" />
<span class="hint">@T["The Stereotypes of the content types that this bag can contain. You may define multiple Stereotypes using the comma (,) as a separator"]</span>
</div>
</div>
<div class="mb-3">
<div class="w-sm-50">
<label asp-for="DisplayType">@T["Display Type"]</label>
<input asp-for="DisplayType" placeholder="Summary" class="form-control medium" />
</div>
<span class="hint">@T["The display type to use when rendering the content items. Default is Summary."]</span>
</div>

<script at="Foot" asp-name="bagPartSettings">
document.addEventListener('DOMContentLoaded', function() {
var sources = document.getElementsByName('@Html.NameFor(x => x.Source)');
var contentTypesContainer = document.getElementById('ContentTypesContainer');
var stereotypeContainer = document.getElementById('StereotypesContainer');
for (var i = 0; i < sources.length; i++) {
var source = sources[i];
source.addEventListener('change', function(src) {
if (!src.target.checked) {
return;
}
if (src.target.value == '@(BagPartSettingType.Stereotypes)') {
contentTypesContainer.classList.add('d-none');
stereotypeContainer.classList.remove('d-none');
} else {
contentTypesContainer.classList.remove('d-none');
stereotypeContainer.classList.add('d-none');
}
});
source.dispatchEvent(new Event('change'));
}
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using OrchardCore.ContentManagement.Metadata.Settings;

namespace OrchardCore.ContentManagement.Metadata.Models;

public static class ContentTypeExtensions
{
public static bool HasStereotype(this ContentTypeDefinition contentTypeDefinition)
{
return !String.IsNullOrEmpty(contentTypeDefinition.GetStereotypeOrDefault());
}

public static string GetStereotypeOrDefault(this ContentTypeDefinition contentTypeDefinition)
{
return contentTypeDefinition.GetSettings().Stereotype;
}

public static bool IsListable(this ContentTypeDefinition contentTypeDefinition)
{
return contentTypeDefinition.GetSettings().Listable;
}

public static bool IsCreatable(this ContentTypeDefinition contentTypeDefinition)
{
return contentTypeDefinition.GetSettings().Creatable;
}

public static bool IsDraftable(this ContentTypeDefinition contentTypeDefinition)
{
return contentTypeDefinition.GetSettings().Draftable;
}

public static bool IsVersionable(this ContentTypeDefinition contentTypeDefinition)
{
return contentTypeDefinition.GetSettings().Versionable;
}

public static bool IsSecurable(this ContentTypeDefinition contentTypeDefinition)
{
return contentTypeDefinition.GetSettings().Securable;
}

public static bool HasDescription(this ContentTypeDefinition contentTypeDefinition)
{
return !String.IsNullOrEmpty(contentTypeDefinition.GetSettings().Description);
}

public static string GetDescription(this ContentTypeDefinition contentTypeDefinition)
{
return contentTypeDefinition.GetSettings().Description;
}

public static ContentTypeSettings GetSettings(this ContentTypeDefinition contentTypeDefinition)
{
return contentTypeDefinition.GetSettings<ContentTypeSettings>();
}
}

0 comments on commit c13ef60

Please sign in to comment.