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
	 Ben
					Ben