Image Node for Tiptap working
parent
2169e07ab2
commit
5513dc178e
|
|
@ -6,10 +6,10 @@
|
|||
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."
|
||||
>
|
||||
>
|
||||
<!-- <cc:attribute
|
||||
name="addMethod"
|
||||
required="true"
|
||||
|
|
@ -63,14 +63,26 @@
|
|||
required="true"
|
||||
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"
|
||||
required="false"
|
||||
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']}"
|
||||
|
|
@ -84,41 +96,41 @@
|
|||
required="false"
|
||||
shortDescription="Label for the cancel and close button of the edit dialog"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="editDialogSubmitLabel"
|
||||
default="#{CmsAdminMessages['save_button.label']}"
|
||||
required="false"
|
||||
shortDescription="Label for the submit button of the edit dialog"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="editDialogValueHelp"
|
||||
default="Value to update"
|
||||
required="false"
|
||||
shortDescription="Help text for the value field"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="editDialogValueLabel"
|
||||
default="Value"
|
||||
required="false"
|
||||
shortDescription="Label for the value field"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="editDialogTitle"
|
||||
default="#{CmsAdminMessages['text.edit.dialog.title']}"
|
||||
required="false"
|
||||
shortDescription="Title for the edit dialog"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="editMethod"
|
||||
required="true"
|
||||
shortDescription="URL of the endpoint for editing/updating a value. The value of the locale to update is added after the provided URL, eg. /de for updating the german value."
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<!-- <cc:attribute
|
||||
name="hasUnusedLocales"
|
||||
required="true"
|
||||
|
|
@ -131,13 +143,13 @@
|
|||
required="false"
|
||||
shortDescription="Level of the heading used for the component. Also determines the heading levels used for other parts of the component."
|
||||
type="int"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="editorId"
|
||||
required="true"
|
||||
shortDescription="ID for the editor. Also used as prefix to generate IDs for some subcomponents"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<!-- <cc:attribute
|
||||
name="emptyText"
|
||||
default="#{text.editor.no_localized_values}"
|
||||
|
|
@ -150,38 +162,38 @@
|
|||
default="Failed to save."
|
||||
required="false"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="messageSaveSuccessful"
|
||||
default="Saved sucessfully."
|
||||
required="false"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="messageVariantLoadFailed"
|
||||
default="Failed to load variant."
|
||||
required="false"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="mode"
|
||||
default="full"
|
||||
shortDescription="The editor mode. Use 'full' to enable all options including adding images etc. Use 'textonly' for a minimal version that only supports text editing, but does not allow insertation of images etc."
|
||||
required="false"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="objectIdentifier"
|
||||
required="true"
|
||||
shortDescription="Identifier of the object to which the localized string belongs"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<cc:attribute
|
||||
name="selectedLocale"
|
||||
required="true"
|
||||
shortDescription="The selected locale."
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<!-- <cc:attribute
|
||||
name="removeButtonLabel"
|
||||
default="Remove"
|
||||
|
|
@ -249,7 +261,7 @@
|
|||
required="true"
|
||||
shortDescription="Title/Heading of the editor widget"
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<!-- <cc:attribute
|
||||
name="unusedLocales"
|
||||
required="true"
|
||||
|
|
@ -267,7 +279,7 @@
|
|||
required="true"
|
||||
shortDescription="URL of the endpoint for retrieving a variant. The locale of the variant to retrieve is appended as last token."
|
||||
type="String"
|
||||
/>
|
||||
/>
|
||||
<!-- <cc:attribute name="viewButtonLabel" default="View" type="String" />
|
||||
<cc:attribute name="viewDialogTitle" default="View" type="String" />
|
||||
<cc:attribute
|
||||
|
|
@ -290,11 +302,13 @@
|
|||
<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}"
|
||||
id="#{cc.attrs.editorId}"
|
||||
>
|
||||
>
|
||||
<c:choose>
|
||||
<c:when test="#{cc.attrs.headingLevel == 1}">
|
||||
<h1>#{cc.attrs.title}</h1>
|
||||
|
|
@ -376,14 +390,14 @@
|
|||
class="cms-tiptap-editor"
|
||||
data-locale="#{cc.attrs.selectedLocale}"
|
||||
data-variant-url="#{cc.attrs.variantUrl}/#{cc.attrs.selectedLocale}"
|
||||
>
|
||||
>
|
||||
<div class="cms-tiptap-editor-buttons mb-1">
|
||||
<div class="px-2 cms-tiptap-editor-button-row cms-tiptap-editor-textformatting">
|
||||
<button
|
||||
class="btn btn-outline-dark tiptap-emph"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.emph']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!-- <bootstrap:svgIcon icon="type-italic" /> -->
|
||||
<librecms:remixSvgIcon icon="ri-italic" />
|
||||
</button>
|
||||
|
|
@ -391,7 +405,7 @@
|
|||
class="btn btn-outline-dark tiptap-strong-emph"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.strong_emph']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!-- <bootstrap:svgIcon icon="type-bold" />-->
|
||||
<librecms:remixSvgIcon icon="ri-bold" />
|
||||
</button>
|
||||
|
|
@ -399,7 +413,7 @@
|
|||
class="btn btn-outline-dark tiptap-code"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.code']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<bootstrap:svgIcon icon="code" />-->
|
||||
<librecms:remixSvgIcon icon="ri-code-view" />
|
||||
</button>
|
||||
|
|
@ -407,7 +421,7 @@
|
|||
class="btn btn-outline-dark tiptap-strikethrough"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.strikethrough']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<bootstrap:svgIcon icon="type-strikethrough" />-->
|
||||
<librecms:remixSvgIcon icon="ri-strikethrough" />
|
||||
</button>
|
||||
|
|
@ -415,7 +429,7 @@
|
|||
class="btn btn-outline-dark tiptap-subscript"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.subscript']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<span aria-hidden="true">x<sub>n</sub></span>-->
|
||||
<librecms:remixSvgIcon icon="ri-subscript" />
|
||||
</button>
|
||||
|
|
@ -423,7 +437,7 @@
|
|||
class="btn btn-outline-dark tiptap-superscript"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.superscript']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<span aria-hidden="true">x<sup>n</sup></span>-->
|
||||
<librecms:remixSvgIcon icon="ri-superscript" />
|
||||
</button>
|
||||
|
|
@ -434,8 +448,8 @@
|
|||
class="btn btn-outline-dark tiptap-h#{level}"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.h'.concat(level)]}"
|
||||
type="button"
|
||||
>
|
||||
<!--<span aria-hidden="true">H#{level}</span>-->
|
||||
>
|
||||
<!--<span aria-hidden="true">H#{level}</span>-->
|
||||
<librecms:remixSvgIcon icon="ri-h-#{level}" />
|
||||
</button>
|
||||
</ui:repeat>
|
||||
|
|
@ -445,7 +459,7 @@
|
|||
class="btn btn-outline-dark tiptap-paragraph"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.paragraph']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<bootstrap:svgIcon icon="type" />-->
|
||||
<librecms:remixSvgIcon icon="ri-text" />
|
||||
</button>
|
||||
|
|
@ -453,7 +467,7 @@
|
|||
class="btn btn-outline-dark tiptap-blockquote"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.blockquote']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--bootstrap:svgIcon icon="blockquote-left" />-->
|
||||
<librecms:remixSvgIcon icon="ri-double-quotes-l" />
|
||||
</button>
|
||||
|
|
@ -461,7 +475,7 @@
|
|||
class="btn btn-outline-dark tiptap-codeblock"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.codeblock']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<bootstrap:svgIcon icon="code-square" />-->
|
||||
<librecms:remixSvgIcon icon="ri-code-box-line" />
|
||||
</button>
|
||||
|
|
@ -471,7 +485,7 @@
|
|||
class="btn btn-outline-dark tiptap-ul"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.ul']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<bootstrap:svgIcon icon="list-ul" />-->
|
||||
<librecms:remixSvgIcon icon="ri-list-unordered" />
|
||||
</button>
|
||||
|
|
@ -479,7 +493,7 @@
|
|||
class="btn btn-outline-dark tiptap-ol"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.ol']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<bootstrap:svgIcon icon="list-ol" />-->
|
||||
<librecms:remixSvgIcon icon="ri-list-ordered" />
|
||||
</button>
|
||||
|
|
@ -491,7 +505,7 @@
|
|||
data-toggle="modal"
|
||||
title="#{CmsAdminMessage['cms_editor.buttons.insert_table']}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<!--<bootstrap:svgIcon icon="table" />-->
|
||||
<librecms:remixSvgIcon icon="ri-table-2" />
|
||||
</button>
|
||||
|
|
@ -501,14 +515,14 @@
|
|||
class="modal fade cms-editor-insert-table-dialog"
|
||||
id="insert-table-dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<form class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4
|
||||
class="modal-title"
|
||||
id="insert-table-dialog-title"
|
||||
>
|
||||
>
|
||||
#{CmsAdminMessages['cms_editor.dialogs.insert_table.title']}
|
||||
</h4>
|
||||
<button
|
||||
|
|
@ -516,7 +530,7 @@
|
|||
class="close"
|
||||
data-dismiss="modal"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
<bootstrap:svgIcon icon="x" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -526,30 +540,30 @@
|
|||
inputId="rows"
|
||||
label="#{CmsDefaultStepsMessageBundle['cms_editor.dialogs.insert_table.rows.label']}"
|
||||
name="rows"
|
||||
/>
|
||||
/>
|
||||
<bootstrap:formGroupNumber
|
||||
help="#{CmsDefaultStepsMessageBundle['cms_editor.dialogs.insert_table.cols.help']}"
|
||||
inputId="cols"
|
||||
label="#{CmsDefaultStepsMessageBundle['cms_editor.dialogs.insert_table.cols.label']}"
|
||||
name="cols"
|
||||
/>
|
||||
/>
|
||||
<bootstrap:formCheck
|
||||
checked="true"
|
||||
inputId="headerRow"
|
||||
label="#{CmsDefaultStepsMessageBundle['cms_editor.dialogs.insert_table.header_row.label']}"
|
||||
name="headerRow"
|
||||
value="true"
|
||||
/>
|
||||
/>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
class="
|
||||
btn btn-warning
|
||||
cms-editor-cancel-button
|
||||
btn btn-warning
|
||||
cms-editor-cancel-button
|
||||
"
|
||||
data-dismiss="modal"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
#{CmsDefaultStepsMessageBundle['cms_editor.dialogs.insert_table.close']}
|
||||
</button>
|
||||
<button
|
||||
|
|
@ -557,7 +571,7 @@
|
|||
data-dismiss="modal"
|
||||
data-backdrop="false"
|
||||
type="submit"
|
||||
>
|
||||
>
|
||||
#{CmsDefaultStepsMessageBundle['cms_editor.dialogs.insert_table.submit']}
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -568,23 +582,23 @@
|
|||
class="btn btn-outline-dark tiptap-remove-table"
|
||||
title="#{CmsAdminMessage['cms_editor.buttons.remove_table']}"
|
||||
type="button"
|
||||
>
|
||||
<img src="#{request.contextPath}/icons/cms-editor/table-remove.svg" />
|
||||
>
|
||||
<img src="#{request.contextPath}/icons/cms-editor/table-remove.svg" />
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-outline-dark tiptap-insert-table-row-before"
|
||||
title="#{CmsAdminMessage['cms_editor.buttons.insert_table_row_before']}"
|
||||
type="button"
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-add-row-before.svg" />-->
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-add-row-before.svg" />-->
|
||||
<librecms:remixSvgIcon icon="ri-insert-row-top" />
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-outline-dark tiptap-insert-table-row-after"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.insert_table_row_after']}"
|
||||
type="button"
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-add-row-after.svg" />-->
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-add-row-after.svg" />-->
|
||||
<librecms:remixSvgIcon icon="ri-insert-row-bottom" />
|
||||
</button>
|
||||
<button
|
||||
|
|
@ -598,24 +612,24 @@
|
|||
class="btn btn-outline-dark tiptap-insert-table-column-before"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.insert_table_column_before']}"
|
||||
type="button"
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-add-column-before.svg" />-->
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-add-column-before.svg" />-->
|
||||
<librecms:remixSvgIcon icon="ri-insert-column-left" />
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-outline-dark tiptap-insert-table-column-after"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.insert_table_column_after']}"
|
||||
type="button"
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-add-column-after.svg" />-->
|
||||
<librecms:remixSvgIcon icon="ri-insert-column-right" />
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-add-column-after.svg" />-->
|
||||
<librecms:remixSvgIcon icon="ri-insert-column-right" />
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-outline-dark tiptap-remove-table-column"
|
||||
title="#{CmsAdminMessages['cms_editor.buttons.remove_table_column']}"
|
||||
type="button"
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-remove-column.svg" />-->
|
||||
>
|
||||
<!--<img src="#{request.contextPath}/icons/cms-editor/table-remove-column.svg" />-->
|
||||
<librecms:remixSvgIcon icon="ri-delete-column" />
|
||||
</button>
|
||||
<button
|
||||
|
|
@ -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">
|
||||
|
|
@ -765,19 +846,19 @@
|
|||
class="cms-tiptap-editor-canvas border"
|
||||
data-locale="#{cc.attrs.selectedLocale}"
|
||||
data-variant-url="#{cc.attrs.variantUrl}"
|
||||
></div>
|
||||
></div>
|
||||
<div class="mt-3">
|
||||
<a
|
||||
class="btn btn-warning cms-editor-cancel-button"
|
||||
href="#{backUrl}"
|
||||
>
|
||||
>
|
||||
#{cc.attrs.editDialogCancelLabel}
|
||||
</a>
|
||||
<button
|
||||
class="btn btn-success cms-editor-save-button"
|
||||
disabled="#{cc.attrs.canEdit ? '' : 'disabled'}"
|
||||
type="button"
|
||||
>
|
||||
>
|
||||
#{cc.attrs.editDialogSubmitLabel}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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