import { defineComponent, onMounted, onUnmounted, ref, } from 'vue'; import { NodeViewWrapper, nodeViewProps } from '@tiptap/vue-3'; import { BCMSPropEditor } from '../props'; import type { BCMSArrayPropMoveEventData, BCMSEntryExtendedContentAttrWidget, BCMSEntrySync, BCMSPropValueExtended, } from '../../types'; import { BCMSStoreMutationTypes } from '../../types'; import { BCMSIcon, BCMSImage } from '../index'; import { type BCMSMedia, BCMSPropType, type BCMSSocketSyncChangeDataProp, type BCMSSocketSyncChangeEvent, BCMSSocketSyncChangeType, type BCMSWidget, } from '@becomes/cms-sdk/types'; import { BCMSEntrySyncService } from '../../services'; import { patienceDiff, patienceDiffToSocket } from '../../util'; const component = defineComponent({ props: nodeViewProps, setup(props) { const store = window.bcms.vue.store; const rootClass = 'bcmsWidget'; const attrs = ref( JSON.parse( JSON.stringify(props.node?.attrs as BCMSEntryExtendedContentAttrWidget) ) ); if (typeof attrs.value.widget === 'string') { attrs.value.widget = JSON.parse(attrs.value.widget as never); } if (typeof attrs.value.content === 'string') { attrs.value.content = JSON.parse(attrs.value.content as never); } const image = ref(null); const showImage = ref(true); const handleRef = ref(null); const entrySync = BCMSEntrySyncService.instance as BCMSEntrySync; const language = BCMSEntrySyncService.language; const storeUnsub = store.subscribe(async (mutation) => { if (mutation.type === BCMSStoreMutationTypes.widget_set) { if (mutation.payload._id === attrs.value.widget?._id) { attrs.value.widget = mutation.payload; await parseWidget(); } } }); async function parseWidget() { const contentItems: BCMSPropValueExtended[] = []; if (attrs.value.widget && attrs.value.widget.props) { for (let i = 0; i < attrs.value.widget.props.length; i++) { const prop = attrs.value.widget.props[i]; const targetValue = attrs.value.content.find((e) => e.id === prop.id); const result = await window.bcms.prop.toPropValueExtended({ prop, value: targetValue, lang: attrs.value.lang, }); if (result) { // TODO: Improve implementation @Branislav if (prop.type === BCMSPropType.COLOR_PICKER) { (result.data as any).value = (result.data as any).value.value; } contentItems.push(result); } } attrs.value.content = contentItems; if (attrs.value.widget.previewImage) { await window.bcms.util.throwable( async () => { return await window.bcms.sdk.media.getById( (attrs.value.widget as BCMSWidget).previewImage ); }, async (result) => { image.value = result; } ); } } } function onResize() { if (window.innerWidth > 1300) { showImage.value = true; } else { showImage.value = false; } } function resolvePath(path: string): Array { let p = window.bcms.prop.pathStrToArr(path); if (typeof p[1] === 'number' && typeof p[2] === 'number') { p = p.slice(2); } else { p = p.slice(1); } return p; } async function onSyncChangeSignal(event: BCMSSocketSyncChangeEvent) { if (event.sct === BCMSSocketSyncChangeType.PROP) { const data = event.data as BCMSSocketSyncChangeDataProp; if (attrs.value.content && data.p.startsWith(attrs.value.basePath)) { const content = attrs.value.content; if ( data.sd || typeof data.rep !== 'undefined' || data.addI || data.remI || data.movI ) { const path = window.bcms.prop.pathStrToArr(data.p).slice(2); if (data.sd) { window.bcms.prop.mutateValue.string(content, path, data.sd); } else if (typeof data.rep !== 'undefined') { window.bcms.prop.mutateValue.any(content, path, data.rep); } else if (data.movI) { window.bcms.prop.mutateValue.reorderArrayItems( content, path, data.movI as BCMSArrayPropMoveEventData ); } else if (data.remI) { window.bcms.prop.mutateValue.removeArrayItem(content, path); } else if (data.addI) { const widget = attrs.value.widget; if (widget) { window.bcms.prop.mutateValue.addArrayItem( content, widget.props, window.bcms.prop.pathStrToArr(data.p), data.l ); } } else { return; } if (props.updateAttributes) { props.updateAttributes({ content: JSON.stringify(content), widget: JSON.stringify(attrs.value.widget), }); } } } } } onMounted(async () => { await parseWidget(); onResize(); window.addEventListener('resize', onResize); if (handleRef.value) { const parent = handleRef.value.parentElement as HTMLElement; if (parent) { parent.setAttribute('id', 'widget_wrapper'); } } if (store.getters.feature_available('content_sync')) { entrySync.onChange((event) => { onSyncChangeSignal(event).catch((err) => { console.error(err); }); }); } }); onUnmounted(() => { window.removeEventListener('resize', onResize); storeUnsub(); }); return () => (
Widget | {attrs.value?.widget?.label}
{ if (!language) { return; } const path = resolvePath(propPath); const content = attrs.value.content as BCMSPropValueExtended[]; if (typeof value === 'string') { const curr: string = window.bcms.prop.getValueFromPath( content, path ); if (typeof curr === 'string') { entrySync.emit.propValueChange({ propPath, languageCode: language.value.target.code, languageIndex: language.value.targetIndex, sd: patienceDiffToSocket( patienceDiff(curr.split(''), value.split('')).lines ), }); } } else if (!propPath.endsWith('nodes')) { entrySync.emit.propValueChange({ propPath, languageCode: language.value.target.code, languageIndex: language.value.targetIndex, replaceValue: value, }); } window.bcms.prop.mutateValue.any(content, path, value); if (props.updateAttributes) { props.updateAttributes({ content: JSON.stringify(content), widget: JSON.stringify(attrs.value.widget), }); } }} onAdd={async (propPath) => { if (!language) { return; } const content = attrs.value.content as BCMSPropValueExtended[]; const widget = attrs.value.widget as BCMSWidget; await window.bcms.prop.mutateValue.addArrayItem( content, widget.props, resolvePath(propPath), language.value.target.code ); entrySync.emit.propAddArrayItem({ propPath, languageCode: language.value.target.code, languageIndex: language.value.targetIndex, }); if (props.updateAttributes) { props.updateAttributes({ content: JSON.stringify(content), widget: JSON.stringify(attrs.value.widget), }); } }} onRemove={(propPath) => { if (!language) { return; } const content = attrs.value.content as BCMSPropValueExtended[]; window.bcms.prop.mutateValue.removeArrayItem( content, resolvePath(propPath) ); entrySync.emit.propRemoveArrayItem({ propPath, languageCode: language.value.target.code, languageIndex: language.value.targetIndex, }); if (props.updateAttributes) { props.updateAttributes({ content: JSON.stringify(content), widget: JSON.stringify(attrs.value.widget), }); } }} onMove={(propPath, data) => { if (!language) { return; } const content = attrs.value.content as BCMSPropValueExtended[]; window.bcms.prop.mutateValue.reorderArrayItems( content, resolvePath(propPath), data ); entrySync.emit.propMoveArrayItem({ propPath, languageCode: language.value.target.code, languageIndex: language.value.targetIndex, data, }); if (props.updateAttributes) { props.updateAttributes({ content: JSON.stringify(content), widget: JSON.stringify(attrs.value.widget), }); } }} onUpdateContent={(propPath, updates) => { if (!language) { return; } entrySync.emit.contentUpdate({ propPath: propPath, languageCode: language.value.target.code, languageIndex: language.value.targetIndex, data: { updates, }, }); }} />
{image.value ? (
) : ( '' )}
); }, }); export default component;