Image Node for Tiptap working
parent
2169e07ab2
commit
5513dc178e
|
|
@ -6,7 +6,7 @@
|
|||
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
|
||||
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
>
|
||||
>
|
||||
<cc:interface
|
||||
shortDescription="A editor component for HTML texts using the TipTap editor. To use this component you have also to include the cms-editor.js file into the page."
|
||||
>
|
||||
|
|
@ -64,6 +64,12 @@
|
|||
shortDescription="The back URL."
|
||||
type="String"
|
||||
/>
|
||||
<cc:attribute
|
||||
name="baseUrl"
|
||||
required="true"
|
||||
shortDescription="Base URL for generating URLs of API endpoints."
|
||||
type="String"
|
||||
/>
|
||||
<cc:attribute
|
||||
name="canEdit"
|
||||
default="true"
|
||||
|
|
@ -71,6 +77,12 @@
|
|||
shortDescription="Can the current user edit the text?"
|
||||
type="boolean"
|
||||
/>
|
||||
<cc:attribute
|
||||
name="contentSection"
|
||||
required="true"
|
||||
shortDescription="The name of the current content section. Required for generating URLs of API endpoints."
|
||||
type="String"
|
||||
/>
|
||||
<!-- <cc:attribute
|
||||
name="editButtonLabel"
|
||||
default="#{CmsAdminMessages['edit_button.label']}"
|
||||
|
|
@ -290,6 +302,8 @@
|
|||
<cc:implementation>
|
||||
<div
|
||||
class="cms-editor"
|
||||
data-baseUrl="#{cc.attrs.baseUrl}"
|
||||
data-contentsection="#{cc.attrs.contentSection}"
|
||||
data-locale="#{cc.attrs.selectedLocale}"
|
||||
data-save-url="#{cc.attrs.editMethod}/#{variant.locale}"
|
||||
data-variant-url="#{cc.attrs.variantUrl}/#{cc.attrs.selectedLocale}"
|
||||
|
|
@ -655,6 +669,20 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<template id="librecms-image-node-view-row">
|
||||
<tr>
|
||||
<td class="col-name"></td>
|
||||
<td class="col-type"></td>
|
||||
<td class="col-action">
|
||||
<button class="btn btn-primary"
|
||||
data-assetuuid=""
|
||||
data-dismiss="modal"
|
||||
type="button">
|
||||
#{CmsAssetsStepsDefaultMessagesBundle['assetpicker.select']}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<template id="librecms-image-node-view">
|
||||
<figure>
|
||||
<!--img src="#{request.contextPath}/assets/remixicon/image-line.svg" />-->
|
||||
|
|
@ -662,10 +690,59 @@
|
|||
src=""
|
||||
style="min-height: 4em;" />
|
||||
<div class="border-light librecms-image-node-view-buttons">
|
||||
<button class="btn btn-outline-dark select-image-button">
|
||||
<button class="btn btn-outline-dark select-image-button"
|
||||
data-toggle="modal"
|
||||
data-target="#librecms-imge-node-select-image-dialog-">
|
||||
<librecms:remixSvgIcon icon="ri-image-edit-line" />
|
||||
<span class="sr-only">#{CmsAdminMessages['cms_editor.image_node_view.select_image.label']}</span>
|
||||
</button>
|
||||
<div aria-hidden="true"
|
||||
aria-labelledby="librecms-image-node-select-image-dialog-title-"
|
||||
class="modal fade select-image-dialog ccm-cms-asset-picker"
|
||||
id="librecms-image-node-select-image-dialog-"
|
||||
tabindex="-1">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"
|
||||
id="librecms-image-node-select-image-dialog-title-">
|
||||
#{CmsAdminMessages['cms_editor.image_node_view.selectimage.dialog.title']}
|
||||
<button aria-label="#{CmsAdminMessages['cms_editor.image_node_view.selectimage.dialog.close']}"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
type="button">
|
||||
<bootstrap:svgIcon icon="x-circle" />
|
||||
</button>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<bootstrap:formGroupText
|
||||
class="assetpicker-filter"
|
||||
help="#{CmsAssetsStepsDefaultMessagesBundle['assetpicker.filter.help']}"
|
||||
inputId="#{cc.attrs.assetPickerId}-filter"
|
||||
label="#{CmsAssetsStepsDefaultMessagesBundle['assetpicker.filter.label']}"
|
||||
name="" />
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#{CmsAssetsStepsDefaultMessagesBundle['assetpicker.column.name']}</th>
|
||||
<th>#{CmsAssetsStepsDefaultMessagesBundle['assetpicker.column.type']}</th>
|
||||
<th>#{CmsAssetsStepsDefaultMessagesBundle['assetpicker.column.action']}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning"
|
||||
data-dismiss="modal"
|
||||
type="button">
|
||||
#{CmsAdminMessages['cms_editor.image_node_view.selectimage.dialog.close']}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-outline-dark image-settings-button"
|
||||
data-toggle="modal"
|
||||
data-target="#librecms-image-node-view-settings-dialog-">
|
||||
|
|
@ -754,6 +831,10 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!--<button class="btn btn-outline-dark image-remove-button">
|
||||
<librecms:remixSvgIcon icon="ri-close-line" />
|
||||
<span class="sr-only">#{CmsAdminMessages['cms_editor.image_node_view.remove.label']}</span>
|
||||
</button>-->
|
||||
</div>
|
||||
<figcaption aria-label="#{CmsAdminMessages['cms_editor.image_node_view.figcaption.label']}"
|
||||
contenteditable="true">
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
<c:if test="#{CmsArticleTextBodyStep.canEdit}">
|
||||
<librecms:cmsEditor
|
||||
backUrl="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text"
|
||||
baseUrl="#{mvc.basePath}"
|
||||
canEdit="#{CmsArticleTextBodyStep.canEdit}"
|
||||
contentSection="#{ContentSectionModel.sectionName}"
|
||||
editMethod="#{mvc.basePath}/#{ContentSectionModel.sectionName}/documents/#{CmsSelectedDocumentModel.itemPath}/@article-text/edit"
|
||||
editorId="cms-article-text-editor"
|
||||
objectIdentifier="#{CmsSelectedDocumentModel.itemPath}"
|
||||
|
|
|
|||
|
|
@ -890,3 +890,6 @@ cms_editor.image_node_view.settings.dialog.fullsizeoverlay.help=Enables a fullsi
|
|||
cms_editor.image_node_view.settings.dialog.save=Submit
|
||||
cms_editor.image_node_view.figcaption.label=Caption
|
||||
cms_editor.image_node_view.figcaption.placeholder=Caption
|
||||
cms_editor.image_node_view.selectimage.dialog.title=Select image
|
||||
cms_editor.image_node_view.selectimage.dialog.close=Cancel
|
||||
cms_editor.image_node_view.remove.label=Remove image
|
||||
|
|
|
|||
|
|
@ -891,3 +891,6 @@ cms_editor.image_node_view.settings.dialog.fullsizeoverlay.help=Aktiviert ein Gr
|
|||
cms_editor.image_node_view.settings.dialog.save=\u00dcbernehmen
|
||||
cms_editor.image_node_view.figcaption.label=Bildunterschrift
|
||||
cms_editor.image_node_view.figcaption.placeholder=Bildunterschrift
|
||||
cms_editor.image_node_view.selectimage.dialog.title=Bild ausw\u00e4hlen
|
||||
cms_editor.image_node_view.selectimage.dialog.close=Abbrechen
|
||||
cms_editor.image_node_view.remove.label=Bild entfernen
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ table.wor{
|
|||
|
||||
.cms-tiptap-editor-canvas {
|
||||
max-height: 75vh;
|
||||
min-height: 35vh;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
|
|
@ -144,9 +145,76 @@ table.wor{
|
|||
position: relative;
|
||||
|
||||
.librecms-image-node-view-buttons {
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 3em;
|
||||
top: 0.5rem;
|
||||
right: 0.5rem;
|
||||
|
||||
width: 2.66rem;
|
||||
|
||||
& > button {
|
||||
width: 2.66rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.librecms-image-node-width-25 {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&.librecms-image-node-width-33 {
|
||||
width: 33%;
|
||||
}
|
||||
|
||||
&.librecms-image-node-width-50 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&.librecms-image-node-width-66 {
|
||||
width: 66%;
|
||||
}
|
||||
|
||||
&.librecms-image-node-width-75 {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
&.librecms-image-node-width-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.librecms-image-node-align-floatleft {
|
||||
float: left;
|
||||
}
|
||||
|
||||
&.librecms-image-node-align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
&.librecms-image-node-align-floatright {
|
||||
float: right;
|
||||
}
|
||||
|
||||
figure img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.select-image-dialog {
|
||||
table {
|
||||
border: none;
|
||||
width: 100%;
|
||||
|
||||
thead th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
thead tr, tbody tr:nth-child(even) {
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
tr, th, td {
|
||||
border: none
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ async function initAssetPicker(assetPickerElem: Element) {
|
|||
|
||||
console.log(`assetPickerId = ${assetPickerId}`);
|
||||
|
||||
const fetchUrl = `${baseUrl}/content-sections/${contentSection}/assets?type=${assetType}`;
|
||||
const fetchUrl = `/content-sections/${contentSection}/assets?type=${assetType}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(fetchUrl);
|
||||
|
|
|
|||
|
|
@ -341,9 +341,9 @@ const BUTTONS: CmsEditorButton[] = [
|
|||
const headerRowInput = dialog.querySelector(
|
||||
"input#headerRow"
|
||||
) as HTMLInputElement;
|
||||
console.log(`rowsInput = ${rowsInput}`);
|
||||
console.log(`colsInput = ${colsInput}`);
|
||||
console.log(`headerRowInput = ${headerRowInput}`);
|
||||
// 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;
|
||||
|
|
@ -555,6 +555,7 @@ const BUTTONS: CmsEditorButton[] = [
|
|||
.chain()
|
||||
.focus()
|
||||
.setLibreCmsImage()
|
||||
.insertContent("<p></p>")
|
||||
.run();
|
||||
},
|
||||
can: (cmsEditor) => {
|
||||
|
|
@ -598,7 +599,7 @@ class CmsEditor {
|
|||
this.editorElem = editorElem;
|
||||
this.saveUrl = saveUrl;
|
||||
|
||||
console.log("initializing editor buttons");
|
||||
// console.log("initializing editor buttons");
|
||||
const buttonsElem = editorElem.querySelector(
|
||||
".cms-tiptap-editor-buttons"
|
||||
);
|
||||
|
|
@ -620,7 +621,7 @@ class CmsEditor {
|
|||
}
|
||||
|
||||
editor.on("selectionUpdate", ({ editor }: { editor: Editor }) => {
|
||||
console.log(`checkButton - this.editorElem = ${this.editorElem}`);
|
||||
// console.log(`checkButton - this.editorElem = ${this.editorElem}`);
|
||||
const buttonsElem = editorElem.querySelector(
|
||||
".cms-tiptap-editor-buttons"
|
||||
);
|
||||
|
|
@ -642,7 +643,7 @@ class CmsEditor {
|
|||
}
|
||||
});
|
||||
|
||||
console.log(`editorElem = ${editorElem}`);
|
||||
// console.log(`editorElem = ${editorElem}`);
|
||||
|
||||
const saveButton = editorElem.querySelector(".cms-editor-save-button");
|
||||
saveButton?.addEventListener("click", (event) => this.save(event));
|
||||
|
|
@ -716,7 +717,7 @@ class CmsEditorBuilder {
|
|||
}
|
||||
|
||||
public async buildEditor(): Promise<CmsEditor> {
|
||||
console.log("Build CMS Editor.");
|
||||
// console.log("Build CMS Editor.");
|
||||
const canvasElement = this.editorElem.querySelector(
|
||||
".cms-tiptap-editor-canvas"
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Node, nodeInputRule, mergeAttributes } from "@tiptap/core";
|
||||
import { Node, nodeInputRule, mergeAttributes, Range } from "@tiptap/core";
|
||||
import { Node as ProsemirrorNode } from "prosemirror-model";
|
||||
|
||||
declare module "@tiptap/core" {
|
||||
interface Commands<ReturnType> {
|
||||
|
|
@ -64,6 +65,16 @@ export const ImageNode = Node.create({
|
|||
}
|
||||
},
|
||||
},
|
||||
imgSrc: {
|
||||
parseHTML: (element) => {
|
||||
const imgElem = element.querySelector("img");
|
||||
if (imgElem) {
|
||||
return imgElem.src;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
},
|
||||
size: {
|
||||
parseHTML: (element) => {
|
||||
if (element.hasAttribute("data-size")) {
|
||||
|
|
@ -121,32 +132,101 @@ export const ImageNode = Node.create({
|
|||
|
||||
// console.log(`extension = ${extension}`);
|
||||
// console.dir(extension);
|
||||
const dom = document.createElement("div");
|
||||
dom.classList.add("librecms-image-node-view", "p-2");
|
||||
if (!node.attrs.size) {
|
||||
node.attrs.size = "50";
|
||||
}
|
||||
dom.classList.add(`librecms-image-node-width-${node.attrs.size}`);
|
||||
if (!node.attrs.align) {
|
||||
node.attrs.align = "center";
|
||||
}
|
||||
dom.classList.add(`librecms-image-node-align-${node.attrs.align}`);
|
||||
|
||||
const template = templateNode as HTMLTemplateElement;
|
||||
const nodeView = template.content.cloneNode(true) as HTMLElement;
|
||||
const imgElem = nodeView.querySelector("img");
|
||||
const dialogIdNr = Math.floor(Math.random() * 1000000000);
|
||||
const dialogId = `librecms-image-node-view-settings-dialog-${dialogIdNr}`;
|
||||
const dialogTitleId = `${dialogId}-title`;
|
||||
|
||||
const selectDialogId = `librecms-image-node-select-image-dialog-title-${dialogIdNr}`;
|
||||
const selectDialogTitleId = `librecms-image-node-select-image-dialog-title-${dialogIdNr}-title`;
|
||||
const selectButtonElem = nodeView.querySelector(
|
||||
".select-image-button"
|
||||
);
|
||||
if (selectButtonElem) {
|
||||
selectButtonElem.setAttribute(
|
||||
"data-target",
|
||||
`#${selectDialogId}`
|
||||
);
|
||||
}
|
||||
const selectDialogElem = nodeView.querySelector(
|
||||
".modal.select-image-dialog"
|
||||
);
|
||||
if (selectDialogElem) {
|
||||
selectDialogElem.id = selectDialogId;
|
||||
selectDialogElem.setAttribute(
|
||||
"aria-labelledby",
|
||||
selectDialogTitleId
|
||||
);
|
||||
|
||||
const selectDialogTitleElem =
|
||||
selectDialogElem.querySelector(".modal-title");
|
||||
if (selectDialogTitleElem) {
|
||||
selectDialogTitleElem.id = selectDialogTitleId;
|
||||
}
|
||||
|
||||
const selectDialogIds =
|
||||
selectDialogElem.querySelectorAll("*[id]");
|
||||
selectDialogIds.forEach((elemWithId) => {
|
||||
elemWithId.id = `${elemWithId.id}-${dialogIdNr}`;
|
||||
});
|
||||
const selectDialogLabels =
|
||||
selectDialogElem.querySelectorAll("*[for]");
|
||||
selectDialogLabels.forEach((label) => {
|
||||
label.setAttribute(
|
||||
"for",
|
||||
`${label.getAttribute("for")}-${dialogIdNr}`
|
||||
);
|
||||
});
|
||||
|
||||
const describedElems = selectDialogElem.querySelectorAll(
|
||||
"*[aria-describedby]"
|
||||
);
|
||||
describedElems.forEach((describedElem) => {
|
||||
describedElem.setAttribute(
|
||||
"aria-describedby",
|
||||
`${describedElem.getAttribute(
|
||||
"aria-describedby"
|
||||
)}-${dialogIdNr}`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const settingsDialogId = `librecms-image-node-view-settings-dialog-${dialogIdNr}`;
|
||||
const settingsDialogTitleId = `${settingsDialogId}-title`;
|
||||
const settingsButtonElem = nodeView.querySelector(
|
||||
".image-settings-button"
|
||||
);
|
||||
if (settingsButtonElem) {
|
||||
settingsButtonElem.setAttribute("data-target", `#${dialogId}`);
|
||||
settingsButtonElem.setAttribute(
|
||||
"data-target",
|
||||
`#${settingsDialogId}`
|
||||
);
|
||||
}
|
||||
const settingsDialogElem = nodeView.querySelector(
|
||||
".modal.image-settings-dialog"
|
||||
);
|
||||
if (settingsDialogElem) {
|
||||
settingsDialogElem.id = dialogId;
|
||||
settingsDialogElem.id = settingsDialogId;
|
||||
settingsDialogElem.setAttribute(
|
||||
"aria-labelledby",
|
||||
dialogTitleId
|
||||
settingsDialogTitleId
|
||||
);
|
||||
|
||||
const settingsDialogTitleElem =
|
||||
settingsDialogElem.querySelector(".modal-title");
|
||||
if (settingsDialogTitleElem) {
|
||||
settingsDialogTitleElem.id = dialogTitleId;
|
||||
settingsDialogTitleElem.id = settingsDialogTitleId;
|
||||
}
|
||||
|
||||
const settingDialogIds =
|
||||
|
|
@ -245,6 +325,9 @@ export const ImageNode = Node.create({
|
|||
const inputElem = altTextInput as HTMLInputElement;
|
||||
if (altTextInput) {
|
||||
node.attrs.altText = inputElem.value;
|
||||
if (imgElem) {
|
||||
imgElem.alt = inputElem.value;
|
||||
}
|
||||
} else {
|
||||
console.warn("Input for alt text not found.");
|
||||
}
|
||||
|
|
@ -253,6 +336,15 @@ export const ImageNode = Node.create({
|
|||
const selectElem = alignSelect as HTMLSelectElement;
|
||||
node.attrs.align =
|
||||
selectElem.selectedOptions.item(0)?.value;
|
||||
["floatleft", "center", "floatright"].forEach(
|
||||
(align) =>
|
||||
dom.classList.remove(
|
||||
`librecms-image-node-align-${align}`
|
||||
)
|
||||
);
|
||||
dom.classList.add(
|
||||
`librecms-image-node-align-${node.attrs.align}`
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
"Select for image alignment not found."
|
||||
|
|
@ -263,6 +355,15 @@ export const ImageNode = Node.create({
|
|||
const selectElem = sizeSelect as HTMLSelectElement;
|
||||
node.attrs.size =
|
||||
selectElem.selectedOptions.item(0)?.value;
|
||||
["25", "33", "50", "66", "75", "100"].forEach(
|
||||
(size) =>
|
||||
dom.classList.remove(
|
||||
`librecms-image-node-width-${size}`
|
||||
)
|
||||
);
|
||||
dom.classList.add(
|
||||
`librecms-image-node-width-${node.attrs.size}`
|
||||
);
|
||||
} else {
|
||||
console.warn("Select for image size not found.");
|
||||
}
|
||||
|
|
@ -282,16 +383,43 @@ export const ImageNode = Node.create({
|
|||
"Submit button for image settings dialog not found."
|
||||
);
|
||||
}
|
||||
|
||||
// const removeImageButton = nodeView.querySelector(
|
||||
// ".image-remove-button"
|
||||
// );
|
||||
// if (removeImageButton) {
|
||||
// removeImageButton.addEventListener("click", (event) => {
|
||||
// if (typeof getPos === "number") {
|
||||
// const from = getPos as number;
|
||||
// const range: Range = {
|
||||
// from,
|
||||
// to: node.nodeSize,
|
||||
// };
|
||||
// editor.chain().focus().deleteRange(range);
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// console.error("removeImageButton not found.");
|
||||
// }
|
||||
}
|
||||
|
||||
const figCaptionElem = nodeView.querySelector("figcaption");
|
||||
if (node.attrs.figCaption !== "" && figCaptionElem) {
|
||||
figCaptionElem.innerHTML = node.attrs.figCaption;
|
||||
}
|
||||
const dom = document.createElement("div");
|
||||
dom.classList.add("librecms-image-node-view", "p-2");
|
||||
|
||||
dom.appendChild(nodeView);
|
||||
|
||||
if (selectButtonElem) {
|
||||
if (imgElem) {
|
||||
selectButtonElem.addEventListener("click", (event) =>
|
||||
loadImages(event, node, imgElem)
|
||||
);
|
||||
} else {
|
||||
console.error("img elem not found.");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
dom,
|
||||
};
|
||||
|
|
@ -307,11 +435,11 @@ export const ImageNode = Node.create({
|
|||
},
|
||||
|
||||
renderHTML({ node, HTMLAttributes }) {
|
||||
console.log("node = ");
|
||||
console.dir(node);
|
||||
// console.log("node = ");
|
||||
// console.dir(node);
|
||||
return [
|
||||
"figure",
|
||||
mergeAttributes(HTMLAttributes, {
|
||||
mergeAttributes({
|
||||
"data-align": node.attrs.align,
|
||||
"data-fullsizeoverlay": node.attrs.fullSizeOverlay,
|
||||
"data-size": node.attrs.size,
|
||||
|
|
@ -321,10 +449,115 @@ export const ImageNode = Node.create({
|
|||
"img",
|
||||
{
|
||||
alt: node.attrs.altText,
|
||||
src: "/assets/remixicon/image-line.svg",
|
||||
src: node.attrs.imgSrc,
|
||||
},
|
||||
],
|
||||
["figcaption"],
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
function loadImages(
|
||||
event: Event,
|
||||
node: ProsemirrorNode<any>,
|
||||
imgElem: HTMLImageElement
|
||||
) {
|
||||
console.log("Loading images...");
|
||||
const eventTarget = event.currentTarget as HTMLElement;
|
||||
const editorElem = document.querySelector(".cms-editor");
|
||||
if (!editorElem) {
|
||||
return;
|
||||
}
|
||||
const baseUrl = editorElem.getAttribute("data-baseUrl");
|
||||
const contentSection = editorElem.getAttribute("data-contentsection");
|
||||
const dialogId = eventTarget.getAttribute("data-target");
|
||||
if (!dialogId) {
|
||||
console.error("data-target attribute is missing.");
|
||||
return;
|
||||
}
|
||||
const dialog = document.querySelector(dialogId);
|
||||
if (!dialog) {
|
||||
console.error("dialog element not found is missing.");
|
||||
return;
|
||||
}
|
||||
const rowTemplateResult = document.querySelector(
|
||||
"#librecms-image-node-view-row"
|
||||
);
|
||||
if (!rowTemplateResult) {
|
||||
console.error("template for result row not found.");
|
||||
return;
|
||||
}
|
||||
const rowTemplate = rowTemplateResult as HTMLTemplateElement;
|
||||
const table = dialog.querySelector("table");
|
||||
if (!table) {
|
||||
console.error("result table not found.");
|
||||
return;
|
||||
}
|
||||
const tableBody = table.querySelector("tbody");
|
||||
if (!tableBody) {
|
||||
console.error("table body not found.");
|
||||
return;
|
||||
}
|
||||
tableBody.innerHTML = "";
|
||||
const fetchUrl = `/content-sections/${contentSection}/assets?type=org.librecms.assets.Image`;
|
||||
fetch(fetchUrl)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
response
|
||||
.json()
|
||||
.then((data) => {
|
||||
const images = data as [];
|
||||
for (const image of images) {
|
||||
const row = rowTemplate.content.cloneNode(
|
||||
true
|
||||
) as Element;
|
||||
const colName = row.querySelector(".col-name");
|
||||
const colType = row.querySelector(".col-type");
|
||||
const selectButton =
|
||||
row.querySelector(".col-action button");
|
||||
|
||||
if (colName) {
|
||||
colName.textContent = image["name"];
|
||||
}
|
||||
if (colType) {
|
||||
colType.textContent = image["name"];
|
||||
}
|
||||
|
||||
if (selectButton) {
|
||||
selectButton.setAttribute(
|
||||
"data-imageuuid",
|
||||
image["uuid"]
|
||||
);
|
||||
|
||||
selectButton.addEventListener(
|
||||
"click",
|
||||
(event) => {
|
||||
const imgUrl = `/content-sections/info/images/uuid-${image["uuid"]}`;
|
||||
node.attrs.imgSrc = imgUrl;
|
||||
if (imgElem) {
|
||||
imgElem.src = imgUrl;
|
||||
} else {
|
||||
console.error(
|
||||
"img element not found."
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
tableBody.appendChild(row);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
} else {
|
||||
console.error(
|
||||
`Error. Status: ${response.status}. Status Text: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue