Fixed ui errors to do with ck-editor
This commit is contained in:
parent
49bac1091a
commit
9565b80fb1
@ -5,7 +5,8 @@
|
||||
}
|
||||
|
||||
.mailTemplate-editor {
|
||||
width: calc(100% - ($gridGap + $mailtemplateNameListWidth));
|
||||
//width: calc(100% - ($gridGap + $mailtemplateNameListWidth));
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media print {
|
||||
@ -17,7 +18,7 @@
|
||||
.ck-main-container {
|
||||
// --ckeditor5-preview-height: 700px;
|
||||
font-family: "Lato";
|
||||
width: fit-content;
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
@ -35,6 +36,7 @@
|
||||
font-family: "Lato";
|
||||
line-height: 1.6;
|
||||
word-break: break-word;
|
||||
color: var(--bs-body-color);
|
||||
|
||||
.table table {
|
||||
overflow: auto;
|
||||
@ -42,8 +44,7 @@
|
||||
}
|
||||
|
||||
.editor-container__editor-wrapper {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.editor-container_document-editor {
|
||||
@ -96,12 +97,12 @@
|
||||
//min-width: calc(100vw - ($leftMenuWidth + ($frameWorkAreaPadding * 2)));
|
||||
//max-width: calc(100vw - ($leftMenuWidth + ($frameWorkAreaPadding * 2)));
|
||||
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
|
||||
// min-width: calc(210mm + 2px);
|
||||
// max-width: calc(210mm + 2px);
|
||||
height: fit-content;
|
||||
|
||||
// padding: 20mm 12mm;
|
||||
border: 1px hsl(0, 0%, 82.7%) solid;
|
||||
//background: hsl(0, 0%, 100%);
|
||||
|
||||
@ -11,6 +11,7 @@ export interface SelectProps {
|
||||
value: unknown;
|
||||
options?: Option[];
|
||||
includeBlankFirstEntry?: boolean;
|
||||
multiple?: boolean;
|
||||
onChange?: (e: React.ChangeEvent<HTMLSelectElement>) => void;
|
||||
}
|
||||
|
||||
@ -20,6 +21,24 @@ function GenerateValue(value: unknown) {
|
||||
return value as string | number | readonly string[] | undefined;
|
||||
}
|
||||
|
||||
function NormalizeSelectValue(value: unknown, isMultiple: boolean) {
|
||||
const actualValue = GenerateValue(value);
|
||||
|
||||
if (!isMultiple) {
|
||||
return actualValue;
|
||||
}
|
||||
|
||||
if (Array.isArray(actualValue)) {
|
||||
return actualValue;
|
||||
}
|
||||
|
||||
if (actualValue === undefined || actualValue === null || actualValue === "") {
|
||||
return [] as readonly string[];
|
||||
}
|
||||
|
||||
return [actualValue] as readonly (string | number)[];
|
||||
}
|
||||
|
||||
export default function Select({
|
||||
includeLabel,
|
||||
name,
|
||||
@ -28,11 +47,13 @@ export default function Select({
|
||||
value,
|
||||
options,
|
||||
includeBlankFirstEntry,
|
||||
multiple,
|
||||
onChange,
|
||||
...rest
|
||||
}: SelectProps) {
|
||||
const { t } = useTranslation<typeof Namespaces.Common>();
|
||||
const actualValue = GenerateValue(value);
|
||||
const isMultiple = multiple ?? options === undefined;
|
||||
const actualValue = NormalizeSelectValue(value, isMultiple);
|
||||
|
||||
return (
|
||||
<div className="form-group">
|
||||
@ -41,7 +62,7 @@ export default function Select({
|
||||
)}
|
||||
{!options && (
|
||||
<select
|
||||
multiple
|
||||
multiple={isMultiple}
|
||||
{...rest}
|
||||
id={name}
|
||||
value={actualValue}
|
||||
@ -54,6 +75,7 @@ export default function Select({
|
||||
)}
|
||||
{options && (
|
||||
<select
|
||||
multiple={isMultiple}
|
||||
{...rest}
|
||||
id={name}
|
||||
value={actualValue}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { CKEditor } from '@ckeditor/ckeditor5-react';
|
||||
import Field from './plugins/field/field';
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { CKEditor } from "@ckeditor/ckeditor5-react";
|
||||
import Field from "./plugins/field/field";
|
||||
|
||||
import {
|
||||
DecoupledEditor,
|
||||
@ -66,10 +66,10 @@ import {
|
||||
TextTransformation,
|
||||
TodoList,
|
||||
Underline,
|
||||
Undo
|
||||
} from 'ckeditor5';
|
||||
Undo,
|
||||
} from "ckeditor5";
|
||||
|
||||
import 'ckeditor5/ckeditor5.css';
|
||||
import "ckeditor5/ckeditor5.css";
|
||||
|
||||
// export interface TextEditorProps {
|
||||
// className : String;
|
||||
@ -93,34 +93,34 @@ export default function TextEditor( props ) {
|
||||
}, []);
|
||||
|
||||
let toobarItems = [
|
||||
'undo',
|
||||
'redo',
|
||||
'|',
|
||||
'heading',
|
||||
'|',
|
||||
'fontSize',
|
||||
'fontFamily',
|
||||
'fontColor',
|
||||
'fontBackgroundColor',
|
||||
'|',
|
||||
'bold',
|
||||
'italic',
|
||||
'underline',
|
||||
'|',
|
||||
'link',
|
||||
'insertImage',
|
||||
'insertTable',
|
||||
'highlight',
|
||||
'blockQuote',
|
||||
'codeBlock',
|
||||
'|',
|
||||
'alignment',
|
||||
'|',
|
||||
'bulletedList',
|
||||
'numberedList',
|
||||
'todoList',
|
||||
'outdent',
|
||||
'indent',
|
||||
"undo",
|
||||
"redo",
|
||||
"|",
|
||||
"heading",
|
||||
"|",
|
||||
"fontSize",
|
||||
"fontFamily",
|
||||
"fontColor",
|
||||
"fontBackgroundColor",
|
||||
"|",
|
||||
"bold",
|
||||
"italic",
|
||||
"underline",
|
||||
"|",
|
||||
"link",
|
||||
"insertImage",
|
||||
"insertTable",
|
||||
"highlight",
|
||||
"blockQuote",
|
||||
"codeBlock",
|
||||
"|",
|
||||
"alignment",
|
||||
"|",
|
||||
"bulletedList",
|
||||
"numberedList",
|
||||
"todoList",
|
||||
"outdent",
|
||||
"indent",
|
||||
];
|
||||
|
||||
let plugins = [
|
||||
@ -186,109 +186,123 @@ export default function TextEditor( props ) {
|
||||
TextTransformation,
|
||||
TodoList,
|
||||
Underline,
|
||||
Undo
|
||||
Undo,
|
||||
];
|
||||
|
||||
let customfields = []
|
||||
let customfields = [];
|
||||
|
||||
if (props.customFields && props.customFields.length > 0) {
|
||||
toobarItems.push( '|' );
|
||||
toobarItems.push( 'Field' );
|
||||
toobarItems.push("|");
|
||||
toobarItems.push("Field");
|
||||
plugins.push(Field);
|
||||
customfields = props.customFields;
|
||||
}
|
||||
|
||||
const licenseKey = window.__RUNTIME_CONFIG__?.CKEDITOR_LICENSE_KEY || "GPL";
|
||||
|
||||
const editorConfig = {
|
||||
licenseKey: licenseKey,
|
||||
toolbar: {
|
||||
items: toobarItems,
|
||||
shouldNotGroupWhenFull: false
|
||||
shouldNotGroupWhenFull: false,
|
||||
},
|
||||
plugins: plugins,
|
||||
balloonToolbar: ['bold', 'italic', '|', 'link', 'insertImage', '|', 'bulletedList', 'numberedList'],
|
||||
balloonToolbar: [
|
||||
"bold",
|
||||
"italic",
|
||||
"|",
|
||||
"link",
|
||||
"insertImage",
|
||||
"|",
|
||||
"bulletedList",
|
||||
"numberedList",
|
||||
"|",
|
||||
"field",
|
||||
],
|
||||
fontFamily: {
|
||||
supportAllValues: true
|
||||
supportAllValues: true,
|
||||
},
|
||||
fontSize: {
|
||||
options: [10, 12, 14, 'default', 18, 20, 22],
|
||||
supportAllValues: true
|
||||
options: [10, 12, 14, "default", 18, 20, 22],
|
||||
supportAllValues: true,
|
||||
},
|
||||
heading: {
|
||||
options: [
|
||||
{
|
||||
model: 'paragraph',
|
||||
title: 'Paragraph',
|
||||
class: 'ck-heading_paragraph'
|
||||
model: "paragraph",
|
||||
title: "Paragraph",
|
||||
class: "ck-heading_paragraph",
|
||||
},
|
||||
{
|
||||
model: 'heading1',
|
||||
view: 'h1',
|
||||
title: 'Heading 1',
|
||||
class: 'ck-heading_heading1'
|
||||
model: "heading1",
|
||||
view: "h1",
|
||||
title: "Heading 1",
|
||||
class: "ck-heading_heading1",
|
||||
},
|
||||
{
|
||||
model: 'heading2',
|
||||
view: 'h2',
|
||||
title: 'Heading 2',
|
||||
class: 'ck-heading_heading2'
|
||||
model: "heading2",
|
||||
view: "h2",
|
||||
title: "Heading 2",
|
||||
class: "ck-heading_heading2",
|
||||
},
|
||||
{
|
||||
model: 'heading3',
|
||||
view: 'h3',
|
||||
title: 'Heading 3',
|
||||
class: 'ck-heading_heading3'
|
||||
model: "heading3",
|
||||
view: "h3",
|
||||
title: "Heading 3",
|
||||
class: "ck-heading_heading3",
|
||||
},
|
||||
{
|
||||
model: 'heading4',
|
||||
view: 'h4',
|
||||
title: 'Heading 4',
|
||||
class: 'ck-heading_heading4'
|
||||
model: "heading4",
|
||||
view: "h4",
|
||||
title: "Heading 4",
|
||||
class: "ck-heading_heading4",
|
||||
},
|
||||
{
|
||||
model: 'heading5',
|
||||
view: 'h5',
|
||||
title: 'Heading 5',
|
||||
class: 'ck-heading_heading5'
|
||||
model: "heading5",
|
||||
view: "h5",
|
||||
title: "Heading 5",
|
||||
class: "ck-heading_heading5",
|
||||
},
|
||||
{
|
||||
model: 'heading6',
|
||||
view: 'h6',
|
||||
title: 'Heading 6',
|
||||
class: 'ck-heading_heading6'
|
||||
}
|
||||
]
|
||||
model: "heading6",
|
||||
view: "h6",
|
||||
title: "Heading 6",
|
||||
class: "ck-heading_heading6",
|
||||
},
|
||||
],
|
||||
},
|
||||
image: {
|
||||
toolbar: [
|
||||
'toggleImageCaption',
|
||||
'imageTextAlternative',
|
||||
'|',
|
||||
'imageStyle:inline',
|
||||
'imageStyle:wrapText',
|
||||
'imageStyle:breakText',
|
||||
'|',
|
||||
'resizeImage'
|
||||
]
|
||||
"toggleImageCaption",
|
||||
"imageTextAlternative",
|
||||
"|",
|
||||
"imageStyle:inline",
|
||||
"imageStyle:wrapText",
|
||||
"imageStyle:breakText",
|
||||
"|",
|
||||
"resizeImage",
|
||||
],
|
||||
},
|
||||
//initialData: props.data,
|
||||
link: {
|
||||
addTargetToExternalLinks: true,
|
||||
defaultProtocol: 'https://',
|
||||
defaultProtocol: "https://",
|
||||
decorators: {
|
||||
toggleDownloadable: {
|
||||
mode: 'manual',
|
||||
label: 'Downloadable',
|
||||
mode: "manual",
|
||||
label: "Downloadable",
|
||||
attributes: {
|
||||
download: 'file'
|
||||
}
|
||||
}
|
||||
}
|
||||
download: "file",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
list: {
|
||||
properties: {
|
||||
styles: true,
|
||||
startIndex: true,
|
||||
reversed: true
|
||||
}
|
||||
reversed: true,
|
||||
},
|
||||
},
|
||||
// mention: {
|
||||
// feeds: [
|
||||
@ -301,39 +315,66 @@ export default function TextEditor( props ) {
|
||||
// ]
|
||||
// },
|
||||
menuBar: {
|
||||
isVisible: true
|
||||
isVisible: true,
|
||||
},
|
||||
placeholder: 'Type or paste your content here!',
|
||||
placeholder: "Type or paste your content here!",
|
||||
table: {
|
||||
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties']
|
||||
contentToolbar: [
|
||||
"tableColumn",
|
||||
"tableRow",
|
||||
"mergeTableCells",
|
||||
"tableProperties",
|
||||
"tableCellProperties",
|
||||
],
|
||||
},
|
||||
fieldConfig: {
|
||||
fields : customfields
|
||||
}
|
||||
fields: customfields,
|
||||
},
|
||||
};
|
||||
|
||||
const editorClasses = "editor-container__editor " + props.className;
|
||||
const editorClasses = props.className || "";
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="ck-main-container">
|
||||
<div className="editor-container editor-container_document-editor" ref={editorContainerRef}>
|
||||
<div className="editor-container__menu-bar" ref={editorMenuBarRef}></div>
|
||||
<div className="editor-container__toolbar" ref={editorToolbarRef}></div>
|
||||
<div className="editor-container__editor-wrapper">
|
||||
<div className={editorClasses}>
|
||||
<div className="ck-main-container">
|
||||
<div
|
||||
className="editor-container editor-container_document-editor"
|
||||
ref={editorContainerRef}
|
||||
>
|
||||
<div
|
||||
className="editor-container__menu-bar"
|
||||
ref={editorMenuBarRef}
|
||||
></div>
|
||||
<div
|
||||
className="editor-container__toolbar"
|
||||
ref={editorToolbarRef}
|
||||
></div>
|
||||
<div className="editor-container__editor-wrapper">
|
||||
<div className="editor-container__editor">
|
||||
<div ref={editorRef}>
|
||||
{isLayoutReady && (
|
||||
<CKEditor
|
||||
onReady={editor => {
|
||||
Array.from(editorToolbarRef.current?.children).forEach(child => child.remove());
|
||||
Array.from(editorMenuBarRef.current?.children).forEach(child => child.remove());
|
||||
editorToolbarRef.current.appendChild(editor.ui.view.toolbar.element);
|
||||
editorMenuBarRef.current.appendChild(editor.ui.view.menuBarView.element);
|
||||
onReady={(editor) => {
|
||||
Array.from(editorToolbarRef.current?.children).forEach(
|
||||
(child) => child.remove(),
|
||||
);
|
||||
Array.from(editorMenuBarRef.current?.children).forEach(
|
||||
(child) => child.remove(),
|
||||
);
|
||||
editorToolbarRef.current.appendChild(
|
||||
editor.ui.view.toolbar.element,
|
||||
);
|
||||
editorMenuBarRef.current.appendChild(
|
||||
editor.ui.view.menuBarView?.element,
|
||||
);
|
||||
}}
|
||||
onAfterDestroy={() => {
|
||||
Array.from(editorToolbarRef.current.children).forEach(child => child.remove());
|
||||
Array.from(editorMenuBarRef.current.children).forEach(child => child.remove());
|
||||
Array.from(editorToolbarRef.current.children).forEach(
|
||||
(child) => child.remove(),
|
||||
);
|
||||
Array.from(editorMenuBarRef.current.children).forEach(
|
||||
(child) => child.remove(),
|
||||
);
|
||||
}}
|
||||
editor={DecoupledEditor}
|
||||
config={editorConfig}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Plugin } from 'ckeditor5';
|
||||
import FieldEditing from './fieldediting';
|
||||
import FieldUI from './fieldui';
|
||||
import { Plugin } from "ckeditor5";
|
||||
import FieldEditing from "./fieldediting";
|
||||
import FieldUI from "./fieldui";
|
||||
|
||||
export default class Field extends Plugin {
|
||||
static get requires() {
|
||||
|
||||
@ -1,15 +1,21 @@
|
||||
import { Plugin, Collection, addListToDropdown, createDropdown, ViewModel } from 'ckeditor5';
|
||||
import './styles.css';
|
||||
import {
|
||||
Plugin,
|
||||
Collection,
|
||||
addListToDropdown,
|
||||
createDropdown,
|
||||
ViewModel,
|
||||
} from "ckeditor5";
|
||||
import "./styles.css";
|
||||
|
||||
export default class FieldUI extends Plugin {
|
||||
init() {
|
||||
const editor = this.editor;
|
||||
const t = editor.t;
|
||||
const fields = editor.config.get( 'fieldConfig' ).fields;
|
||||
const fields = editor.config.get("fieldConfig").fields;
|
||||
|
||||
// The "field" dropdown must be registered among the UI components of the editor
|
||||
// to be displayed in the toolbar.
|
||||
editor.ui.componentFactory.add( 'field', locale => {
|
||||
editor.ui.componentFactory.add("field", (locale) => {
|
||||
const dropdownView = createDropdown(locale);
|
||||
|
||||
// Populate the list in the dropdown with items.
|
||||
@ -18,44 +24,38 @@ import './styles.css';
|
||||
dropdownView.buttonView.set({
|
||||
// The t() function helps localize the editor. All strings enclosed in t() can be
|
||||
// translated and change when the language of the editor changes.
|
||||
label: t( 'Insert Field' ),
|
||||
label: t("Insert Field"),
|
||||
tooltip: true,
|
||||
withText: true
|
||||
withText: true,
|
||||
});
|
||||
|
||||
// Disable the field button when the command is disabled.
|
||||
const command = editor.commands.get( 'field' );
|
||||
dropdownView.bind( 'isEnabled' ).to( command );
|
||||
const command = editor.commands.get("field");
|
||||
dropdownView.bind("isEnabled").to(command);
|
||||
|
||||
// Execute the command when the dropdown item is clicked (executed).
|
||||
this.listenTo( dropdownView, 'execute', evt => {
|
||||
editor.execute( 'field', { value: evt.source.commandParam } );
|
||||
this.listenTo(dropdownView, "execute", (evt) => {
|
||||
editor.execute("field", { value: evt.source.commandParam });
|
||||
editor.editing.view.focus();
|
||||
});
|
||||
|
||||
return dropdownView;
|
||||
});
|
||||
|
||||
editor.ui.extendMenuBar( {
|
||||
item: 'field',
|
||||
position: 'after:bold'
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
function getDropdownItemsDefinitions(fields) {
|
||||
const itemDefinitions = new Collection();
|
||||
|
||||
if (fields !== undefined)
|
||||
{
|
||||
if (fields !== undefined) {
|
||||
for (const field of fields) {
|
||||
const definition = {
|
||||
type: 'button',
|
||||
type: "button",
|
||||
model: new ViewModel({
|
||||
commandParam: field,
|
||||
label: field.name,
|
||||
withText: true
|
||||
} )
|
||||
withText: true,
|
||||
}),
|
||||
};
|
||||
|
||||
// Add the item definition to the collection.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user