Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a way to hide ContentTypeDefinitionSettings #15472

Merged
merged 8 commits into from
Mar 24, 2024
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using OrchardCore.ContentManagement.Metadata.Models;
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.ContentTypes.ViewModels;
Expand All @@ -10,16 +11,22 @@ namespace OrchardCore.ContentTypes.Editors
{
public class ContentTypeSettingsDisplayDriver : ContentTypeDefinitionDisplayDriver
{
private static readonly ContentTypeDefinitionDriverOptions _defaultOptions = new();

private readonly ContentTypeDefinitionOptions _options;

protected readonly IStringLocalizer S;

public ContentTypeSettingsDisplayDriver(IStringLocalizer<ContentTypeSettingsDisplayDriver> stringLocalizer)
public ContentTypeSettingsDisplayDriver(
IStringLocalizer<ContentTypeSettingsDisplayDriver> stringLocalizer,
IOptions<ContentTypeDefinitionOptions> options)
{
S = stringLocalizer;
_options = options.Value;
}

public override IDisplayResult Edit(ContentTypeDefinition contentTypeDefinition)
{
return Initialize<ContentTypeSettingsViewModel>("ContentTypeSettings_Edit", model =>
=> Initialize<ContentTypeSettingsViewModel>("ContentTypeSettings_Edit", model =>
{
var settings = contentTypeDefinition.GetSettings<ContentTypeSettings>();

Expand All @@ -30,34 +37,72 @@ public override IDisplayResult Edit(ContentTypeDefinition contentTypeDefinition)
model.Securable = settings.Securable;
model.Stereotype = settings.Stereotype;
model.Description = settings.Description;
model.Options = GetOptions(contentTypeDefinition, settings.Stereotype);
}).Location("Content:5");
}

public override async Task<IDisplayResult> UpdateAsync(ContentTypeDefinition contentTypeDefinition, UpdateTypeEditorContext context)
{
var model = new ContentTypeSettingsViewModel();

if (await context.Updater.TryUpdateModelAsync(model, Prefix))
{
context.Builder.Creatable(model.Creatable);
context.Builder.Listable(model.Listable);
context.Builder.Draftable(model.Draftable);
context.Builder.Versionable(model.Versionable);
context.Builder.Securable(model.Securable);
context.Builder.WithDescription(model.Description);

var stereotype = model.Stereotype?.Trim();
context.Builder.WithDescription(model.Description);
context.Builder.Stereotype(stereotype);

if (!IsAlphaNumericOrEmpty(stereotype))
{
context.Updater.ModelState.AddModelError(nameof(ContentTypeSettingsViewModel.Stereotype), S["The stereotype should be alphanumeric."]);
}

var options = GetOptions(contentTypeDefinition, stereotype);

Apply(context, model, options);
}

return Edit(contentTypeDefinition);
}

private static void Apply(UpdateTypeEditorContext context, ContentTypeSettingsViewModel model, ContentTypeDefinitionDriverOptions options)
{
if (options.ShowVersionable)
{
context.Builder.Versionable(model.Versionable);
}

if (options.ShowCreatable)
{
context.Builder.Creatable(model.Creatable);
}

if (options.ShowSecurable)
{
context.Builder.Securable(model.Securable);
}

if (options.ShowListable)
{
context.Builder.Listable(model.Listable);
}
}

private ContentTypeDefinitionDriverOptions GetOptions(ContentTypeDefinition contentTypeDefinition, string stereotype)
{
if (contentTypeDefinition.Name != null
&& _options.ContentTypes.TryGetValue(contentTypeDefinition.Name, out var typeOptions))
{
return typeOptions;
}

if (stereotype != null
&& _options.Stereotypes.TryGetValue(stereotype, out var stereotypesOptions))
{
return stereotypesOptions;
}

return _defaultOptions;
}

private static bool IsAlphaNumericOrEmpty(string value)
{
if (string.IsNullOrEmpty(value))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
using Microsoft.AspNetCore.Mvc.ModelBinding;
using OrchardCore.ContentManagement.Metadata.Models;

namespace OrchardCore.ContentTypes.ViewModels
{
public class ContentTypeSettingsViewModel
{
public bool Creatable { get; set; }

public bool Listable { get; set; }

public bool Draftable { get; set; }

public bool Versionable { get; set; }

public bool Securable { get; set; }

public string Stereotype { get; set; }

public string Description { get; set; }

[BindNever]
public ContentTypeDefinitionDriverOptions Options { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,60 @@
<span class="hint">@T["(Optional) Description of the content type"]</span>
</div>

<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Creatable">
<label class="form-check-label" asp-for="Creatable">@T["Creatable"]</label>
<span class="hint dashed">@T["Determines if an instance of this content type can be created through the UI."]</span>
@if (Model.Options.ShowCreatable)
{
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Creatable">
<label class="form-check-label" asp-for="Creatable">@T["Creatable"]</label>
<span class="hint dashed">@T["Determines if an instance of this content type can be created through the UI."]</span>
</div>
</div>
</div>
}

<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Listable">
<label class="form-check-label" asp-for="Listable">@T["Listable"]</label>
<span class="hint dashed">@T["Determines if an instance of this content type can be listed through the UI."]</span>
@if (Model.Options.ShowListable)
{
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Listable">
<label class="form-check-label" asp-for="Listable">@T["Listable"]</label>
<span class="hint dashed">@T["Determines if an instance of this content type can be listed through the UI."]</span>
</div>
</div>
</div>
}

<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Draftable">
<label class="form-check-label" asp-for="Draftable">@T["Draftable"]</label>
<span class="hint dashed">@T["Determines if this content type supports draft versions."]</span>
@if (Model.Options.ShowDraftable)
{
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Draftable">
<label class="form-check-label" asp-for="Draftable">@T["Draftable"]</label>
<span class="hint dashed">@T["Determines if this content type supports draft versions."]</span>
</div>
</div>
</div>
}

<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Versionable">
<label class="form-check-label" asp-for="Versionable">@T["Versionable"]</label>
<span class="hint dashed">@T["Determines if this content type supports versioning."]</span>
@if (Model.Options.ShowVersionable)
{
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Versionable">
<label class="form-check-label" asp-for="Versionable">@T["Versionable"]</label>
<span class="hint dashed">@T["Determines if this content type supports versioning."]</span>
</div>
</div>
</div>
}

<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Securable">
<label class="form-check-label" asp-for="Securable">@T["Securable"]</label>
<span class="hint dashed">@T["Determines if this content type can have custom permissions."]</span>
@if (Model.Options.ShowSecurable)
{
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="Securable">
<label class="form-check-label" asp-for="Securable">@T["Securable"]</label>
<span class="hint dashed">@T["Determines if this content type can have custom permissions."]</span>
</div>
</div>
</div>
}

<div class="mb-3">
<div class="w-md-75 w-xl-50">
Expand Down
6 changes: 6 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.CustomSettings/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.ContentManagement.Metadata.Models;
using OrchardCore.CustomSettings.Deployment;
using OrchardCore.CustomSettings.Drivers;
using OrchardCore.CustomSettings.Recipes;
Expand Down Expand Up @@ -27,6 +28,11 @@ public override void ConfigureServices(IServiceCollection services)
services.AddScoped<IAuthorizationHandler, CustomSettingsAuthorizationHandler>();

services.AddRecipeExecutionStep<CustomSettingsStep>();

services.Configure<ContentTypeDefinitionOptions>(options =>
{
options.Stereotypes.TryAdd("CustomSettings", new ContentTypeDefinitionDriverOptions(false));
});
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/OrchardCore.Modules/OrchardCore.Users/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using OrchardCore.Admin.Models;
using OrchardCore.ContentManagement.Metadata.Models;
using OrchardCore.Data;
using OrchardCore.Data.Migration;
using OrchardCore.Deployment;
Expand Down Expand Up @@ -459,6 +460,11 @@ public override void ConfigureServices(IServiceCollection services)
services.AddScoped<IDisplayDriver<User>, CustomUserSettingsDisplayDriver>();
services.AddScoped<IPermissionProvider, CustomUserSettingsPermissions>();
services.AddDeployment<CustomUserSettingsDeploymentSource, CustomUserSettingsDeploymentStep, CustomUserSettingsDeploymentStepDriver>();

services.Configure<ContentTypeDefinitionOptions>(options =>
{
options.Stereotypes.TryAdd("CustomUserSettings", new ContentTypeDefinitionDriverOptions(false));
});
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace OrchardCore.ContentManagement.Metadata.Models;

public class ContentTypeDefinitionDriverOptions
{
public bool ShowCreatable { get; set; }

public bool ShowListable { get; set; }

public bool ShowDraftable { get; set; }

public bool ShowVersionable { get; set; }

public bool ShowSecurable { get; set; }

public ContentTypeDefinitionDriverOptions(bool defaultValue = true)
{
ShowCreatable = defaultValue;
ShowListable = defaultValue;
ShowDraftable = defaultValue;
ShowVersionable = defaultValue;
ShowSecurable = defaultValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Collections.Generic;

namespace OrchardCore.ContentManagement.Metadata.Models;

/// <summary>
/// Offers a method for configuring content type definitions to either display or conceal global settings from appearing on the UI.
/// </summary>
public class ContentTypeDefinitionOptions
Piedone marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// Configure the driver options for all content types that share the same Stereotype.
/// In this dictionary, the 'key' denotes the Stereotype, while the 'value' corresponds to the driver options.
/// </summary>
public Dictionary<string, ContentTypeDefinitionDriverOptions> Stereotypes { get; } = [];

/// <summary>
/// Configure the driver options for each content type.
/// In this dictionary, the 'key' denotes the content type, while the 'value' corresponds to the driver options.
/// </summary>
public Dictionary<string, ContentTypeDefinitionDriverOptions> ContentTypes { get; } = [];
}
Loading