enable to insert file link in radzen editor.

This commit is contained in:
Ben
2025-09-27 09:31:16 +08:00
parent 92496f4369
commit 2a302a187a
6 changed files with 229 additions and 22 deletions

View File

@ -1,19 +1,23 @@
@namespace Oqtane.Modules.Controls @namespace Oqtane.Modules.Controls
@using System.IO
@using Radzen @using Radzen
@using Radzen.Blazor @using Radzen.Blazor
@inject DialogService DialogService @inject DialogService DialogService
@inject IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor> Localizer @inject IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor> Localizer
<div class="d-flex"> @if (!string.IsNullOrEmpty(_message))
{
<div class="rz-html-editor-dialog-item">
<div class="alert alert-warning alert-dismissible fade show mb-3" role="alert">
@((MarkupString)_message)
</div>
</div>
}
<div class="rz-html-editor-dialog-item">
<FileManager @ref="_fileManager" Filter="@Filters" /> <FileManager @ref="_fileManager" Filter="@Filters" />
</div> </div>
<div class="d-flex"> <div class="rz-html-editor-dialog-buttons">
<ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage> <RadzenButton Text="@Localizer["InsertImage"]" Click="InsertImage" />
</div> <RadzenButton Text="@Localizer["Cancel"]" Click="() => DialogService.Close()" ButtonStyle="ButtonStyle.Secondary" />
<div class="mt-1 text-end">
<RadzenButton Text="OK" Click=@OnOkClick />
<RadzenButton Text="Cancel" Click=@OnCancelClick ButtonStyle="ButtonStyle.Secondary" />
</div> </div>
@code { @code {
private FileManager _fileManager; private FileManager _fileManager;
@ -22,12 +26,7 @@
[Parameter] [Parameter]
public string Filters { get; set; } public string Filters { get; set; }
private void OnCancelClick() private void InsertImage()
{
DialogService.Close(null);
}
private void OnOkClick()
{ {
_message = string.Empty; _message = string.Empty;
var file = _fileManager.GetFile(); var file = _fileManager.GetFile();

View File

@ -0,0 +1,134 @@
@namespace Oqtane.Modules.Controls
@using Radzen
@using Radzen.Blazor
@using System.Text
@inject DialogService DialogService
@inject IStringLocalizer<Oqtane.Modules.Controls.RadzenTextEditor> Localizer
@if (_linkAttributes != null)
{
@if (!string.IsNullOrWhiteSpace(_message))
{
<div class="rz-html-editor-dialog-item">
<div class="alert alert-warning alert-dismissible fade show mb-3" role="alert">
@((MarkupString)_message)
</div>
</div>
}
<div class="rz-html-editor-dialog-item">
<RadzenDropDown TValue="int" class="form-control" PopupStyle="color: var(--rz-input-value-color);" @bind-Value="_linkType" Data="_linkTypes" TextProperty="Value" ValueProperty="Key" />
</div>
@if (_linkType == 0)
{
<div class="rz-html-editor-dialog-item">
<RadzenTextBox class="form-control" @bind-Value="@_linkAttributes.Href" Placeholder="@Localizer["WebAddress"]" />
</div>
}
else
{
<div class="rz-html-editor-dialog-item">
<FileManager @ref="_fileManager" OnSelectFile="SelectFile" OnSelectFolder="SelectFile" />
</div>
}
@if (_linkTextEditable)
{
<div class="rz-html-editor-dialog-item">
<RadzenTextBox class="form-control" @bind-Value="@_linkAttributes.InnerText" Placeholder="@Localizer["LinkText"]" />
</div>
}
<div class="rz-html-editor-dialog-item">
<RadzenDropDown TValue="bool" class="form-control" PopupStyle="color: var(--rz-input-value-color);" @bind-Value="_blank" Data="_linkTargets" TextProperty="Value" ValueProperty="Key" />
</div>
}
<div class="rz-html-editor-dialog-buttons">
<RadzenButton Text=@Localizer["InsertLink"] Click="InsertLink" />
<RadzenButton Text=@Localizer["Cancel"] Click="() => DialogService.Close()" ButtonStyle="ButtonStyle.Secondary" />
</div>
@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<int, string> _linkTypes;
private IDictionary<bool, string> _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<LinkAttributes>("a", new[] { "innerText", "href", "target" });
if (_linkAttributes.Target == "_blank")
{
_blank = true;
}
_linkTextEditable = string.IsNullOrWhiteSpace(_linkAttributes.InnerHtml) || _linkAttributes.InnerHtml == "<br>";
_linkTypes = new Dictionary<int, string>
{
{ 0, Localizer["WebLink"] },
{ 1, Localizer["FileLink"] }
};
_linkTargets = new Dictionary<bool, string>
{
{ 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("<a href=\"{0}\"", _linkAttributes.Href);
if (_blank)
{
html.Append(" target=\"_blank\"");
}
html.AppendFormat(">{0}</a>", string.IsNullOrWhiteSpace(_linkAttributes.InnerText) ? _linkAttributes.InnerHtml : _linkAttributes.InnerText);
DialogService.Close(html.ToString());
}
else
{
StateHasChanged();
}
}
}

View File

@ -147,13 +147,17 @@
private async Task OnExecute(HtmlEditorExecuteEventArgs args) private async Task OnExecute(HtmlEditorExecuteEventArgs args)
{ {
if (args.CommandName == "InsertImage") switch(args.CommandName)
{ {
await InsertImage(args.Editor); case "InsertImage":
} await InsertImage(args.Editor);
else if (args.CommandName == "Settings") break;
{ case "InsertLink":
await UpdateSettings(args.Editor); await InsertLink(args.Editor);
break;
case "Settings":
await UpdateSettings(args.Editor);
break;
} }
} }
@ -164,7 +168,24 @@
var result = await DialogService.OpenAsync<RadzenFileManagerDialog>(Localizer["DialogTitle.SelectImage"], new Dictionary<string, object> var result = await DialogService.OpenAsync<RadzenFileManagerDialog>(Localizer["DialogTitle.SelectImage"], new Dictionary<string, object>
{ {
{ "Filters", PageState.Site.ImageFiles } { "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<RadzenInsertLinkDialog>(Localizer["DialogTitle.InsertLink"], new Dictionary<string, object>
{
{ "Editor", editor }
}, new DialogOptions { CssClass = "rz-text-editor-dialog" });
await editor.RestoreSelectionAsync(); await editor.RestoreSelectionAsync();

View File

@ -33,7 +33,7 @@ namespace Oqtane.Modules.Controls
{ "InsertImage", (builder, sequence) => CreateFragment(builder, sequence, "InsertImage", "RadzenHtmlEditorCustomTool", "InsertImage", "image") }, { "InsertImage", (builder, sequence) => CreateFragment(builder, sequence, "InsertImage", "RadzenHtmlEditorCustomTool", "InsertImage", "image") },
{ "Italic", (builder, sequence) => CreateFragment(builder, sequence, "Italic", "RadzenHtmlEditorItalic") }, { "Italic", (builder, sequence) => CreateFragment(builder, sequence, "Italic", "RadzenHtmlEditorItalic") },
{ "Justify", (builder, sequence) => CreateFragment(builder, sequence, "Justify", "RadzenHtmlEditorJustify") }, { "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") }, { "OrderedList", (builder, sequence) => CreateFragment(builder, sequence, "OrderedList", "RadzenHtmlEditorOrderedList") },
{ "Outdent", (builder, sequence) => CreateFragment(builder, sequence, "Outdent", "RadzenHtmlEditorOutdent") }, { "Outdent", (builder, sequence) => CreateFragment(builder, sequence, "Outdent", "RadzenHtmlEditorOutdent") },
{ "Redo", (builder, sequence) => CreateFragment(builder, sequence, "Redo", "RadzenHtmlEditorRedo") }, { "Redo", (builder, sequence) => CreateFragment(builder, sequence, "Redo", "RadzenHtmlEditorRedo") },

View File

@ -216,4 +216,37 @@
<data name="Reset" xml:space="preserve"> <data name="Reset" xml:space="preserve">
<value>Reset</value> <value>Reset</value>
</data> </data>
<data name="InsertLink" xml:space="preserve">
<value>Insert Link</value>
</data>
<data name="DialogTitle.InsertLink" xml:space="preserve">
<value>Insert Link</value>
</data>
<data name="WebAddress" xml:space="preserve">
<value>Enter Web Address</value>
</data>
<data name="LinkText" xml:space="preserve">
<value>Enter Link Text</value>
</data>
<data name="OpenInNewWindow" xml:space="preserve">
<value>Open In New Window</value>
</data>
<data name="WebLink" xml:space="preserve">
<value>Web Link</value>
</data>
<data name="FileLink" xml:space="preserve">
<value>File Link</value>
</data>
<data name="OpenInExistingWindow" xml:space="preserve">
<value>Open In Existing Window</value>
</data>
<data name="Message.Require.WebAddress" xml:space="preserve">
<value>The Web Address is Empty</value>
</data>
<data name="Message.Require.LinkText" xml:space="preserve">
<value>The Link Text is Empty</value>
</data>
<data name="Message.Require.File" xml:space="preserve">
<value>You Must Select a File</value>
</data>
</root> </root>

View File

@ -19,4 +19,24 @@
} }
.rz-text-editor .rz-colorpicker.rz-state-disabled { .rz-text-editor .rz-colorpicker.rz-state-disabled {
border: none !important; 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;
} }