From c2bb83c32109df38e69bc7123af9cf6a1dfc53ca Mon Sep 17 00:00:00 2001 From: Niraj Soni <23270244+ns8482e@users.noreply.github.com> Date: Thu, 15 Feb 2024 08:25:11 -0600 Subject: [PATCH] - Add Blazor to orchard core - Options Editor and ModalDialog in Blazor - Using blazor in PredefinedList --- OrchardCore.sln | 28 +- .../Dependencies.AspNetCore.props | 5 + .../OrchardCore.Cms.Web.csproj | 5 +- src/OrchardCore.Cms.Web/Program.cs | 6 +- .../Properties/launchSettings.json | 1 + .../Directory.Build.props | 10 + .../Directory.Build.targets | 5 + .../OrchardAdminApp.razor | 5 + .../OrchardCore.Admin.Components.csproj | 21 ++ .../_Imports.razor | 1 + .../Initializer.razor | 5 + .../OrchardCore.Admin.WebAssembly.App.csproj | 22 ++ .../Program.cs | 12 + .../_Imports.razor | 9 + .../ColloctedJSComponent.cs | 43 +++ .../ModalDialog.razor | 59 ++++ .../OptionEditor.razor | 309 ++++++++++++++++++ .../OptionEditor.razor.js | 10 + .../OrchardCore.Common.Components.csproj | 19 ++ .../_Imports.razor | 4 + .../OrchardCore.Admin.csproj | 8 +- .../OrchardCore.Admin/Startup.cs | 32 ++ .../OrchardCore.ContentFields.csproj | 1 + ...ldPredefinedListEditorSettings.Edit.cshtml | 61 ++-- .../ResourceManagementOptionsConfiguration.cs | 10 + .../TheAdmin/Views/Layout.cshtml | 8 +- 26 files changed, 669 insertions(+), 30 deletions(-) create mode 100644 src/OrchardCore.Components/Directory.Build.props create mode 100644 src/OrchardCore.Components/Directory.Build.targets create mode 100644 src/OrchardCore.Components/OrchardCore.Admin.Components/OrchardAdminApp.razor create mode 100644 src/OrchardCore.Components/OrchardCore.Admin.Components/OrchardCore.Admin.Components.csproj create mode 100644 src/OrchardCore.Components/OrchardCore.Admin.Components/_Imports.razor create mode 100644 src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/Initializer.razor create mode 100644 src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/OrchardCore.Admin.WebAssembly.App.csproj create mode 100644 src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/Program.cs create mode 100644 src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/_Imports.razor create mode 100644 src/OrchardCore.Components/OrchardCore.Common.Components/ColloctedJSComponent.cs create mode 100644 src/OrchardCore.Components/OrchardCore.Common.Components/ModalDialog.razor create mode 100644 src/OrchardCore.Components/OrchardCore.Common.Components/OptionEditor.razor create mode 100644 src/OrchardCore.Components/OrchardCore.Common.Components/OptionEditor.razor.js create mode 100644 src/OrchardCore.Components/OrchardCore.Common.Components/OrchardCore.Common.Components.csproj create mode 100644 src/OrchardCore.Components/OrchardCore.Common.Components/_Imports.razor diff --git a/OrchardCore.sln b/OrchardCore.sln index a390bc69109..a3695492c63 100644 --- a/OrchardCore.sln +++ b/OrchardCore.sln @@ -511,9 +511,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Search.AzureAI" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Search.AzureAI.Core", "src\OrchardCore\OrchardCore.Search.AzureAI.Core\OrchardCore.Search.AzureAI.Core.csproj", "{E9428DE8-5D81-4359-BF84-31435041FF1A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrchardCore.Media.Indexing.Pdf", "src\OrchardCore.Modules\OrchardCore.Media.Indexing.Pdf\OrchardCore.Media.Indexing.Pdf.csproj", "{95187E6A-5B74-4475-8FEB-758ACD012DCC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Media.Indexing.Pdf", "src\OrchardCore.Modules\OrchardCore.Media.Indexing.Pdf\OrchardCore.Media.Indexing.Pdf.csproj", "{95187E6A-5B74-4475-8FEB-758ACD012DCC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrchardCore.Media.Indexing.OpenXML", "src\OrchardCore.Modules\OrchardCore.Media.Indexing.OpenXML\OrchardCore.Media.Indexing.OpenXML.csproj", "{47777735-7432-4CCA-A8C5-672E9EE65121}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Media.Indexing.OpenXML", "src\OrchardCore.Modules\OrchardCore.Media.Indexing.OpenXML\OrchardCore.Media.Indexing.OpenXML.csproj", "{47777735-7432-4CCA-A8C5-672E9EE65121}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OrchardCore.Components", "OrchardCore.Components", "{7525406F-AEA0-4397-8E6B-3837ABEC2A36}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Admin.Components", "src\OrchardCore.Components\OrchardCore.Admin.Components\OrchardCore.Admin.Components.csproj", "{0734E6A3-5D42-4698-91F1-4068364E8FCC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Admin.WebAssembly.App", "src\OrchardCore.Components\OrchardCore.Admin.WebAssembly.App\OrchardCore.Admin.WebAssembly.App.csproj", "{361B5892-DE24-4249-827E-3D144CC68643}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Common.Components", "src\OrchardCore.Components\OrchardCore.Common.Components\OrchardCore.Common.Components.csproj", "{2C2CD2A9-BFD8-4A9C-A30F-3CA973E734B7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1359,6 +1367,18 @@ Global {47777735-7432-4CCA-A8C5-672E9EE65121}.Debug|Any CPU.Build.0 = Debug|Any CPU {47777735-7432-4CCA-A8C5-672E9EE65121}.Release|Any CPU.ActiveCfg = Release|Any CPU {47777735-7432-4CCA-A8C5-672E9EE65121}.Release|Any CPU.Build.0 = Release|Any CPU + {0734E6A3-5D42-4698-91F1-4068364E8FCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0734E6A3-5D42-4698-91F1-4068364E8FCC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0734E6A3-5D42-4698-91F1-4068364E8FCC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0734E6A3-5D42-4698-91F1-4068364E8FCC}.Release|Any CPU.Build.0 = Release|Any CPU + {361B5892-DE24-4249-827E-3D144CC68643}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {361B5892-DE24-4249-827E-3D144CC68643}.Debug|Any CPU.Build.0 = Debug|Any CPU + {361B5892-DE24-4249-827E-3D144CC68643}.Release|Any CPU.ActiveCfg = Release|Any CPU + {361B5892-DE24-4249-827E-3D144CC68643}.Release|Any CPU.Build.0 = Release|Any CPU + {2C2CD2A9-BFD8-4A9C-A30F-3CA973E734B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C2CD2A9-BFD8-4A9C-A30F-3CA973E734B7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C2CD2A9-BFD8-4A9C-A30F-3CA973E734B7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C2CD2A9-BFD8-4A9C-A30F-3CA973E734B7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1594,6 +1614,10 @@ Global {E9428DE8-5D81-4359-BF84-31435041FF1A} = {F23AC6C2-DE44-4699-999D-3C478EF3D691} {95187E6A-5B74-4475-8FEB-758ACD012DCC} = {90030E85-0C4F-456F-B879-443E8A3F220D} {47777735-7432-4CCA-A8C5-672E9EE65121} = {90030E85-0C4F-456F-B879-443E8A3F220D} + {7525406F-AEA0-4397-8E6B-3837ABEC2A36} = {275E087F-A4E2-4A7B-A924-ED68E3A52086} + {0734E6A3-5D42-4698-91F1-4068364E8FCC} = {7525406F-AEA0-4397-8E6B-3837ABEC2A36} + {361B5892-DE24-4249-827E-3D144CC68643} = {7525406F-AEA0-4397-8E6B-3837ABEC2A36} + {2C2CD2A9-BFD8-4A9C-A30F-3CA973E734B7} = {7525406F-AEA0-4397-8E6B-3837ABEC2A36} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {46A1D25A-78D1-4476-9CBF-25B75E296341} diff --git a/src/OrchardCore.Build/Dependencies.AspNetCore.props b/src/OrchardCore.Build/Dependencies.AspNetCore.props index 213d63860e0..d86f7cebe10 100644 --- a/src/OrchardCore.Build/Dependencies.AspNetCore.props +++ b/src/OrchardCore.Build/Dependencies.AspNetCore.props @@ -42,6 +42,11 @@ + + + + + diff --git a/src/OrchardCore.Cms.Web/OrchardCore.Cms.Web.csproj b/src/OrchardCore.Cms.Web/OrchardCore.Cms.Web.csproj index a5ac7fee774..ecb0407c3ea 100644 --- a/src/OrchardCore.Cms.Web/OrchardCore.Cms.Web.csproj +++ b/src/OrchardCore.Cms.Web/OrchardCore.Cms.Web.csproj @@ -1,4 +1,4 @@ - + @@ -30,10 +30,13 @@ + + + diff --git a/src/OrchardCore.Cms.Web/Program.cs b/src/OrchardCore.Cms.Web/Program.cs index f5e06716d21..dbc1af10d87 100644 --- a/src/OrchardCore.Cms.Web/Program.cs +++ b/src/OrchardCore.Cms.Web/Program.cs @@ -10,7 +10,11 @@ var app = builder.Build(); -if (!app.Environment.IsDevelopment()) +if (app.Environment.IsDevelopment()) +{ + app.UseWebAssemblyDebugging(); +} +else { app.UseExceptionHandler("/Error"); } diff --git a/src/OrchardCore.Cms.Web/Properties/launchSettings.json b/src/OrchardCore.Cms.Web/Properties/launchSettings.json index ef8cc6e703c..e6a7de11e84 100644 --- a/src/OrchardCore.Cms.Web/Properties/launchSettings.json +++ b/src/OrchardCore.Cms.Web/Properties/launchSettings.json @@ -18,6 +18,7 @@ "Kestrel": { "commandName": "Project", "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "launchUrl": "https://localhost:5001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/src/OrchardCore.Components/Directory.Build.props b/src/OrchardCore.Components/Directory.Build.props new file mode 100644 index 00000000000..a49d641582b --- /dev/null +++ b/src/OrchardCore.Components/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + + + $(CommonTargetFrameworks) + + + diff --git a/src/OrchardCore.Components/Directory.Build.targets b/src/OrchardCore.Components/Directory.Build.targets new file mode 100644 index 00000000000..f20824469e8 --- /dev/null +++ b/src/OrchardCore.Components/Directory.Build.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/src/OrchardCore.Components/OrchardCore.Admin.Components/OrchardAdminApp.razor b/src/OrchardCore.Components/OrchardCore.Admin.Components/OrchardAdminApp.razor new file mode 100644 index 00000000000..dfe4bf31dc4 --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Admin.Components/OrchardAdminApp.razor @@ -0,0 +1,5 @@ +

