Merge pull request #15 from oqtane/master

sync with upstream
This commit is contained in:
Shaun Walker 2019-12-04 13:50:13 -05:00 committed by GitHub
commit 91c96475de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 318 additions and 17 deletions

View 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);
}
}

View File

@ -1,5 +1,6 @@
@using Oqtane.Modules.HtmlText.Services @using Oqtane.Modules.HtmlText.Services
@using Oqtane.Modules.HtmlText.Models @using Oqtane.Modules.HtmlText.Models
@using Oqtane.Modules.Controls
@namespace Oqtane.Modules.HtmlText @namespace Oqtane.Modules.HtmlText
@inherits ModuleBase @inherits ModuleBase
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@ -12,10 +13,53 @@
<label for="Name" class="control-label">Content: </label> <label for="Name" class="control-label">Content: </label>
</td> </td>
<td> <td>
@if (!RichTextEditorMode)
{
<textarea class="form-control" @bind="@content" rows="5" /> <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> </td>
</tr> </tr>
</table> </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> <button type="button" class="btn btn-success" @onclick="SaveContent">Save</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink> <NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
<br /> <br />
@ -26,15 +70,32 @@
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Edit; } } public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Edit; } }
public override string Title { get { return "Edit Html/Text"; } } public override string Title { get { return "Edit Html/Text"; } }
RichTextEditor RichTextEditorHtml;
bool RichTextEditorMode = true;
string content; string content;
string createdby; string createdby;
DateTime createdon; DateTime createdon;
string modifiedby; string modifiedby;
DateTime modifiedon; DateTime modifiedon;
protected override async Task OnInitializedAsync() protected override async Task
OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{ {
try 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); HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, NavigationManager);
HtmlTextInfo htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId); HtmlTextInfo htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
@ -45,17 +106,34 @@
createdon = htmltext.CreatedOn; createdon = htmltext.CreatedOn;
modifiedby = htmltext.ModifiedBy; modifiedby = htmltext.ModifiedBy;
modifiedon = htmltext.ModifiedOn; modifiedon = htmltext.ModifiedOn;
}
} if (RichTextEditorMode)
catch (Exception ex)
{ {
await logger.LogError(ex, "An Error Occurred Loading Html/Text Content. " + ex.Message); await RichTextEditorHtml.LoadContent(content);
AddModuleMessage(ex.Message, MessageType.Error); StateHasChanged();
} }
} }
}
private async Task RichTextEditor()
{
RichTextEditorMode = true;
await LoadText();
}
private async Task RawHTMLEditor()
{
RichTextEditorMode = false;
await LoadText();
}
private async Task SaveContent() private async Task SaveContent()
{ {
if (RichTextEditorMode)
{
content = await this.RichTextEditorHtml.GetHTML();
}
try try
{ {
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, NavigationManager); HtmlTextService htmltextservice = new HtmlTextService(http, sitestate, NavigationManager);

View File

@ -1,4 +1,5 @@
using Microsoft.JSInterop; using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;

View 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);
}
}
}

View File

@ -5,6 +5,8 @@
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<title>Oqtane</title> <title>Oqtane</title>
<base href="/" /> <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 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" /> <link href="css/app.css" rel="stylesheet" />
</head> </head>
@ -17,6 +19,7 @@
<script src="js/site.js"></script> <script src="js/site.js"></script>
<script src="js/interop.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://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://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> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

View File

@ -127,5 +127,36 @@ window.interop = {
request.send(data); 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);
} }
}; };

View File

@ -10,6 +10,8 @@
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<title>Oqtane</title> <title>Oqtane</title>
<base href="~/" /> <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 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" /> <link href="css/app.css" rel="stylesheet" />
</head> </head>
@ -19,6 +21,7 @@
<script src="js/site.js"></script> <script src="js/site.js"></script>
<script src="js/interop.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://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://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> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

View File

@ -1,5 +1,5 @@
{ {
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "" "DefaultConnection": "Data Source=(Local);Initial Catalog=Oqtane;Integrated Security=SSPI;"
} }
} }

View File

@ -127,5 +127,36 @@ window.interop = {
request.send(data); 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);
} }
}; };