Fix #4316: add text editor interfaces.
This commit is contained in:
		@ -4,11 +4,11 @@ using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace Oqtane.Modules.Controls
 | 
			
		||||
{
 | 
			
		||||
    public class RichTextEditorInterop
 | 
			
		||||
    public class QuillEditorInterop
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IJSRuntime _jsRuntime;
 | 
			
		||||
 | 
			
		||||
        public RichTextEditorInterop(IJSRuntime jsRuntime)
 | 
			
		||||
        public QuillEditorInterop(IJSRuntime jsRuntime)
 | 
			
		||||
        {
 | 
			
		||||
            _jsRuntime = jsRuntime;
 | 
			
		||||
        }
 | 
			
		||||
							
								
								
									
										210
									
								
								Oqtane.Client/Modules/Controls/QuillTextEditor.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								Oqtane.Client/Modules/Controls/QuillTextEditor.razor
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,210 @@
 | 
			
		||||
@namespace Oqtane.Modules.Controls
 | 
			
		||||
@inherits ModuleControlBase
 | 
			
		||||
@implements ITextEditor
 | 
			
		||||
@inject IStringLocalizer<QuillTextEditor> Localizer
 | 
			
		||||
 | 
			
		||||
<div class="quill-text-editor">
 | 
			
		||||
    @if (_richfilemanager)
 | 
			
		||||
    {
 | 
			
		||||
        <FileManager @ref="_fileManager" Filter="@PageState.Site.ImageFiles" />
 | 
			
		||||
        <ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage>
 | 
			
		||||
        <br />
 | 
			
		||||
    }
 | 
			
		||||
    <div class="d-flex justify-content-center mb-2">
 | 
			
		||||
        @if (AllowFileManagement)
 | 
			
		||||
        {
 | 
			
		||||
            <button type="button" class="btn btn-primary" @onclick="InsertRichImage">@Localizer["InsertImage"]</button>
 | 
			
		||||
        }
 | 
			
		||||
        @if (_richfilemanager)
 | 
			
		||||
        {
 | 
			
		||||
            @((MarkupString)"  ")
 | 
			
		||||
            <button type="button" class="btn btn-secondary" @onclick="CloseRichFileManager">@Localizer["Close"]</button>
 | 
			
		||||
        }
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="row">
 | 
			
		||||
        <div class="col">
 | 
			
		||||
            <div @ref="@_toolBar">
 | 
			
		||||
                @if (ToolbarContent != null)
 | 
			
		||||
                {
 | 
			
		||||
                    @ToolbarContent
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    <select class="ql-header">
 | 
			
		||||
                        <option selected=""></option>
 | 
			
		||||
                        <option value="1"></option>
 | 
			
		||||
                        <option value="2"></option>
 | 
			
		||||
                        <option value="3"></option>
 | 
			
		||||
                        <option value="4"></option>
 | 
			
		||||
                        <option value="5"></option>
 | 
			
		||||
                    </select>
 | 
			
		||||
                    <span class="ql-formats">
 | 
			
		||||
                        <button class="ql-bold"></button>
 | 
			
		||||
                        <button class="ql-italic"></button>
 | 
			
		||||
                        <button class="ql-underline"></button>
 | 
			
		||||
                        <button class="ql-strike"></button>
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <span class="ql-formats">
 | 
			
		||||
                        <select class="ql-color"></select>
 | 
			
		||||
                        <select class="ql-background"></select>
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <span class="ql-formats">
 | 
			
		||||
                        <button class="ql-list" value="ordered"></button>
 | 
			
		||||
                        <button class="ql-list" value="bullet"></button>
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <span class="ql-formats">
 | 
			
		||||
                        <button class="ql-link"></button>
 | 
			
		||||
                    </span>
 | 
			
		||||
                }
 | 
			
		||||
            </div>
 | 
			
		||||
            <div @ref="@_editorElement"></div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@code {
 | 
			
		||||
    private bool _richfilemanager = false;
 | 
			
		||||
    private FileManager _fileManager;
 | 
			
		||||
    private string _message = string.Empty;
 | 
			
		||||
    private ElementReference _editorElement;
 | 
			
		||||
    private ElementReference _toolBar;
 | 
			
		||||
    private QuillEditorInterop interop;
 | 
			
		||||
    private int _editorIndex;
 | 
			
		||||
    private string _richhtml = string.Empty;
 | 
			
		||||
    private string _originalrichhtml = string.Empty;
 | 
			
		||||
    private bool _initialized = false;
 | 
			
		||||
    private bool _contentchanged = false;
 | 
			
		||||
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public bool AllowFileManagement{ get; set; }
 | 
			
		||||
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public bool ReadOnly { get; set; }
 | 
			
		||||
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public string Placeholder { get; set; }
 | 
			
		||||
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public string Theme { get; set; }
 | 
			
		||||
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public string DebugLevel { get; set; }
 | 
			
		||||
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public RenderFragment ToolbarContent { get; set; }
 | 
			
		||||
 | 
			
		||||
    public override List<Resource> Resources { get; set; } = new List<Resource>()
 | 
			
		||||
    {
 | 
			
		||||
        new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js", Location = ResourceLocation.Body },
 | 
			
		||||
        new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js", Location = ResourceLocation.Body },
 | 
			
		||||
        new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js", Location = ResourceLocation.Body }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    protected override void OnInitialized()
 | 
			
		||||
    {
 | 
			
		||||
        interop = new QuillEditorInterop(JSRuntime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override async Task OnAfterRenderAsync(bool firstRender)
 | 
			
		||||
    {
 | 
			
		||||
        await base.OnAfterRenderAsync(firstRender);
 | 
			
		||||
 | 
			
		||||
        if (firstRender)
 | 
			
		||||
        {
 | 
			
		||||
            await interop.CreateEditor(
 | 
			
		||||
                _editorElement,
 | 
			
		||||
                _toolBar,
 | 
			
		||||
                ReadOnly,
 | 
			
		||||
                Placeholder,
 | 
			
		||||
                Theme,
 | 
			
		||||
                DebugLevel);
 | 
			
		||||
 | 
			
		||||
            await interop.LoadEditorContent(_editorElement, _richhtml);
 | 
			
		||||
 | 
			
		||||
            // preserve a copy of the content (Quill sanitizes content so we need to retrieve it from the editor as it may have been modified)
 | 
			
		||||
            _originalrichhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
 | 
			
		||||
            _initialized = true;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (_initialized)
 | 
			
		||||
            {
 | 
			
		||||
                if (_contentchanged)
 | 
			
		||||
                {
 | 
			
		||||
                    // reload editor if Content passed to component has changed
 | 
			
		||||
                    await interop.LoadEditorContent(_editorElement, _richhtml);
 | 
			
		||||
                    _originalrichhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    // preserve changed content on re-render event
 | 
			
		||||
                    var richhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
                    if (richhtml != _richhtml)
 | 
			
		||||
                    {
 | 
			
		||||
                        _richhtml = richhtml;
 | 
			
		||||
                        await interop.LoadEditorContent(_editorElement, _richhtml);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _contentchanged = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void Initialize(string content, bool updated)
 | 
			
		||||
    {
 | 
			
		||||
        _richhtml = content;
 | 
			
		||||
        _contentchanged = updated;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task InsertRichImage()
 | 
			
		||||
    {
 | 
			
		||||
        _message = string.Empty;
 | 
			
		||||
        if (_richfilemanager)
 | 
			
		||||
        {
 | 
			
		||||
            var file = _fileManager.GetFile();
 | 
			
		||||
            if (file != null)
 | 
			
		||||
            {
 | 
			
		||||
                await interop.InsertImage(_editorElement, file.Url, ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name), _editorIndex);
 | 
			
		||||
                _richhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
                _richfilemanager = false;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                _message = Localizer["Message.Require.Image"];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            _editorIndex = await interop.GetCurrentCursor(_editorElement);
 | 
			
		||||
            _richfilemanager = true;
 | 
			
		||||
        }
 | 
			
		||||
        StateHasChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void CloseRichFileManager()
 | 
			
		||||
    {
 | 
			
		||||
        _richfilemanager = false;
 | 
			
		||||
        _message = string.Empty;
 | 
			
		||||
        StateHasChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task<string> GetContent()
 | 
			
		||||
    {
 | 
			
		||||
        var richhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
        if (richhtml != _originalrichhtml && !string.IsNullOrEmpty(richhtml))
 | 
			
		||||
        {
 | 
			
		||||
            // convert Quill's empty content to empty string
 | 
			
		||||
            if (richhtml == "<p><br></p>")
 | 
			
		||||
            {
 | 
			
		||||
                richhtml = string.Empty;
 | 
			
		||||
            }
 | 
			
		||||
            return richhtml;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,9 @@
 | 
			
		||||
@using System.Text.RegularExpressions
 | 
			
		||||
@using Microsoft.AspNetCore.Components.Rendering
 | 
			
		||||
@using Microsoft.Extensions.DependencyInjection
 | 
			
		||||
@namespace Oqtane.Modules.Controls
 | 
			
		||||
@inherits ModuleControlBase
 | 
			
		||||
@inject IServiceProvider ServiceProvider
 | 
			
		||||
@inject ISettingService SettingService
 | 
			
		||||
@inject IStringLocalizer<RichTextEditor> Localizer 
 | 
			
		||||
 | 
			
		||||
@ -10,62 +13,7 @@
 | 
			
		||||
			@if (AllowRichText)
 | 
			
		||||
            {
 | 
			
		||||
                <TabPanel Name="Rich" Heading="Rich Text Editor" ResourceKey="RichTextEditor">
 | 
			
		||||
                    @if (_richfilemanager)
 | 
			
		||||
                    {
 | 
			
		||||
                        <FileManager @ref="_fileManager" Filter="@PageState.Site.ImageFiles" />
 | 
			
		||||
                        <ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage>
 | 
			
		||||
                        <br />
 | 
			
		||||
                    }
 | 
			
		||||
                    <div class="d-flex justify-content-center mb-2">
 | 
			
		||||
                        @if (AllowFileManagement)
 | 
			
		||||
                        {
 | 
			
		||||
                            <button type="button" class="btn btn-primary" @onclick="InsertRichImage">@Localizer["InsertImage"]</button>
 | 
			
		||||
                        }
 | 
			
		||||
                        @if (_richfilemanager)
 | 
			
		||||
                        {
 | 
			
		||||
                            @((MarkupString)"  ")
 | 
			
		||||
                            <button type="button" class="btn btn-secondary" @onclick="CloseRichFileManager">@Localizer["Close"]</button>
 | 
			
		||||
                        }
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="row">
 | 
			
		||||
                        <div class="col">
 | 
			
		||||
                            <div @ref="@_toolBar">
 | 
			
		||||
                                @if (ToolbarContent != null)
 | 
			
		||||
                                {
 | 
			
		||||
                                    @ToolbarContent
 | 
			
		||||
                                }
 | 
			
		||||
                                else
 | 
			
		||||
                                {
 | 
			
		||||
                                    <select class="ql-header">
 | 
			
		||||
                                        <option selected=""></option>
 | 
			
		||||
                                        <option value="1"></option>
 | 
			
		||||
                                        <option value="2"></option>
 | 
			
		||||
                                        <option value="3"></option>
 | 
			
		||||
                                        <option value="4"></option>
 | 
			
		||||
                                        <option value="5"></option>
 | 
			
		||||
                                    </select>
 | 
			
		||||
                                    <span class="ql-formats">
 | 
			
		||||
                                        <button class="ql-bold"></button>
 | 
			
		||||
                                        <button class="ql-italic"></button>
 | 
			
		||||
                                        <button class="ql-underline"></button>
 | 
			
		||||
                                        <button class="ql-strike"></button>
 | 
			
		||||
                                    </span>
 | 
			
		||||
                                    <span class="ql-formats">
 | 
			
		||||
                                        <select class="ql-color"></select>
 | 
			
		||||
                                        <select class="ql-background"></select>
 | 
			
		||||
                                    </span>
 | 
			
		||||
                                    <span class="ql-formats">
 | 
			
		||||
                                        <button class="ql-list" value="ordered"></button>
 | 
			
		||||
                                        <button class="ql-list" value="bullet"></button>
 | 
			
		||||
                                    </span>
 | 
			
		||||
                                    <span class="ql-formats">
 | 
			
		||||
                                        <button class="ql-link"></button>
 | 
			
		||||
                                    </span>
 | 
			
		||||
                                }
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div @ref="@_editorElement"></div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    @_textEditorComponent
 | 
			
		||||
                </TabPanel>
 | 
			
		||||
            }
 | 
			
		||||
			@if (AllowRawHtml)
 | 
			
		||||
@ -103,26 +51,18 @@
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@code {
 | 
			
		||||
    private bool _initialized = false;
 | 
			
		||||
 | 
			
		||||
    private RichTextEditorInterop interop;
 | 
			
		||||
    private FileManager _fileManager;
 | 
			
		||||
    private string _activetab = "Rich";
 | 
			
		||||
 | 
			
		||||
    private ElementReference _editorElement;
 | 
			
		||||
    private ElementReference _toolBar;
 | 
			
		||||
    private bool _richfilemanager = false;
 | 
			
		||||
    private string _richhtml = string.Empty;
 | 
			
		||||
    private string _originalrichhtml = string.Empty;
 | 
			
		||||
 | 
			
		||||
    private bool _rawfilemanager = false;
 | 
			
		||||
    private FileManager _fileManager;
 | 
			
		||||
    private string _message = string.Empty;
 | 
			
		||||
    private string _rawhtmlid = "RawHtmlEditor_" + Guid.NewGuid().ToString("N");
 | 
			
		||||
    private string _rawhtml = string.Empty;
 | 
			
		||||
    private string _originalrawhtml = string.Empty;
 | 
			
		||||
 | 
			
		||||
    private string _message = string.Empty;
 | 
			
		||||
    private bool _contentchanged = false;
 | 
			
		||||
    private int _editorIndex;
 | 
			
		||||
    private ITextEditorProvider _textEditorProvider;
 | 
			
		||||
    private RenderFragment _textEditorComponent;
 | 
			
		||||
    private ITextEditor _textEditor;
 | 
			
		||||
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public string Content { get; set; }
 | 
			
		||||
@ -152,96 +92,47 @@
 | 
			
		||||
    [Parameter]
 | 
			
		||||
    public string DebugLevel { get; set; } = "info";
 | 
			
		||||
 | 
			
		||||
    public override List<Resource> Resources => new List<Resource>()
 | 
			
		||||
    {
 | 
			
		||||
        new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js", Location = ResourceLocation.Body },
 | 
			
		||||
        new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js", Location = ResourceLocation.Body },
 | 
			
		||||
        new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js", Location = ResourceLocation.Body }
 | 
			
		||||
    };
 | 
			
		||||
    public override List<Resource> Resources { get; set; } = new List<Resource>();
 | 
			
		||||
 | 
			
		||||
    protected override void OnInitialized()
 | 
			
		||||
    protected override async Task OnInitializedAsync()
 | 
			
		||||
    {
 | 
			
		||||
        interop = new RichTextEditorInterop(JSRuntime);
 | 
			
		||||
        if (string.IsNullOrEmpty(Placeholder))
 | 
			
		||||
        {
 | 
			
		||||
            Placeholder = Localizer["Placeholder"];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(AllowRichText)
 | 
			
		||||
        {
 | 
			
		||||
            _textEditorProvider = await GetTextEditorProvider();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override void OnParametersSet()
 | 
			
		||||
    {
 | 
			
		||||
        _richhtml = Content;
 | 
			
		||||
        _rawhtml = Content;
 | 
			
		||||
        _originalrawhtml = _rawhtml; // preserve for comparison later
 | 
			
		||||
        _originalrichhtml = "";
 | 
			
		||||
 | 
			
		||||
        if (Content != _originalrawhtml)
 | 
			
		||||
        {
 | 
			
		||||
            _contentchanged = true; // identifies when Content parameter has changed
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!AllowRichText)
 | 
			
		||||
        {
 | 
			
		||||
            _activetab = "Raw";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _textEditorComponent = (builder) =>
 | 
			
		||||
        {
 | 
			
		||||
            CreateTextEditor(builder);
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override async Task OnAfterRenderAsync(bool firstRender)
 | 
			
		||||
    {
 | 
			
		||||
        await base.OnAfterRenderAsync(firstRender);
 | 
			
		||||
 | 
			
		||||
        if (AllowRichText)
 | 
			
		||||
        if(_textEditor != null)
 | 
			
		||||
        {
 | 
			
		||||
            if (firstRender)
 | 
			
		||||
            {
 | 
			
		||||
                await interop.CreateEditor(
 | 
			
		||||
                    _editorElement,
 | 
			
		||||
                    _toolBar,
 | 
			
		||||
                    ReadOnly,
 | 
			
		||||
                    Placeholder,
 | 
			
		||||
                    Theme,
 | 
			
		||||
                    DebugLevel);
 | 
			
		||||
 | 
			
		||||
                await interop.LoadEditorContent(_editorElement, _richhtml);
 | 
			
		||||
 | 
			
		||||
                // preserve a copy of the content (Quill sanitizes content so we need to retrieve it from the editor as it may have been modified)
 | 
			
		||||
                _originalrichhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
 | 
			
		||||
                _initialized = true;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (_initialized)
 | 
			
		||||
                {
 | 
			
		||||
                    if (_contentchanged)
 | 
			
		||||
                    {
 | 
			
		||||
                        // reload editor if Content passed to component has changed
 | 
			
		||||
                        await interop.LoadEditorContent(_editorElement, _richhtml);
 | 
			
		||||
                        _originalrichhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        // preserve changed content on re-render event
 | 
			
		||||
                        var richhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
                        if (richhtml != _richhtml)
 | 
			
		||||
                        {
 | 
			
		||||
                            _richhtml = richhtml;
 | 
			
		||||
                            await interop.LoadEditorContent(_editorElement, _richhtml);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            _contentchanged = false;
 | 
			
		||||
            _textEditor.Initialize(Content, Content != _originalrawhtml);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await base.OnAfterRenderAsync(firstRender);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void CloseRichFileManager()
 | 
			
		||||
    {
 | 
			
		||||
        _richfilemanager = false;
 | 
			
		||||
        _message = string.Empty;
 | 
			
		||||
        StateHasChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void CloseRawFileManager()
 | 
			
		||||
    {
 | 
			
		||||
@ -259,78 +150,101 @@
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            var richhtml = "";
 | 
			
		||||
 | 
			
		||||
            if (AllowRichText)
 | 
			
		||||
            var richhtml = string.Empty;
 | 
			
		||||
            if (AllowRichText && _textEditor != null)
 | 
			
		||||
            {
 | 
			
		||||
                richhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
                richhtml = await _textEditor.GetContent();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (richhtml != _originalrichhtml && !string.IsNullOrEmpty(richhtml))
 | 
			
		||||
            return richhtml != null ? richhtml : _originalrawhtml;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public async Task InsertRawImage()
 | 
			
		||||
    {
 | 
			
		||||
        _message = string.Empty;
 | 
			
		||||
        if (_rawfilemanager)
 | 
			
		||||
        {
 | 
			
		||||
            var file = _fileManager.GetFile();
 | 
			
		||||
            if (file != null)
 | 
			
		||||
            {
 | 
			
		||||
                // convert Quill's empty content to empty string
 | 
			
		||||
                if (richhtml == "<p><br></p>")
 | 
			
		||||
                {
 | 
			
		||||
                    richhtml = string.Empty;
 | 
			
		||||
                }
 | 
			
		||||
                return richhtml;
 | 
			
		||||
                var interop = new Interop(JSRuntime);
 | 
			
		||||
                int pos = await interop.GetCaretPosition(_rawhtmlid);
 | 
			
		||||
                var image = "<img src=\"" + file.Url + "\" alt=\"" + ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name) + "\" class=\"img-fluid\">";
 | 
			
		||||
                _rawhtml = _rawhtml.Substring(0, pos) + image + _rawhtml.Substring(pos);
 | 
			
		||||
                _rawfilemanager = false;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // return original raw html content
 | 
			
		||||
                return _originalrawhtml;
 | 
			
		||||
                _message = Localizer["Message.Require.Image"];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            _rawfilemanager = true;
 | 
			
		||||
        }
 | 
			
		||||
        StateHasChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void CreateTextEditor(RenderTreeBuilder builder)
 | 
			
		||||
    {
 | 
			
		||||
        if(_textEditorProvider != null)
 | 
			
		||||
        {
 | 
			
		||||
            var editorType = Type.GetType(_textEditorProvider.EditorType);
 | 
			
		||||
            if (editorType != null)
 | 
			
		||||
            {
 | 
			
		||||
                builder.OpenComponent(0, editorType);
 | 
			
		||||
 | 
			
		||||
                //set editor parameters if available.
 | 
			
		||||
                var attributes = new Dictionary<string, object>
 | 
			
		||||
                {
 | 
			
		||||
                    { "AllowFileManagement", AllowFileManagement },
 | 
			
		||||
                    { "ReadOnly", ReadOnly },
 | 
			
		||||
                    { "Placeholder", Placeholder },
 | 
			
		||||
                    { "Theme", Theme },
 | 
			
		||||
                    { "DebugLevel", DebugLevel },
 | 
			
		||||
                    { "ToolbarContent", ToolbarContent }
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                var index = 1;
 | 
			
		||||
                foreach(var name in attributes.Keys)
 | 
			
		||||
                {
 | 
			
		||||
                    if (editorType.GetProperty(name) != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        builder.AddAttribute(index++, name, attributes[name]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                builder.AddComponentReferenceCapture(index, (c) =>
 | 
			
		||||
                {
 | 
			
		||||
                    _textEditor = (ITextEditor)c;
 | 
			
		||||
                });
 | 
			
		||||
                builder.CloseComponent();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task InsertRichImage()
 | 
			
		||||
    private async Task<ITextEditorProvider> GetTextEditorProvider()
 | 
			
		||||
    {
 | 
			
		||||
        _message = string.Empty;
 | 
			
		||||
        if (_richfilemanager)
 | 
			
		||||
        {            
 | 
			
		||||
            var file = _fileManager.GetFile();
 | 
			
		||||
			if (file != null)
 | 
			
		||||
			{
 | 
			
		||||
                await interop.InsertImage(_editorElement, file.Url, ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name), _editorIndex);
 | 
			
		||||
                _richhtml = await interop.GetHtml(_editorElement);
 | 
			
		||||
                _richfilemanager = false;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				_message = Localizer["Message.Require.Image"];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
            _editorIndex = await interop.GetCurrentCursor(_editorElement);
 | 
			
		||||
			_richfilemanager = true;
 | 
			
		||||
		}
 | 
			
		||||
		StateHasChanged();
 | 
			
		||||
	}
 | 
			
		||||
        const string DefaultEditorName = "Quill";
 | 
			
		||||
 | 
			
		||||
	public async Task InsertRawImage()
 | 
			
		||||
	{
 | 
			
		||||
		_message = string.Empty;
 | 
			
		||||
		if (_rawfilemanager)
 | 
			
		||||
		{
 | 
			
		||||
			var file = _fileManager.GetFile();
 | 
			
		||||
			if (file != null)
 | 
			
		||||
			{
 | 
			
		||||
				var interop = new Interop(JSRuntime);
 | 
			
		||||
                int pos = await interop.GetCaretPosition(_rawhtmlid);
 | 
			
		||||
				var image = "<img src=\"" + file.Url + "\" alt=\"" + ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name) + "\" class=\"img-fluid\">";
 | 
			
		||||
				_rawhtml = _rawhtml.Substring(0, pos) + image + _rawhtml.Substring(pos);
 | 
			
		||||
				_rawfilemanager = false;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				_message = Localizer["Message.Require.Image"];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			_rawfilemanager = true;
 | 
			
		||||
		}
 | 
			
		||||
		StateHasChanged();
 | 
			
		||||
	}
 | 
			
		||||
        var editorName = await GetTextEditorName(DefaultEditorName);
 | 
			
		||||
        var editorProviders = ServiceProvider.GetServices<ITextEditorProvider>();
 | 
			
		||||
        var editorProvider = editorProviders.FirstOrDefault(i => i.Name == editorName);
 | 
			
		||||
        if(editorProvider == null)
 | 
			
		||||
        {
 | 
			
		||||
            editorProvider = editorProviders.FirstOrDefault(i => i.Name == DefaultEditorName);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return editorProvider;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async Task<string> GetTextEditorName(string defaultName)
 | 
			
		||||
    {
 | 
			
		||||
        const string EditorSettingName = "TextEditor";
 | 
			
		||||
 | 
			
		||||
        var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
 | 
			
		||||
        return SettingService.GetSetting(settings, EditorSettingName, defaultName);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user