Template and code for video node and audio node of the ccm-editor
parent
5513dc178e
commit
470cca567a
|
|
@ -664,9 +664,20 @@
|
||||||
class="btn btn-outline-dark tiptap-insert-image"
|
class="btn btn-outline-dark tiptap-insert-image"
|
||||||
title="#{CmsAdminMessages['cms_editor.buttons.media.insert_image']}"
|
title="#{CmsAdminMessages['cms_editor.buttons.media.insert_image']}"
|
||||||
type="button">
|
type="button">
|
||||||
<!--<bootstrap:svgIcon icon="image" />-->
|
|
||||||
<librecms:remixSvgIcon icon="ri-image-line" />
|
<librecms:remixSvgIcon icon="ri-image-line" />
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-dark tiptap-insert-video"
|
||||||
|
title="#{CmsAdminMessages['cms_editor.buttons.media.insert_video']}"
|
||||||
|
type="button">
|
||||||
|
<librecms:remixSvgIcon icon="ri-video-line" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-dark tiptap-insert-audio"
|
||||||
|
title="#{CmsAdminMessages['cms_editor.buttons.media.insert_audio']}"
|
||||||
|
type="button">
|
||||||
|
<librecms:remixSvgIcon icon="ri-music-line" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template id="librecms-image-node-view-row">
|
<template id="librecms-image-node-view-row">
|
||||||
|
|
@ -692,7 +703,7 @@
|
||||||
<div class="border-light librecms-image-node-view-buttons">
|
<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-toggle="modal"
|
||||||
data-target="#librecms-imge-node-select-image-dialog-">
|
data-target="#librecms-image-node-select-image-dialog-">
|
||||||
<librecms:remixSvgIcon icon="ri-image-edit-line" />
|
<librecms:remixSvgIcon icon="ri-image-edit-line" />
|
||||||
<span class="sr-only">#{CmsAdminMessages['cms_editor.image_node_view.select_image.label']}</span>
|
<span class="sr-only">#{CmsAdminMessages['cms_editor.image_node_view.select_image.label']}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -842,6 +853,316 @@
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template id="librecms-video-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-video-node-view">
|
||||||
|
<figure>
|
||||||
|
<video controls="controls"
|
||||||
|
src=""
|
||||||
|
style="min-heigth: 4em;">
|
||||||
|
#{CmsAdminMessages['cms_editor.video_node_view.video.none']}
|
||||||
|
</video>
|
||||||
|
<div class="border-light librecms-video-node-view-buttons">
|
||||||
|
<button class="btn btn-outline-dark select-video-button"
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#librecms-video-node-select-video-dialog-">
|
||||||
|
<librecms:remixSvgIcon icon="ri-video-edit-line" />
|
||||||
|
<span class="sr-only">#{CmsAdminMessages['cms_editor.video_node_view.select_video.label']}</span>
|
||||||
|
</button>
|
||||||
|
<div aria-hidden="true"
|
||||||
|
aria-labelledby="librecms-video-node-select-video-dialog-title-"
|
||||||
|
class="modal fade select-video-dialog ccm-cms-asset-picker"
|
||||||
|
id="librecms-video-node-select-video-dialog-"
|
||||||
|
tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-xl">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title"
|
||||||
|
id="librecms-video-node-select-video-dialog-title-">
|
||||||
|
#{CmsAdminMessages['cms_editor.video_node_view.selectvideo.dialog.title']}
|
||||||
|
<button aria-label="#{CmsAdminMessages['cms_editor.video_node_view.selectvideo.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.video_node_view.selectvideo.dialog.close']}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-outline-dark video-settings-button"
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#librecms-video-node-view-settings-dialog-">
|
||||||
|
<librecms:remixSvgIcon icon="ri-settings-2-line" />
|
||||||
|
<span class="sr-only">#{CmsAdminMessages['cms_editor.video_node_view.video_settings.label']}</span>
|
||||||
|
</button>
|
||||||
|
<div aria-hidden="true"
|
||||||
|
aria-labelledby="librecms-video-node-view-settings-dialog-title-"
|
||||||
|
class="modal fade video-settings-dialog"
|
||||||
|
id="librecms-video-node-view-settings-dialog-"
|
||||||
|
tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<form action="#" class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title"
|
||||||
|
id="librecms-video-node-view-settings-dialog-title-">
|
||||||
|
#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.title']}
|
||||||
|
</h3>
|
||||||
|
<button aria-label="#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.close']}"
|
||||||
|
class="close"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
<bootstrap:svgIcon icon="x-circle" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="alttext">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.alttext.label']}</label>
|
||||||
|
<input aria-describedby="alttext-help"
|
||||||
|
class="form-control"
|
||||||
|
id="alttext"
|
||||||
|
required="true"
|
||||||
|
type="text" />
|
||||||
|
<small class="form-text text-muted"
|
||||||
|
id="alttext-help">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.alttext.help']}</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="size">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.size.label']}</label>
|
||||||
|
<select aria-describedby="size-help"
|
||||||
|
class="custom-select"
|
||||||
|
id="size">
|
||||||
|
<option value="25">25%</option>
|
||||||
|
<option value="33">33%</option>
|
||||||
|
<option value="50">50%</option>
|
||||||
|
<option value="66">66%</option>
|
||||||
|
<option value="75">75%</option>
|
||||||
|
<option value="100">100%</option>
|
||||||
|
</select>
|
||||||
|
<small class="form-text text-muted"
|
||||||
|
id="size-help">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.size.help']}</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="align">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.align.label']}</label>
|
||||||
|
<select aria-describedby="align-help"
|
||||||
|
class="custom-select"
|
||||||
|
id="align">
|
||||||
|
<option value="floatleft">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.align.floatleft']}</option>
|
||||||
|
<option value="center">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.align.center']}</option>
|
||||||
|
<option value="floatright">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.align.floatright']}</option>
|
||||||
|
</select>
|
||||||
|
<small class="form-text text-muted"
|
||||||
|
id="align-help">#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.align.help']}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-warning"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.close']}
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary video-settings-dialog-save"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
#{CmsAdminMessages['cms_editor.video_node_view.settings.dialog.save']}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<figcaption aria-label="#{CmsAdminMessages['cms_editor.video_node_view.figcaption.label']}"
|
||||||
|
contenteditable="true">
|
||||||
|
#{CmsAdminMessages['cms_editor.video_node_view.figcaption.placeholder']}
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="librecms-audio-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-audio-node-view">
|
||||||
|
<figure>
|
||||||
|
<audio controls="controls"
|
||||||
|
src=""
|
||||||
|
style="min-height: 4em">
|
||||||
|
#{CmsAdminMessages['cms_editor.audio_node_view.image.none']}
|
||||||
|
</audio>
|
||||||
|
<div class="border-light librecms-audio-node-view-buttons">
|
||||||
|
<button class="btn btn-outline-dark select-audio-button"
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#librecms-audio-node-select-audio-dialog-">
|
||||||
|
<librecms:remixSvgIcon icon="ri-music-line" />
|
||||||
|
<span class="sr-only">#{CmsAdminMessages['cms_editor.audio_node_view.select_audio.label']}</span>
|
||||||
|
</button>
|
||||||
|
<div aria-hidden="true"
|
||||||
|
aria-labelledby="librecms-audio-node-select-audio-dialog-title-"
|
||||||
|
class="modal fade select-audio-dialog ccm-cms-asset-picker"
|
||||||
|
id="librecms-audio-node-select-audio-dialog-"
|
||||||
|
tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-xl">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title"
|
||||||
|
id="librecms-audio-node-select-audio-dialog-title-">
|
||||||
|
#{CmsAdminMessages['cms_editor.audio_node_view.selectaudio.dialog.title']}
|
||||||
|
<button aria-label="#{CmsAdminMessages['cms_editor.audio_node_view.selectaudio.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.audio_node_view.selectimage.dialog.close']}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-outline-dark audio-settings-button"
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#librecms-audio-node-view-settings-dialog-">
|
||||||
|
<librecms:remixSvgIcon icon="ri-settings-2-line" />
|
||||||
|
<span class="sr-only">#{CmsAdminMessages['cms_editor.audio_node_view.image_settings.label']}</span>
|
||||||
|
</button>
|
||||||
|
<div aria-hidden="true"
|
||||||
|
aria-labelledby="librecms-audio-node-view-settings-dialog-title-"
|
||||||
|
class="modal fade audio-settings-dialog"
|
||||||
|
id="librecms-audio-node-view-settings-dialog-"
|
||||||
|
tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<form action="#" class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="modal-title"
|
||||||
|
id="librecms-audio-node-view-settings-dialog-title-">
|
||||||
|
#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.title']}
|
||||||
|
</h3>
|
||||||
|
<button aria-label="#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.close']}"
|
||||||
|
class="close"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
<bootstrap:svgIcon icon="x-circle" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="alttext">#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.alttext.label']}</label>
|
||||||
|
<input aria-describedby="alttext-help"
|
||||||
|
class="form-control"
|
||||||
|
id="alttext"
|
||||||
|
required="true"
|
||||||
|
type="text" />
|
||||||
|
<small class="form-text text-muted"
|
||||||
|
id="alttext-help">#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.alttext.help']}</small>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="align">#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.align.label']}</label>
|
||||||
|
<select aria-describedby="align-help"
|
||||||
|
class="custom-select"
|
||||||
|
id="align">
|
||||||
|
<option value="floatleft">#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.align.floatleft']}</option>
|
||||||
|
<option value="center">#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.align.center']}</option>
|
||||||
|
<option value="floatright">#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.align.floatright']}</option>
|
||||||
|
</select>
|
||||||
|
<small class="form-text text-muted"
|
||||||
|
id="align-help">#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.align.help']}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-warning"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.close']}
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary image-settings-dialog-save"
|
||||||
|
data-dismiss="modal"
|
||||||
|
type="button">
|
||||||
|
#{CmsAdminMessages['cms_editor.audio_node_view.settings.dialog.save']}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<figcaption aria-label="#{CmsAdminMessages['cms_editor.audio_node_view.figcaption.label']}"
|
||||||
|
contenteditable="true">
|
||||||
|
#{CmsAdminMessages['cms_editor.audio_node_view.figcaption.placeholder']}
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="cms-tiptap-editor-canvas border"
|
class="cms-tiptap-editor-canvas border"
|
||||||
data-locale="#{cc.attrs.selectedLocale}"
|
data-locale="#{cc.attrs.selectedLocale}"
|
||||||
|
|
|
||||||
|
|
@ -893,3 +893,41 @@ 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.title=Select image
|
||||||
cms_editor.image_node_view.selectimage.dialog.close=Cancel
|
cms_editor.image_node_view.selectimage.dialog.close=Cancel
|
||||||
cms_editor.image_node_view.remove.label=Remove image
|
cms_editor.image_node_view.remove.label=Remove image
|
||||||
|
cms_editor.video_node_view.video.none=No video selecte yet.
|
||||||
|
cms_editor.video_node_view.select_video.label=Select video
|
||||||
|
cms_editor.video_node_view.selectvideo.dialog.title=Select video
|
||||||
|
cms_editor.video_node_view.selectvideo.dialog.close=Cancel
|
||||||
|
cms_editor.video_node_view.video_settings.label=Settings
|
||||||
|
cms_editor.video_node_view.settings.dialog.title=Video Settings
|
||||||
|
cms_editor.video_node_view.settings.dialog.close=Cancel
|
||||||
|
cms_editor.video_node_view.settings.dialog.alttext.label=Alternative text
|
||||||
|
cms_editor.video_node_view.settings.dialog.alttext.help=An alternative text that is shown if the video can't be displayed.
|
||||||
|
cms_editor.video_node_view.settings.dialog.size.label=Size
|
||||||
|
cms_editor.video_node_view.settings.dialog.size.help=Size of the video.
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.label=Alignment
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.floatleft=Float left
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.center=Centered
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.floatright=Float right
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.help=The alignment of the video in the surrounding text.
|
||||||
|
cms_editor.video_node_view.settings.dialog.save=Submit
|
||||||
|
cms_editor.video_node_view.figcaption.label=Caption
|
||||||
|
cms_editor.video_node_view.figcaption.placeholder=No caption yet.
|
||||||
|
cms_editor.audio_node_view.image.none=No audio media selected yet.
|
||||||
|
cms_editor.audio_node_view.select_audio.label=Select audio media
|
||||||
|
cms_editor.audio_node_view.selectaudio.dialog.title=Select audio media
|
||||||
|
cms_editor.audio_node_view.selectaudio.dialog.close=Cancel
|
||||||
|
cms_editor.audio_node_view.image_settings.label=Settings
|
||||||
|
cms_editor.audio_node_view.settings.dialog.title=Audio media settings
|
||||||
|
cms_editor.audio_node_view.settings.dialog.close=Cancel
|
||||||
|
cms_editor.audio_node_view.settings.dialog.alttext.label=Alternative text
|
||||||
|
cms_editor.audio_node_view.settings.dialog.alttext.help=An alternative text shown when the audio medium can't be displayed.
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.label=Alignment
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.floatleft=Float left
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.center=Centered
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.floatright=Rechts umflie\u00dfend
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.help=The alignment of the audio medium in the surrounding text.
|
||||||
|
cms_editor.audio_node_view.settings.dialog.save=Submit
|
||||||
|
cms_editor.audio_node_view.figcaption.label=Caption
|
||||||
|
cms_editor.audio_node_view.figcaption.placeholder=No description added yet.
|
||||||
|
cms_editor.buttons.media.insert_video=Insert video
|
||||||
|
cms_editor.buttons.media.insert_audio=Insert audio media
|
||||||
|
|
|
||||||
|
|
@ -894,3 +894,41 @@ 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.title=Bild ausw\u00e4hlen
|
||||||
cms_editor.image_node_view.selectimage.dialog.close=Abbrechen
|
cms_editor.image_node_view.selectimage.dialog.close=Abbrechen
|
||||||
cms_editor.image_node_view.remove.label=Bild entfernen
|
cms_editor.image_node_view.remove.label=Bild entfernen
|
||||||
|
cms_editor.video_node_view.video.none=Es wurde noch keine Video ausgew\u00e4hlt.
|
||||||
|
cms_editor.video_node_view.select_video.label=Video ausw\u00e4hlen
|
||||||
|
cms_editor.video_node_view.selectvideo.dialog.title=Video ausw\u00e4hlen
|
||||||
|
cms_editor.video_node_view.selectvideo.dialog.close=Abbrechen
|
||||||
|
cms_editor.video_node_view.video_settings.label=Einstellungen
|
||||||
|
cms_editor.video_node_view.settings.dialog.title=Video Einstellungen
|
||||||
|
cms_editor.video_node_view.settings.dialog.close=Abbrechen
|
||||||
|
cms_editor.video_node_view.settings.dialog.alttext.label=Alternativ-Text
|
||||||
|
cms_editor.video_node_view.settings.dialog.alttext.help=Ein alternativer Text, der angezeigt wird, wenn das Video nicht geladen werden kann.
|
||||||
|
cms_editor.video_node_view.settings.dialog.size.label=Gr\u00f6\u00dfe
|
||||||
|
cms_editor.video_node_view.settings.dialog.size.help=Gr\u00f6\u00dfe des Videos.
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.label=Ausrichtung
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.floatleft=Links umflie\u00dfend
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.center=Zentriert
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.floatright=Rechts umflie\u00dfend
|
||||||
|
cms_editor.video_node_view.settings.dialog.align.help=Die Aussrichtung des Videos im umgebendem Text.
|
||||||
|
cms_editor.video_node_view.settings.dialog.save=Anwenden
|
||||||
|
cms_editor.video_node_view.figcaption.label=Beschriftung
|
||||||
|
cms_editor.video_node_view.figcaption.placeholder=Es wurde noch eine Beschriftung hinzugef\u00fcgt.
|
||||||
|
cms_editor.audio_node_view.image.none=Es wurde noch ein Audio-Medium ausgew\u00e4hlt.
|
||||||
|
cms_editor.audio_node_view.select_audio.label=Audio-Medium ausw\u00e4hlen
|
||||||
|
cms_editor.audio_node_view.selectaudio.dialog.title=Audio-Medium ausw\u00e4hlen
|
||||||
|
cms_editor.audio_node_view.selectaudio.dialog.close=Abbrechen
|
||||||
|
cms_editor.audio_node_view.image_settings.label=Einstellungen
|
||||||
|
cms_editor.audio_node_view.settings.dialog.title=Audio-Medium Einstellungen
|
||||||
|
cms_editor.audio_node_view.settings.dialog.close=Abbrechen
|
||||||
|
cms_editor.audio_node_view.settings.dialog.alttext.label=Alternativ-Text
|
||||||
|
cms_editor.audio_node_view.settings.dialog.alttext.help=Ein alternativer Text, der angezeigt wird, wenn das Audio-Medium nicht geladen werden kann.
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.label=Ausrichtung
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.floatleft=Links umflie\u00dfend
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.center=Zentriert
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.floatright=Rechts umflie\u00dfend
|
||||||
|
cms_editor.audio_node_view.settings.dialog.align.help=Die Ausrichtung des Audio-Mediums im umflie\u00dfenden Text.
|
||||||
|
cms_editor.audio_node_view.settings.dialog.save=Anwenden
|
||||||
|
cms_editor.audio_node_view.figcaption.label=Beschriftung
|
||||||
|
cms_editor.audio_node_view.figcaption.placeholder=Es wurde noch keine Beschriftung hinzugef\u00fcgt.
|
||||||
|
cms_editor.buttons.media.insert_video=Video einf\u00fcgen
|
||||||
|
cms_editor.buttons.media.insert_audio=Audio-Medium einf\u00fcgen
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,445 @@
|
||||||
|
import { Node, nodeInputRule, mergeAttributes, Range } from "@tiptap/core";
|
||||||
|
import { merge } from "jquery";
|
||||||
|
import { Node as ProsemirrorNode } from "prosemirror-model";
|
||||||
|
|
||||||
|
declare module "@tiptap/core" {
|
||||||
|
interface Commands<ReturnType> {
|
||||||
|
libreCmsAudioNode: {
|
||||||
|
setLibreCmsAudio: (attributes?: { language: string }) => ReturnType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AudioNode = Node.create({
|
||||||
|
name: "libreCmsAudioNode",
|
||||||
|
|
||||||
|
content: "inline*",
|
||||||
|
|
||||||
|
marks: "",
|
||||||
|
|
||||||
|
group: "block",
|
||||||
|
|
||||||
|
code: false,
|
||||||
|
|
||||||
|
defining: true,
|
||||||
|
|
||||||
|
addAttributes() {
|
||||||
|
return {
|
||||||
|
align: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
if (element.hasAttribute("data-align")) {
|
||||||
|
return element.getAttribute("data-align");
|
||||||
|
} else {
|
||||||
|
return "center";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
altText: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const audioElem = element.querySelector("audio");
|
||||||
|
if (audioElem) {
|
||||||
|
return audioElem.textContent;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
figCaption: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const figCaptionElem = element.querySelector("figcaption");
|
||||||
|
if (figCaptionElem) {
|
||||||
|
return figCaptionElem.innerHTML;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
audioSrc: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const audioElem = element.querySelector("audio");
|
||||||
|
if (audioElem) {
|
||||||
|
return audioElem.src;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
addCommands() {
|
||||||
|
return {
|
||||||
|
setLibreCmsAudio:
|
||||||
|
(attributes) =>
|
||||||
|
({ commands }) => {
|
||||||
|
return commands.setNode("libreCmsAudioNode", attributes);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
addNodeView() {
|
||||||
|
return ({
|
||||||
|
editor,
|
||||||
|
node,
|
||||||
|
getPos,
|
||||||
|
HTMLAttributes,
|
||||||
|
decorations,
|
||||||
|
extension,
|
||||||
|
}) => {
|
||||||
|
const templateNode = document.querySelector(
|
||||||
|
"#librecms-audio-node-view"
|
||||||
|
);
|
||||||
|
if (!templateNode) {
|
||||||
|
const errorMsg = document.createElement("div");
|
||||||
|
errorMsg.classList.add("alert", "alert-danger");
|
||||||
|
errorMsg.textContent = "Failed to create audio node view.";
|
||||||
|
|
||||||
|
return errorMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dom = document.createElement("div");
|
||||||
|
dom.classList.add("librecms-audio-node-view", "p-2");
|
||||||
|
if (!node.attrs.align) {
|
||||||
|
node.attrs.align = "center";
|
||||||
|
}
|
||||||
|
dom.classList.add(`librecms-audio-node-align-${node.attrs.align}`);
|
||||||
|
const template = templateNode as HTMLTemplateElement;
|
||||||
|
const nodeView = template.content.cloneNode(true) as HTMLElement;
|
||||||
|
const audioElem = nodeView.querySelector("audio");
|
||||||
|
const dialogIdNr = Math.floor(Math.random() * 1000000000);
|
||||||
|
|
||||||
|
const selectDialogId = `librecms-image-audio-select-audio-dialog-${dialogIdNr}`;
|
||||||
|
const selectDialogTitleId = `librecms-audio-node-select-audio-dialog-${dialogIdNr}-title`;
|
||||||
|
const selectButtonElem = nodeView.querySelector(
|
||||||
|
".select-audio-button"
|
||||||
|
);
|
||||||
|
if (selectButtonElem) {
|
||||||
|
selectButtonElem.setAttribute(
|
||||||
|
"data-target",
|
||||||
|
`#${selectDialogId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const selectDialogElem = nodeView.querySelector(
|
||||||
|
".modal.select-audio-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-audio-node-view-settings-dialog-${dialogIdNr}`;
|
||||||
|
const settingsDialogTitleId = `${settingsDialogId}-title`;
|
||||||
|
const settingsButtonElem = nodeView.querySelector(
|
||||||
|
".audio-settings-button"
|
||||||
|
);
|
||||||
|
if (settingsButtonElem) {
|
||||||
|
settingsButtonElem.setAttribute(
|
||||||
|
"data-target",
|
||||||
|
`#${settingsDialogId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const settingsDialogElem = nodeView.querySelector(
|
||||||
|
".modal.audio-settings-dialog"
|
||||||
|
);
|
||||||
|
if (settingsDialogElem) {
|
||||||
|
settingsDialogElem.id = settingsDialogId;
|
||||||
|
settingsDialogElem.setAttribute(
|
||||||
|
"aria-labelledby",
|
||||||
|
settingsDialogTitleId
|
||||||
|
);
|
||||||
|
|
||||||
|
const settingsDialogTitleElem =
|
||||||
|
settingsDialogElem.querySelector(".modal-title");
|
||||||
|
if (settingsDialogTitleElem) {
|
||||||
|
settingsDialogTitleElem.id = settingsDialogTitleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const settingDialogIds =
|
||||||
|
settingsDialogElem.querySelectorAll("*[id]");
|
||||||
|
for (let i = 0; i < settingDialogIds.length; i++) {
|
||||||
|
const elemWithId = settingDialogIds.item(i);
|
||||||
|
elemWithId.id = `${elemWithId.id}-${dialogIdNr}`;
|
||||||
|
}
|
||||||
|
const settingDialogLabels =
|
||||||
|
settingsDialogElem.querySelectorAll("*[for]");
|
||||||
|
for (let i = 0; i < settingDialogLabels.length; i++) {
|
||||||
|
const label = settingDialogLabels.item(
|
||||||
|
i
|
||||||
|
) as HTMLLabelElement;
|
||||||
|
label.setAttribute(
|
||||||
|
"for",
|
||||||
|
`${label.getAttribute("for")}-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const describedElems = settingsDialogElem.querySelectorAll(
|
||||||
|
"*[aria-describedby]"
|
||||||
|
);
|
||||||
|
for (let i = 0; i < describedElems.length; i++) {
|
||||||
|
const describedElem = describedElems.item(i);
|
||||||
|
describedElem.setAttribute(
|
||||||
|
"aria-describedby",
|
||||||
|
`${describedElem.getAttribute(
|
||||||
|
"aria-describedby"
|
||||||
|
)}-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitButton = settingsDialogElem.querySelector(
|
||||||
|
"button.audio-settings-dialog-save"
|
||||||
|
);
|
||||||
|
|
||||||
|
const altTextInput = settingsDialogElem.querySelector(
|
||||||
|
`input#alttext-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
const alignSelect = settingsDialogElem.querySelector(
|
||||||
|
`select#align-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (altTextInput) {
|
||||||
|
(altTextInput as HTMLInputElement).value =
|
||||||
|
node.attrs.altText;
|
||||||
|
} else {
|
||||||
|
console.warn("Input for alt text not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignSelect) {
|
||||||
|
const optionElems = alignSelect.querySelectorAll("option");
|
||||||
|
for (let i = 0; i < optionElems.length; i++) {
|
||||||
|
const optionElem = optionElems.item(
|
||||||
|
i
|
||||||
|
) as HTMLOptionElement;
|
||||||
|
if (optionElem.value === node.attrs.align) {
|
||||||
|
optionElem.selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("Select for image alignment not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (submitButton) {
|
||||||
|
submitButton.addEventListener("click", (event) => {
|
||||||
|
const inputElem = altTextInput as HTMLInputElement;
|
||||||
|
if (altTextInput) {
|
||||||
|
node.attrs.altText = inputElem.value;
|
||||||
|
if (audioElem) {
|
||||||
|
audioElem.textContent = inputElem.value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("Input for alt text not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignSelect) {
|
||||||
|
const selectElem = alignSelect as HTMLSelectElement;
|
||||||
|
node.attrs.align =
|
||||||
|
selectElem.selectedOptions.item(0)?.value;
|
||||||
|
["floatleft", "center", "floatright"].forEach(
|
||||||
|
(align) =>
|
||||||
|
dom.classList.remove(
|
||||||
|
`librecms-audio-node-align-${align}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
dom.classList.add(
|
||||||
|
`librecms-audio-node-align-${node.attrs.align}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
"Select for audio alignment not found."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
"Submit button for image settings dialog not found."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const figCaptionElem = nodeView.querySelector("figcaption");
|
||||||
|
if (node.attrs.figCaption !== "" && figCaptionElem) {
|
||||||
|
figCaptionElem.innerHTML = node.attrs.figCaption;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom.appendChild(nodeView);
|
||||||
|
|
||||||
|
if (selectButtonElem) {
|
||||||
|
if (audioElem) {
|
||||||
|
selectButtonElem.addEventListener("click", (event) =>
|
||||||
|
loadAudioAssets(event, node, audioElem)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.error("audio elem not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
dom,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
parseHTML() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tag: "figure[data-type=librecms-audio-node]",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
renderHTML({ node, HTMLAttributes }) {
|
||||||
|
return [
|
||||||
|
"figure",
|
||||||
|
mergeAttributes({
|
||||||
|
"data-align": node.attrs.align,
|
||||||
|
"data-type": "librecms-image-node",
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
"audio",
|
||||||
|
{
|
||||||
|
src: node.attrs.audioSrc,
|
||||||
|
textContent: node.attrs.altText,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
["figcaption", [node.attrs.figCaption]],
|
||||||
|
];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function loadAudioAssets(
|
||||||
|
event: Event,
|
||||||
|
node: ProsemirrorNode<any>,
|
||||||
|
audioElem: HTMLAudioElement
|
||||||
|
) {
|
||||||
|
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-audio-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.AudioAsset,org.librecms.assets.ExternalAudioAsset`;
|
||||||
|
fetch(fetchUrl)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
response
|
||||||
|
.json()
|
||||||
|
.then((data) => {
|
||||||
|
const audioAssets = data as [];
|
||||||
|
for (const audioAsset of audioAssets) {
|
||||||
|
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 = audioAsset["name"];
|
||||||
|
}
|
||||||
|
if (colType) {
|
||||||
|
colType.textContent = audioAsset["type"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectButton) {
|
||||||
|
selectButton.setAttribute(
|
||||||
|
"data-audiouuid",
|
||||||
|
audioAsset["uuid"]
|
||||||
|
);
|
||||||
|
|
||||||
|
selectButton.addEventListener(
|
||||||
|
"click",
|
||||||
|
(event) => {
|
||||||
|
const audioUrl = `/content-sections/info/audio/uuid-${audioAsset["uuid"]}`;
|
||||||
|
node.attrs.imgSrc = audioUrl;
|
||||||
|
if (audioElem) {
|
||||||
|
audioElem.src = audioUrl;
|
||||||
|
} 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { AudioNode } from "./audio-node";
|
||||||
|
|
||||||
|
export * from "./audio-node";
|
||||||
|
|
||||||
|
export default AudioNode;
|
||||||
|
|
@ -111,8 +111,7 @@ export const ImageNode = Node.create({
|
||||||
);
|
);
|
||||||
if (!templateNode) {
|
if (!templateNode) {
|
||||||
const errorMsg = document.createElement("div");
|
const errorMsg = document.createElement("div");
|
||||||
errorMsg.classList.add("alert");
|
errorMsg.classList.add("alert", "alert-danger");
|
||||||
errorMsg.classList.add("alert-danger");
|
|
||||||
errorMsg.textContent = "Failed to create image node view.";
|
errorMsg.textContent = "Failed to create image node view.";
|
||||||
|
|
||||||
return errorMsg;
|
return errorMsg;
|
||||||
|
|
@ -148,8 +147,8 @@ export const ImageNode = Node.create({
|
||||||
const imgElem = nodeView.querySelector("img");
|
const imgElem = nodeView.querySelector("img");
|
||||||
const dialogIdNr = Math.floor(Math.random() * 1000000000);
|
const dialogIdNr = Math.floor(Math.random() * 1000000000);
|
||||||
|
|
||||||
const selectDialogId = `librecms-image-node-select-image-dialog-title-${dialogIdNr}`;
|
const selectDialogId = `librecms-image-node-select-image-dialog-${dialogIdNr}`;
|
||||||
const selectDialogTitleId = `librecms-image-node-select-image-dialog-title-${dialogIdNr}-title`;
|
const selectDialogTitleId = `librecms-image-node-select-image-dialog-${dialogIdNr}-title`;
|
||||||
const selectButtonElem = nodeView.querySelector(
|
const selectButtonElem = nodeView.querySelector(
|
||||||
".select-image-button"
|
".select-image-button"
|
||||||
);
|
);
|
||||||
|
|
@ -180,6 +179,7 @@ export const ImageNode = Node.create({
|
||||||
selectDialogIds.forEach((elemWithId) => {
|
selectDialogIds.forEach((elemWithId) => {
|
||||||
elemWithId.id = `${elemWithId.id}-${dialogIdNr}`;
|
elemWithId.id = `${elemWithId.id}-${dialogIdNr}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectDialogLabels =
|
const selectDialogLabels =
|
||||||
selectDialogElem.querySelectorAll("*[for]");
|
selectDialogElem.querySelectorAll("*[for]");
|
||||||
selectDialogLabels.forEach((label) => {
|
selectDialogLabels.forEach((label) => {
|
||||||
|
|
@ -383,24 +383,6 @@ export const ImageNode = Node.create({
|
||||||
"Submit button for image settings dialog not found."
|
"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");
|
const figCaptionElem = nodeView.querySelector("figcaption");
|
||||||
|
|
@ -452,7 +434,7 @@ export const ImageNode = Node.create({
|
||||||
src: node.attrs.imgSrc,
|
src: node.attrs.imgSrc,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
["figcaption"],
|
["figcaption", [node.attrs.figCaption]],
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
@ -462,7 +444,7 @@ function loadImages(
|
||||||
node: ProsemirrorNode<any>,
|
node: ProsemirrorNode<any>,
|
||||||
imgElem: HTMLImageElement
|
imgElem: HTMLImageElement
|
||||||
) {
|
) {
|
||||||
console.log("Loading images...");
|
// console.log("Loading images...");
|
||||||
const eventTarget = event.currentTarget as HTMLElement;
|
const eventTarget = event.currentTarget as HTMLElement;
|
||||||
const editorElem = document.querySelector(".cms-editor");
|
const editorElem = document.querySelector(".cms-editor");
|
||||||
if (!editorElem) {
|
if (!editorElem) {
|
||||||
|
|
@ -520,7 +502,7 @@ function loadImages(
|
||||||
colName.textContent = image["name"];
|
colName.textContent = image["name"];
|
||||||
}
|
}
|
||||||
if (colType) {
|
if (colType) {
|
||||||
colType.textContent = image["name"];
|
colType.textContent = image["type"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectButton) {
|
if (selectButton) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { VideoNode } from "./video-node";
|
||||||
|
|
||||||
|
export * from "./video-node";
|
||||||
|
|
||||||
|
export default VideoNode;
|
||||||
|
|
@ -0,0 +1,493 @@
|
||||||
|
import { Node, nodeInputRule, mergeAttributes, Range } from "@tiptap/core";
|
||||||
|
import { merge } from "jquery";
|
||||||
|
import { Node as ProsemirrorNode } from "prosemirror-model";
|
||||||
|
|
||||||
|
declare module "@tiptap/core" {
|
||||||
|
interface Commands<ReturnType> {
|
||||||
|
libreCmsVideoNode: {
|
||||||
|
setLibreCmsVideo: (attributes?: { language: string }) => ReturnType;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const VideoNode = Node.create({
|
||||||
|
name: "libreCmsVideoNode",
|
||||||
|
|
||||||
|
content: "inline*",
|
||||||
|
|
||||||
|
marks: "",
|
||||||
|
|
||||||
|
group: "block",
|
||||||
|
|
||||||
|
code: false,
|
||||||
|
|
||||||
|
defining: true,
|
||||||
|
|
||||||
|
addAttributes() {
|
||||||
|
return {
|
||||||
|
align: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
if (element.hasAttribute("data-align")) {
|
||||||
|
return element.getAttribute("data-align");
|
||||||
|
} else {
|
||||||
|
return "center";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
altText: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const videoElem = element.querySelector("video");
|
||||||
|
if (videoElem) {
|
||||||
|
return videoElem.textContent;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
figCaption: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const figCaptionElem = element.querySelector("figcaption");
|
||||||
|
if (figCaptionElem) {
|
||||||
|
return figCaptionElem.innerHTML;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
videoSrc: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
const videoElem = element.querySelector("video");
|
||||||
|
if (videoElem) {
|
||||||
|
return videoElem.src;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
parseHTML: (element) => {
|
||||||
|
if (element.hasAttribute("data-size")) {
|
||||||
|
return element.getAttribute("data-size");
|
||||||
|
} else {
|
||||||
|
return "50";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
addCommands() {
|
||||||
|
return {
|
||||||
|
setLibreCmsVideo:
|
||||||
|
(attributes) =>
|
||||||
|
({ commands }) => {
|
||||||
|
return commands.setNode("libreCmsVideoNode", attributes);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
addNodeView() {
|
||||||
|
return ({
|
||||||
|
editor,
|
||||||
|
node,
|
||||||
|
getPos,
|
||||||
|
HTMLAttributes,
|
||||||
|
decorations,
|
||||||
|
extension,
|
||||||
|
}) => {
|
||||||
|
const templateNode = document.querySelector(
|
||||||
|
"#librecms-video-node-view"
|
||||||
|
);
|
||||||
|
if (!templateNode) {
|
||||||
|
const errorMsg = document.createElement("div");
|
||||||
|
errorMsg.classList.add("alert alert-danger");
|
||||||
|
errorMsg.textContent = "Failed to create video node view.";
|
||||||
|
}
|
||||||
|
|
||||||
|
const dom = document.createElement("div");
|
||||||
|
dom.classList.add("librecms-video-node-view", "p-2");
|
||||||
|
if (!node.attrs.size) {
|
||||||
|
node.attrs.size = "50";
|
||||||
|
}
|
||||||
|
dom.classList.add(`librecms-video-node-width-${node.attrs.size}`);
|
||||||
|
if (!node.attrs.align) {
|
||||||
|
node.attrs.align = "center";
|
||||||
|
}
|
||||||
|
dom.classList.add(`librecms-video-node-align-${node.attrs.align}`);
|
||||||
|
|
||||||
|
const template = templateNode as HTMLTemplateElement;
|
||||||
|
const nodeView = template.content.cloneNode(true) as HTMLElement;
|
||||||
|
const videoElem = nodeView.querySelector("video");
|
||||||
|
const dialogIdNr = Math.floor(Math.random() * 1000000000);
|
||||||
|
|
||||||
|
const selectDialogId = `librecms-video-node-select-video-dialog-title-${dialogIdNr}`;
|
||||||
|
const selectDialogTitleId = `librecms-video-node-select-video-dialog-${dialogIdNr}-title`;
|
||||||
|
const selectButtonElem = nodeView.querySelector(
|
||||||
|
".select-video-button"
|
||||||
|
);
|
||||||
|
if (selectButtonElem) {
|
||||||
|
selectButtonElem.setAttribute(
|
||||||
|
"data-target",
|
||||||
|
`#${selectDialogId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const selectDialogElem = nodeView.querySelector(
|
||||||
|
".modal.select-video-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-video-node-view-settings-dialog-${dialogIdNr}`;
|
||||||
|
const settingsDialogTitleId = `${settingsDialogId}-title`;
|
||||||
|
const settingsButtonElem = nodeView.querySelector(
|
||||||
|
".video-settings-button"
|
||||||
|
);
|
||||||
|
if (settingsButtonElem) {
|
||||||
|
settingsButtonElem.setAttribute(
|
||||||
|
"data-target",
|
||||||
|
`#${settingsDialogId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const settingsDialogElem = nodeView.querySelector(
|
||||||
|
".modal.video-settings-dialog"
|
||||||
|
);
|
||||||
|
if (settingsDialogElem) {
|
||||||
|
settingsDialogElem.id = settingsDialogId;
|
||||||
|
settingsDialogElem.setAttribute(
|
||||||
|
"aria-labelledby",
|
||||||
|
settingsDialogTitleId
|
||||||
|
);
|
||||||
|
|
||||||
|
const settingsDialogTitleElem =
|
||||||
|
settingsDialogElem.querySelector(".modal-title");
|
||||||
|
if (settingsDialogTitleElem) {
|
||||||
|
settingsDialogTitleElem.id = settingsDialogTitleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const settingDialogIds =
|
||||||
|
settingsDialogElem.querySelectorAll("*[id]");
|
||||||
|
for (let i = 0; i < settingDialogIds.length; i++) {
|
||||||
|
const elemWithId = settingDialogIds.item(i);
|
||||||
|
elemWithId.id = `${elemWithId.id}-${dialogIdNr}`;
|
||||||
|
}
|
||||||
|
const settingDialogLabels =
|
||||||
|
settingsDialogElem.querySelectorAll("*[for]");
|
||||||
|
for (let i = 0; i < settingDialogLabels.length; i++) {
|
||||||
|
const label = settingDialogLabels.item(
|
||||||
|
i
|
||||||
|
) as HTMLLabelElement;
|
||||||
|
label.setAttribute(
|
||||||
|
"for",
|
||||||
|
`${label.getAttribute("for")}-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const describedElems = settingsDialogElem.querySelectorAll(
|
||||||
|
"*[aria-describedby]"
|
||||||
|
);
|
||||||
|
for (let i = 0; i < describedElems.length; i++) {
|
||||||
|
const describedElem = describedElems.item(i);
|
||||||
|
describedElem.setAttribute(
|
||||||
|
"aria-describedby",
|
||||||
|
`${describedElem.getAttribute(
|
||||||
|
"aria-describedby"
|
||||||
|
)}-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitButton = settingsDialogElem.querySelector(
|
||||||
|
"button.video-settings-dialog-save"
|
||||||
|
);
|
||||||
|
|
||||||
|
const altTextInput = settingsDialogElem.querySelector(
|
||||||
|
`input#alttext-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
const alignSelect = settingsDialogElem.querySelector(
|
||||||
|
`select#align-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const sizeSelect = settingsDialogElem.querySelector(
|
||||||
|
`select#size-${dialogIdNr}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (altTextInput) {
|
||||||
|
(altTextInput as HTMLInputElement).value =
|
||||||
|
node.attrs.altText;
|
||||||
|
} else {
|
||||||
|
console.warn("Input for alt text not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignSelect) {
|
||||||
|
const optionElems = alignSelect.querySelectorAll("option");
|
||||||
|
for (let i = 0; i < optionElems.length; i++) {
|
||||||
|
const optionElem = optionElems.item(
|
||||||
|
i
|
||||||
|
) as HTMLOptionElement;
|
||||||
|
if (optionElem.value === node.attrs.align) {
|
||||||
|
optionElem.selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("Select for video alignment not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeSelect) {
|
||||||
|
const optionElems = sizeSelect.querySelectorAll("option");
|
||||||
|
for (let i = 0; i < optionElems.length; i++) {
|
||||||
|
const optionElem = optionElems.item(
|
||||||
|
i
|
||||||
|
) as HTMLOptionElement;
|
||||||
|
if (optionElem.value === node.attrs.size) {
|
||||||
|
optionElem.selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("Select for video size not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (submitButton) {
|
||||||
|
submitButton.addEventListener("click", (event) => {
|
||||||
|
const inputElem = altTextInput as HTMLInputElement;
|
||||||
|
if (altTextInput) {
|
||||||
|
node.attrs.altText = inputElem.value;
|
||||||
|
if (videoElem) {
|
||||||
|
videoElem.textContent = inputElem.value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("Input for alt text not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignSelect) {
|
||||||
|
const selectElem = alignSelect as HTMLSelectElement;
|
||||||
|
node.attrs.align =
|
||||||
|
selectElem.selectedOptions.item(0)?.value;
|
||||||
|
["floatleft", "center", "floatright"].forEach(
|
||||||
|
(align) =>
|
||||||
|
dom.classList.remove(
|
||||||
|
`librecms-video-node-align-${align}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
dom.classList.add(
|
||||||
|
`librecms-video-node-align-${node.attrs.align}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
"Select for video alignment not found."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeSelect) {
|
||||||
|
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-video-node-width-${size}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
dom.classList.add(
|
||||||
|
`librecms-video-node-width-${node.attrs.size}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.warn("Select for video size not found.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
"Submit button for video settings dialog not found."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const figCaptionElem = nodeView.querySelector("figcaption");
|
||||||
|
if (node.attrs.figCaption !== "" && figCaptionElem) {
|
||||||
|
figCaptionElem.innerHTML = node.attrs.figCaption;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom.appendChild(nodeView);
|
||||||
|
|
||||||
|
if (selectButtonElem) {
|
||||||
|
if (videoElem) {
|
||||||
|
selectButtonElem.addEventListener("click", (event) =>
|
||||||
|
loadVideos(event, node, videoElem)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.error("video elem not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
dom,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
parseHTML() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
tag: "figure[data-type=librecms-video-node]",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
renderHTML({ node, HTMLAttributes }) {
|
||||||
|
return [
|
||||||
|
"figure",
|
||||||
|
mergeAttributes({
|
||||||
|
"data-align": node.attrs.align,
|
||||||
|
"data-size": node.attrs.size,
|
||||||
|
"data-type": "librecms-video-node",
|
||||||
|
}),
|
||||||
|
[
|
||||||
|
"video",
|
||||||
|
{
|
||||||
|
src: node.attrs.videoSrc,
|
||||||
|
textContent: node.attrs.altText,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
["figcaption", [node.attrs.figCaption]],
|
||||||
|
];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function loadVideos(
|
||||||
|
event: Event,
|
||||||
|
node: ProsemirrorNode<any>,
|
||||||
|
videoElem: HTMLVideoElement
|
||||||
|
) {
|
||||||
|
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-video-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.VideoAsset,org.librecms.assets.ExternalVideoAsset`;
|
||||||
|
fetch(fetchUrl)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
response
|
||||||
|
.json()
|
||||||
|
.then((data) => {
|
||||||
|
const videos = data as [];
|
||||||
|
for (const video of videos) {
|
||||||
|
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 = video["name"];
|
||||||
|
}
|
||||||
|
if (colType) {
|
||||||
|
colType.textContent = video["type"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectButton) {
|
||||||
|
selectButton.setAttribute(
|
||||||
|
"data-videouuid",
|
||||||
|
video["uuid"]
|
||||||
|
);
|
||||||
|
|
||||||
|
selectButton.addEventListener(
|
||||||
|
"click",
|
||||||
|
(event) => {
|
||||||
|
const videoUrl = `/content-sections/info/videos/uuid-${video["uuid"]}`;
|
||||||
|
node.attrs.videoSrc = videoUrl;
|
||||||
|
if (videoElem) {
|
||||||
|
videoElem.src = videoUrl;
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
"video 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