Fix #4358: RichTextEditor Provider Abstraction.
This commit is contained in:
		| @ -1,6 +1,7 @@ | ||||
| @namespace Oqtane.Modules.Admin.Site | ||||
| @inherits ModuleBase | ||||
| @using System.Text.RegularExpressions | ||||
| @using Microsoft.Extensions.DependencyInjection | ||||
| @inject NavigationManager NavigationManager | ||||
| @inject ISiteService SiteService | ||||
| @inject ITenantService TenantService | ||||
| @ -8,6 +9,7 @@ | ||||
| @inject IAliasService AliasService | ||||
| @inject IThemeService  ThemeService | ||||
| @inject ISettingService  SettingService | ||||
| @inject IServiceProvider ServiceProvider | ||||
| @inject IStringLocalizer<Index> Localizer | ||||
| @inject INotificationService NotificationService | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
| @ -123,6 +125,28 @@ | ||||
|                         </select> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <div class="row mb-1 align-items-center"> | ||||
|                     <Label Class="col-sm-3" For="textEditorProvider" HelpText="Select the text editor provider for the site" ResourceKey="TextEditorProvider">Text Editor Provider: </Label> | ||||
|                     <div class="col-sm-9"> | ||||
|                         <select id="textEditorProvider" class="form-select" value="@_textEditorProvider" required @onchange="TextEditorProviderChanged"> | ||||
|                             @if (_textEditorProviders != null) | ||||
|                             { | ||||
|                                 @foreach (var provider in _textEditorProviders) | ||||
|                                 { | ||||
|                                     <option value="@provider.EditorType">@provider.Name</option> | ||||
|                                 } | ||||
|                             } | ||||
|                         </select> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 @if (_textEditorProviderSettings != null) | ||||
|                 { | ||||
|                     <div class="row mb-1 align-items-center"> | ||||
|                         <div class="col-sm-9 offset-sm-3"> | ||||
|                         @_textEditorProviderSettings | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 } | ||||
|             </div> | ||||
|         </Section> | ||||
|         <Section Name="FileExtensions" Heading="File Extensions" ResourceKey="FileExtensions"> | ||||
| @ -438,6 +462,10 @@ | ||||
|     private string _tenant = string.Empty; | ||||
|     private string _database = string.Empty; | ||||
|     private string _connectionstring = string.Empty; | ||||
|     private string _textEditorProvider = ""; | ||||
|     private IEnumerable<ITextEditorProvider> _textEditorProviders; | ||||
|     private RenderFragment _textEditorProviderSettings; | ||||
|     private ISettingsControl _textEditorProviderSettingsControl; | ||||
|     private string _createdby; | ||||
|     private DateTime _createdon; | ||||
|     private string _modifiedby; | ||||
| @ -479,6 +507,7 @@ | ||||
|                 _containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype); | ||||
|                 _containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer; | ||||
|                 _admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer; | ||||
|                 _textEditorProviders = ServiceProvider.GetServices<ITextEditorProvider>(); | ||||
|  | ||||
|                 // page content | ||||
|                 _headcontent = site.HeadContent; | ||||
| @ -517,6 +546,10 @@ | ||||
|                 // aliases | ||||
|                 await GetAliases(); | ||||
|  | ||||
|                 //text editor | ||||
|                 _textEditorProvider = SettingService.GetSetting(settings, "TextEditorProvider", Constants.DefaultTextEditorProvider); | ||||
|                 LoadTextEditorProviderSettingsControl(); | ||||
|  | ||||
|                 // hosting model | ||||
|                 _rendermode = site.RenderMode; | ||||
|                 _runtime = site.Runtime; | ||||
| @ -673,17 +706,17 @@ | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
| 						site = await SiteService.UpdateSiteAsync(site); | ||||
|                         site = await SiteService.UpdateSiteAsync(site); | ||||
|  | ||||
|                         // SMTP | ||||
| 						var settings = await SettingService.GetSiteSettingsAsync(site.SiteId); | ||||
|                         var settings = await SettingService.GetSiteSettingsAsync(site.SiteId); | ||||
|                         settings = SettingService.SetSetting(settings, "SMTPHost", _smtphost, true); | ||||
| 						settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true); | ||||
| 						settings = SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, true); | ||||
| 						settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true); | ||||
| 						settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true); | ||||
| 						settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true); | ||||
| 						settings = SettingService.SetSetting(settings, "SMTPRelay", _smtprelay, true); | ||||
|                         settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true); | ||||
|                         settings = SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, true); | ||||
|                         settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true); | ||||
|                         settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true); | ||||
|                         settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true); | ||||
|                         settings = SettingService.SetSetting(settings, "SMTPRelay", _smtprelay, true); | ||||
|                         settings = SettingService.SetSetting(settings, "SMTPEnabled", _smtpenabled, true); | ||||
|                         settings = SettingService.SetSetting(settings, "SiteGuid", _siteguid, true); | ||||
|                         settings = SettingService.SetSetting(settings, "NotificationRetention", _retention.ToString(), true); | ||||
| @ -692,141 +725,149 @@ | ||||
|                         settings = SettingService.SetSetting(settings, "ImageFiles", (_ImageFiles != Constants.ImageFiles) ? _ImageFiles.Replace(" ", "") : "", false); | ||||
|                         settings = SettingService.SetSetting(settings, "UploadableFiles", (_UploadableFiles != Constants.UploadableFiles) ? _UploadableFiles.Replace(" ", "") : "", false); | ||||
|  | ||||
| 						await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId); | ||||
|                         //text editor | ||||
|                         settings = SettingService.SetSetting(settings, "TextEditorProvider", _textEditorProvider); | ||||
|  | ||||
| 						await logger.LogInformation("Site Settings Saved {Site}", site); | ||||
|                         await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId); | ||||
|  | ||||
| 					    NavigationManager.NavigateTo(NavigateUrl(), true); // reload | ||||
| 					} | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					AddModuleMessage(Localizer["Message.Required.SiteName"], MessageType.Warning); | ||||
| 				} | ||||
| 			} | ||||
| 			catch (Exception ex) | ||||
| 			{ | ||||
| 				await logger.LogError(ex, "Error Saving Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message); | ||||
| 				AddModuleMessage(Localizer["Error.SaveSite"], MessageType.Error); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
| 		} | ||||
| 	} | ||||
|                         await logger.LogInformation("Site Settings Saved {Site}", site); | ||||
|  | ||||
| 	private async Task DeleteSite() | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| 			var aliases = await AliasService.GetAliasesAsync(); | ||||
| 			if (aliases.Any(item => item.SiteId != PageState.Site.SiteId || item.TenantId != PageState.Site.TenantId)) | ||||
| 			{ | ||||
| 				await SiteService.DeleteSiteAsync(PageState.Site.SiteId); | ||||
| 				await logger.LogInformation("Site Deleted {SiteId}", PageState.Site.SiteId); | ||||
|                         if(_textEditorProviderSettingsControl != null) | ||||
|                         { | ||||
|                             await _textEditorProviderSettingsControl.UpdateSettings(); | ||||
|                         } | ||||
|  | ||||
| 				foreach (Alias alias in aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId)) | ||||
| 				{ | ||||
| 					await AliasService.DeleteAliasAsync(alias.AliasId); | ||||
| 				} | ||||
|                         NavigationManager.NavigateTo(NavigateUrl(), true); // reload | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     AddModuleMessage(Localizer["Message.Required.SiteName"], MessageType.Warning); | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 await logger.LogError(ex, "Error Saving Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message); | ||||
|                 AddModuleMessage(Localizer["Error.SaveSite"], MessageType.Error); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 				var redirect = aliases.First(item => item.SiteId != PageState.Site.SiteId || item.TenantId != PageState.Site.TenantId); | ||||
| 				NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + redirect.Name, true); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				AddModuleMessage(Localizer["Message.FailAuth.DeleteSite"], MessageType.Warning); | ||||
| 			} | ||||
| 		} | ||||
| 		catch (Exception ex) | ||||
| 		{ | ||||
| 			await logger.LogError(ex, "Error Deleting Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message); | ||||
| 			AddModuleMessage(Localizer["Error.DeleteSite"], MessageType.Error); | ||||
| 		} | ||||
| 	} | ||||
|     private async Task DeleteSite() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             var aliases = await AliasService.GetAliasesAsync(); | ||||
|             if (aliases.Any(item => item.SiteId != PageState.Site.SiteId || item.TenantId != PageState.Site.TenantId)) | ||||
|             { | ||||
|                 await SiteService.DeleteSiteAsync(PageState.Site.SiteId); | ||||
|                 await logger.LogInformation("Site Deleted {SiteId}", PageState.Site.SiteId); | ||||
|  | ||||
| 	private async Task SendEmail() | ||||
| 	{ | ||||
| 		if (_smtphost != "" && _smtpport != "" && _smtpsender != "") | ||||
| 		{ | ||||
| 			try | ||||
| 			{ | ||||
| 				var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
| 				settings = SettingService.SetSetting(settings, "SMTPHost", _smtphost, true); | ||||
| 				settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true); | ||||
| 				settings = SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, true); | ||||
| 				settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true); | ||||
| 				settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true); | ||||
| 				settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true); | ||||
| 				await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); | ||||
| 				await logger.LogInformation("Site SMTP Settings Saved"); | ||||
|                 foreach (Alias alias in aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId)) | ||||
|                 { | ||||
|                     await AliasService.DeleteAliasAsync(alias.AliasId); | ||||
|                 } | ||||
|  | ||||
| 				await NotificationService.AddNotificationAsync(new Notification(PageState.Site.SiteId, PageState.User, PageState.Site.Name + " SMTP Configuration Test", "SMTP Server Is Configured Correctly.")); | ||||
| 				AddModuleMessage(Localizer["Info.Smtp.SaveSettings"], MessageType.Info); | ||||
|                 var redirect = aliases.First(item => item.SiteId != PageState.Site.SiteId || item.TenantId != PageState.Site.TenantId); | ||||
|                 NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + redirect.Name, true); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 AddModuleMessage(Localizer["Message.FailAuth.DeleteSite"], MessageType.Warning); | ||||
|             } | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Deleting Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.DeleteSite"], MessageType.Error); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task SendEmail() | ||||
|     { | ||||
|         if (_smtphost != "" && _smtpport != "" && _smtpsender != "") | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
|                 settings = SettingService.SetSetting(settings, "SMTPHost", _smtphost, true); | ||||
|                 settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true); | ||||
|                 settings = SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, true); | ||||
|                 settings = SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, true); | ||||
|                 settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true); | ||||
|                 settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true); | ||||
|                 await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); | ||||
|                 await logger.LogInformation("Site SMTP Settings Saved"); | ||||
|  | ||||
|                 await NotificationService.AddNotificationAsync(new Notification(PageState.Site.SiteId, PageState.User, PageState.Site.Name + " SMTP Configuration Test", "SMTP Server Is Configured Correctly.")); | ||||
|                 AddModuleMessage(Localizer["Info.Smtp.SaveSettings"], MessageType.Info); | ||||
|                 await ScrollToPageTop(); | ||||
|             } | ||||
| 			catch (Exception ex) | ||||
| 			{ | ||||
| 				await logger.LogError(ex, "Error Testing SMTP Configuration"); | ||||
| 				AddModuleMessage(Localizer["Error.Smtp.TestConfig"], MessageType.Error); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			AddModuleMessage(Localizer["Message.Required.Smtp"], MessageType.Warning); | ||||
| 		} | ||||
| 	} | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 await logger.LogError(ex, "Error Testing SMTP Configuration"); | ||||
|                 AddModuleMessage(Localizer["Error.Smtp.TestConfig"], MessageType.Error); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             AddModuleMessage(Localizer["Message.Required.Smtp"], MessageType.Warning); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private void ToggleSMTPPassword() | ||||
| 	{ | ||||
| 		if (_smtppasswordtype == "password") | ||||
| 		{ | ||||
| 			_smtppasswordtype = "text"; | ||||
| 			_togglesmtppassword = SharedLocalizer["HidePassword"]; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			_smtppasswordtype = "password"; | ||||
| 			_togglesmtppassword = SharedLocalizer["ShowPassword"]; | ||||
| 		} | ||||
| 	} | ||||
|     private void ToggleSMTPPassword() | ||||
|     { | ||||
|         if (_smtppasswordtype == "password") | ||||
|         { | ||||
|             _smtppasswordtype = "text"; | ||||
|             _togglesmtppassword = SharedLocalizer["HidePassword"]; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             _smtppasswordtype = "password"; | ||||
|             _togglesmtppassword = SharedLocalizer["ShowPassword"]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private async Task GetAliases() | ||||
| 	{ | ||||
| 		if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) | ||||
| 		{ | ||||
| 			_aliases = await AliasService.GetAliasesAsync(); | ||||
| 			_aliases = _aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId).OrderBy(item => item.AliasId).ToList(); | ||||
| 		} | ||||
| 	} | ||||
|     private async Task GetAliases() | ||||
|     { | ||||
|         if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) | ||||
|         { | ||||
|             _aliases = await AliasService.GetAliasesAsync(); | ||||
|             _aliases = _aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId).OrderBy(item => item.AliasId).ToList(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private void AddAlias() | ||||
| 	{ | ||||
| 		_aliases.Add(new Alias { AliasId = 0, Name = "", IsDefault = false }); | ||||
| 		_aliasid = 0; | ||||
| 		_aliasname = ""; | ||||
| 		_defaultalias = "False"; | ||||
| 		StateHasChanged(); | ||||
| 	} | ||||
|     private void AddAlias() | ||||
|     { | ||||
|         _aliases.Add(new Alias { AliasId = 0, Name = "", IsDefault = false }); | ||||
|         _aliasid = 0; | ||||
|         _aliasname = ""; | ||||
|         _defaultalias = "False"; | ||||
|         StateHasChanged(); | ||||
|     } | ||||
|  | ||||
| 	private void EditAlias(Alias alias) | ||||
| 	{ | ||||
| 		_aliasid = alias.AliasId; | ||||
| 		_aliasname = alias.Name; | ||||
| 		_defaultalias = alias.IsDefault.ToString(); | ||||
| 		StateHasChanged(); | ||||
| 	} | ||||
|     private void EditAlias(Alias alias) | ||||
|     { | ||||
|         _aliasid = alias.AliasId; | ||||
|         _aliasname = alias.Name; | ||||
|         _defaultalias = alias.IsDefault.ToString(); | ||||
|         StateHasChanged(); | ||||
|     } | ||||
|  | ||||
| 	private async Task DeleteAlias(Alias alias) | ||||
| 	{ | ||||
| 		if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) | ||||
| 		{ | ||||
| 			await AliasService.DeleteAliasAsync(alias.AliasId); | ||||
| 			await GetAliases(); | ||||
| 			StateHasChanged(); | ||||
| 		} | ||||
| 	} | ||||
|     private async Task DeleteAlias(Alias alias) | ||||
|     { | ||||
|         if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) | ||||
|         { | ||||
|             await AliasService.DeleteAliasAsync(alias.AliasId); | ||||
|             await GetAliases(); | ||||
|             StateHasChanged(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task SaveAlias() | ||||
|     { | ||||
| @ -878,11 +919,42 @@ | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private async Task CancelAlias() | ||||
| 	{ | ||||
| 		await GetAliases(); | ||||
| 		_aliasid = -1; | ||||
| 		_aliasname = ""; | ||||
| 		StateHasChanged(); | ||||
| 	} | ||||
|     private async Task CancelAlias() | ||||
|     { | ||||
|         await GetAliases(); | ||||
|         _aliasid = -1; | ||||
|         _aliasname = ""; | ||||
|         StateHasChanged(); | ||||
|     } | ||||
|  | ||||
|     private void TextEditorProviderChanged(ChangeEventArgs e) | ||||
|     { | ||||
|         _textEditorProvider = e.Value.ToString(); | ||||
|         LoadTextEditorProviderSettingsControl(); | ||||
|  | ||||
|         StateHasChanged(); | ||||
|     } | ||||
|  | ||||
|     private void LoadTextEditorProviderSettingsControl() | ||||
|     { | ||||
|         var provider = _textEditorProviders.FirstOrDefault(i => i.EditorType == _textEditorProvider); | ||||
|         var settingsType = provider != null && !string.IsNullOrEmpty(provider.SettingsType) ? Type.GetType(provider.SettingsType) : null; | ||||
|         if (settingsType != null) | ||||
|         { | ||||
|             _textEditorProviderSettings = builder => | ||||
|             { | ||||
|                 builder.OpenComponent(0, settingsType); | ||||
|                 builder.AddComponentReferenceCapture(1, (c) => | ||||
|                 { | ||||
|                     _textEditorProviderSettingsControl = (ISettingsControl)c; | ||||
|                 }); | ||||
|                 builder.CloseComponent(); | ||||
|             }; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             _textEditorProviderSettings = null; | ||||
|             _textEditorProviderSettingsControl = null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,11 +1,12 @@ | ||||
| @namespace Oqtane.Modules.Controls | ||||
| @inherits ModuleControlBase | ||||
| @implements ITextEditor | ||||
| @inject IStringLocalizer<QuillTextEditor> Localizer | ||||
| @inject ISettingService SettingService | ||||
| @inject IStringLocalizer<QuillJSTextEditor> Localizer | ||||
| 
 | ||||
| <div class="quill-text-editor"> | ||||
|     <TabStrip ActiveTab="@_activetab"> | ||||
|         @if (AllowRichText) | ||||
|         @if (_allowRichText) | ||||
|         { | ||||
|             <TabPanel Name="Rich" Heading="Rich Text Editor" ResourceKey="RichTextEditor"> | ||||
|                 @if (_richfilemanager) | ||||
| @ -15,7 +16,7 @@ | ||||
|                     <br /> | ||||
|                 } | ||||
|                 <div class="d-flex justify-content-center mb-2"> | ||||
|                     @if (AllowFileManagement) | ||||
|                     @if (_allowFileManagement) | ||||
|                     { | ||||
|                         <button type="button" class="btn btn-primary" @onclick="InsertRichImage">@Localizer["InsertImage"]</button> | ||||
|                     } | ||||
| @ -28,9 +29,9 @@ | ||||
|                 <div class="row"> | ||||
|                     <div class="col"> | ||||
|                         <div @ref="@_toolBar"> | ||||
|                             @if (ToolbarContent != null) | ||||
|                             @if (!string.IsNullOrEmpty(_toolbarContent)) | ||||
|                             { | ||||
|                                 @ToolbarContent | ||||
|                                 @((MarkupString)_toolbarContent) | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
| @ -66,7 +67,7 @@ | ||||
|                 </div> | ||||
|             </TabPanel> | ||||
|         } | ||||
|         @if (AllowRawHtml) | ||||
|         @if (_allowRawHtml) | ||||
|         { | ||||
|             <TabPanel Name="Raw" Heading="Raw HTML Editor" ResourceKey="HtmlEditor"> | ||||
|                 @if (_rawfilemanager) | ||||
| @ -76,7 +77,7 @@ | ||||
|                     <br /> | ||||
|                 } | ||||
|                 <div class="d-flex justify-content-center mb-2"> | ||||
|                     @if (AllowFileManagement) | ||||
|                     @if (_allowFileManagement) | ||||
|                     { | ||||
|                         <button type="button" class="btn btn-primary" @onclick="InsertRawImage">@Localizer["InsertImage"]</button> | ||||
|                     } | ||||
| @ -106,6 +107,14 @@ | ||||
|     private FileManager _fileManager; | ||||
|     private string _activetab = "Rich"; | ||||
| 
 | ||||
|     private bool _allowFileManagement = false; | ||||
|     private bool _allowRawHtml = false; | ||||
|     private bool _allowRichText = false; | ||||
|     private string _theme = "snow"; | ||||
|     private string _debugLevel = "info"; | ||||
|     private string _toolbarContent = string.Empty; | ||||
|     private bool _settingsLoaded; | ||||
| 
 | ||||
|     private ElementReference _editorElement; | ||||
|     private ElementReference _toolBar; | ||||
|     private bool _richfilemanager = false; | ||||
| @ -121,38 +130,22 @@ | ||||
|     private bool _contentchanged = false; | ||||
|     private int _editorIndex; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public bool AllowFileManagement{ get; set; } | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public bool AllowRichText { get; set; } = true; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public bool AllowRawHtml { get; set; } = true; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public bool ReadOnly { get; set; } | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public string Placeholder { get; set; } | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public string Theme { get; set; } = "snow"; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public string DebugLevel { get; set; } = "info"; | ||||
| 
 | ||||
|     [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 } | ||||
|         new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js", Location = ResourceLocation.Body }, | ||||
|         new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.bubble.css" }, | ||||
|         new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.snow.css" } | ||||
|     }; | ||||
| 
 | ||||
|     protected override void OnInitialized() | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         interop = new QuillEditorInterop(JSRuntime); | ||||
| 
 | ||||
| @ -160,11 +153,13 @@ | ||||
|         { | ||||
|             Placeholder = Localizer["Placeholder"]; | ||||
|         } | ||||
| 
 | ||||
|         await LoadSettings(); | ||||
|     } | ||||
| 
 | ||||
|     protected override void OnParametersSet() | ||||
|     { | ||||
|         if (!AllowRichText) | ||||
|         if (!_allowRichText) | ||||
|         { | ||||
|             _activetab = "Raw"; | ||||
|         } | ||||
| @ -174,17 +169,17 @@ | ||||
|     { | ||||
|         await base.OnAfterRenderAsync(firstRender); | ||||
| 
 | ||||
|         if (AllowRichText) | ||||
|         if (_allowRichText) | ||||
|         { | ||||
|             if (firstRender) | ||||
|             if (_settingsLoaded && !_initialized) | ||||
|             { | ||||
|                 await interop.CreateEditor( | ||||
|                     _editorElement, | ||||
|                     _toolBar, | ||||
|                     ReadOnly, | ||||
|                     Placeholder, | ||||
|                     Theme, | ||||
|                     DebugLevel); | ||||
|                     _theme, | ||||
|                     _debugLevel); | ||||
| 
 | ||||
|                 await interop.LoadEditorContent(_editorElement, _richhtml); | ||||
| 
 | ||||
| @ -202,6 +197,8 @@ | ||||
|                         // reload editor if Content passed to component has changed | ||||
|                         await interop.LoadEditorContent(_editorElement, _richhtml); | ||||
|                         _originalrichhtml = await interop.GetHtml(_editorElement); | ||||
| 
 | ||||
|                         _contentchanged = false; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
| @ -215,8 +212,6 @@ | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             _contentchanged = false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -224,10 +219,14 @@ | ||||
|     { | ||||
|         _richhtml = content; | ||||
|         _rawhtml = content; | ||||
|         _originalrawhtml = _rawhtml; // preserve for comparison later | ||||
|         _originalrichhtml = ""; | ||||
|         _richhtml = content; | ||||
|         _contentchanged = content != _originalrawhtml; | ||||
|         if (!_contentchanged) | ||||
|         { | ||||
|             _contentchanged = content != _originalrawhtml; | ||||
|         } | ||||
| 
 | ||||
|         _originalrawhtml = _rawhtml; // preserve for comparison later | ||||
| 
 | ||||
|         StateHasChanged(); | ||||
|     } | ||||
| @ -243,7 +242,7 @@ | ||||
|         { | ||||
|             var richhtml = ""; | ||||
| 
 | ||||
|             if (AllowRichText) | ||||
|             if (_allowRichText) | ||||
|             { | ||||
|                 richhtml = await interop.GetHtml(_editorElement); | ||||
|             } | ||||
| @ -290,7 +289,7 @@ | ||||
|         { | ||||
|             var richhtml = ""; | ||||
| 
 | ||||
|             if (AllowRichText) | ||||
|             if (_allowRichText) | ||||
|             { | ||||
|                 richhtml = await interop.GetHtml(_editorElement); | ||||
|             } | ||||
| @ -362,4 +361,24 @@ | ||||
|         } | ||||
|         StateHasChanged(); | ||||
|     } | ||||
| 
 | ||||
|     private async Task LoadSettings() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
|             _allowFileManagement = SettingService.GetSetting(settings, "QuillTextEditor_AllowFileManagement", "true") == "true"; | ||||
|             _allowRawHtml = SettingService.GetSetting(settings, "QuillTextEditor_AllowRawHtml", "true") == "true"; | ||||
|             _allowRichText = SettingService.GetSetting(settings, "QuillTextEditor_AllowRichText", "true") == "true"; | ||||
|             _theme = SettingService.GetSetting(settings, "QuillTextEditor_Theme", "snow"); | ||||
|             _debugLevel = SettingService.GetSetting(settings, "QuillTextEditor_DebugLevel", "info"); | ||||
|             _toolbarContent = SettingService.GetSetting(settings, "QuillTextEditor_ToolbarContent", string.Empty); | ||||
| 
 | ||||
|             _settingsLoaded = true; | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AddModuleMessage(ex.Message, MessageType.Error); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,99 @@ | ||||
| @namespace Oqtane.Modules.Controls | ||||
| @inherits ModuleBase | ||||
| @inject ISettingService SettingService | ||||
| @implements Oqtane.Interfaces.ISettingsControl | ||||
| @inject IStringLocalizer<QuillJSTextEditorSettings> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <div class="container"> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="AllowFileManagement" ResourceKey="AllowFileManagement" ResourceType="@resourceType" HelpText="Specify If Editors Can Upload and Select Files">Allow File Management: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input type="checkbox" id="AllowFileManagement" class="form-check-input" @bind="_allowFileManagement" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="AllowRawHtml" ResourceKey="AllowRawHtml" ResourceType="@resourceType" HelpText="Specify If Editors Can Enter Raw HTML">Allow Raw HTML: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input type="checkbox" id="AllowRawHtml" class="form-check-input" @bind="_allowRawHtml" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="AllowRichText" ResourceKey="AllowRichText" ResourceType="@resourceType" HelpText="Specify If Editors Can Use Rich Text Editor">Allow Rich Text: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input type="checkbox" id="AllowRichText" class="form-check-input" @bind="_allowRichText" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="Theme" ResourceKey="Theme" ResourceType="@resourceType" HelpText="Specify the Rich Text Editor's Theme">Theme: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input type="text" id="Theme" class="form-control" @bind="_theme" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="DebugLevel" ResourceKey="DebugLevel" ResourceType="@resourceType" HelpText="Specify the Debug Level">Debug Level: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <select id="DebugLevel" class="form-select" @bind="_debugLevel"> | ||||
|                 @foreach (var level in _debugLevels) | ||||
|                 { | ||||
|                     <option value="@level">@level</option> | ||||
|                 } | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="ToolbarContent" ResourceKey="ToolbarContent" ResourceType="@resourceType" HelpText="Specify the Toolbar Content">Toolbar Content: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <textarea id="ToolbarContent" class="form-control" @bind="_toolbarContent" rows="5" /> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private string resourceType = "Oqtane.Modules.Controls.QuillJSTextEditorSettings, Oqtane.Client"; | ||||
|     private bool _allowFileManagement; | ||||
|     private bool _allowRawHtml; | ||||
|     private bool _allowRichText; | ||||
|     private string _theme; | ||||
|     private string _debugLevel; | ||||
|     private string _toolbarContent; | ||||
|  | ||||
|     private List<string> _debugLevels = new List<string> { "info", "log", "warn", "error" }; | ||||
|  | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
|             _allowFileManagement = SettingService.GetSetting(settings, "QuillTextEditor_AllowFileManagement", "true") == "true"; | ||||
|             _allowRawHtml = SettingService.GetSetting(settings, "QuillTextEditor_AllowRawHtml", "true") == "true"; | ||||
|             _allowRichText = SettingService.GetSetting(settings, "QuillTextEditor_AllowRichText", "true") == "true"; | ||||
|             _theme = SettingService.GetSetting(settings, "QuillTextEditor_Theme", "snow"); | ||||
|             _debugLevel = SettingService.GetSetting(settings, "QuillTextEditor_DebugLevel", "info"); | ||||
|             _toolbarContent = SettingService.GetSetting(settings, "QuillTextEditor_ToolbarContent", string.Empty); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AddModuleMessage(ex.Message, MessageType.Error); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public async Task UpdateSettings() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_AllowFileManagement", _allowFileManagement.ToString().ToLower()); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_AllowRawHtml", _allowRawHtml.ToString().ToLower()); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_AllowRichText", _allowRichText.ToString().ToLower()); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_Theme", _theme); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_DebugLevel", _debugLevel); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_ToolbarContent", _toolbarContent); | ||||
|             await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AddModuleMessage(ex.Message, MessageType.Error); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -4,7 +4,6 @@ | ||||
| @namespace Oqtane.Modules.Controls | ||||
| @inherits ModuleControlBase | ||||
| @inject IServiceProvider ServiceProvider | ||||
| @inject ISettingService SettingService | ||||
| @inject IStringLocalizer<RichTextEditor> Localizer  | ||||
|  | ||||
| <div class="row" style="margin-bottom: 50px;"> | ||||
| @ -14,7 +13,7 @@ | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private ITextEditorProvider _textEditorProvider; | ||||
|     private string _textEditorProvider; | ||||
|     private RenderFragment _textEditorComponent; | ||||
|     private ITextEditor _textEditor; | ||||
|  | ||||
| @ -28,29 +27,14 @@ | ||||
|     public string Placeholder { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public bool AllowFileManagement { get; set; } = true; | ||||
|     public string Provider { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public bool AllowRichText { get; set; } = true;   | ||||
|  | ||||
|     [Parameter] | ||||
|     public bool AllowRawHtml { get; set; } = true;   | ||||
|  | ||||
|     // parameters only applicable to rich text editor | ||||
|     [Parameter] | ||||
|     public RenderFragment ToolbarContent { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public string Theme { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public string DebugLevel { get; set; } | ||||
|  | ||||
|     public override List<Resource> Resources { get; set; } = new List<Resource>(); | ||||
|     [Parameter(CaptureUnmatchedValues = true)] | ||||
|     public Dictionary<string, object> AdditionalAttributes { get; set; } = new Dictionary<string, object>(); | ||||
|  | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         _textEditorProvider = await GetTextEditorProvider(); | ||||
|         _textEditorProvider = await GetTextEditorType(ServiceProvider, PageState.Site.SiteId); | ||||
|     } | ||||
|  | ||||
|     protected override void OnParametersSet() | ||||
| @ -71,6 +55,22 @@ | ||||
|         await base.OnAfterRenderAsync(firstRender); | ||||
|     } | ||||
|  | ||||
|     public override async Task<List<Resource>> GetResources(IServiceProvider serviceProvider, Page page) | ||||
|     { | ||||
|         var type = await GetTextEditorType(serviceProvider, page.SiteId); | ||||
|         if (!string.IsNullOrEmpty(type)) | ||||
|         { | ||||
|             var editorType = Type.GetType(type); | ||||
|             if (editorType != null && editorType.GetInterfaces().Contains(typeof(IModuleControl))) | ||||
|             { | ||||
|                 var control = Activator.CreateInstance(editorType) as IModuleControl; | ||||
|                 return await control?.GetResources(serviceProvider, page); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return await base.GetResources(serviceProvider, page); | ||||
|     } | ||||
|  | ||||
|     public async Task<string> GetHtml() | ||||
|     { | ||||
|         return await _textEditor.GetContent(); | ||||
| @ -78,37 +78,32 @@ | ||||
|  | ||||
|     private void CreateTextEditor(RenderTreeBuilder builder) | ||||
|     { | ||||
|         if(_textEditorProvider != null) | ||||
|         if(!string.IsNullOrEmpty(_textEditorProvider)) | ||||
|         { | ||||
|             var editorType = Type.GetType(_textEditorProvider.EditorType); | ||||
|             var editorType = Type.GetType(_textEditorProvider); | ||||
|             if (editorType != null) | ||||
|             { | ||||
|                 builder.OpenComponent(0, editorType); | ||||
|  | ||||
|                 //set editor parameters if available. | ||||
|                 var attributes = new Dictionary<string, object> | ||||
|                 { | ||||
|                     { "AllowFileManagement", AllowFileManagement }, | ||||
|                     { "AllowRichText", AllowRichText }, | ||||
|                     { "AllowRawHtml", AllowRawHtml }, | ||||
|                     { "Placeholder", Placeholder }, | ||||
|                     { "ReadOnly", ReadOnly } | ||||
|                 }; | ||||
|  | ||||
|                 if(!string.IsNullOrEmpty(Theme)) | ||||
|                 if (AdditionalAttributes != null) | ||||
|                 { | ||||
|                     attributes.Add("Theme", Theme); | ||||
|                 } | ||||
|                 if (!string.IsNullOrEmpty(DebugLevel)) | ||||
|                 { | ||||
|                     attributes.Add("DebugLevel", DebugLevel); | ||||
|                 } | ||||
|                 if (!string.IsNullOrEmpty(Placeholder)) | ||||
|                 { | ||||
|                     attributes.Add("Placeholder", Placeholder); | ||||
|                 } | ||||
|                 if(ToolbarContent != null) | ||||
|                 { | ||||
|                     attributes.Add("ToolbarContent", ToolbarContent); | ||||
|                     foreach(var key in AdditionalAttributes.Keys) | ||||
|                     { | ||||
|                         if(!attributes.ContainsKey(key)) | ||||
|                         { | ||||
|                             attributes.Add(key, AdditionalAttributes[key]); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             attributes[key] = AdditionalAttributes[key]; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 var index = 1; | ||||
| @ -129,26 +124,21 @@ | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task<ITextEditorProvider> GetTextEditorProvider() | ||||
|     private async Task<string> GetTextEditorType(IServiceProvider serviceProvider, int siteId) | ||||
|     { | ||||
|         const string DefaultEditorName = "Quill"; | ||||
|         const string EditorSettingName = "TextEditorProvider"; | ||||
|  | ||||
|         var editorName = await GetTextEditorName(DefaultEditorName); | ||||
|         var editorProviders = ServiceProvider.GetServices<ITextEditorProvider>(); | ||||
|         var editorProvider = editorProviders.FirstOrDefault(i => i.Name == editorName); | ||||
|         if(editorProvider == null) | ||||
|         if(!string.IsNullOrEmpty(Provider)) | ||||
|         { | ||||
|             editorProvider = editorProviders.FirstOrDefault(i => i.Name == DefaultEditorName); | ||||
|             var provider = serviceProvider.GetServices<ITextEditorProvider>().FirstOrDefault(i => i.Name.Equals(Provider, StringComparison.OrdinalIgnoreCase)); | ||||
|             if(provider != null) | ||||
|             { | ||||
|                 return provider.EditorType; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         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); | ||||
|         var settingService = serviceProvider.GetService<ISettingService>(); | ||||
|         var settings = await settingService.GetSiteSettingsAsync(siteId); | ||||
|         return settingService.GetSetting(settings, EditorSettingName, Constants.DefaultTextEditorProvider); | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										31
									
								
								Oqtane.Client/Modules/Controls/TextAreaTextEditor.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Oqtane.Client/Modules/Controls/TextAreaTextEditor.razor
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| @namespace Oqtane.Modules.Controls | ||||
| @inherits ModuleControlBase | ||||
| @implements ITextEditor | ||||
|  | ||||
| <div class="text-area-editor"> | ||||
|     <textarea @bind="_content" @ref="_editor" placeholder="@Placeholder" readonly="@ReadOnly" /> | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private ElementReference _editor; | ||||
|     private string _content; | ||||
|  | ||||
|     [Parameter] | ||||
|     public bool ReadOnly { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public string Placeholder { get; set; } | ||||
|  | ||||
|     public void Initialize(string content) | ||||
|     { | ||||
|         _content = content; | ||||
|  | ||||
|         StateHasChanged(); | ||||
|     } | ||||
|  | ||||
|     public async Task<string> GetContent() | ||||
|     { | ||||
|         await Task.CompletedTask; | ||||
|         return _content; | ||||
|     } | ||||
| } | ||||
| @ -13,7 +13,7 @@ | ||||
|     <TabPanel Name="Edit" Heading="Edit" ResourceKey="Edit"> | ||||
| 		@if (_content != null) | ||||
| 		{ | ||||
| 			<RichTextEditor Content="@_content" AllowFileManagement="@_allowfilemanagement" AllowRawHtml="@_allowrawhtml" @ref="@RichTextEditorHtml"></RichTextEditor> | ||||
| 			<RichTextEditor Content="@_content" @ref="@RichTextEditorHtml"></RichTextEditor> | ||||
| 			<br /> | ||||
| 			<button type="button" class="btn btn-success" @onclick="SaveContent">@SharedLocalizer["Save"]</button> | ||||
| 			<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> | ||||
| @ -47,44 +47,36 @@ | ||||
| </TabStrip> | ||||
|  | ||||
| @code { | ||||
| 	public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; | ||||
|     public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; | ||||
|  | ||||
| 	public override string Title => "Edit Html/Text"; | ||||
|     public override string Title => "Edit Html/Text"; | ||||
|  | ||||
| 	public override List<Resource> Resources => new List<Resource>() | ||||
| 	{ | ||||
|         new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.bubble.css" }, | ||||
|         new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.snow.css" } | ||||
|     }; | ||||
|     private RichTextEditor RichTextEditorHtml; | ||||
|     private string _content = null; | ||||
|     private string _createdby; | ||||
|     private DateTime _createdon; | ||||
|     private string _modifiedby; | ||||
|     private DateTime _modifiedon; | ||||
|     private List<Models.HtmlText> _htmltexts; | ||||
|     private string _view = ""; | ||||
|  | ||||
| 	private RichTextEditor RichTextEditorHtml; | ||||
| 	private bool _allowfilemanagement; | ||||
| 	private bool _allowrawhtml; | ||||
| 	private string _content = null; | ||||
| 	private string _createdby; | ||||
| 	private DateTime _createdon; | ||||
| 	private string _modifiedby; | ||||
| 	private DateTime _modifiedon; | ||||
| 	private List<Models.HtmlText> _htmltexts; | ||||
| 	private string _view = ""; | ||||
|     public override List<string> ResourcesRegistrationTypes => new List<string> { typeof(RichTextEditor).FullName }; | ||||
|  | ||||
| 	protected override async Task OnInitializedAsync() | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| 			_allowfilemanagement = bool.Parse(SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true")); | ||||
| 			_allowrawhtml = bool.Parse(SettingService.GetSetting(ModuleState.Settings, "AllowRawHtml", "true")); | ||||
| 			await LoadContent(); | ||||
| 		} | ||||
| 		catch (Exception ex) | ||||
| 		{ | ||||
| 			await logger.LogError(ex, "Error Loading Content {Error}", ex.Message); | ||||
| 			AddModuleMessage(Localizer["Error.Content.Load"], MessageType.Error); | ||||
| 		} | ||||
| 	} | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             await LoadContent(); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             await logger.LogError(ex, "Error Loading Content {Error}", ex.Message); | ||||
|             AddModuleMessage(Localizer["Error.Content.Load"], MessageType.Error); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	private async Task LoadContent() | ||||
| 	{ | ||||
|     private async Task LoadContent() | ||||
|     { | ||||
| 		var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId); | ||||
| 		if (htmltext != null) | ||||
| 		{ | ||||
|  | ||||
| @ -15,7 +15,7 @@ namespace Oqtane.Modules.HtmlText | ||||
|             Version = "1.0.1", | ||||
|             ServerManagerType = "Oqtane.Modules.HtmlText.Manager.HtmlTextManager, Oqtane.Server", | ||||
|             ReleaseVersions = "1.0.0,1.0.1", | ||||
|             SettingsType = "Oqtane.Modules.HtmlText.Settings, Oqtane.Client", | ||||
|             SettingsType = string.Empty, | ||||
|             Resources = new List<Resource>() | ||||
|             { | ||||
|                 new Resource { ResourceType = ResourceType.Stylesheet, Url = "~/Module.css" } | ||||
|  | ||||
| @ -1,61 +0,0 @@ | ||||
| @namespace Oqtane.Modules.HtmlText | ||||
| @inherits ModuleBase | ||||
| @inject ISettingService SettingService | ||||
| @implements Oqtane.Interfaces.ISettingsControl | ||||
| @inject IStringLocalizer<Settings> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <div class="container"> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="files" ResourceKey="AllowFileManagement" ResourceType="@resourceType" HelpText="Specify If Editors Can Upload and Select Files">Allow File Management: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <select id="files" class="form-select" @bind="@_allowfilemanagement"> | ||||
|                 <option value="true">@SharedLocalizer["Yes"]</option> | ||||
|                 <option value="false">@SharedLocalizer["No"]</option> | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="files" ResourceKey="AllowRawHtml" ResourceType="@resourceType" HelpText="Specify If Editors Can Enter Raw HTML">Allow Raw HTML: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <select id="files" class="form-select" @bind="@_allowrawhtml"> | ||||
|                 <option value="true">@SharedLocalizer["Yes"]</option> | ||||
|                 <option value="false">@SharedLocalizer["No"]</option> | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| @code {		 | ||||
| 	private string resourceType = "Oqtane.Modules.HtmlText.Settings, Oqtane.Client"; // for localization | ||||
|     private string _allowfilemanagement; | ||||
| 	private string _allowrawhtml; | ||||
|  | ||||
|     protected override void OnInitialized() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
| 			_allowfilemanagement = SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true"); | ||||
| 			_allowrawhtml = SettingService.GetSetting(ModuleState.Settings, "AllowRawHtml", "true"); | ||||
| 		} | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AddModuleMessage(ex.Message, MessageType.Error); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public async Task UpdateSettings() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
| 			var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId); | ||||
|             settings = SettingService.SetSetting(settings, "AllowFileManagement", _allowfilemanagement); | ||||
| 			settings = SettingService.SetSetting(settings, "AllowRawHtml", _allowrawhtml); | ||||
| 			await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AddModuleMessage(ex.Message, MessageType.Error); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -50,6 +50,8 @@ namespace Oqtane.Modules | ||||
|  | ||||
|         public virtual List<Resource> Resources { get; set; } | ||||
|  | ||||
|         public virtual List<string> ResourcesRegistrationTypes { get; } | ||||
|  | ||||
|         public virtual string RenderMode { get { return RenderModes.Interactive; } } // interactive by default | ||||
|  | ||||
|         public virtual bool? Prerender { get { return null; } } // allows the Site Prerender property to be overridden | ||||
| @ -71,6 +73,21 @@ namespace Oqtane.Modules | ||||
|  | ||||
|         // base lifecycle method for handling JSInterop script registration | ||||
|  | ||||
|         public virtual async Task<List<Resource>> GetResources(IServiceProvider serviceProvider, Page page) | ||||
|         { | ||||
|             var resources = Resources ?? new List<Resource>(); | ||||
|  | ||||
|             if(ResourcesRegistrationTypes != null) | ||||
|             { | ||||
|                 foreach(var type in ResourcesRegistrationTypes) | ||||
|                 { | ||||
|                     resources.AddRange(await LoadResourcesFromType(serviceProvider, page, type)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return resources; | ||||
|         } | ||||
|  | ||||
|         protected override async Task OnAfterRenderAsync(bool firstRender) | ||||
|         { | ||||
|             if (firstRender) | ||||
| @ -482,6 +499,25 @@ namespace Oqtane.Modules | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private async Task<List<Resource>> LoadResourcesFromType(IServiceProvider serviceProvider, Page page, string typeName) | ||||
|         { | ||||
|             try | ||||
|             { | ||||
|                 var type = Type.GetType(typeName, false, true); | ||||
|                 if (type != null && type.GetInterfaces().Contains(typeof(IModuleControl))) | ||||
|                 { | ||||
|                     var control = Activator.CreateInstance(type) as IModuleControl; | ||||
|                     return await control?.GetResources(serviceProvider, page); | ||||
|                 } | ||||
|             } | ||||
|             catch(Exception ex) | ||||
|             { | ||||
|                 //await Log(null, LogLevel.Error, string.Empty, ex, "Load Resources From Type {Type} Failed. {Message}", typeName, ex.Message); | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         [Obsolete("ContentUrl(int fileId) is deprecated. Use FileUrl(int fileId) instead.", false)] | ||||
|         public string ContentUrl(int fileid) | ||||
|         { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Ben
					Ben