commit
91c96475de
84
Oqtane.Client/Modules/Controls/RichTextEditor.razor
Normal file
84
Oqtane.Client/Modules/Controls/RichTextEditor.razor
Normal file
@ -0,0 +1,84 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<div @ref="@ToolBar">
|
||||
@ToolbarContent
|
||||
</div>
|
||||
<div @ref="@EditorElement">
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public RenderFragment ToolbarContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool ReadOnly { get; set; }
|
||||
= false;
|
||||
|
||||
[Parameter]
|
||||
public string Placeholder { get; set; }
|
||||
= "Compose an epic...";
|
||||
|
||||
[Parameter]
|
||||
public string Theme { get; set; }
|
||||
= "snow";
|
||||
|
||||
[Parameter]
|
||||
public string DebugLevel { get; set; }
|
||||
= "info";
|
||||
|
||||
private ElementReference EditorElement;
|
||||
private ElementReference ToolBar;
|
||||
|
||||
protected override async Task
|
||||
OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await RichTextEditorInterop.CreateEditor(
|
||||
JSRuntime,
|
||||
EditorElement,
|
||||
ToolBar,
|
||||
ReadOnly,
|
||||
Placeholder,
|
||||
Theme,
|
||||
DebugLevel);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> GetText()
|
||||
{
|
||||
return await RichTextEditorInterop.GetText(
|
||||
JSRuntime,
|
||||
EditorElement);
|
||||
}
|
||||
|
||||
public async Task<string> GetHTML()
|
||||
{
|
||||
return await RichTextEditorInterop.GetHTML(
|
||||
JSRuntime,
|
||||
EditorElement);
|
||||
}
|
||||
|
||||
public async Task<string> GetContent()
|
||||
{
|
||||
return await RichTextEditorInterop.GetContent(
|
||||
JSRuntime,
|
||||
EditorElement);
|
||||
}
|
||||
|
||||
public async Task LoadContent(string Content)
|
||||
{
|
||||
await RichTextEditorInterop.LoadEditorContent(
|
||||
JSRuntime,
|
||||
EditorElement, Content);
|
||||
}
|
||||
|
||||
public async Task EnableEditor(bool mode)
|
||||
{
|
||||
await RichTextEditorInterop.EnableEditor(
|
||||
JSRuntime,
|
||||
EditorElement, mode);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
@using Oqtane.Modules.HtmlText.Services
|
||||
@using Oqtane.Modules.HtmlText.Models
|
||||
@using Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.HtmlText
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@ -12,10 +13,53 @@
|
||||
<label for="Name" class="control-label">Content: </label>
|
||||
</td>
|
||||
<td>
|
||||
@if (!RichTextEditorMode)
|
||||
{
|
||||
<textarea class="form-control" @bind="@content" rows="5" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<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>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@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>
|
||||
<br />
|
||||
@ -26,15 +70,32 @@
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Edit; } }
|
||||
public override string Title { get { return "Edit Html/Text"; } }
|
||||
|
||||
RichTextEditor RichTextEditorHtml;
|
||||
bool RichTextEditorMode = true;
|
||||
string content;
|
||||
string createdby;
|
||||
DateTime createdon;
|
||||
string modifiedby;
|
||||
DateTime modifiedon;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
protected override async Task
|
||||
OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
try
|
||||
{
|
||||
await LoadText();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "An Error Occurred Loading Html/Text Content. " + ex.Message);
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadText()
|
||||
{
|
||||
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, NavigationManager);
|
||||
HtmlTextInfo htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||
@ -45,17 +106,34 @@
|
||||
createdon = htmltext.CreatedOn;
|
||||
modifiedby = htmltext.ModifiedBy;
|
||||
modifiedon = htmltext.ModifiedOn;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
if (RichTextEditorMode)
|
||||
{
|
||||
await logger.LogError(ex, "An Error Occurred Loading Html/Text Content. " + ex.Message);
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
await RichTextEditorHtml.LoadContent(content);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RichTextEditor()
|
||||
{
|
||||
RichTextEditorMode = true;
|
||||
await LoadText();
|
||||
}
|
||||
|
||||
private async Task RawHTMLEditor()
|
||||
{
|
||||
RichTextEditorMode = false;
|
||||
await LoadText();
|
||||
}
|
||||
|
||||
private async Task SaveContent()
|
||||
{
|
||||
if (RichTextEditorMode)
|
||||
{
|
||||
content = await this.RichTextEditorHtml.GetHTML();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, NavigationManager);
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Microsoft.JSInterop;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
70
Oqtane.Client/Shared/RichTextEditorInterop.cs
Normal file
70
Oqtane.Client/Shared/RichTextEditorInterop.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Modules.Controls
|
||||
{
|
||||
public static class RichTextEditorInterop
|
||||
{
|
||||
internal static ValueTask<object> CreateEditor(
|
||||
IJSRuntime jsRuntime,
|
||||
ElementReference quillElement,
|
||||
ElementReference toolbar,
|
||||
bool readOnly,
|
||||
string placeholder,
|
||||
string theme,
|
||||
string debugLevel)
|
||||
{
|
||||
return jsRuntime.InvokeAsync<object>(
|
||||
"interop.createQuill",
|
||||
quillElement, toolbar, readOnly,
|
||||
placeholder, theme, debugLevel);
|
||||
}
|
||||
|
||||
internal static ValueTask<string> GetText(
|
||||
IJSRuntime jsRuntime,
|
||||
ElementReference quillElement)
|
||||
{
|
||||
return jsRuntime.InvokeAsync<string>(
|
||||
"interop.getQuillText",
|
||||
quillElement);
|
||||
}
|
||||
|
||||
internal static ValueTask<string> GetHTML(
|
||||
IJSRuntime jsRuntime,
|
||||
ElementReference quillElement)
|
||||
{
|
||||
return jsRuntime.InvokeAsync<string>(
|
||||
"interop.getQuillHTML",
|
||||
quillElement);
|
||||
}
|
||||
|
||||
internal static ValueTask<string> GetContent(
|
||||
IJSRuntime jsRuntime,
|
||||
ElementReference quillElement)
|
||||
{
|
||||
return jsRuntime.InvokeAsync<string>(
|
||||
"interop.getQuillContent",
|
||||
quillElement);
|
||||
}
|
||||
|
||||
internal static ValueTask<object> LoadEditorContent(
|
||||
IJSRuntime jsRuntime,
|
||||
ElementReference quillElement,
|
||||
string Content)
|
||||
{
|
||||
return jsRuntime.InvokeAsync<object>(
|
||||
"interop.loadQuillContent",
|
||||
quillElement, Content);
|
||||
}
|
||||
|
||||
internal static ValueTask<object> EnableEditor(
|
||||
IJSRuntime jsRuntime,
|
||||
ElementReference quillElement,
|
||||
bool mode)
|
||||
{
|
||||
return jsRuntime.InvokeAsync<object>(
|
||||
"interop.enableQuillEditor", quillElement, mode);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Oqtane</title>
|
||||
<base href="/" />
|
||||
<link href="//cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
|
||||
<link href="//cdn.quilljs.com/1.3.6/quill.bubble.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||
<link href="css/app.css" rel="stylesheet" />
|
||||
</head>
|
||||
@ -17,6 +19,7 @@
|
||||
|
||||
<script src="js/site.js"></script>
|
||||
<script src="js/interop.js"></script>
|
||||
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||
|
@ -127,5 +127,36 @@ window.interop = {
|
||||
request.send(data);
|
||||
}
|
||||
}
|
||||
},
|
||||
createQuill: function (
|
||||
editorElement, toolBar, readOnly,
|
||||
placeholder, theme, debugLevel) {
|
||||
|
||||
var options = {
|
||||
debug: debugLevel,
|
||||
modules: {
|
||||
toolbar: toolBar
|
||||
},
|
||||
placeholder: placeholder,
|
||||
readOnly: readOnly,
|
||||
theme: theme
|
||||
};
|
||||
|
||||
new Quill(editorElement, options);
|
||||
},
|
||||
getQuillContent: function (editorElement) {
|
||||
return JSON.stringify(editorElement.__quill.getContents());
|
||||
},
|
||||
getQuillText: function (editorElement) {
|
||||
return editorElement.__quill.getText();
|
||||
},
|
||||
getQuillHTML: function (editorElement) {
|
||||
return editorElement.__quill.root.innerHTML;
|
||||
},
|
||||
loadQuillContent: function (editorElement, editorContent) {
|
||||
return editorElement.__quill.root.innerHTML = editorContent;
|
||||
},
|
||||
enableQuillEditor: function (editorElement, mode) {
|
||||
editorElement.__quill.enable(mode);
|
||||
}
|
||||
};
|
||||
|
@ -10,6 +10,8 @@
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Oqtane</title>
|
||||
<base href="~/" />
|
||||
<link href="//cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
|
||||
<link href="//cdn.quilljs.com/1.3.6/quill.bubble.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||
<link href="css/app.css" rel="stylesheet" />
|
||||
</head>
|
||||
@ -19,6 +21,7 @@
|
||||
|
||||
<script src="js/site.js"></script>
|
||||
<script src="js/interop.js"></script>
|
||||
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": ""
|
||||
"DefaultConnection": "Data Source=(Local);Initial Catalog=Oqtane;Integrated Security=SSPI;"
|
||||
}
|
||||
}
|
@ -127,5 +127,36 @@ window.interop = {
|
||||
request.send(data);
|
||||
}
|
||||
}
|
||||
},
|
||||
createQuill: function (
|
||||
editorElement, toolBar, readOnly,
|
||||
placeholder, theme, debugLevel) {
|
||||
|
||||
var options = {
|
||||
debug: debugLevel,
|
||||
modules: {
|
||||
toolbar: toolBar
|
||||
},
|
||||
placeholder: placeholder,
|
||||
readOnly: readOnly,
|
||||
theme: theme
|
||||
};
|
||||
|
||||
new Quill(editorElement, options);
|
||||
},
|
||||
getQuillContent: function (editorElement) {
|
||||
return JSON.stringify(editorElement.__quill.getContents());
|
||||
},
|
||||
getQuillText: function (editorElement) {
|
||||
return editorElement.__quill.getText();
|
||||
},
|
||||
getQuillHTML: function (editorElement) {
|
||||
return editorElement.__quill.root.innerHTML;
|
||||
},
|
||||
loadQuillContent: function (editorElement, editorContent) {
|
||||
return editorElement.__quill.root.innerHTML = editorContent;
|
||||
},
|
||||
enableQuillEditor: function (editorElement, mode) {
|
||||
editorElement.__quill.enable(mode);
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user