From 90d5ac4ffc0f456f7242bbee529b6a7ad4d08c87 Mon Sep 17 00:00:00 2001 From: Jhon Vente <134975835+johnvente@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:02:34 -0500 Subject: [PATCH] feat: TinyMCE plugin insert iframe (#427) --- src/editors/data/constants/tinyMCE.js | 2 + .../customTinyMcePlugins/embedIframePlugin.js | 205 +++++++++ .../embedIframePlugin.test.js | 408 ++++++++++++++++++ .../sharedComponents/TinyMceWidget/index.jsx | 1 + .../TinyMceWidget/pluginConfig.js | 3 +- 5 files changed, 618 insertions(+), 1 deletion(-) create mode 100644 src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.js create mode 100644 src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.test.js diff --git a/src/editors/data/constants/tinyMCE.js b/src/editors/data/constants/tinyMCE.js index f98333580..f7edbe273 100644 --- a/src/editors/data/constants/tinyMCE.js +++ b/src/editors/data/constants/tinyMCE.js @@ -52,6 +52,7 @@ export const buttons = StrictDict({ undo: 'undo', underline: 'underline', a11ycheck: 'a11ycheck', + embediframe: 'embediframe', }); export const plugins = listKeyStore([ @@ -69,6 +70,7 @@ export const plugins = listKeyStore([ 'quickbars', 'a11ychecker', 'powerpaste', + 'embediframe', ]); export const textToSpeechIcon = ''; diff --git a/src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.js b/src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.js new file mode 100644 index 000000000..04057ca3a --- /dev/null +++ b/src/editors/sharedComponents/TinyMceWidget/customTinyMcePlugins/embedIframePlugin.js @@ -0,0 +1,205 @@ +function tinyMCEEmbedIframePlugin(editor) { + function openInsertIframeModal() { + const defaultConfig = { + title: 'Insert iframe', + body: { + type: 'tabpanel', + tabs: [ + { + title: 'General', + items: [ + { + type: 'input', + name: 'source', + label: 'Source URL', + multiline: false, + autofocus: true, + required: true, + }, + { + type: 'selectbox', + name: 'sizeType', + label: 'Size', + items: [ + { text: 'Inline Value', value: 'inline' }, + { text: 'Big embed', value: 'big' }, + { text: 'Small embed', value: 'small' }, + ], + }, + + { + type: 'sizeinput', + name: 'size', + label: 'Dimensions', + }, + ], + }, + { + title: 'Advanced', + items: [ + { + type: 'input', + name: 'name', + label: 'Name', + value: '', + }, + { + type: 'input', + name: 'title', + label: 'Title', + value: '', + }, + { + type: 'input', + name: 'longDescriptionURL', + label: 'Long description URL', + value: '', + }, + { + type: 'checkbox', + name: 'border', + label: 'Show iframe border', + text: 'Border', + checked: false, + }, + { + type: 'checkbox', + name: 'scrollbar', + label: 'Enable scrollbar', + text: 'Scrollbar', + checked: false, + }, + ], + }, + ], + }, + buttons: [ + { + type: 'cancel', + name: 'cancel', + text: 'Cancel', + }, + { + type: 'submit', + name: 'save', + text: 'Save', + primary: true, + }, + ], + onChange(api, field) { + const { name } = field; + const data = api.getData(); + const { sizeType, ...fields } = data; + const isSizeTypeFiled = name === 'sizeType'; + const hasCustomSize = sizeType === 'inline'; + + if (!hasCustomSize && isSizeTypeFiled) { + const { + body: { + tabs: [generalTab], + }, + } = defaultConfig; + + generalTab.items = generalTab.items.filter( + (item) => item.type !== 'sizeinput', + ); + + defaultConfig.initialData = { ...fields, sizeType }; + api.redial(defaultConfig); + } + + if (hasCustomSize && isSizeTypeFiled) { + const { + body: { + tabs: [generalTab], + }, + } = defaultConfig; + + const hasSizeInput = generalTab.items.some((item) => item.name === 'size'); + + if (!hasSizeInput) { + generalTab.items = [ + ...generalTab.items, + { + type: 'sizeinput', + name: 'size', + label: 'Dimensions', + }, + ]; + } + + defaultConfig.initialData = { ...fields, sizeType }; + api.redial(defaultConfig); + } + }, + onSubmit(api) { + const data = api.getData(); + const sizeTypes = { + small: { + height: '100px', + width: '100px', + }, + big: { + height: '800px', + width: '800px', + }, + }; + if (data.source) { + const { + size, sizeType, name, title, longDescriptionURL, border, scrollbar, + } = data; + const { width, height } = sizeTypes[sizeType] || { width: size.width, height: size.height }; + + const pxRegex = /^\d+px$/; + const widthFormat = pxRegex.test(width) ? width : '300px'; + const heightFormat = pxRegex.test(height) ? height : '300px'; + const hasScroll = scrollbar ? 'yes' : 'no'; + + let iframeCode = `