resolved #270 - migrated raw html entry into richtexteditor control

This commit is contained in:
Shaun Walker 2020-05-08 12:17:06 -04:00
parent f07146fd50
commit 051534b80c
4 changed files with 158 additions and 172 deletions

View File

@ -3,27 +3,80 @@
@attribute [OqtaneIgnore]
@inject IJSRuntime JsRuntime
@if (_filemanagervisible)
{
<FileManager @ref="_fileManager" Filter="@Constants.ImageFiles" />
@((MarkupString)_message)
<br />
}
<div class="row justify-content-center">
<button type="button" class="btn btn-success" @onclick="InsertImage">Insert Image</button>
@if (_filemanagervisible)
{
@((MarkupString)"&nbsp;&nbsp;")
<button type="button" class="btn btn-secondary" @onclick="CloseFileManager">Close</button>
}
</div>
<div class="row">
<div class ="col">
<div @ref="@_toolBar">
@ToolbarContent
</div>
<div @ref="@_editorElement">
</div>
<div class="row" style="margin-bottom: 50px;">
<div class="col">
<TabStrip>
<TabPanel Name="Rich" Heading="Rich Text Editor">
@if (_filemanagervisible)
{
<FileManager @ref="_fileManager" Filter="@Constants.ImageFiles" />
@((MarkupString)_message)
<br />
}
<div class="row justify-content-center" style="margin-bottom: 20px;">
<button type="button" class="btn btn-secondary" @onclick="RefreshRichText">Synchronize Content</button>&nbsp;&nbsp;
<button type="button" class="btn btn-primary" @onclick="InsertImage">Insert Image</button>
@if (_filemanagervisible)
{
@((MarkupString)"&nbsp;&nbsp;")
<button type="button" class="btn btn-secondary" @onclick="CloseFileManager">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>
</TabPanel>
<TabPanel Name="Raw" Heading="Raw HTML Editor">
<div class="row justify-content-center" style="margin-bottom: 20px;">
<button type="button" class="btn btn-secondary" @onclick="RefreshRawHtml">Synchronize Content</button>
</div>
@if (ReadOnly)
{
<textarea class="form-control" @bind="@_content" rows="10" readonly></textarea>
}
else
{
<textarea class="form-control" @bind="@_content" rows="10"></textarea>
}
</TabPanel>
</TabStrip>
</div>
</div>
@ -32,10 +85,12 @@
private ElementReference _toolBar;
private bool _filemanagervisible = false;
private FileManager _fileManager;
private string _original = string.Empty;
private string _content = string.Empty;
private string _message = string.Empty;
[Parameter]
public RenderFragment ToolbarContent { get; set; }
public string Content { get; set; }
[Parameter]
public bool ReadOnly { get; set; } = false;
@ -43,12 +98,27 @@
[Parameter]
public string Placeholder { get; set; } = "Enter Your Content...";
// parameters only applicable to rich text editor
[Parameter]
public RenderFragment ToolbarContent { get; set; }
[Parameter]
public string Theme { get; set; } = "snow";
[Parameter]
public string DebugLevel { get; set; } = "info";
protected override void OnInitialized()
{
_original = Content;
_content = _original;
if (string.IsNullOrEmpty(_content))
{
_content = Placeholder;
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
@ -61,6 +131,10 @@
Placeholder,
Theme,
DebugLevel);
await RichTextEditorInterop.LoadEditorContent(
JsRuntime,
_editorElement, _original);
}
}
@ -73,9 +147,18 @@
public async Task<string> GetHtml()
{
return await RichTextEditorInterop.GetHtml(
JsRuntime,
_editorElement);
if (_original != _content)
{
// raw html content changed
return _content;
}
else
{
// return rich text content
return await RichTextEditorInterop.GetHtml(
JsRuntime,
_editorElement);
}
}
public async Task<string> GetContent()
@ -85,13 +168,6 @@
_editorElement);
}
public async Task LoadContent(string content)
{
await RichTextEditorInterop.LoadEditorContent(
JsRuntime,
_editorElement, content);
}
public async Task EnableEditor(bool mode)
{
await RichTextEditorInterop.EnableEditor(
@ -122,7 +198,6 @@
_filemanagervisible = true;
_message = string.Empty;
}
StateHasChanged();
}
@ -130,8 +205,21 @@
{
_filemanagervisible = false;
_message = string.Empty;
StateHasChanged();
}
public async Task RefreshRichText()
{
await RichTextEditorInterop.LoadEditorContent(
JsRuntime,
_editorElement, _content);
}
public async Task RefreshRawHtml()
{
_content = await RichTextEditorInterop.GetHtml(
JsRuntime,
_editorElement);
StateHasChanged();
}
}

