diff --git a/client/src/campaigns/CUD.js b/client/src/campaigns/CUD.js index c7d014d4..945965a9 100644 --- a/client/src/campaigns/CUD.js +++ b/client/src/campaigns/CUD.js @@ -82,7 +82,7 @@ export default class CUD extends Component { ]; this.sourceOptions = []; - for (const key in sourceLabelsOrder) { + for (const key of sourceLabelsOrder) { this.sourceOptions.push({key, label: this.sourceLabels[key]}); } @@ -134,8 +134,9 @@ export default class CUD extends Component { if (key === 'data_sourceCustom_tag_language') { if (newValue) { + const currentType = this.getFormValue('data_sourceCustom_type'); const isEdit = !!this.props.entity; - this.templateTypes[newValue].afterTagLanguageChange(mutStateData, isEdit); + this.templateTypes[currentType].afterTagLanguageChange(mutStateData, isEdit); } } diff --git a/client/src/campaigns/Content.js b/client/src/campaigns/Content.js index 4d218cd8..4880538a 100644 --- a/client/src/campaigns/Content.js +++ b/client/src/campaigns/Content.js @@ -83,8 +83,8 @@ export default class CustomContent extends Component { onTagLanguageChanged(mutStateData, key, oldTagLanguage, tagLanguage) { if (tagLanguage) { - const type = mutStateData.getIn(['data_sourceCustom_tag_language', 'value']); - this.tagLanguages[type].afterTagLanguageChange(mutStateData, true); + const type = mutStateData.getIn(['data_sourceCustom_type', 'value']); + this.templateTypes[type].afterTagLanguageChange(mutStateData, true); } } diff --git a/client/src/templates/CUD.js b/client/src/templates/CUD.js index 39bab165..c89166de 100644 --- a/client/src/templates/CUD.js +++ b/client/src/templates/CUD.js @@ -98,9 +98,13 @@ export default class CUD extends Component { } submitFormValuesMutator(data) { - this.templateTypes[data.type].beforeSave(data); + if (data.fromExistingEntity) { + return filterData(data, ['name', 'description', 'namespace', 'fromExistingEntity', 'existingEntity']); - return filterData(data, ['name', 'description', 'type', 'tag_language', 'data', 'html', 'text', 'namespace', 'fromExistingEntity', 'existingEntity']); + } else { + this.templateTypes[data.type].beforeSave(data); + return filterData(data, ['name', 'description', 'type', 'tag_language', 'data', 'html', 'text', 'namespace', 'fromExistingEntity']); + } } async getPreSubmitFormValuesUpdater() { @@ -151,25 +155,28 @@ export default class CUD extends Component { state.setIn(['name', 'error'], t('nameMustNotBeEmpty')); } - const typeKey = state.getIn(['type', 'value']); - if (!typeKey) { - state.setIn(['type', 'error'], t('typeMustBeSelected')); - } - - if (!state.getIn(['tag_language', 'value'])) { - state.setIn(['tag_language', 'error'], t('Tag language must be selected')); - } - - if (state.getIn(['fromExistingEntity', 'value']) && !state.getIn(['existingEntity', 'value'])) { - state.setIn(['existingEntity', 'error'], t('sourceTemplateMustNotBeEmpty')); - } else { - state.setIn(['existingEntity', 'error'], null); - } - validateNamespace(t, state); - if (typeKey) { - this.templateTypes[typeKey].validate(state); + const fromExistingEntity = state.getIn(['fromExistingEntity', 'value']); + + if (fromExistingEntity) { + if (!state.getIn(['existingEntity', 'value'])) { + state.setIn(['existingEntity', 'error'], t('sourceTemplateMustNotBeEmpty')); + } + + } else { + const typeKey = state.getIn(['type', 'value']); + if (!typeKey) { + state.setIn(['type', 'error'], t('typeMustBeSelected')); + } + + if (!state.getIn(['tag_language', 'value'])) { + state.setIn(['tag_language', 'error'], t('Tag language must be selected')); + } + + if (typeKey) { + this.templateTypes[typeKey].validate(state); + } } } diff --git a/server/lib/message-sender.js b/server/lib/message-sender.js index ec90eefd..7b0360ef 100644 --- a/server/lib/message-sender.js +++ b/server/lib/message-sender.js @@ -293,6 +293,8 @@ class MessageSender { let subscriptionGrouped, list; // May be undefined const campaign = this.campaign; // May be undefined + const sendConfiguration = this.sendConfiguration; + let mergeTags = subData.mergeTags; if (subData.listId) { @@ -389,7 +391,6 @@ class MessageSender { return; } - const sendConfiguration = this.sendConfiguration; const mailer = await mailers.getOrCreateMailer(sendConfiguration.id); await mailer.throttleWait(); diff --git a/server/models/campaigns.js b/server/models/campaigns.js index 2e6aaa8f..7c8c5bfa 100644 --- a/server/models/campaigns.js +++ b/server/models/campaigns.js @@ -529,7 +529,6 @@ async function _createTx(tx, context, entity, content) { if (copyFilesFrom) { await files.copyAllTx(tx, context, copyFilesFrom.entityType, 'file', copyFilesFrom.entityId, 'campaign', 'file', id); - convertFileURLs(data.sourceCustom, copyFilesFrom.entityType, copyFilesFrom.entityId, 'campaign', id); await tx('campaigns') .update({ diff --git a/server/models/templates.js b/server/models/templates.js index 68d34c28..209e1635 100644 --- a/server/models/templates.js +++ b/server/models/templates.js @@ -67,8 +67,6 @@ async function _validateAndPreprocess(tx, entity) { enforce(allTagLanguages.includes(entity.tag_language), `Invalid tag language '${entity.tag_language}'`); // We don't check contents of the "data" because it is processed solely on the client. The client generates the HTML code we use when sending out campaigns. - - entity.data = JSON.stringify(entity.data); } async function create(context, entity) { @@ -87,7 +85,13 @@ async function create(context, entity) { await _validateAndPreprocess(tx, entity); - const ids = await tx('templates').insert(filterObject(entity, allowedKeys)); + const filteredEntityWithUnstringifiedData = filterObject(entity, allowedKeys); + const filteredEntity = { + ...filteredEntityWithUnstringifiedData, + data: JSON.stringify(filteredEntityWithUnstringifiedData.data) + }; + + const ids = await tx('templates').insert(filteredEntity); const id = ids[0]; await shares.rebuildPermissionsTx(tx, { entityTypeId: 'template', entityId: id }); @@ -95,8 +99,14 @@ async function create(context, entity) { if (entity.fromExistingEntity) { await files.copyAllTx(tx, context, 'template', 'file', entity.existingEntity, 'template', 'file', id); - convertFileURLs(entity, 'template', entity.existingEntity, 'template', id); - await tx('templates').update(filterObject(entity, allowedKeys)).where('id', id); + convertFileURLs(filteredEntityWithUnstringifiedData, 'template', entity.existingEntity, 'template', id); + + const filteredEntity = { + ...filteredEntityWithUnstringifiedData, + data: JSON.stringify(filteredEntityWithUnstringifiedData.data) + }; + + await tx('templates').update(filteredEntity).where('id', id); } return id; @@ -120,10 +130,13 @@ async function updateWithConsistencyCheck(context, entity) { } await _validateAndPreprocess(tx, entity); + entity.data = JSON.stringify(entity.data); await namespaceHelpers.validateMove(context, entity, existing, 'template', 'createTemplate', 'delete'); - await tx('templates').where('id', entity.id).update(filterObject(entity, allowedKeys)); + const filteredEntity = filterObject(entity, allowedKeys); + + await tx('templates').where('id', entity.id).update(filteredEntity); await shares.rebuildPermissionsTx(tx, { entityTypeId: 'template', entityId: entity.id }); });