Moved cms-editor back to ccm-cms, refactored to general script configured using data attributes
parent
5e44817505
commit
0f457f0ec0
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "@librecms/ccm-cms-editor",
|
||||
"version": "7.0.0-SNAPSHOT.2022-04-28T174914",
|
||||
"version": "7.0.0-SNAPSHOT.2022-04-28T183714",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@librecms/ccm-cms-editor",
|
||||
"version": "7.0.0-SNAPSHOT.2022-04-28T174914",
|
||||
"version": "7.0.0-SNAPSHOT.2022-04-28T183714",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@tiptap/core": "^2.0.0-beta.127",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@librecms/ccm-cms-editor",
|
||||
"version": "7.0.0-SNAPSHOT.2022-04-28T174914",
|
||||
"version": "7.0.0-SNAPSHOT.2022-04-28T183714",
|
||||
"description": "HTML WYSIWYG editor for LibreCMS based on TipTap",
|
||||
"main": "target/generated-resources/assets/ccm-cms-editor.js",
|
||||
"types": "target/generated-resources/assets/ccm-cms-editor.d.ts",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@librecms/ccm-cms",
|
||||
"version": "7.0.0-SNAPSHOT.2022-04-28T174914",
|
||||
"version": "7.0.0-SNAPSHOT.2022-05-03T181122",
|
||||
"description": "JavaScript stuff for ccm-cms",
|
||||
"main": "target/generated-resources/assets/@content-sections/cms-admin.js",
|
||||
"types": "target/generated-resources/assets/@content-sections/cms-admin.d.ts",
|
||||
|
|
@ -23,7 +23,14 @@
|
|||
"webpack-cli": "^4.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@librecms/ccm-cms-editor": "../ccm-cms-editor",
|
||||
"@tiptap/core": "^2.0.0-beta.127",
|
||||
"@tiptap/extension-subscript": "^2.0.0-beta.4",
|
||||
"@tiptap/extension-superscript": "^2.0.0-beta.4",
|
||||
"@tiptap/extension-table": "^2.0.0-beta.35",
|
||||
"@tiptap/extension-table-cell": "^2.0.0-beta.15",
|
||||
"@tiptap/extension-table-header": "^2.0.0-beta.17",
|
||||
"@tiptap/extension-table-row": "^2.0.0-beta.14",
|
||||
"@tiptap/starter-kit": "^2.0.0-beta.129",
|
||||
"acorn": "^8.5.0",
|
||||
"bootstrap": "^4.6.0",
|
||||
"bootstrap-icons": "^1.5.0",
|
||||
|
|
|
|||
|
|
@ -42,12 +42,6 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.librecms</groupId>
|
||||
<artifactId>ccm-cms-editor</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
|
|
@ -243,16 +237,7 @@
|
|||
<arguments>pkg set version=${project.version}.${timestamp}</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<!-- <execution>
|
||||
<id>npm link @librecms/ccm-cms-editor</id>
|
||||
<goals>
|
||||
<goal>npm</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<arguments>link @librecms/ccm-cms-editor</arguments>
|
||||
</configuration>
|
||||
</execution> -->
|
||||
<execution>
|
||||
<execution>
|
||||
<id>npm install</id>
|
||||
<goals>
|
||||
<goal>npm</goal>
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@
|
|||
data-baseUrl="#{cc.attrs.baseUrl}"
|
||||
data-contentsection="#{cc.attrs.contentSection}"
|
||||
data-locale="#{cc.attrs.selectedLocale}"
|
||||
data-save-button="##{cc.attrs.editorId}-save-button"
|
||||
data-save-url="#{cc.attrs.editMethod}/#{cc.attrs.selectedLocale}"
|
||||
data-variant-url="#{cc.attrs.variantUrl}/#{cc.attrs.selectedLocale}"
|
||||
id="#{cc.attrs.editorId}"
|
||||
|
|
@ -1021,6 +1022,7 @@
|
|||
</button>
|
||||
<button class="btn btn-primary video-settings-dialog-save"
|
||||
data-dismiss="modal"
|
||||
id="#{cc.attrs.editorId}-save-button"
|
||||
type="button">
|
||||
#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.save']}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@
|
|||
/>
|
||||
<cc:attribute name="viewButtonLabel" default="View" type="String" />
|
||||
<cc:implementation>
|
||||
<div class="cms-editor">
|
||||
<div class="cms-editor-variants">
|
||||
<c:choose>
|
||||
<c:when test="#{cc.attrs.headingLevel == 1}">
|
||||
<h1>#{cc.attrs.title}</h1>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
</ui:define>
|
||||
|
||||
<ui:define name="scripts">
|
||||
<script src="#{request.contextPath}/assets/@content-sections/article-text-step.js"></script>
|
||||
<script src="#{request.contextPath}/assets/@content-sections/cms-editor.js"></script>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,889 @@
|
|||
import "bootstrap";
|
||||
import * as $ from "jquery";
|
||||
import { ChainedCommands, Editor, Node, mergeAttributes } from "@tiptap/core";
|
||||
// import Gapcursor from "@tiptap/extension-gapcursor";
|
||||
import StarterKit from "@tiptap/starter-kit";
|
||||
import Subscript from "@tiptap/extension-subscript";
|
||||
import Superscript from "@tiptap/extension-superscript";
|
||||
import Table from "@tiptap/extension-table";
|
||||
import TableRow from "@tiptap/extension-table-row";
|
||||
import TableCell from "@tiptap/extension-table-cell";
|
||||
import TableHeader from "@tiptap/extension-table-header";
|
||||
|
||||
import AudioNode from "./cms-editor/audio-node";
|
||||
import ImageNode from "./cms-editor/image-node";
|
||||
import VideoNode from "./cms-editor/video-node";
|
||||
|
||||
const BUTTONS: CmsEditorButton[] = [
|
||||
{
|
||||
selector: ".tiptap-emph",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().toggleItalic().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleItalic()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-strong-emph",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().toggleBold().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleBold()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-code",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().toggleCode().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleCode()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-strikethrough",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().toggleStrike().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleStrike()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-subscript",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleSubscript()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleSubscript()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-superscript",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleSuperscript()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleSuperscript()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-h1",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 1 })
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 1 })
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-h2",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 2 })
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 2 })
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-h3",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 3 })
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 3 })
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-h5",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 5 })
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 5 })
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-h6",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 6 })
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeading({ level: 6 })
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-paragraph",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().clearNodes().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.clearNodes()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-blockquote",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleBlockquote()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleBlockquote()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-codeblock",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleCodeBlock()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleCodeBlock()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-ul",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleBulletList()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleBulletList()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-ol",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleOrderedList()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleOrderedList()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".cms-editor-insert-table-dialog",
|
||||
command: (cmsEditor) => {
|
||||
return true;
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.insertTable()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".cms-editor-insert-table-dialog .btn-success",
|
||||
command: (cmsEditor) => {
|
||||
const dialog = cmsEditor
|
||||
.getEditorElem()
|
||||
.querySelector(".cms-editor-insert-table-dialog");
|
||||
if (!dialog) {
|
||||
return false;
|
||||
}
|
||||
const rowsInput = dialog.querySelector(
|
||||
"input#rows"
|
||||
) as HTMLInputElement;
|
||||
const colsInput = dialog.querySelector(
|
||||
"input#cols"
|
||||
) as HTMLInputElement;
|
||||
const headerRowInput = dialog.querySelector(
|
||||
"input#headerRow"
|
||||
) as HTMLInputElement;
|
||||
// console.log(`rowsInput = ${rowsInput}`);
|
||||
// console.log(`colsInput = ${colsInput}`);
|
||||
// console.log(`headerRowInput = ${headerRowInput}`);
|
||||
const rows = parseInt(rowsInput.value, 10);
|
||||
const cols = parseInt(colsInput.value, 10);
|
||||
const headerRow = JSON.parse(headerRowInput.value) as Boolean;
|
||||
const insertTableDialog = $("#insert-table-dialog") as any;
|
||||
insertTableDialog.modal("hide");
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.insertTable({
|
||||
// allowTableNodeSelection: true,
|
||||
// cellMinWidth: 150,
|
||||
cols: cols,
|
||||
// headerRow: headerRow,
|
||||
// resizable: true,
|
||||
rows: rows,
|
||||
})
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-insert-table-row-before",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().addRowBefore().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.addRowBefore()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-insert-table-row-after",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().addRowAfter().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.addRowAfter()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-insert-table-column-before",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.addColumnBefore()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.addColumnBefore()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-insert-table-column-after",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().addColumnAfter().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.addColumnAfter()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-remove-table-row",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().deleteRow().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.deleteRow()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-remove-table-column",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().deleteColumn().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.deleteColumn()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-remove-table",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().deleteTable().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.deleteTable()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-toggle-table-header-row",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeaderRow()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeaderRow()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-toggle-table-header-column",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeaderColumn()
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleHeaderColumn()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-merge-table-cells",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().mergeCells().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.mergeCells()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-split-table-cell",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor.getEditor().chain().focus().splitCell().run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.splitCell()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-insert-audio",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.setLibreCmsAudio()
|
||||
.insertContent("<p></p>")
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.setLibreCmsAudio()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-insert-image",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.setLibreCmsImage()
|
||||
.insertContent("<p></p>")
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.setLibreCmsImage()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
{
|
||||
selector: ".tiptap-insert-video",
|
||||
command: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.chain()
|
||||
.focus()
|
||||
.setLibreCmsVideo()
|
||||
.insertContent("<p></p>")
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
return cmsEditor
|
||||
.getEditor()
|
||||
.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.setLibreCmsVideo()
|
||||
.run();
|
||||
},
|
||||
},
|
||||
// {
|
||||
// selector: "",
|
||||
// command: cmsEditor => {},
|
||||
// can: cmsEditor => {}
|
||||
// },
|
||||
// {
|
||||
// selector: "",
|
||||
// command: cmsEditor => {},
|
||||
// can: cmsEditor => {}
|
||||
// },
|
||||
// {
|
||||
// selector: "",
|
||||
// command: cmsEditor => {},
|
||||
// can: cmsEditor => {}
|
||||
// }
|
||||
];
|
||||
|
||||
export class CmsEditor {
|
||||
private editor: Editor;
|
||||
private editorElem: HTMLElement;
|
||||
private saveUrl: string;
|
||||
|
||||
public constructor(
|
||||
editor: Editor,
|
||||
editorElem: HTMLElement,
|
||||
saveUrl: string
|
||||
) {
|
||||
this.editor = editor;
|
||||
this.editorElem = editorElem;
|
||||
this.saveUrl = saveUrl;
|
||||
|
||||
// console.log("initializing editor buttons");
|
||||
const buttonsElem = editorElem.querySelector(
|
||||
".cms-tiptap-editor-buttons"
|
||||
);
|
||||
if (buttonsElem) {
|
||||
for (const button of BUTTONS) {
|
||||
const buttonElem = buttonsElem.querySelector(button.selector);
|
||||
if (buttonElem) {
|
||||
buttonElem.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
button.command(this);
|
||||
});
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error("editorButtonsElem not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
editor.on("selectionUpdate", ({ editor }: { editor: Editor }) => {
|
||||
// console.log(`checkButton - this.editorElem = ${this.editorElem}`);
|
||||
const buttonsElem = editorElem.querySelector(
|
||||
".cms-tiptap-editor-buttons"
|
||||
);
|
||||
if (!buttonsElem) {
|
||||
return;
|
||||
}
|
||||
for (const button of BUTTONS) {
|
||||
const elem = buttonsElem.querySelector(button.selector);
|
||||
if (elem) {
|
||||
const buttonElem = elem as HTMLButtonElement;
|
||||
if (button.can(this)) {
|
||||
buttonElem.removeAttribute("disabled");
|
||||
} else {
|
||||
buttonElem.setAttribute("disabled", "disabled");
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// console.log(`editorElem = ${editorElem}`);
|
||||
|
||||
const saveButton = editorElem.querySelector(".cms-editor-save-button");
|
||||
saveButton?.addEventListener("click", (event) => this.save(event));
|
||||
}
|
||||
|
||||
protected async save(event: Event) {
|
||||
event.preventDefault();
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.append("value", this.editor.getHTML());
|
||||
|
||||
try {
|
||||
const response = await fetch(this.saveUrl, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: params,
|
||||
});
|
||||
if (response.ok) {
|
||||
console.log(`Save response status: ${response.status}`);
|
||||
window.location.href = response.url;
|
||||
// const location = response.headers.get("Location");
|
||||
// if (location) {
|
||||
// window.location.href = location;
|
||||
// } else {
|
||||
// this.showMessage("#cms-editor-msg-save-successful");
|
||||
// }
|
||||
} else {
|
||||
this.showSaveFailedMessage(
|
||||
response.status,
|
||||
response.statusText
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.trace(error);
|
||||
this.showSaveFailedErrMessage(error as string);
|
||||
}
|
||||
}
|
||||
|
||||
protected showSaveFailedMessage(status: number, statusText: string) {
|
||||
this.showMessage("#cms-editor-msg-save-failed");
|
||||
console.error(
|
||||
`Failed to save text. Status: ${statusText}. Status Text: ${statusText}`
|
||||
);
|
||||
}
|
||||
|
||||
protected showSaveFailedErrMessage(error: string) {
|
||||
this.showMessage("#cms-editor-msg-save-failed");
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
protected showMessage(messageId: string) {
|
||||
const template = this.editorElem.querySelector(
|
||||
messageId
|
||||
) as HTMLTemplateElement;
|
||||
const message = template.content.cloneNode(true);
|
||||
this.editorElem.querySelector(".cms-editor-messages")?.append(message);
|
||||
}
|
||||
|
||||
public getEditor(): Editor {
|
||||
return this.editor;
|
||||
}
|
||||
|
||||
public getEditorElem(): HTMLElement {
|
||||
return this.editorElem;
|
||||
}
|
||||
}
|
||||
|
||||
function buildCmsEditor(editorElement: HTMLElement) {
|
||||
const saveButtonSelector = editorElement.getAttribute("data-save-button");
|
||||
const saveUrl = editorElement.getAttribute("data-save-url");
|
||||
const variantUrl = editorElement.getAttribute("data-variant-url");
|
||||
|
||||
if (!saveButtonSelector) {
|
||||
console.error(
|
||||
`Element ${editorElement} has no value for data-save-button.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!saveUrl) {
|
||||
console.error(
|
||||
`Element ${editorElement} has no value of data-save-url.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!variantUrl) {
|
||||
console.error(
|
||||
`Element ${editorElement} has not value for data-variant-url.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const canvasElement = editorElement.querySelector(
|
||||
".cms-tiptap-editor-canvas"
|
||||
);
|
||||
if (!canvasElement) {
|
||||
const template = editorElement.querySelector(
|
||||
"#cms-editor-msg-canvas-element-not-found"
|
||||
) as HTMLTemplateElement;
|
||||
const message = template.content.cloneNode(true);
|
||||
editorElement.querySelector(".cms-editor-messages")?.append(message);
|
||||
console.error("canvasElem not found.");
|
||||
throw "canvasElem not found.";
|
||||
}
|
||||
|
||||
fetch(variantUrl, { method: "GET", credentials: "include" })
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
const text = response.text().then((variant) => {
|
||||
try {
|
||||
const editor: Editor = new Editor({
|
||||
element: canvasElement,
|
||||
extensions: [
|
||||
AudioNode,
|
||||
// Gapcursor,
|
||||
ImageNode,
|
||||
StarterKit,
|
||||
Subscript,
|
||||
Superscript,
|
||||
Table.configure({
|
||||
allowTableNodeSelection: true,
|
||||
cellMinWidth: 100,
|
||||
handleWidth: 25,
|
||||
resizable: true,
|
||||
}),
|
||||
TableRow,
|
||||
TableHeader,
|
||||
TableCell,
|
||||
VideoNode,
|
||||
],
|
||||
content: variant,
|
||||
});
|
||||
|
||||
const cmsEditor = new CmsEditor(
|
||||
editor,
|
||||
editorElement,
|
||||
saveUrl
|
||||
);
|
||||
|
||||
const saveButtons =
|
||||
document.querySelectorAll(saveButtonSelector);
|
||||
for (let i = 0; i < saveButtons.length; i++) {
|
||||
const saveButton = saveButtons[i];
|
||||
saveButton.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
console.log("HTML output of editor: ");
|
||||
console.log(cmsEditor.getEditor().getHTML());
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.trace(error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const template = editorElement.querySelector(
|
||||
"#cms-editor-msg-variant-load-failed"
|
||||
) as HTMLTemplateElement;
|
||||
const message = template.content.cloneNode(true);
|
||||
editorElement
|
||||
.querySelector(".cms-editor-messages")
|
||||
?.append(message);
|
||||
console.error(
|
||||
`Failed to load variant. Status: ${response.status}, Status Text: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
console.trace(error);
|
||||
const template = editorElement.querySelector(
|
||||
"#cms-editor-msg-variant-load-failed"
|
||||
) as HTMLTemplateElement;
|
||||
const message = template.content.cloneNode(true);
|
||||
editorElement
|
||||
.querySelector(".cms-editor-messages")
|
||||
?.append(message);
|
||||
});
|
||||
}
|
||||
|
||||
interface CmsEditorButton {
|
||||
selector: string;
|
||||
command: (cmsEditor: CmsEditor) => boolean;
|
||||
can: (cmsEditor: CmsEditor) => boolean;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", (event) => {
|
||||
const editorElements = document.querySelectorAll(".cms-editor");
|
||||
|
||||
for (let i = 0; i < editorElements.length; i++) {
|
||||
buildCmsEditor(editorElements[i] as HTMLElement);
|
||||
}
|
||||
});
|
||||
|
|
@ -6,13 +6,14 @@ module.exports = {
|
|||
},
|
||||
entry: {
|
||||
"cms-admin": "./src/main/typescript/content-sections/cms-admin.ts",
|
||||
"article-text-step": "./src/main/typescript/content-sections/article-text-step.ts",
|
||||
"event-info-step-eventdate": "./src/main/typescript/content-sections/event-info-step-eventdate.ts",
|
||||
"event-info-step-eventtype": "./src/main/typescript/content-sections/event-info-step-eventtype.ts",
|
||||
"event-info-step-location": "./src/main/typescript/content-sections/event-info-step-location.ts",
|
||||
"event-info-step-maincontributor": "./src/main/typescript/content-sections/event-info-step-maincontributor.ts",
|
||||
"mpa-section-edit-text": "./src/main/typescript/content-sections/mpa-section-edit-text.ts",
|
||||
"news-text-step": "./src/main/typescript/content-sections/news-text-step.ts"
|
||||
"cms-editor": "./src/main/typescript/content-sections/cms-editor.ts"
|
||||
// "article-text-step": "./src/main/typescript/content-sections/article-text-step.ts",
|
||||
// "event-info-step-eventdate": "./src/main/typescript/content-sections/event-info-step-eventdate.ts",
|
||||
// "event-info-step-eventtype": "./src/main/typescript/content-sections/event-info-step-eventtype.ts",
|
||||
// "event-info-step-location": "./src/main/typescript/content-sections/event-info-step-location.ts",
|
||||
// "event-info-step-maincontributor": "./src/main/typescript/content-sections/event-info-step-maincontributor.ts",
|
||||
// "mpa-section-edit-text": "./src/main/typescript/content-sections/mpa-section-edit-text.ts",
|
||||
// "news-text-step": "./src/main/typescript/content-sections/news-text-step.ts"
|
||||
},
|
||||
output: {
|
||||
filename: "[name].js",
|
||||
|
|
|
|||
Loading…
Reference in New Issue