View File

@ -2,7 +2,7 @@
using Microsoft.JSInterop;
using System.Threading.Tasks;
namespace Oqtane.UI
namespace Oqtane.Modules.Controls
{
public static class RichTextEditorInterop
{

View File

@ -7,111 +7,48 @@
@inject HttpClient http
@inject SiteState sitestate
<div class="row" style="margin-bottom: 50px;">
<div class="col @_visibleText">
<textarea class="form-control" @bind="@content" rows="10"></textarea>
</div>
<div class="col @_visibleRich">
<RichTextEditor @ref="@RichTextEditorHtml">
<ToolbarContent>
<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>
</ToolbarContent>
</RichTextEditor>
</div>
</div>
<div class="row">
<div class="col">
@if (!RichTextEditorMode)
{
<button type="button" class="btn btn-secondary" @onclick="RichTextEditor">Rich Text Editor</button>
}
else
{
<button type="button" class="btn btn-secondary" @onclick="RawHtmlEditor">Raw HTML Editor</button>
}
<button type="button" class="btn btn-success" @onclick="SaveContent">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
</div>
</div>
<div class="row">
<div class="col">
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
</div>
</div>
@if (_content != null)
{
<RichTextEditor Content="@_content" @ref="@RichTextEditorHtml"></RichTextEditor>
<button type="button" class="btn btn-success" @onclick="SaveContent">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
@if (!string.IsNullOrEmpty(_content))
{
<br /><br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
}
}
@code {
private string _visibleText = "d-none";
private string _visibleRich;
private bool _richTextEditorMode;
private RichTextEditor RichTextEditorHtml;
private string content;
private string createdby;
private DateTime createdon;
private string modifiedby;
private DateTime modifiedon;
private string _content = null;
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
private DateTime _modifiedon;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override string Title => "Edit Html/Text";
public bool RichTextEditorMode
{
get => _richTextEditorMode;
set
{
_richTextEditorMode = value;
if (_richTextEditorMode)
{
_visibleText = "d-none";
_visibleRich = string.Empty;
}
else
{
_visibleText = string.Empty;
_visibleRich = "d-none";
}
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
protected override async Task OnInitializedAsync()
{
try
{
if (firstRender)
var htmltextservice = new HtmlTextService(http, sitestate);
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
if (content == null)
{
RichTextEditorMode = true;
await LoadText();
}
_content = htmltext.Content;
_content = _content.Replace(Constants.ContentUrl, "/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl);
_createdby = htmltext.CreatedBy;
_createdon = htmltext.CreatedOn;
_modifiedby = htmltext.ModifiedBy;
_modifiedon = htmltext.ModifiedOn;
}
else
{
_content = string.Empty;
}
}
catch (Exception ex)
@ -121,48 +58,10 @@
}
}
private async Task LoadText()
{
var htmltextservice = new HtmlTextService(http, sitestate);
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{
content = htmltext.Content;
createdby = htmltext.CreatedBy;
createdon = htmltext.CreatedOn;
modifiedby = htmltext.ModifiedBy;
modifiedon = htmltext.ModifiedOn;
if (RichTextEditorMode)
{
await RichTextEditorHtml.LoadContent(content);
StateHasChanged();
}
}
}
private async Task RichTextEditor()
{
RichTextEditorMode = true;
await RichTextEditorHtml.LoadContent(content);
StateHasChanged();
}
private async Task RawHtmlEditor()
{
content = await this.RichTextEditorHtml.GetHtml();
RichTextEditorMode = false;
StateHasChanged();
}
private async Task SaveContent()
{
if (RichTextEditorMode)
{
content = await RichTextEditorHtml.GetHtml();
}
content = content.Replace(((PageState.Alias.Path == string.Empty) ? "/~" : PageState.Alias.Path) + Constants.ContentUrl, Constants.ContentUrl);
string content = await RichTextEditorHtml.GetHtml();
content = content.Replace("/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl, Constants.ContentUrl);
try
{
@ -190,5 +89,4 @@
AddModuleMessage("Error Saving Content", MessageType.Error);
}
}
}

View File

@ -30,7 +30,7 @@
if (htmltext != null)
{
content = htmltext.Content;
content = content.Replace(Constants.ContentUrl, ((PageState.Alias.Path == "") ? "/~" : PageState.Alias.Path) + Constants.ContentUrl);
content = content.Replace(Constants.ContentUrl, "/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl);
}
}
catch (Exception ex)