Future Admin App in Blazor

+ +@code { + +} diff --git a/src/OrchardCore.Components/OrchardCore.Admin.Components/OrchardCore.Admin.Components.csproj b/src/OrchardCore.Components/OrchardCore.Admin.Components/OrchardCore.Admin.Components.csproj new file mode 100644 index 00000000000..73a3385b13d --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Admin.Components/OrchardCore.Admin.Components.csproj @@ -0,0 +1,21 @@ + + + + $(CommonTargetFrameworks) + enable + enable + + + + + + + + + + + + + + + diff --git a/src/OrchardCore.Components/OrchardCore.Admin.Components/_Imports.razor b/src/OrchardCore.Components/OrchardCore.Admin.Components/_Imports.razor new file mode 100644 index 00000000000..77285129dab --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Admin.Components/_Imports.razor @@ -0,0 +1 @@ +@using Microsoft.AspNetCore.Components.Web diff --git a/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/Initializer.razor b/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/Initializer.razor new file mode 100644 index 00000000000..c863efaac91 --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/Initializer.razor @@ -0,0 +1,5 @@ +

Initializer

+ +@code { + +} diff --git a/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/OrchardCore.Admin.WebAssembly.App.csproj b/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/OrchardCore.Admin.WebAssembly.App.csproj new file mode 100644 index 00000000000..9c989392163 --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/OrchardCore.Admin.WebAssembly.App.csproj @@ -0,0 +1,22 @@ + + + + $(CommonTargetFrameworks) + + enable + enable + true + Default + + + + + + + + + + + + + diff --git a/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/Program.cs b/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/Program.cs new file mode 100644 index 00000000000..2fd586a0722 --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/Program.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Components.Web; +using Microsoft.AspNetCore.Components.WebAssembly.Hosting; +using OrchardCore.Admin.WebAssembly.App; +using OrchardCore.Common.Components; + +var builder = WebAssemblyHostBuilder.CreateDefault(args); +builder.RootComponents.RegisterCustomElement("option-editor"); +builder.RootComponents.RegisterCustomElement("init"); +builder.Services.AddScoped(); + + +await builder.Build().RunAsync(); diff --git a/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/_Imports.razor b/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/_Imports.razor new file mode 100644 index 00000000000..8a2c0c8c0a4 --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Admin.WebAssembly.App/_Imports.razor @@ -0,0 +1,9 @@ +@using System.Net.Http +@using System.Net.Http.Json +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using static Microsoft.AspNetCore.Components.Web.RenderMode +@using Microsoft.AspNetCore.Components.Web.Virtualization +@using Microsoft.JSInterop +@using OrchardCore.Admin.WebAssembly.App diff --git a/src/OrchardCore.Components/OrchardCore.Common.Components/ColloctedJSComponent.cs b/src/OrchardCore.Components/OrchardCore.Common.Components/ColloctedJSComponent.cs new file mode 100644 index 00000000000..9725457134a --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Common.Components/ColloctedJSComponent.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; + +namespace OrchardCore.Common.Components; + +public class ColloctedJSComponent : ComponentBase, IAsyncDisposable +{ + [Inject] + private IJSRuntime? JS { get; set; } + + [Parameter] + public bool RaiseDomEvents { get; set; } + + protected IJSObjectReference? JSModule { get; private set; } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + var ns = GetType().Namespace; + var cmp = GetType().Name; + if (JS is not null) + { + JSModule = await JS.InvokeAsync("import", + $"./_content/{ns}/{cmp}.razor.js"); + } + } + } + + async ValueTask IAsyncDisposable.DisposeAsync() + { + if (JSModule is not null) + { + await JSModule.DisposeAsync(); + } + } + +} diff --git a/src/OrchardCore.Components/OrchardCore.Common.Components/ModalDialog.razor b/src/OrchardCore.Components/OrchardCore.Common.Components/ModalDialog.razor new file mode 100644 index 00000000000..8ff6dfd03b0 --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Common.Components/ModalDialog.razor @@ -0,0 +1,59 @@ + + +@if (ShowBackdrop && IsOpen) +{ + +} + +@code { + + [Parameter] + public string? Title { get; set; } + [Parameter] + public bool ShowBackdrop { get; set; } + [Parameter] + public RenderFragment? Body { get; set; } + [Parameter] + public RenderFragment? Actions { get; set; } + + + public bool IsOpen { get; set; } + + string IsOpenClass { get; set; } = string.Empty; + + string IsOpenDisplayStyle { get; set; } = "none"; + + public async Task Open() + { + IsOpenDisplayStyle = "block"; + IsOpen = true; + await Task.Delay(100);//Delay allows bootstrap to perform nice fade animation + IsOpenClass = "show"; + StateHasChanged(); + + } + + public async Task Close() + { + IsOpenClass = ""; + IsOpen = false; + await Task.Delay(250);//Delay allows bootstrap to perform nice fade animation + IsOpenDisplayStyle = "none"; + StateHasChanged(); + } +} diff --git a/src/OrchardCore.Components/OrchardCore.Common.Components/OptionEditor.razor b/src/OrchardCore.Components/OrchardCore.Common.Components/OptionEditor.razor new file mode 100644 index 00000000000..ac70feb63ad --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Common.Components/OptionEditor.razor @@ -0,0 +1,309 @@ +@using System.Text.Json +@using System.ComponentModel.DataAnnotations +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.JSInterop + +@inherits ColloctedJSComponent + + + + + + + + + + + + + + + + + @for (var keyIndex = 0; keyIndex < Options!.Count; keyIndex++) + { + var option = Options![keyIndex]; + + + + + + + + + + + } + + + + + + + +
Option LabelValueDefault?
+ + +
+ + +
+
+ + +
+ +
+
+ +
+ + + + +
+ + + @("A JSON representation of the allowed values, e.g. {0}") @("[{ name: 'First option', value: 'option1' }, { name: 'Second option', value: 'option2' } ]") +
+
+ + + @("(Optional) The default to assign to the text field.") +
+ + + + + +
+ +@code { + [Parameter] + public string? OptionsJson { get; set; } + + [Parameter] + public string? DefaultValue { get; set; } + + + ElementReference tableElement; + + private ModalDialog? Modal { get; set; } + + private List? Options { get; set; } + private string? OptionsJsonInternal { get; set; } + private string? DefaultValueInternal { get; set; } + private string IsInvalidClass { get; set; } = string.Empty; + private const string OptionsJsonEmpty = "[]"; + + + + private void SetOptionsEmpty() + { + Options = new List(); + OptionsJsonInternal = OptionsJsonEmpty; + } + + private bool TryJsonValid(string? json) + { + if (string.IsNullOrWhiteSpace(json)) + return false; + try + { + _ = JsonSerializer.Deserialize>(json, new JsonSerializerOptions(JsonSerializerDefaults.Web)); + return true; + } + catch (JsonException) + { + return false; + } + } + + private bool TryUpdateOptions(string? json) + { + if (string.IsNullOrWhiteSpace(json)) + return false; + try + { + + var updated = JsonSerializer.Deserialize>(json, new JsonSerializerOptions(JsonSerializerDefaults.Web)); + if (updated != null && !Options!.Equals(updated)) + { + Options.Clear(); + Options.AddRange(updated!); + } + return true; + } + catch (JsonException ex) + { + Console.WriteLine(ex); + return false; + } + } + + private bool TryUpdateOptionsJson(List? options) + { + if (options is null) + return false; + try + { + OptionsJsonInternal = JsonSerializer.Serialize(options!, new JsonSerializerOptions(JsonSerializerDefaults.Web)); + return true; + } + catch (JsonException ex) + { + Console.WriteLine(ex); + return false; + } + } + + private async Task OptionItemChangeAsync(Action update) + { + update(); + TryUpdateOptionsJson(Options); + await TriggerEventAsync(); + } + + + protected override Task OnInitializedAsync() + { + SetOptionsEmpty(); + return base.OnInitializedAsync(); + } + + + protected override Task OnParametersSetAsync() + { + if (!string.IsNullOrWhiteSpace(OptionsJson)) + { + if (TryUpdateOptions(OptionsJson)) + { + OptionsJsonInternal = OptionsJson; + } + } + + if (!string.IsNullOrWhiteSpace(DefaultValue)) + DefaultValueInternal = DefaultValue.Trim(); + else + DefaultValueInternal = string.Empty; + + return base.OnParametersSetAsync(); + } + private Task AddNewOptionAsync() + { + Options!.Add(new OptionsModel()); + TryUpdateOptionsJson(Options); + return TriggerEventAsync(); + } + + private Task RemoveOptionAsync(OptionsModel option) + { + Options!.Remove(option); + TryUpdateOptionsJson(Options); + return TriggerEventAsync(); + } + + async Task DefaultOptionChangedAsync(ChangeEventArgs args) + { + DefaultValueInternal = args.Value?.ToString(); + await TriggerEventAsync(); + } + + async Task OptionsJsonChangedAsync(ChangeEventArgs e) + { + var newVal = e.Value?.ToString(); + if (TryJsonValid(newVal)) + { + IsInvalidClass = ""; + OptionsJsonInternal = newVal; + } + else + { + IsInvalidClass = "is-invalid"; + } + + await Task.CompletedTask; + } + + async Task SubmitAsync() + { + if (TryUpdateOptions(OptionsJsonInternal)) + { + await Modal!.Close(); + await TriggerEventAsync(); + StateHasChanged(); + } + } + + async Task CancelAsync() + { + TryUpdateOptionsJson(Options); + await Modal!.Close(); + } + + public class OptionsModel + { + [Required(AllowEmptyStrings = false, ErrorMessage = "Provide option name")] + public string? Name { get; set; } + [Required(AllowEmptyStrings = false, ErrorMessage = "Provide option value")] + public string? Value { get; set; } + } + + + int currentIndex; + + void StartDrag(OptionsModel item) + => currentIndex = GetIndex(item); + + int GetIndex(OptionsModel item) + => Options!.FindIndex(a => string.Equals(a.Name, item.Name)); + + async Task Drop(OptionsModel item) + { + if (item != null) + { + var index = GetIndex(item); + + // get current item + var current = Options![currentIndex]; + + // remove game from current index + Options!.RemoveAt(currentIndex); + Options!.Insert(index, current); + + // update current selection + currentIndex = index; + + TryUpdateOptionsJson(Options); + await TriggerEventAsync(); + } + else + { + await Task.CompletedTask; + } + } + + async Task TriggerEventAsync() + { + StateHasChanged(); + if (JSModule is not null) + { + await JSModule.InvokeVoidAsync("optionsChanged", tableElement, OptionsJsonInternal, DefaultValueInternal); + } + } + +} diff --git a/src/OrchardCore.Components/OrchardCore.Common.Components/OptionEditor.razor.js b/src/OrchardCore.Components/OrchardCore.Common.Components/OptionEditor.razor.js new file mode 100644 index 00000000000..ae59baa0fa1 --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Common.Components/OptionEditor.razor.js @@ -0,0 +1,10 @@ +export function optionsChanged(element, jsonValue, defaultValue) { + const evt = new CustomEvent("blazor:optionsChanged", { + bubbles: true, + detail: { + options: jsonValue, + defaultValue: defaultValue + } + }); + element.dispatchEvent(evt); +} diff --git a/src/OrchardCore.Components/OrchardCore.Common.Components/OrchardCore.Common.Components.csproj b/src/OrchardCore.Components/OrchardCore.Common.Components/OrchardCore.Common.Components.csproj new file mode 100644 index 00000000000..2dc00f31670 --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Common.Components/OrchardCore.Common.Components.csproj @@ -0,0 +1,19 @@ + + + + $(CommonTargetFrameworks) + enable + enable + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/OrchardCore.Components/OrchardCore.Common.Components/_Imports.razor b/src/OrchardCore.Components/OrchardCore.Common.Components/_Imports.razor new file mode 100644 index 00000000000..d96cabe770a --- /dev/null +++ b/src/OrchardCore.Components/OrchardCore.Common.Components/_Imports.razor @@ -0,0 +1,4 @@ +@using Microsoft.AspNetCore.Components.Web +@using System.Text.Json + + diff --git a/src/OrchardCore.Modules/OrchardCore.Admin/OrchardCore.Admin.csproj b/src/OrchardCore.Modules/OrchardCore.Admin/OrchardCore.Admin.csproj index 0c2da034003..cb6f73eb467 100644 --- a/src/OrchardCore.Modules/OrchardCore.Admin/OrchardCore.Admin.csproj +++ b/src/OrchardCore.Modules/OrchardCore.Admin/OrchardCore.Admin.csproj @@ -14,8 +14,12 @@ - + + + + + @@ -24,5 +28,5 @@ - +
diff --git a/src/OrchardCore.Modules/OrchardCore.Admin/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Admin/Startup.cs index 7d08f46eabb..5298051afc9 100644 --- a/src/OrchardCore.Modules/OrchardCore.Admin/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Admin/Startup.cs @@ -1,14 +1,19 @@ using System; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Rendering; +using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using OrchardCore.Admin.Components; using OrchardCore.Admin.Controllers; using OrchardCore.Admin.Drivers; using OrchardCore.Admin.Models; +using OrchardCore.Common.Components; using OrchardCore.DisplayManagement.Handlers; using OrchardCore.DisplayManagement.Theming; using OrchardCore.Environment.Shell.Configuration; @@ -85,6 +90,33 @@ public override void ConfigureServices(IServiceCollection services) } } + + public class AdminComponentsStartup : StartupBase + { + public override int Order => 1; + + public override void ConfigureServices(IServiceCollection services) + { + services.AddRazorComponents() + .AddInteractiveServerComponents() + .AddInteractiveWebAssemblyComponents(); + ; + + } + + public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) + { + app.UseStaticFiles(); + routes.MapRazorComponents() + .AddInteractiveServerRenderMode() + .AddInteractiveWebAssemblyRenderMode() + .AddAdditionalAssemblies(typeof(OptionEditor).Assembly) + ; + + } + } + + [RequireFeatures("OrchardCore.Deployment")] public class DeploymentStartup : StartupBase { diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj b/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj index d50cedac85f..782a30f5356 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj @@ -15,6 +15,7 @@ + diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/Views/TextFieldPredefinedListEditorSettings.Edit.cshtml b/src/OrchardCore.Modules/OrchardCore.ContentFields/Views/TextFieldPredefinedListEditorSettings.Edit.cshtml index 448266b0a1b..345aa6d5c43 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/Views/TextFieldPredefinedListEditorSettings.Edit.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/Views/TextFieldPredefinedListEditorSettings.Edit.cshtml @@ -1,13 +1,20 @@ +@using Microsoft.AspNetCore.Components +@using Microsoft.AspNetCore.Components.Endpoints +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.Extensions.DependencyInjection +@using OrchardCore.Admin.Components +@using OrchardCore.Common.Components @using OrchardCore.ContentFields.Settings @model OrchardCore.ContentFields.ViewModels.PredefinedListSettingsViewModel - +@* - - - + *@ +@* + *@
-
-
- - -
-
+
+
+ + +
+
-
-
- - - - -
-
+
+
+ + @* + *@ + + +
+
+ \ No newline at end of file diff --git a/src/OrchardCore.Modules/OrchardCore.Resources/ResourceManagementOptionsConfiguration.cs b/src/OrchardCore.Modules/OrchardCore.Resources/ResourceManagementOptionsConfiguration.cs index d29aa803543..f8f6e1cbc9b 100644 --- a/src/OrchardCore.Modules/OrchardCore.Resources/ResourceManagementOptionsConfiguration.cs +++ b/src/OrchardCore.Modules/OrchardCore.Resources/ResourceManagementOptionsConfiguration.cs @@ -500,6 +500,16 @@ ResourceManifest BuildManifest() .SetDependencies("monaco-loader") .SetVersion(MonacoEditorVersion); + manifest + .DefineScript("blazor-custom-elements") + .SetUrl("~/_content/Microsoft.AspNetCore.Components.CustomElements/Microsoft.AspNetCore.Components.CustomElements.lib.module.js") + .SetVersion("8.0.1"); + + manifest + .DefineScript("blazor-web-js") + .SetUrl("~/_framework/blazor.web.js") + .SetVersion("8.0.1"); + return manifest; } diff --git a/src/OrchardCore.Themes/TheAdmin/Views/Layout.cshtml b/src/OrchardCore.Themes/TheAdmin/Views/Layout.cshtml index f1f5e2e92c2..1b446466215 100644 --- a/src/OrchardCore.Themes/TheAdmin/Views/Layout.cshtml +++ b/src/OrchardCore.Themes/TheAdmin/Views/Layout.cshtml @@ -21,8 +21,8 @@ - - + + @@ -39,10 +39,13 @@ } + + @await RenderSectionAsync("HeadMeta", required: false) +
@@ -91,5 +94,6 @@
+