From 2a302a187aa6de624b71dd94bb3731898c325a68 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 27 Sep 2025 09:31:16 +0800 Subject: [PATCH] enable to insert file link in radzen editor. --- .../Radzen/RadzenFileManagerDialog.razor | 27 ++-- .../Radzen/RadzenInsertLinkDialog.razor | 134 ++++++++++++++++++ .../TextEditors/Radzen/RadzenTextEditor.razor | 35 ++++- .../Radzen/RadzenTextEditorDefinitions.cs | 2 +- .../Modules/Controls/RadzenTextEditor.resx | 33 +++++ .../texteditors/radzen/radzentexteditor.css | 20 +++ 6 files changed, 229 insertions(+), 22 deletions(-) create mode 100644 Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenInsertLinkDialog.razor diff --git a/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenFileManagerDialog.razor b/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenFileManagerDialog.razor index 48fdbc37..d0948af9 100644 --- a/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenFileManagerDialog.razor +++ b/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenFileManagerDialog.razor @@ -1,19 +1,23 @@ @namespace Oqtane.Modules.Controls -@using System.IO @using Radzen @using Radzen.Blazor @inject DialogService DialogService @inject IStringLocalizer Localizer -
+@if (!string.IsNullOrEmpty(_message)) +{ +
+ +
+} +
-
- -
-
- - +
+ +
@code { private FileManager _fileManager; @@ -22,12 +26,7 @@ [Parameter] public string Filters { get; set; } - private void OnCancelClick() - { - DialogService.Close(null); - } - - private void OnOkClick() + private void InsertImage() { _message = string.Empty; var file = _fileManager.GetFile(); diff --git a/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenInsertLinkDialog.razor b/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenInsertLinkDialog.razor new file mode 100644 index 00000000..d2c9fdd5 --- /dev/null +++ b/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenInsertLinkDialog.razor @@ -0,0 +1,134 @@ +@namespace Oqtane.Modules.Controls +@using Radzen +@using Radzen.Blazor +@using System.Text +@inject DialogService DialogService +@inject IStringLocalizer Localizer + +@if (_linkAttributes != null) +{ + @if (!string.IsNullOrWhiteSpace(_message)) + { +
+ +
+ } +
+ +
+ @if (_linkType == 0) + { +
+ +
+ } + else + { +
+ +
+ } + @if (_linkTextEditable) + { +
+ +
+ } +
+ +
+} +
+ + +
+ +@code { + class LinkAttributes + { + public string InnerText { get; set; } + public string InnerHtml { get; set; } + public string Href { get; set; } + public string Target { get; set; } + } + + [Parameter] + public RadzenHtmlEditor Editor { get; set; } + + private IDictionary _linkTypes; + private IDictionary _linkTargets; + private LinkAttributes _linkAttributes; + private bool _blank; + private int _linkType; + private string _message; + private bool _linkTextEditable; + private FileManager _fileManager; + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + _linkAttributes = await Editor.GetSelectionAttributes("a", new[] { "innerText", "href", "target" }); + if (_linkAttributes.Target == "_blank") + { + _blank = true; + } + + _linkTextEditable = string.IsNullOrWhiteSpace(_linkAttributes.InnerHtml) || _linkAttributes.InnerHtml == "
"; + + _linkTypes = new Dictionary + { + { 0, Localizer["WebLink"] }, + { 1, Localizer["FileLink"] } + }; + + _linkTargets = new Dictionary + { + { false, Localizer["OpenInExistingWindow"] }, + { true, Localizer["OpenInNewWindow"] } + }; + } + + private void SelectFile() + { + var file = _fileManager.GetFile(); + var url = file != null ? file.Url : string.Empty; + var text = file != null && _linkTextEditable ? file.Name : string.Empty; + + _linkAttributes.Href = url; + _linkAttributes.InnerText = text; + StateHasChanged(); + } + + private void InsertLink() + { + _message = string.Empty; + if (string.IsNullOrWhiteSpace(_linkAttributes.Href)) + { + _message = _linkType == 1 ? Localizer["Message.Require.File"] : Localizer["Message.Require.WebAddress"]; + } + else if (string.IsNullOrWhiteSpace(_linkAttributes.InnerText) && _linkTextEditable) + { + _message = Localizer["Message.Require.LinkText"]; + } + + if (string.IsNullOrWhiteSpace(_message)) + { + var html = new StringBuilder(); + html.AppendFormat("{0}", string.IsNullOrWhiteSpace(_linkAttributes.InnerText) ? _linkAttributes.InnerHtml : _linkAttributes.InnerText); + + DialogService.Close(html.ToString()); + } + else + { + StateHasChanged(); + } + } +} \ No newline at end of file diff --git a/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenTextEditor.razor b/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenTextEditor.razor index 0ef0fe03..fc4e4f9f 100644 --- a/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenTextEditor.razor +++ b/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenTextEditor.razor @@ -147,13 +147,17 @@ private async Task OnExecute(HtmlEditorExecuteEventArgs args) { - if (args.CommandName == "InsertImage") + switch(args.CommandName) { - await InsertImage(args.Editor); - } - else if (args.CommandName == "Settings") - { - await UpdateSettings(args.Editor); + case "InsertImage": + await InsertImage(args.Editor); + break; + case "InsertLink": + await InsertLink(args.Editor); + break; + case "Settings": + await UpdateSettings(args.Editor); + break; } } @@ -164,7 +168,24 @@ var result = await DialogService.OpenAsync(Localizer["DialogTitle.SelectImage"], new Dictionary { { "Filters", PageState.Site.ImageFiles } - }); + }, new DialogOptions { CssClass = "rz-text-editor-dialog" }); + + await editor.RestoreSelectionAsync(); + + if (result != null) + { + await editor.ExecuteCommandAsync(HtmlEditorCommands.InsertHtml, result); + } + } + + private async Task InsertLink(RadzenHtmlEditor editor) + { + await editor.SaveSelectionAsync(); + + var result = await DialogService.OpenAsync(Localizer["DialogTitle.InsertLink"], new Dictionary + { + { "Editor", editor } + }, new DialogOptions { CssClass = "rz-text-editor-dialog" }); await editor.RestoreSelectionAsync(); diff --git a/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenTextEditorDefinitions.cs b/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenTextEditorDefinitions.cs index 9fdd778d..2326bae7 100644 --- a/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenTextEditorDefinitions.cs +++ b/Oqtane.Client/Modules/Controls/TextEditors/Radzen/RadzenTextEditorDefinitions.cs @@ -33,7 +33,7 @@ namespace Oqtane.Modules.Controls { "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") }, + { "Link", (builder, sequence) => CreateFragment(builder, sequence, "InsertLink", "RadzenHtmlEditorCustomTool", "InsertLink", "insert_link") }, { "OrderedList", (builder, sequence) => CreateFragment(builder, sequence, "OrderedList", "RadzenHtmlEditorOrderedList") }, { "Outdent", (builder, sequence) => CreateFragment(builder, sequence, "Outdent", "RadzenHtmlEditorOutdent") }, { "Redo", (builder, sequence) => CreateFragment(builder, sequence, "Redo", "RadzenHtmlEditorRedo") }, diff --git a/Oqtane.Client/Resources/Modules/Controls/RadzenTextEditor.resx b/Oqtane.Client/Resources/Modules/Controls/RadzenTextEditor.resx index 4c84d4df..43f6e734 100644 --- a/Oqtane.Client/Resources/Modules/Controls/RadzenTextEditor.resx +++ b/Oqtane.Client/Resources/Modules/Controls/RadzenTextEditor.resx @@ -216,4 +216,37 @@ Reset + + Insert Link + + + Insert Link + + + Enter Web Address + + + Enter Link Text + + + Open In New Window + + + Web Link + + + File Link + + + Open In Existing Window + + + The Web Address is Empty + + + The Link Text is Empty + + + You Must Select a File + \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/css/texteditors/radzen/radzentexteditor.css b/Oqtane.Server/wwwroot/css/texteditors/radzen/radzentexteditor.css index e142053b..dbdd62f8 100644 --- a/Oqtane.Server/wwwroot/css/texteditors/radzen/radzentexteditor.css +++ b/Oqtane.Server/wwwroot/css/texteditors/radzen/radzentexteditor.css @@ -19,4 +19,24 @@ } .rz-text-editor .rz-colorpicker.rz-state-disabled { border: none !important; +} +.rz-text-editor-dialog .rz-html-editor-dialog-item select{ + border: var(--rz-input-border); + border-block-end: var(--rz-input-border-block-end); + border-radius: var(--rz-input-border-radius); + box-shadow: var(--rz-input-shadow); + background-color: var(--rz-input-background-color); + padding-block: var(--rz-input-padding-block); + padding-inline: var(--rz-input-padding-inline); + font-size: var(--rz-input-font-size); + color: var(--rz-input-value-color); +} +.rz-text-editor-dialog .rz-html-editor-dialog-item select:hover, .rz-text-edit-dialog .rz-html-editor-dialog-item select:active { + box-shadow: var(--rz-input-hover-shadow); + background-color: var(--rz-input-hover-background-color); + border: var(--rz-input-hover-border); + border-block-end: var(--rz-input-hover-border-block-end); +} +.rz-text-editor-dialog .alert form{ + display: none; } \ No newline at end of file