Merge pull request #3585 from sbwalker/dev

add an AllowRichText parameter to the RichTextEditor component and add logic to handle JS Interop failures
This commit is contained in:
Shaun Walker 2023-12-20 16:59:06 -05:00 committed by GitHub
commit e99df58bce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -6,70 +6,75 @@
<div class="row" style="margin-bottom: 50px;"> <div class="row" style="margin-bottom: 50px;">
<div class="col"> <div class="col">
<TabStrip ActiveTab="@_activeTab"> <TabStrip>
<TabPanel Name="Rich" Heading="Rich Text Editor" ResourceKey="RichTextEditor"> @if (AllowRichText)
@if (_richfilemanager) {
{ <TabPanel Name="Rich" Heading="Rich Text Editor" ResourceKey="RichTextEditor">
<FileManager @ref="_fileManager" Filter="@PageState.Site.ImageFiles" /> @if (_richfilemanager)
<ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage> {
<br /> <FileManager @ref="_fileManager" Filter="@PageState.Site.ImageFiles" />
} <ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage>
<div class="d-flex justify-content-center mb-2"> <br />
@if (AllowRawHtml) }
{ <div class="d-flex justify-content-center mb-2">
<button type="button" class="btn btn-secondary" @onclick="RefreshRichText">@Localizer["SynchronizeContent"]</button>@((MarkupString)"&nbsp;&nbsp;") @if (AllowRawHtml)
} {
@if (AllowFileManagement) <button type="button" class="btn btn-secondary" @onclick="RefreshRichText">@Localizer["SynchronizeContent"]</button>
{
<button type="button" class="btn btn-primary" @onclick="InsertRichImage">@Localizer["InsertImage"]</button> @((MarkupString)"&nbsp;&nbsp;")
} }
@if (_richfilemanager) @if (AllowFileManagement)
{ {
@((MarkupString)"&nbsp;&nbsp;") <button type="button" class="btn btn-primary" @onclick="InsertRichImage">@Localizer["InsertImage"]</button>
<button type="button" class="btn btn-secondary" @onclick="CloseRichFileManager">@Localizer["Close"]</button> }
} @if (_richfilemanager)
</div> {
<div class="row"> @((MarkupString)"&nbsp;&nbsp;")
<div class="col"> <button type="button" class="btn btn-secondary" @onclick="CloseRichFileManager">@Localizer["Close"]</button>
<div @ref="@_toolBar"> }
@if (ToolbarContent != null) </div>
{ <div class="row">
@ToolbarContent <div class="col">
} <div @ref="@_toolBar">
else @if (ToolbarContent != null)
{ {
<select class="ql-header"> @ToolbarContent
<option selected=""></option> }
<option value="1"></option> else
<option value="2"></option> {
<option value="3"></option> <select class="ql-header">
<option value="4"></option> <option selected=""></option>
<option value="5"></option> <option value="1"></option>
</select> <option value="2"></option>
<span class="ql-formats"> <option value="3"></option>
<button class="ql-bold"></button> <option value="4"></option>
<button class="ql-italic"></button> <option value="5"></option>
<button class="ql-underline"></button> </select>
<button class="ql-strike"></button> <span class="ql-formats">
</span> <button class="ql-bold"></button>
<span class="ql-formats"> <button class="ql-italic"></button>
<select class="ql-color"></select> <button class="ql-underline"></button>
<select class="ql-background"></select> <button class="ql-strike"></button>
</span> </span>
<span class="ql-formats"> <span class="ql-formats">
<button class="ql-list" value="ordered"></button> <select class="ql-color"></select>
<button class="ql-list" value="bullet"></button> <select class="ql-background"></select>
</span> </span>
<span class="ql-formats"> <span class="ql-formats">
<button class="ql-link"></button> <button class="ql-list" value="ordered"></button>
</span> <button class="ql-list" value="bullet"></button>
} </span>
</div> <span class="ql-formats">
<div @ref="@_editorElement"> <button class="ql-link"></button>
</div> </span>
</div> }
</div> </div>
</TabPanel> <div @ref="@_editorElement">
</div>
</div>
</div>
</TabPanel>
}
@if (AllowRawHtml) @if (AllowRawHtml)
{ {
<TabPanel Name="Raw" Heading="Raw HTML Editor" ResourceKey="HtmlEditor"> <TabPanel Name="Raw" Heading="Raw HTML Editor" ResourceKey="HtmlEditor">
@ -106,7 +111,6 @@
</div> </div>
@code { @code {
private string _activeTab = "Rich";
private ElementReference _editorElement; private ElementReference _editorElement;
private ElementReference _toolBar; private ElementReference _toolBar;
private bool _richfilemanager = false; private bool _richfilemanager = false;
@ -130,6 +134,9 @@
[Parameter] [Parameter]
public bool AllowFileManagement { get; set; } = true; public bool AllowFileManagement { get; set; } = true;
[Parameter]
public bool AllowRichText { get; set; } = true;
[Parameter] [Parameter]
public bool AllowRawHtml { get; set; } = true; public bool AllowRawHtml { get; set; } = true;
@ -175,57 +182,59 @@
await interop.LoadEditorContent(_editorElement, _richhtml); await interop.LoadEditorContent(_editorElement, _richhtml);
// preserve a copy of the rich text content (Quill sanitizes content so we need to retrieve it from the editor) if (AllowRichText)
_originalrichhtml = await interop.GetHtml(_editorElement);
if (_originalrichhtml != _originalrawhtml)
{ {
_activeTab = "Raw"; // preserve a copy of the rich text content (Quill sanitizes content so we need to retrieve it from the editor)
StateHasChanged(); _originalrichhtml = await interop.GetHtml(_editorElement);
} }
}
}
} public void CloseRichFileManager()
} {
_richfilemanager = false;
_message = string.Empty;
StateHasChanged();
}
public void CloseRichFileManager() public void CloseRawFileManager()
{ {
_richfilemanager = false; _rawfilemanager = false;
_message = string.Empty; _message = string.Empty;
StateHasChanged(); StateHasChanged();
} }
public void CloseRawFileManager() public void RefreshRichText()
{ {
_rawfilemanager = false; _richhtml = _rawhtml;
_message = string.Empty; StateHasChanged();
StateHasChanged(); }
}
public void RefreshRichText() public async Task RefreshRawHtml()
{ {
_richhtml = _rawhtml; var interop = new RichTextEditorInterop(JSRuntime);
StateHasChanged(); _rawhtml = await interop.GetHtml(_editorElement);
} StateHasChanged();
}
public async Task RefreshRawHtml() public async Task<string> GetHtml()
{ {
var interop = new RichTextEditorInterop(JSRuntime); // evaluate raw html content as first priority
_rawhtml = await interop.GetHtml(_editorElement); if (_rawhtml != _originalrawhtml)
StateHasChanged(); {
} return _rawhtml;
}
public async Task<string> GetHtml() else
{ {
// evaluate raw html content as first priority var richhtml = "";
if (_rawhtml != _originalrawhtml) if (AllowRichText)
{ {
return _rawhtml; // return rich text content if it has changed
} var interop = new RichTextEditorInterop(JSRuntime);
else richhtml = await interop.GetHtml(_editorElement);
{ }
// return rich text content if it has changed // rich text value will only be blank if AllowRichText is disabled or the JS Interop method failed
var interop = new RichTextEditorInterop(JSRuntime); if (richhtml != _originalrichhtml && !string.IsNullOrEmpty(richhtml) && !string.IsNullOrEmpty(_originalrichhtml))
var richhtml = await interop.GetHtml(_editorElement);
if (richhtml != _originalrichhtml)
{ {
return richhtml; return richhtml;
} }