diff --git a/client/src/campaigns/CUD.js b/client/src/campaigns/CUD.js index 945965a9..3ce6b395 100644 --- a/client/src/campaigns/CUD.js +++ b/client/src/campaigns/CUD.js @@ -721,7 +721,7 @@ export default class CUD extends Component { templateEdit =
- + {customTemplateTypeForm}
; diff --git a/client/src/campaigns/Content.js b/client/src/campaigns/Content.js index 4880538a..3b654ce6 100644 --- a/client/src/campaigns/Content.js +++ b/client/src/campaigns/Content.js @@ -277,7 +277,7 @@ export default class CustomContent extends Component { {customTemplateTypeKey && this.templateTypes[customTemplateTypeKey].typeName} - + {customTemplateTypeKey && getTypeForm(this, customTemplateTypeKey, true)} diff --git a/client/src/lib/sandbox-common.js b/client/src/lib/sandbox-common.js new file mode 100644 index 00000000..a5b93441 --- /dev/null +++ b/client/src/lib/sandbox-common.js @@ -0,0 +1,9 @@ +'use strict'; + +export function getTagLanguageFromEntity(entity, entityTypeId) { + if (entityTypeId === 'template') { + return entity.tag_language; + } else if (entityTypeId === 'campaign') { + return entity.data.sourceCustom.tag_language; + } +} \ No newline at end of file diff --git a/client/src/lib/sandboxed-ckeditor-root.js b/client/src/lib/sandboxed-ckeditor-root.js index 6ab2f49f..d09159b9 100644 --- a/client/src/lib/sandboxed-ckeditor-root.js +++ b/client/src/lib/sandboxed-ckeditor-root.js @@ -27,7 +27,7 @@ class CKEditorSandbox extends Component { const trustedUrlBase = getTrustedUrl(); const sandboxUrlBase = getSandboxUrl(); const publicUrlBase = getPublicUrl(); - const source = this.props.initialSource && base(this.props.initialSource, trustedUrlBase, sandboxUrlBase, publicUrlBase); + const source = this.props.initialSource && base(this.props.initialSource, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase); this.state = { source @@ -37,6 +37,7 @@ class CKEditorSandbox extends Component { static propTypes = { entityTypeId: PropTypes.string, entityId: PropTypes.number, + tagLanguage: PropTypes.string, initialSource: PropTypes.string } @@ -48,7 +49,7 @@ class CKEditorSandbox extends Component { const preHtml = ''; const postHtml = ''; - const unbasedSource = unbase(this.state.source, trustedUrlBase, sandboxUrlBase, publicUrlBase, true); + const unbasedSource = unbase(this.state.source, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase, true); return { source: unbasedSource, diff --git a/client/src/lib/sandboxed-ckeditor.js b/client/src/lib/sandboxed-ckeditor.js index 7e0c96d1..f9b644af 100644 --- a/client/src/lib/sandboxed-ckeditor.js +++ b/client/src/lib/sandboxed-ckeditor.js @@ -11,6 +11,7 @@ import {getTrustedUrl} from "./urls"; import {initialHeight} from "./sandboxed-ckeditor-shared"; import {withComponentMixins} from "./decorator-helpers"; +import {getTagLanguageFromEntity} from "./sandbox-common"; const navbarHeight = 34; // Sync this with navbarheight in sandboxed-ckeditor.scss @@ -83,6 +84,7 @@ export class CKEditorHost extends Component { const editorData = { entityTypeId: this.props.entityTypeId, entityId: this.props.entity.id, + tagLanguage: getTagLanguageFromEntity(this.props.entity, this.props.entityTypeId), initialSource: this.props.initialSource }; diff --git a/client/src/lib/sandboxed-codeeditor-root.js b/client/src/lib/sandboxed-codeeditor-root.js index 97326e06..1501985d 100644 --- a/client/src/lib/sandboxed-codeeditor-root.js +++ b/client/src/lib/sandboxed-codeeditor-root.js @@ -66,7 +66,7 @@ class CodeEditorSandbox extends Component { const trustedUrlBase = getTrustedUrl(); const sandboxUrlBase = getSandboxUrl(); const publicUrlBase = getPublicUrl(); - const source = this.props.initialSource ? base(this.props.initialSource, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultSource; + const source = this.props.initialSource ? base(this.props.initialSource, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultSource; this.state = { source, @@ -87,6 +87,7 @@ class CodeEditorSandbox extends Component { static propTypes = { entityTypeId: PropTypes.string, entityId: PropTypes.number, + tagLanguage: PropTypes.string, initialSource: PropTypes.string, sourceType: PropTypes.string, initialPreview: PropTypes.bool, @@ -98,8 +99,8 @@ class CodeEditorSandbox extends Component { const sandboxUrlBase = getSandboxUrl(); const publicUrlBase = getPublicUrl(); return { - html: unbase(this.getHtml(), trustedUrlBase, sandboxUrlBase, publicUrlBase, true), - source: unbase(this.state.source, trustedUrlBase, sandboxUrlBase, publicUrlBase, true) + html: unbase(this.getHtml(), this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase, true), + source: unbase(this.state.source, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase, true) }; } @@ -149,7 +150,7 @@ class CodeEditorSandbox extends Component { }); if (!this.refreshTimeoutId) { - this.refreshTimeoutId = setTimeout(() => this.refresh(), refreshTimeout); + this.refreshTimeoutId = setTimeout(this.refreshHandler, refreshTimeout); } } diff --git a/client/src/lib/sandboxed-codeeditor.js b/client/src/lib/sandboxed-codeeditor.js index 21d59a8a..3f2f5420 100644 --- a/client/src/lib/sandboxed-codeeditor.js +++ b/client/src/lib/sandboxed-codeeditor.js @@ -9,6 +9,7 @@ import {UntrustedContentHost} from './untrusted'; import {Icon} from "./bootstrap-components"; import {getTrustedUrl} from "./urls"; import {withComponentMixins} from "./decorator-helpers"; +import {getTagLanguageFromEntity} from "./sandbox-common"; @withComponentMixins([ withTranslation @@ -75,6 +76,7 @@ export class CodeEditorHost extends Component { const editorData = { entityTypeId: this.props.entityTypeId, entityId: this.props.entity.id, + tagLanguage: getTagLanguageFromEntity(this.props.entity, this.props.entityTypeId), initialSource: this.props.initialSource, sourceType: this.props.sourceType, initialPreview: this.state.preview, diff --git a/client/src/lib/sandboxed-grapesjs-root.js b/client/src/lib/sandboxed-grapesjs-root.js index f9c2f76d..00d89fe6 100644 --- a/client/src/lib/sandboxed-grapesjs-root.js +++ b/client/src/lib/sandboxed-grapesjs-root.js @@ -54,6 +54,7 @@ export class GrapesJSSandbox extends Component { static propTypes = { entityTypeId: PropTypes.string, entityId: PropTypes.number, + tagLanguage: PropTypes.string, initialSource: PropTypes.string, initialStyle: PropTypes.string, sourceType: PropTypes.string @@ -75,8 +76,8 @@ export class GrapesJSSandbox extends Component { const sandboxUrlBase = getSandboxUrl(); const publicUrlBase = getPublicUrl(); - const source = unbase(editor.getHtml(), trustedUrlBase, sandboxUrlBase, publicUrlBase, true); - const style = unbase(editor.getCss(), trustedUrlBase, sandboxUrlBase, publicUrlBase, true); + const source = unbase(editor.getHtml(), this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase, true); + const style = unbase(editor.getCss(), this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase, true); let html; @@ -96,7 +97,7 @@ export class GrapesJSSandbox extends Component { const preHtml = ''; const postHtml = ''; - html = preHtml + unbase(htmlBody, trustedUrlBase, sandboxUrlBase, publicUrlBase, true) + postHtml; + html = preHtml + unbase(htmlBody, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase, true) + postHtml; } @@ -603,8 +604,8 @@ export class GrapesJSSandbox extends Component { config.plugins.push('gjs-preset-newsletter'); } - config.components = props.initialSource ? base(props.initialSource, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultSource; - config.style = props.initialStyle ? base(props.initialStyle, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultStyle; + config.components = props.initialSource ? base(props.initialSource, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultSource; + config.style = props.initialStyle ? base(props.initialStyle, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultStyle; config.plugins.push('mailtrain-remove-buttons'); diff --git a/client/src/lib/sandboxed-grapesjs.js b/client/src/lib/sandboxed-grapesjs.js index 42fa23a4..d3de59e3 100644 --- a/client/src/lib/sandboxed-grapesjs.js +++ b/client/src/lib/sandboxed-grapesjs.js @@ -10,6 +10,7 @@ import {Icon} from "./bootstrap-components"; import {getTrustedUrl} from "./urls"; import {withComponentMixins} from "./decorator-helpers"; import {GrapesJSSourceType} from "./sandboxed-grapesjs-shared"; +import {getTagLanguageFromEntity} from "./sandbox-common"; @withComponentMixins([ withTranslation @@ -57,6 +58,7 @@ export class GrapesJSHost extends Component { const editorData = { entityTypeId: this.props.entityTypeId, entityId: this.props.entity.id, + tagLanguage: getTagLanguageFromEntity(this.props.entity, this.props.entityTypeId), initialSource: this.props.initialSource, initialStyle: this.props.initialStyle, sourceType: this.props.sourceType diff --git a/client/src/lib/sandboxed-mosaico-root.js b/client/src/lib/sandboxed-mosaico-root.js index 4a3dfd5a..78bddac0 100644 --- a/client/src/lib/sandboxed-mosaico-root.js +++ b/client/src/lib/sandboxed-mosaico-root.js @@ -27,6 +27,7 @@ class MosaicoSandbox extends Component { static propTypes = { entityTypeId: PropTypes.string, entityId: PropTypes.number, + tagLanguage: PropTypes.string, templateId: PropTypes.number, templatePath: PropTypes.string, initialModel: PropTypes.string, @@ -60,9 +61,9 @@ class MosaicoSandbox extends Component { html = juice(html); return { - html: unbase(html, trustedUrlBase, sandboxUrlBase, publicUrlBase, true), - model: unbase(this.viewModel.exportJSON(), trustedUrlBase, sandboxUrlBase, publicUrlBase), - metadata: unbase(this.viewModel.exportMetadata(), trustedUrlBase, sandboxUrlBase, publicUrlBase) + html: unbase(html, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase, true), + model: unbase(this.viewModel.exportJSON(), this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase), + metadata: unbase(this.viewModel.exportMetadata(), this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase) }; } @@ -128,8 +129,8 @@ class MosaicoSandbox extends Component { const trustedUrlBase = getTrustedUrl(); const sandboxUrlBase = getSandboxUrl(); const publicUrlBase = getPublicUrl(); - const metadata = this.props.initialMetadata && JSON.parse(base(this.props.initialMetadata, trustedUrlBase, sandboxUrlBase, publicUrlBase)); - const model = this.props.initialModel && JSON.parse(base(this.props.initialModel, trustedUrlBase, sandboxUrlBase, publicUrlBase)); + const metadata = this.props.initialMetadata && JSON.parse(base(this.props.initialMetadata, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase)); + const model = this.props.initialModel && JSON.parse(base(this.props.initialModel, this.props.tagLanguage, trustedUrlBase, sandboxUrlBase, publicUrlBase)); const template = this.props.templateId ? getSandboxUrl(`mosaico/templates/${this.props.templateId}/index.html`) : this.props.templatePath; const allPlugins = plugins.concat(window.mosaicoPlugins); diff --git a/client/src/lib/sandboxed-mosaico.js b/client/src/lib/sandboxed-mosaico.js index 7704c0d1..352da1fd 100644 --- a/client/src/lib/sandboxed-mosaico.js +++ b/client/src/lib/sandboxed-mosaico.js @@ -9,6 +9,7 @@ import {UntrustedContentHost} from './untrusted'; import {Icon} from "./bootstrap-components"; import {getTrustedUrl} from "./urls"; import {withComponentMixins} from "./decorator-helpers"; +import {getTagLanguageFromEntity} from "./sandbox-common"; @withComponentMixins([ @@ -58,6 +59,7 @@ export class MosaicoHost extends Component { const editorData = { entityTypeId: this.props.entityTypeId, entityId: this.props.entity.id, + tagLanguage: getTagLanguageFromEntity(this.props.entity, this.props.entityTypeId), templateId: this.props.templateId, templatePath: this.props.templatePath, initialModel: this.props.initialModel, diff --git a/client/src/templates/CUD.js b/client/src/templates/CUD.js index c89166de..59dcb1f9 100644 --- a/client/src/templates/CUD.js +++ b/client/src/templates/CUD.js @@ -376,7 +376,7 @@ export default class CUD extends Component { {typeForm} - + } diff --git a/client/src/templates/helpers.js b/client/src/templates/helpers.js index dd651149..c49a5ad0 100644 --- a/client/src/templates/helpers.js +++ b/client/src/templates/helpers.js @@ -167,7 +167,6 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM mutState.setIn([prefix + 'mosaicoTemplate', 'value'], null); } }, - isTagLanguageSelectorDisabledForEdit: true, validate: state => { const mosaicoTemplate = state.getIn([prefix + 'mosaicoTemplate', 'value']); if (!mosaicoTemplate) { @@ -256,7 +255,6 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM }, afterTagLanguageChange: (mutState, isEdit) => { }, - isTagLanguageSelectorDisabledForEdit: false, validate: state => { } }; @@ -346,7 +344,6 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM }, afterTagLanguageChange: (mutState, isEdit) => { }, - isTagLanguageSelectorDisabledForEdit: false, validate: state => { } }; @@ -408,7 +405,6 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM }, afterTagLanguageChange: (mutState, isEdit) => { }, - isTagLanguageSelectorDisabledForEdit: false, validate: state => { } }; @@ -495,7 +491,6 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM }, afterTagLanguageChange: (mutState, isEdit) => { }, - isTagLanguageSelectorDisabledForEdit: false, validate: state => { } }; diff --git a/server/lib/campaign-content.js b/server/lib/campaign-content.js index 965b6bfb..19728094 100644 --- a/server/lib/campaign-content.js +++ b/server/lib/campaign-content.js @@ -1,7 +1,11 @@ 'use strict'; +const {renderTag} = require('../../shared/templates'); + function convertFileURLs(sourceCustom, fromEntityType, fromEntityId, toEntityType, toEntityId) { + const tagLanguage = sourceCustom.tag_language; + function convertText(text) { if (text) { const fromUrl = `/files/${fromEntityType}/file/${fromEntityId}`; @@ -10,10 +14,10 @@ function convertFileURLs(sourceCustom, fromEntityType, fromEntityId, toEntityTyp const encodedFromUrl = encodeURIComponent(fromUrl); const encodedToUrl = encodeURIComponent(toUrl); - text = text.split('[URL_BASE]' + fromUrl).join('[URL_BASE]' + toUrl); - text = text.split('[SANDBOX_URL_BASE]' + fromUrl).join('[SANDBOX_URL_BASE]' + toUrl); - text = text.split('[ENCODED_URL_BASE]' + encodedFromUrl).join('[ENCODED_URL_BASE]' + encodedToUrl); - text = text.split('[ENCODED_SANDBOX_URL_BASE]' + encodedFromUrl).join('[ENCODED_SANDBOX_URL_BASE]' + encodedToUrl); + text = text.split(renderTag(tagLanguage, 'URL_BASE') + fromUrl).join(renderTag(tagLanguage, 'URL_BASE') + toUrl); + text = text.split(renderTag(tagLanguage,'SANDBOX_URL_BASE') + fromUrl).join(renderTag(tagLanguage, 'SANDBOX_URL_BASE') + toUrl); + text = text.split(renderTag(tagLanguage, 'ENCODED_URL_BASE') + encodedFromUrl).join(renderTag(tagLanguage, 'ENCODED_URL_BASE') + encodedToUrl); + text = text.split(renderTag(tagLanguage, 'ENCODED_SANDBOX_URL_BASE') + encodedFromUrl).join(renderTag(tagLanguage, 'ENCODED_SANDBOX_URL_BASE') + encodedToUrl); } return text; diff --git a/server/routes/sandboxed-mosaico.js b/server/routes/sandboxed-mosaico.js index 98f4854b..ceac02b7 100644 --- a/server/routes/sandboxed-mosaico.js +++ b/server/routes/sandboxed-mosaico.js @@ -141,7 +141,7 @@ async function getRouter(appType) { const tmpl = await mosaicoTemplates.getById(req.context, castToInteger(req.params.mosaicoTemplateId)); res.set('Content-Type', 'text/html'); - res.send(base(tmpl.data.html, getTrustedUrl(), getSandboxUrl('', req.context), getPublicUrl())); + res.send(base(tmpl.data.html, tmpl.tag_language, getTrustedUrl(), getSandboxUrl('', req.context), getPublicUrl())); }); // Mosaico looks for block thumbnails in edres folder relative to index.html of the template. We respond to such requests here. diff --git a/shared/templates.js b/shared/templates.js index 35d819cf..a4c22fa8 100644 --- a/shared/templates.js +++ b/shared/templates.js @@ -44,28 +44,28 @@ function getMergeTagsForBases(trustedBaseUrl, sandboxBaseUrl, publicBaseUrl) { }; } -function base(text, trustedBaseUrl, sandboxBaseUrl, publicBaseUrl) { +function base(text, tagLanguage, trustedBaseUrl, sandboxBaseUrl, publicBaseUrl) { const bases = _getBases(trustedBaseUrl, sandboxBaseUrl, publicBaseUrl); - text = text.split('[URL_BASE]').join(bases.publicBaseUrl); - text = text.split('[TRUSTED_URL_BASE]').join(bases.trustedBaseUrl); - text = text.split('[SANDBOX_URL_BASE]').join(bases.sandboxBaseUrl); - text = text.split('[ENCODED_URL_BASE]').join(encodeURIComponent(bases.publicBaseUrl)); - text = text.split('[ENCODED_TRUSTED_URL_BASE]').join(encodeURIComponent(bases.trustedBaseUrl)); - text = text.split('[ENCODED_SANDBOX_URL_BASE]').join(encodeURIComponent(bases.sandboxBaseUrl)); + text = text.split(renderTag(tagLanguage, 'URL_BASE')).join(bases.publicBaseUrl); + text = text.split(renderTag(tagLanguage, 'TRUSTED_URL_BASE')).join(bases.trustedBaseUrl); + text = text.split(renderTag(tagLanguage, 'SANDBOX_URL_BASE')).join(bases.sandboxBaseUrl); + text = text.split(renderTag(tagLanguage, 'ENCODED_URL_BASE')).join(encodeURIComponent(bases.publicBaseUrl)); + text = text.split(renderTag(tagLanguage, 'ENCODED_TRUSTED_URL_BASE')).join(encodeURIComponent(bases.trustedBaseUrl)); + text = text.split(renderTag(tagLanguage, 'ENCODED_SANDBOX_URL_BASE')).join(encodeURIComponent(bases.sandboxBaseUrl)); return text; } -function unbase(text, trustedBaseUrl, sandboxBaseUrl, publicBaseUrl, treatAllAsPublic = false) { +function unbase(text, tagLanguage, trustedBaseUrl, sandboxBaseUrl, publicBaseUrl, treatAllAsPublic = false) { const bases = _getBases(trustedBaseUrl, sandboxBaseUrl, publicBaseUrl); - text = text.split(bases.publicBaseUrl).join('[URL_BASE]'); - text = text.split(bases.trustedBaseUrl).join(treatAllAsPublic ? '[URL_BASE]' : '[TRUSTED_URL_BASE]'); - text = text.split(bases.sandboxBaseUrl).join(treatAllAsPublic ? '[URL_BASE]' : '[SANDBOX_URL_BASE]'); - text = text.split(encodeURIComponent(bases.publicBaseUrl)).join('[ENCODED_URL_BASE]'); - text = text.split(encodeURIComponent(bases.trustedBaseUrl)).join(treatAllAsPublic ? '[ENCODED_URL_BASE]' : '[ENCODED_TRUSTED_URL_BASE]'); - text = text.split(encodeURIComponent(bases.sandboxBaseUrl)).join(treatAllAsPublic ? '[ENCODED_URL_BASE]' : '[ENCODED_SANDBOX_URL_BASE]'); + text = text.split(bases.publicBaseUrl).join(renderTag(tagLanguage, 'URL_BASE')); + text = text.split(bases.trustedBaseUrl).join(renderTag(tagLanguage, treatAllAsPublic ? 'URL_BASE' : 'TRUSTED_URL_BASE')); + text = text.split(bases.sandboxBaseUrl).join(renderTag(tagLanguage, treatAllAsPublic ? 'URL_BASE' : 'SANDBOX_URL_BASE')); + text = text.split(encodeURIComponent(bases.publicBaseUrl)).join(renderTag(tagLanguage, 'ENCODED_URL_BASE')); + text = text.split(encodeURIComponent(bases.trustedBaseUrl)).join(renderTag(tagLanguage, treatAllAsPublic ? 'ENCODED_URL_BASE' : 'ENCODED_TRUSTED_URL_BASE')); + text = text.split(encodeURIComponent(bases.sandboxBaseUrl)).join(renderTag(tagLanguage, treatAllAsPublic ? 'ENCODED_URL_BASE' : 'ENCODED_SANDBOX_URL_BASE')); return text; }