Merge pull request #5577 from zyhfish/task/radzen-text-editor
implement radzen text editor.
This commit is contained in:
@ -1,8 +1,10 @@
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Oqtane.Interfaces;
|
||||
using Oqtane.Providers;
|
||||
using Oqtane.Services;
|
||||
using Oqtane.Shared;
|
||||
using Radzen;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
@ -23,7 +25,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<SiteState>();
|
||||
services.AddScoped<IInstallationService, InstallationService>();
|
||||
services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>();
|
||||
services.AddScoped<IThemeService, ThemeService>();
|
||||
services.AddScoped<IThemeService, Oqtane.Services.ThemeService>();
|
||||
services.AddScoped<IAliasService, AliasService>();
|
||||
services.AddScoped<ITenantService, TenantService>();
|
||||
services.AddScoped<ISiteService, SiteService>();
|
||||
@ -39,7 +41,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<ILogService, LogService>();
|
||||
services.AddScoped<IJobService, JobService>();
|
||||
services.AddScoped<IJobLogService, JobLogService>();
|
||||
services.AddScoped<INotificationService, NotificationService>();
|
||||
services.AddScoped<INotificationService, Oqtane.Services.NotificationService>();
|
||||
services.AddScoped<IFolderService, FolderService>();
|
||||
services.AddScoped<IFileService, FileService>();
|
||||
services.AddScoped<ISiteTemplateService, SiteTemplateService>();
|
||||
@ -59,6 +61,12 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
// providers
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.TextAreaTextEditor>();
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.RadzenTextEditor>();
|
||||
|
||||
services.AddRadzenComponents();
|
||||
|
||||
var localizer = services.BuildServiceProvider().GetService<IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor>>();
|
||||
Oqtane.Modules.Controls.RadzenEditorDefinitions.Localizer = localizer;
|
||||
|
||||
return services;
|
||||
}
|
||||
|
45
Oqtane.Client/Modules/Controls/FileManagerDialog.razor
Normal file
45
Oqtane.Client/Modules/Controls/FileManagerDialog.razor
Normal file
@ -0,0 +1,45 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@using System.IO
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
@inject DialogService DialogService
|
||||
@inject IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor> Localizer
|
||||
|
||||
<div class="d-flex">
|
||||
<FileManager @ref="_fileManager" Filter="@Filters" />
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage>
|
||||
</div>
|
||||
<div class="mt-1 text-end">
|
||||
<RadzenButton Text="OK" Click=@OnOkClick />
|
||||
<RadzenButton Text="Cancel" Click=@OnCancelClick ButtonStyle="ButtonStyle.Secondary" />
|
||||
</div>
|
||||
@code {
|
||||
private FileManager _fileManager;
|
||||
private string _message = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string Filters { get; set; }
|
||||
|
||||
private void OnCancelClick()
|
||||
{
|
||||
DialogService.Close(null);
|
||||
}
|
||||
|
||||
private void OnOkClick()
|
||||
{
|
||||
_message = string.Empty;
|
||||
var file = _fileManager.GetFile();
|
||||
if (file != null)
|
||||
{
|
||||
var result = $"<img src=\"{file.Url}\" style=\"max-width: 100%\" alt=\"{file.Name}\" />";
|
||||
DialogService.Close(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
_message = Localizer["Message.Require.Image"];
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
85
Oqtane.Client/Modules/Controls/RadzenEditorDefinitions.cs
Normal file
85
Oqtane.Client/Modules/Controls/RadzenEditorDefinitions.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Oqtane.Modules.Controls
|
||||
{
|
||||
public sealed class RadzenEditorDefinitions
|
||||
{
|
||||
public static IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor> Localizer { get; internal set; }
|
||||
|
||||
public const string TransparentBackgroundColor = "rgba(0, 0, 0, 0)";
|
||||
|
||||
public const string LightBackgroundColor = "rgba(255, 255, 255, 1)";
|
||||
|
||||
public const string DarkBackgroundColor = "rgba(0, 0, 0, 1)";
|
||||
|
||||
public const string DefaultTheme = "default";
|
||||
|
||||
public const string DefaultBackground = "Default";
|
||||
|
||||
public static readonly IDictionary<string, Func<RenderTreeBuilder, int, int>> ToolbarItems = new Dictionary<string, Func<RenderTreeBuilder, int, int>>()
|
||||
{
|
||||
{ "AlignCenter", (builder, sequence) => CreateFragment(builder, sequence, "AlignCenter", "RadzenHtmlEditorAlignCenter") },
|
||||
{ "AlignLeft", (builder, sequence) => CreateFragment(builder, sequence, "AlignLeft", "RadzenHtmlEditorAlignLeft") },
|
||||
{ "AlignRight", (builder, sequence) => CreateFragment(builder, sequence, "AlignRight", "RadzenHtmlEditorAlignRight") },
|
||||
{ "Background", (builder, sequence) => CreateFragment(builder, sequence, "Background", "RadzenHtmlEditorBackground") },
|
||||
{ "Color", (builder, sequence) => CreateFragment(builder, sequence, "Color", "RadzenHtmlEditorColor") },
|
||||
{ "FontName", (builder, sequence) => CreateFragment(builder, sequence, "FontName", "RadzenHtmlEditorFontName") },
|
||||
{ "FontSize", (builder, sequence) => CreateFragment(builder, sequence, "FontSize", "RadzenHtmlEditorFontSize") },
|
||||
{ "FormatBlock", (builder, sequence) => CreateFragment(builder, sequence, "FormatBlock", "RadzenHtmlEditorFormatBlock") },
|
||||
{ "Indent", (builder, sequence) => CreateFragment(builder, sequence, "Indent", "RadzenHtmlEditorIndent") },
|
||||
{ "InsertImage", (builder, sequence) => CreateFragment(builder, sequence, "InsertImage", "RadzenHtmlEditorCustomTool", "InsertImage", "image") },
|
||||
{ "Italic", (builder, sequence) => CreateFragment(builder, sequence, "Italic", "RadzenHtmlEditorItalic") },
|
||||
{ "Justify", (builder, sequence) => CreateFragment(builder, sequence, "Justify", "RadzenHtmlEditorJustify") },
|
||||
{ "Link", (builder, sequence) => CreateFragment(builder, sequence, "Link", "RadzenHtmlEditorLink") },
|
||||
{ "OrderedList", (builder, sequence) => CreateFragment(builder, sequence, "OrderedList", "RadzenHtmlEditorOrderedList") },
|
||||
{ "Outdent", (builder, sequence) => CreateFragment(builder, sequence, "Outdent", "RadzenHtmlEditorOutdent") },
|
||||
{ "Redo", (builder, sequence) => CreateFragment(builder, sequence, "Redo", "RadzenHtmlEditorRedo") },
|
||||
{ "RemoveFormat", (builder, sequence) => CreateFragment(builder, sequence, "RemoveFormat", "RadzenHtmlEditorRemoveFormat") },
|
||||
{ "Separator", (builder, sequence) => CreateFragment(builder, sequence, "Separator", "RadzenHtmlEditorSeparator") },
|
||||
{ "Source", (builder, sequence) => CreateFragment(builder, sequence, "Source", "RadzenHtmlEditorSource") },
|
||||
{ "StrikeThrough", (builder, sequence) => CreateFragment(builder, sequence, "StrikeThrough", "RadzenHtmlEditorStrikeThrough") },
|
||||
{ "Subscript", (builder, sequence) => CreateFragment(builder, sequence, "Subscript", "RadzenHtmlEditorSubscript") },
|
||||
{ "Superscript", (builder, sequence) => CreateFragment(builder, sequence, "Superscript", "RadzenHtmlEditorSuperscript") },
|
||||
{ "Underline", (builder, sequence) => CreateFragment(builder, sequence, "Underline", "RadzenHtmlEditorUnderline") },
|
||||
{ "Undo", (builder, sequence) => CreateFragment(builder, sequence, "Undo", "RadzenHtmlEditorUndo") },
|
||||
{ "Unlink", (builder, sequence) => CreateFragment(builder, sequence, "Unlink", "RadzenHtmlEditorUnlink") },
|
||||
{ "UnorderedList", (builder, sequence) => CreateFragment(builder, sequence, "UnorderedList", "RadzenHtmlEditorUnorderedList") },
|
||||
};
|
||||
|
||||
public static readonly string DefaultToolbarItems = "Undo,Redo,Separator,FontName,FontSize,FormatBlock,Bold,Italic,Underline,StrikeThrough,Separator,AlignLeft,AlignCenter,AlignRight,Justify,Separator,Indent,Outdent,UnorderedList,OrderedList,Separator,Color,Background,RemoveFormat,Separator,Subscript,Superscript,Separator,Link,Unlink,InsertImage,Separator,Source";
|
||||
|
||||
private static int CreateFragment(RenderTreeBuilder builder, int sequence, string name, string typeName, string commaneName = "", string icon = "")
|
||||
{
|
||||
var fullTypeName = $"Radzen.Blazor.{typeName}, Radzen.Blazor";
|
||||
var type = Type.GetType(fullTypeName);
|
||||
if (type != null)
|
||||
{
|
||||
var title = Localizer[$"{name}.Title"];
|
||||
var placeholder = Localizer[$"{name}.Placeholder"];
|
||||
builder.OpenComponent(sequence++, type);
|
||||
if (!string.IsNullOrEmpty(title) && title != $"{name}.Title" && type.GetProperty("Title") != null)
|
||||
{
|
||||
builder.AddAttribute(sequence++, "Title", title);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(placeholder) && placeholder != $"{name}.Placeholder" && type.GetProperty("Placeholder") != null)
|
||||
{
|
||||
builder.AddAttribute(sequence++, "Placeholder", placeholder);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(commaneName) && type.GetProperty("CommandName") != null)
|
||||
{
|
||||
builder.AddAttribute(sequence++, "CommandName", commaneName);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(icon) && type.GetProperty("Icon") != null)
|
||||
{
|
||||
builder.AddAttribute(sequence++, "Icon", icon);
|
||||
}
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
}
|
||||
}
|
60
Oqtane.Client/Modules/Controls/RadzenEditorInterop.cs
Normal file
60
Oqtane.Client/Modules/Controls/RadzenEditorInterop.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Modules.Controls
|
||||
{
|
||||
public class RadzenEditorInterop
|
||||
{
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
|
||||
public RadzenEditorInterop(IJSRuntime jsRuntime)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
public Task Initialize(ElementReference editor)
|
||||
{
|
||||
try
|
||||
{
|
||||
_jsRuntime.InvokeVoidAsync("Oqtane.RadzenTextEditor.initialize", editor);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SetBackgroundColor(ElementReference editor, string color)
|
||||
{
|
||||
try
|
||||
{
|
||||
_jsRuntime.InvokeVoidAsync(
|
||||
"Oqtane.RadzenTextEditor.setBackgroundColor",
|
||||
editor, color);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task UpdateDialogLayout(ElementReference editor)
|
||||
{
|
||||
try
|
||||
{
|
||||
_jsRuntime.InvokeVoidAsync("Oqtane.RadzenTextEditor.updateDialogLayout", editor);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
11
Oqtane.Client/Modules/Controls/RadzenEditorSetting.cs
Normal file
11
Oqtane.Client/Modules/Controls/RadzenEditorSetting.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Oqtane.Modules.Controls
|
||||
{
|
||||
public class RadzenEditorSetting
|
||||
{
|
||||
public string Theme { get; set; }
|
||||
|
||||
public string Background { get; set; }
|
||||
|
||||
public string ToolbarItems { get; set; }
|
||||
}
|
||||
}
|
193
Oqtane.Client/Modules/Controls/RadzenTextEditor.razor
Normal file
193
Oqtane.Client/Modules/Controls/RadzenTextEditor.razor
Normal file
@ -0,0 +1,193 @@
|
||||
@using Microsoft.Extensions.Configuration
|
||||
@using Oqtane.Interfaces
|
||||
@using System.Text.RegularExpressions
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleControlBase
|
||||
@implements ITextEditor
|
||||
@implements IDisposable
|
||||
@inject Radzen.ThemeService ThemeService
|
||||
@inject IRadzenEditorSettingService EditorSettingService
|
||||
@inject DialogService DialogService
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor> Localizer
|
||||
|
||||
<RadzenTheme Theme="@RadzenEditorDefinitions.DefaultTheme" />
|
||||
<RadzenComponents />
|
||||
<RadzenHtmlEditor @ref="_editor" Visible="_visible" Placeholder="@Placeholder" style="@($"height: {Height}px;")"
|
||||
@bind-Value="_value" Execute="OnExecute" class="rz-text-editor">
|
||||
<ChildContent>
|
||||
@_toolbar
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
{
|
||||
<RadzenHtmlEditorCustomTool CommandName="Settings" Icon="settings" Title="@Localizer["Settings"]" />
|
||||
}
|
||||
</ChildContent>
|
||||
|
||||
</RadzenHtmlEditor>
|
||||
|
||||
@code {
|
||||
private Oqtane.Modules.Controls.RadzenEditorInterop _interop;
|
||||
private RadzenHtmlEditor _editor;
|
||||
private string _value;
|
||||
private bool _visible = false;
|
||||
private string _theme;
|
||||
private string _background;
|
||||
private IList<string> _toolbarItems;
|
||||
private RenderFragment _toolbar;
|
||||
|
||||
[Parameter]
|
||||
public string Placeholder { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool ReadOnly { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int Height { get; set; } = 450;
|
||||
|
||||
public string Name => "RadzenTextEditor";
|
||||
|
||||
public override List<Resource> Resources { get; set; } = new List<Resource>()
|
||||
{
|
||||
new Resource { ResourceType = ResourceType.Script, Url = "/_content/Radzen.Blazor/Radzen.Blazor.js", Location = ResourceLocation.Head },
|
||||
new Resource { ResourceType = ResourceType.Script, Url = "/Modules/Oqtane.RadzenTextEditor/Resources/js/Interops/RadzenTextEditorInterop.js", Location = ResourceLocation.Head },
|
||||
};
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_interop = new Oqtane.Modules.Controls.RadzenEditorInterop(JSRuntime);
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
if (firstRender)
|
||||
{
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.IncludeLink("", "stylesheet", $"/Modules/Oqtane.RadzenTextEditor/Resources/css/radzentexteditor.override.css", "text/css", "", "", "");
|
||||
await LoadSettings();
|
||||
_visible = true;
|
||||
StateHasChanged();
|
||||
|
||||
await _interop.Initialize(_editor.Element);
|
||||
|
||||
if (!string.IsNullOrEmpty(_theme))
|
||||
{
|
||||
ThemeService.SetTheme(_theme);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_background))
|
||||
{
|
||||
var backgroundColor = RadzenEditorDefinitions.TransparentBackgroundColor;
|
||||
switch (_background)
|
||||
{
|
||||
case "Light":
|
||||
backgroundColor = RadzenEditorDefinitions.LightBackgroundColor;
|
||||
break;
|
||||
case "Dark":
|
||||
backgroundColor = RadzenEditorDefinitions.DarkBackgroundColor;
|
||||
break;
|
||||
}
|
||||
await _interop.SetBackgroundColor(_editor.Element, backgroundColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize(string content)
|
||||
{
|
||||
_value = !string.IsNullOrEmpty(content) ? content : string.Empty;
|
||||
DialogService.OnOpen += OnDialogOpened;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (DialogService != null)
|
||||
{
|
||||
DialogService.OnOpen -= OnDialogOpened;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> GetContent()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
private async Task LoadSettings()
|
||||
{
|
||||
var scope = await EditorSettingService.GetSettingScopeAsync(ModuleState.ModuleId);
|
||||
var editorSetting = scope == 1
|
||||
? await EditorSettingService.LoadSettingsFromModuleAsync(ModuleState.ModuleId)
|
||||
: await EditorSettingService.LoadSettingsFromSiteAsync(PageState.Site.SiteId);
|
||||
|
||||
_theme = editorSetting.Theme;
|
||||
_background = editorSetting.Background;
|
||||
_toolbarItems = editorSetting.ToolbarItems.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList();
|
||||
_toolbar = SetupToolbarItems();
|
||||
}
|
||||
|
||||
private RenderFragment SetupToolbarItems()
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
var sequence = 0;
|
||||
foreach (var item in _toolbarItems)
|
||||
{
|
||||
if (RadzenEditorDefinitions.ToolbarItems.ContainsKey(item))
|
||||
{
|
||||
sequence = RadzenEditorDefinitions.ToolbarItems[item](builder, sequence);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private async Task OnExecute(HtmlEditorExecuteEventArgs args)
|
||||
{
|
||||
if (args.CommandName == "InsertImage")
|
||||
{
|
||||
await InsertImage(args.Editor);
|
||||
}
|
||||
else if (args.CommandName == "Settings")
|
||||
{
|
||||
await UpdateSettings(args.Editor);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InsertImage(RadzenHtmlEditor editor)
|
||||
{
|
||||
await editor.SaveSelectionAsync();
|
||||
|
||||
var result = await DialogService.OpenAsync<FileManagerDialog>(Localizer["DialogTitle.SelectImage"], new Dictionary<string, object>
|
||||
{
|
||||
{ "Filters", PageState.Site.ImageFiles }
|
||||
});
|
||||
|
||||
await editor.RestoreSelectionAsync();
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
await editor.ExecuteCommandAsync(HtmlEditorCommands.InsertHtml, result);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateSettings(RadzenHtmlEditor editor)
|
||||
{
|
||||
await editor.SaveSelectionAsync();
|
||||
|
||||
var result = await DialogService.OpenAsync<SettingsDialog>(Localizer["Settings"], null, new DialogOptions { Width = "650px" });
|
||||
if (result == true)
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigationManager.Uri);
|
||||
}
|
||||
|
||||
await editor.RestoreSelectionAsync();
|
||||
}
|
||||
|
||||
private async void OnDialogOpened(string title, Type componentType, Dictionary<string, object> parameters, DialogOptions options)
|
||||
{
|
||||
await _interop.UpdateDialogLayout(_editor.Element);
|
||||
}
|
||||
}
|
222
Oqtane.Client/Modules/Controls/SettingsDialog.razor
Normal file
222
Oqtane.Client/Modules/Controls/SettingsDialog.razor
Normal file
@ -0,0 +1,222 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@using System.IO
|
||||
@using Radzen
|
||||
@using Radzen.Blazor
|
||||
@inherits ModuleControlBase
|
||||
@inject DialogService DialogService
|
||||
@inject Radzen.ThemeService ThemeService
|
||||
@inject ISettingService SettingService
|
||||
@inject IRadzenEditorSettingService EditorSettingService
|
||||
@inject IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor> Localizer
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-3">
|
||||
@Localizer["Scope"]
|
||||
</div>
|
||||
<div class="col-12 col-sm-9">
|
||||
<RadzenRadioButtonList @bind-Value="@_settingScope" TValue="int" Change="OnScopeChanged">
|
||||
<Items>
|
||||
<RadzenRadioButtonListItem Text="@Localizer["Site"]" Value="0" />
|
||||
<RadzenRadioButtonListItem Text="@Localizer["Module"]" Value="1" />
|
||||
</Items>
|
||||
</RadzenRadioButtonList>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-12 col-sm-3">
|
||||
@Localizer["Theme"]
|
||||
</div>
|
||||
<div class="col-12 col-sm-9">
|
||||
<RadzenDropDown @bind-Value="_theme" TValue="string" Data="@_themes" Style="width: 100%;">
|
||||
<Template>
|
||||
<span>@Localizer[$"theme.{context}"]</span>
|
||||
</Template>
|
||||
</RadzenDropDown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-12 col-sm-3">
|
||||
@Localizer["Background"]
|
||||
</div>
|
||||
<div class="col-12 col-sm-9">
|
||||
<RadzenDropDown @bind-Value="_background" TValue="string" Data="_backgroundColors" Style="width: 100%;">
|
||||
<Template>
|
||||
<span>@Localizer[context]</span>
|
||||
</Template>
|
||||
</RadzenDropDown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-12 col-sm-3">
|
||||
@Localizer["Toolbar"]
|
||||
</div>
|
||||
<div class="col-12 col-sm-9">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-7">
|
||||
<RadzenDropDown TValue="string" @bind-Value="_addToolbarItem" Data="@RadzenEditorDefinitions.ToolbarItems.Keys" Style="width: 100%;">
|
||||
</RadzenDropDown>
|
||||
</div>
|
||||
<div class="col-12 col-sm-5 text-end">
|
||||
<button type="button" class="btn btn-primary" @onclick="AddToolbarItem">@Localizer["Add"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="ResetToolbarItem">@Localizer["Reset"]</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2" style="max-height: 500px; overflow-y: scroll;">
|
||||
<div class="col">
|
||||
<RadzenDropZoneContainer TItem="ToolbarItem" Data="_toolbarItems"
|
||||
ItemSelector="@((i, z) => true)"
|
||||
CanDrop="@((i) => true)"
|
||||
Drop="OnToolbarItemDrop"
|
||||
ItemRender="OnToolbarItemRender">
|
||||
<ChildContent>
|
||||
<RadzenDropZone TItem="ToolbarItem" class="rounded">
|
||||
</RadzenDropZone>
|
||||
</ChildContent>
|
||||
<Template>
|
||||
<div>
|
||||
<strong>@context.Name</strong>
|
||||
<RadzenButton Icon="delete" Click="@((e) => DeleteToolbarItem(context))" Size="ButtonSize.ExtraSmall" ButtonStyle="ButtonStyle.Light" />
|
||||
</div>
|
||||
</Template>
|
||||
</RadzenDropZoneContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 text-end">
|
||||
<RadzenButton Text="OK" Click=@OnOkClick />
|
||||
<RadzenButton Text="Cancel" Click=@OnCancelClick ButtonStyle="ButtonStyle.Secondary" />
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private readonly IList<string> _themes = new List<string>
|
||||
{
|
||||
"default",
|
||||
"dark",
|
||||
"material",
|
||||
"material-dark",
|
||||
"standard",
|
||||
"standard-dark",
|
||||
"humanistic",
|
||||
"humanistic-dark",
|
||||
"software",
|
||||
"software-dark"
|
||||
};
|
||||
private readonly IList<string> _backgroundColors = new List<string> { "Default", "Light", "Dark" };
|
||||
|
||||
private int _settingScope;
|
||||
private string _theme;
|
||||
private string _background;
|
||||
private IList<ToolbarItem> _toolbarItems = new List<ToolbarItem>();
|
||||
private string _addToolbarItem;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_settingScope = await EditorSettingService.GetSettingScopeAsync(ModuleState.ModuleId);
|
||||
|
||||
await LoadSettings();
|
||||
}
|
||||
|
||||
private async Task<RadzenEditorSetting> LoadSettingsFromModule()
|
||||
{
|
||||
return await EditorSettingService.LoadSettingsFromModuleAsync(ModuleState.ModuleId);
|
||||
}
|
||||
|
||||
private async Task<RadzenEditorSetting> LoadSettingsFromSite()
|
||||
{
|
||||
return await EditorSettingService.LoadSettingsFromSiteAsync(PageState.Site.SiteId);
|
||||
}
|
||||
|
||||
private async Task LoadSettings()
|
||||
{
|
||||
var editorSetting = _settingScope == 1 ? await LoadSettingsFromModule() : await LoadSettingsFromSite();
|
||||
_theme = editorSetting.Theme;
|
||||
_background = editorSetting.Background;
|
||||
_toolbarItems = editorSetting.ToolbarItems.Split(',').Select((v, i) =>
|
||||
{
|
||||
return new ToolbarItem { Key = i, Name = v };
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private async Task OnScopeChanged()
|
||||
{
|
||||
await LoadSettings();
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void AddToolbarItem()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_addToolbarItem))
|
||||
{
|
||||
_toolbarItems.Add(new ToolbarItem { Key = _toolbarItems.Count, Name = _addToolbarItem });
|
||||
_addToolbarItem = string.Empty;
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetToolbarItem()
|
||||
{
|
||||
_toolbarItems = RadzenEditorDefinitions.DefaultToolbarItems.Split(',').Select((v, i) =>
|
||||
{
|
||||
return new ToolbarItem { Key = i, Name = v };
|
||||
}).ToList();
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void DeleteToolbarItem(ToolbarItem item)
|
||||
{
|
||||
_toolbarItems.Remove(item);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void OnCancelClick()
|
||||
{
|
||||
DialogService.Close(false);
|
||||
}
|
||||
|
||||
private async Task OnOkClick()
|
||||
{
|
||||
var editorSetting = new RadzenEditorSetting
|
||||
{
|
||||
Theme = _theme,
|
||||
Background = _background,
|
||||
ToolbarItems = string.Join(",", _toolbarItems.Select(i => i.Name))
|
||||
};
|
||||
await EditorSettingService.UpdateSettingScopeAsync(ModuleState.ModuleId, _settingScope);
|
||||
if (_settingScope == 1)
|
||||
{
|
||||
await EditorSettingService.SaveModuleSettingsAsync(ModuleState.ModuleId, editorSetting);
|
||||
}
|
||||
else
|
||||
{
|
||||
await EditorSettingService.SaveSiteSettingsAsync(PageState.Site.SiteId, editorSetting);
|
||||
}
|
||||
|
||||
DialogService.Close(true);
|
||||
}
|
||||
|
||||
private void OnToolbarItemDrop(RadzenDropZoneItemEventArgs<ToolbarItem> args)
|
||||
{
|
||||
if (args.ToItem != null && args.ToItem.Key != args.Item.Key)
|
||||
{
|
||||
_toolbarItems.Remove(args.Item);
|
||||
_toolbarItems.Insert(_toolbarItems.IndexOf(args.ToItem), args.Item);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnToolbarItemRender(RadzenDropZoneItemRenderEventArgs<ToolbarItem> args)
|
||||
{
|
||||
args.Attributes.Add("class", "rz-card rz-variant-flat rz-background-color-primary-lighter rz-color-on-primary-lighter rz-p-2 d-inline-block ms-1 mt-1");
|
||||
}
|
||||
|
||||
public class ToolbarItem
|
||||
{
|
||||
public int Key { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="9.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.8" />
|
||||
<PackageReference Include="Radzen.Blazor" Version="7.3.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
219
Oqtane.Client/Resources/Modules/Controls/RadzenTextEditor.resx
Normal file
219
Oqtane.Client/Resources/Modules/Controls/RadzenTextEditor.resx
Normal file
@ -0,0 +1,219 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Background" xml:space="preserve">
|
||||
<value>Editor Background:</value>
|
||||
</data>
|
||||
<data name="Close" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
</data>
|
||||
<data name="Dark" xml:space="preserve">
|
||||
<value>Dark</value>
|
||||
</data>
|
||||
<data name="Default" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="DialogTitle.SelectImage" xml:space="preserve">
|
||||
<value>Select Image</value>
|
||||
</data>
|
||||
<data name="FontName.Placeholder" xml:space="preserve">
|
||||
<value>Font</value>
|
||||
</data>
|
||||
<data name="FontName.Title" xml:space="preserve">
|
||||
<value>Font Name</value>
|
||||
</data>
|
||||
<data name="FontSize.Placeholder" xml:space="preserve">
|
||||
<value>Size</value>
|
||||
</data>
|
||||
<data name="FontSize.Title" xml:space="preserve">
|
||||
<value>Font Size</value>
|
||||
</data>
|
||||
<data name="FormatBlock.Placeholder" xml:space="preserve">
|
||||
<value>Format</value>
|
||||
</data>
|
||||
<data name="FormatBlock.Title" xml:space="preserve">
|
||||
<value>Format Block</value>
|
||||
</data>
|
||||
<data name="theme.humanistic" xml:space="preserve">
|
||||
<value>Humanistic</value>
|
||||
</data>
|
||||
<data name="theme.humanistic-dark" xml:space="preserve">
|
||||
<value>Humanistic Dark</value>
|
||||
</data>
|
||||
<data name="InsertImage" xml:space="preserve">
|
||||
<value>Insert Image</value>
|
||||
</data>
|
||||
<data name="Light" xml:space="preserve">
|
||||
<value>Light</value>
|
||||
</data>
|
||||
<data name="theme.material" xml:space="preserve">
|
||||
<value>Material</value>
|
||||
</data>
|
||||
<data name="theme.material-dark" xml:space="preserve">
|
||||
<value>Material Dark</value>
|
||||
</data>
|
||||
<data name="Message.Require.Image" xml:space="preserve">
|
||||
<value>You Must Select An Image To Insert</value>
|
||||
</data>
|
||||
<data name="Module" xml:space="preserve">
|
||||
<value>Module</value>
|
||||
</data>
|
||||
<data name="Placeholder" xml:space="preserve">
|
||||
<value>Enter Your Content...</value>
|
||||
</data>
|
||||
<data name="Settings" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="Scope" xml:space="preserve">
|
||||
<value>Scope:</value>
|
||||
</data>
|
||||
<data name="Site" xml:space="preserve">
|
||||
<value>Site</value>
|
||||
</data>
|
||||
<data name="theme.software" xml:space="preserve">
|
||||
<value>Software</value>
|
||||
</data>
|
||||
<data name="theme.software-dark" xml:space="preserve">
|
||||
<value>Software Dark</value>
|
||||
</data>
|
||||
<data name="theme.standard" xml:space="preserve">
|
||||
<value>Standard</value>
|
||||
</data>
|
||||
<data name="theme.standard-dark" xml:space="preserve">
|
||||
<value>Standard Dark</value>
|
||||
</data>
|
||||
<data name="Theme" xml:space="preserve">
|
||||
<value>Theme:</value>
|
||||
</data>
|
||||
<data name="theme.dark" xml:space="preserve">
|
||||
<value>Dark</value>
|
||||
</data>
|
||||
<data name="theme.default" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="Toolbar" xml:space="preserve">
|
||||
<value>Toolbar Items:</value>
|
||||
</data>
|
||||
<data name="Add" xml:space="preserve">
|
||||
<value>Add</value>
|
||||
</data>
|
||||
<data name="Reset" xml:space="preserve">
|
||||
<value>Reset</value>
|
||||
</data>
|
||||
</root>
|
144
Oqtane.Client/Services/RadzenEditorSettingService.cs
Normal file
144
Oqtane.Client/Services/RadzenEditorSettingService.cs
Normal file
@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Modules;
|
||||
using Oqtane.Modules.Controls;
|
||||
using Oqtane.Services;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public interface IRadzenEditorSettingService
|
||||
{
|
||||
Task<int> GetSettingScopeAsync(int moduleId);
|
||||
|
||||
Task UpdateSettingScopeAsync(int moduleId, int scope);
|
||||
|
||||
Task<RadzenEditorSetting> LoadSettingsFromModuleAsync(int moduleId);
|
||||
|
||||
Task<RadzenEditorSetting> LoadSettingsFromSiteAsync(int siteId);
|
||||
|
||||
Task SaveSiteSettingsAsync(int siteId, RadzenEditorSetting editorSetting);
|
||||
|
||||
Task SaveModuleSettingsAsync(int moduleId, RadzenEditorSetting editorSetting);
|
||||
}
|
||||
public class RadzenEditorSettingService : IRadzenEditorSettingService, IService
|
||||
{
|
||||
private const string SettingPrefix = "rzeditor:";
|
||||
|
||||
private readonly ISettingService _settingService;
|
||||
|
||||
public RadzenEditorSettingService(ISettingService settingService)
|
||||
{
|
||||
_settingService = settingService;
|
||||
}
|
||||
|
||||
public async Task<int> GetSettingScopeAsync(int moduleId)
|
||||
{
|
||||
var key = $"{SettingPrefix}Scope";
|
||||
var settings = await _settingService.GetModuleSettingsAsync(moduleId);
|
||||
if (settings.ContainsKey(key) && int.TryParse(settings[key], out int value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return 0; // site as default
|
||||
}
|
||||
|
||||
public async Task UpdateSettingScopeAsync(int moduleId, int scope)
|
||||
{
|
||||
var settings = new Dictionary<string, string>
|
||||
{
|
||||
{ $"{SettingPrefix}Scope", scope.ToString() }
|
||||
};
|
||||
|
||||
await _settingService.UpdateModuleSettingsAsync(settings, moduleId);
|
||||
}
|
||||
|
||||
public async Task<RadzenEditorSetting> LoadSettingsFromModuleAsync(int moduleId)
|
||||
{
|
||||
var settings = await _settingService.GetModuleSettingsAsync(moduleId);
|
||||
return ReadSettings(settings);
|
||||
}
|
||||
|
||||
public async Task<RadzenEditorSetting> LoadSettingsFromSiteAsync(int siteId)
|
||||
{
|
||||
var settings = await _settingService.GetSiteSettingsAsync(siteId);
|
||||
return ReadSettings(settings);
|
||||
}
|
||||
|
||||
public async Task SaveSiteSettingsAsync(int siteId, RadzenEditorSetting editorSetting)
|
||||
{
|
||||
var settings = CreateSettingsDictionary(editorSetting);
|
||||
if (settings.Any())
|
||||
{
|
||||
await _settingService.UpdateSiteSettingsAsync(settings, siteId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveModuleSettingsAsync(int moduleId, RadzenEditorSetting editorSetting)
|
||||
{
|
||||
var settings = CreateSettingsDictionary(editorSetting);
|
||||
if (settings.Any())
|
||||
{
|
||||
await _settingService.UpdateModuleSettingsAsync(settings, moduleId);
|
||||
}
|
||||
}
|
||||
|
||||
private RadzenEditorSetting ReadSettings(IDictionary<string, string> settings)
|
||||
{
|
||||
var setting = new RadzenEditorSetting
|
||||
{
|
||||
Theme = RadzenEditorDefinitions.DefaultTheme,
|
||||
Background = RadzenEditorDefinitions.DefaultBackground,
|
||||
ToolbarItems = RadzenEditorDefinitions.DefaultToolbarItems
|
||||
};
|
||||
|
||||
if (settings != null)
|
||||
{
|
||||
var themeKey = $"{SettingPrefix}Theme";
|
||||
var backgroundKey = $"{SettingPrefix}Background";
|
||||
var toolbarItemsKey = $"{SettingPrefix}ToolbarItems";
|
||||
|
||||
if (settings.ContainsKey(themeKey) && !string.IsNullOrEmpty(settings[themeKey]))
|
||||
{
|
||||
setting.Theme = settings[themeKey];
|
||||
}
|
||||
|
||||
if (settings.ContainsKey(backgroundKey) && !string.IsNullOrEmpty(settings[backgroundKey]))
|
||||
{
|
||||
setting.Background = settings[backgroundKey];
|
||||
}
|
||||
|
||||
if (settings.ContainsKey(toolbarItemsKey) && !string.IsNullOrEmpty(settings[toolbarItemsKey]))
|
||||
{
|
||||
setting.ToolbarItems = settings[toolbarItemsKey];
|
||||
}
|
||||
}
|
||||
|
||||
return setting;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> CreateSettingsDictionary(RadzenEditorSetting editorSetting)
|
||||
{
|
||||
var settings = new Dictionary<string, string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(editorSetting.Theme))
|
||||
{
|
||||
settings.Add($"{SettingPrefix}Theme", editorSetting.Theme);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(editorSetting.Background))
|
||||
{
|
||||
settings.Add($"{SettingPrefix}Background", editorSetting.Background);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(editorSetting.ToolbarItems))
|
||||
{
|
||||
settings.Add($"{SettingPrefix}ToolbarItems", editorSetting.ToolbarItems);
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Oqtane.Extensions;
|
||||
@ -32,6 +33,7 @@ using Oqtane.Repository;
|
||||
using Oqtane.Security;
|
||||
using Oqtane.Services;
|
||||
using Oqtane.Shared;
|
||||
using Radzen;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
@ -193,7 +195,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<Oqtane.Shared.SiteState>();
|
||||
services.AddScoped<IInstallationService, InstallationService>();
|
||||
services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>();
|
||||
services.AddScoped<IThemeService, ThemeService>();
|
||||
services.AddScoped<IThemeService, Oqtane.Services.ThemeService>();
|
||||
services.AddScoped<IAliasService, AliasService>();
|
||||
services.AddScoped<ITenantService, TenantService>();
|
||||
services.AddScoped<IPageService, PageService>();
|
||||
@ -208,7 +210,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
services.AddScoped<ILogService, LogService>();
|
||||
services.AddScoped<IJobService, JobService>();
|
||||
services.AddScoped<IJobLogService, JobLogService>();
|
||||
services.AddScoped<INotificationService, NotificationService>();
|
||||
services.AddScoped<INotificationService, Oqtane.Services.NotificationService>();
|
||||
services.AddScoped<IFolderService, FolderService>();
|
||||
services.AddScoped<IFileService, FileService>();
|
||||
services.AddScoped<ISiteTemplateService, SiteTemplateService>();
|
||||
@ -230,6 +232,12 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
// providers
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.QuillJSTextEditor>();
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.TextAreaTextEditor>();
|
||||
services.AddScoped<ITextEditor, Oqtane.Modules.Controls.RadzenTextEditor>();
|
||||
|
||||
services.AddRadzenComponents();
|
||||
|
||||
var localizer = services.BuildServiceProvider().GetService<IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor>>();
|
||||
Oqtane.Modules.Controls.RadzenEditorDefinitions.Localizer = localizer;
|
||||
|
||||
return services;
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
.rz-text-editor {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.rz-html-editor-dropdown-items,
|
||||
.rz-popup,
|
||||
.rz-editor-dialog-wrapper {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
|
||||
.rz-html-editor-dropdown-items .rz-html-editor-dropdown-item,
|
||||
.rz-html-editor-dropdown-items .rz-html-editor-dropdown-item > * {
|
||||
color: var(--rz-editor-button-color);
|
||||
}
|
||||
.rz-text-editor .rz-html-editor-dropdown .rz-html-editor-dropdown-value,
|
||||
.rz-text-editor .rz-html-editor-dropdown .rz-html-editor-dropdown-trigger,
|
||||
.rz-text-editor .rz-html-editor-colorpicker .rz-html-editor-color {
|
||||
color: var(--rz-editor-button-color);
|
||||
}
|
||||
.rz-text-editor .rz-colorpicker.rz-state-disabled {
|
||||
border: none !important;
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
var Oqtane = Oqtane || {};
|
||||
|
||||
Oqtane.RadzenTextEditor = {
|
||||
initialize: function (editor) {
|
||||
if (typeof Radzen.openPopup === "function" && Radzen.openPopup !== Oqtane.RadzenTextEditor.openPopup) {
|
||||
Oqtane.RadzenTextEditor.radzenOpenPopup = Radzen.openPopup;
|
||||
Radzen.openPopup = Oqtane.RadzenTextEditor.openPopup;
|
||||
}
|
||||
},
|
||||
openPopup: function () {
|
||||
Oqtane.RadzenTextEditor.radzenOpenPopup.apply(this, arguments);
|
||||
var id = arguments[1];
|
||||
var popup = document.getElementById(id);
|
||||
if (popup) {
|
||||
Oqtane.RadzenTextEditor.updateButtonStyles(popup);
|
||||
}
|
||||
},
|
||||
setBackgroundColor: function (editor, color) {
|
||||
editor.getElementsByClassName("rz-html-editor-content")[0].style.backgroundColor = color;
|
||||
},
|
||||
updateDialogLayout: function (editor) {
|
||||
var dialogs = editor.parentElement.getElementsByClassName('rz-dialog-wrapper');
|
||||
for (var dialog of dialogs) {
|
||||
document.body.appendChild(dialog);
|
||||
dialog.classList.add('rz-editor-dialog-wrapper', 'text-dark');
|
||||
|
||||
this.updateButtonStyles(dialog);
|
||||
}
|
||||
},
|
||||
updateButtonStyles: function (parent) {
|
||||
var primaryBtns = parent.getElementsByClassName('rz-primary');
|
||||
if (primaryBtns) {
|
||||
for (var btn of primaryBtns) {
|
||||
btn.classList.remove('rz-button', 'rz-primary');
|
||||
btn.classList.add('btn', 'btn-primary');
|
||||
}
|
||||
}
|
||||
|
||||
var secondaryBtns = parent.getElementsByClassName('rz-secondary');
|
||||
if (secondaryBtns) {
|
||||
for (var btn of secondaryBtns) {
|
||||
btn.classList.remove('rz-button', 'rz-secondary');
|
||||
btn.classList.add('btn', 'btn-secondary');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user