From e55317ec43c1db7f0ede22245c1655b8dcd00b16 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 5 Aug 2019 13:31:56 +0200 Subject: [PATCH 1/7] Clone existing template BUG fixed --- client/src/templates/CUD.js | 6 ++++-- server/models/templates.js | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/src/templates/CUD.js b/client/src/templates/CUD.js index 39bab165..b253f129 100644 --- a/client/src/templates/CUD.js +++ b/client/src/templates/CUD.js @@ -152,8 +152,10 @@ export default class CUD extends Component { } const typeKey = state.getIn(['type', 'value']); - if (!typeKey) { + if (!typeKey && !state.getIn(['fromExistingEntity', 'value'])) { state.setIn(['type', 'error'], t('typeMustBeSelected')); + }else{ + state.setIn(['type', 'error'], null); } if (!state.getIn(['tag_language', 'value'])) { @@ -168,7 +170,7 @@ export default class CUD extends Component { validateNamespace(t, state); - if (typeKey) { + if (typeKey && !state.getIn(['fromExistingEntity', 'value'])) { this.templateTypes[typeKey].validate(state); } } diff --git a/server/models/templates.js b/server/models/templates.js index 68d34c28..5a278a7d 100644 --- a/server/models/templates.js +++ b/server/models/templates.js @@ -92,12 +92,13 @@ async function create(context, entity) { await shares.rebuildPermissionsTx(tx, { entityTypeId: 'template', entityId: id }); - if (entity.fromExistingEntity) { + //Returns an error + /*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); - } + }*/ return id; }); From b08fd079091ff4a55c9a9ae3b8d92baca42f6f3b Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Aug 2019 09:25:22 +0200 Subject: [PATCH 2/7] convertFileURLs fix --- server/lib/campaign-content.js | 4 ++-- server/models/templates.js | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/server/lib/campaign-content.js b/server/lib/campaign-content.js index 965b6bfb..1f6901d8 100644 --- a/server/lib/campaign-content.js +++ b/server/lib/campaign-content.js @@ -1,6 +1,6 @@ 'use strict'; -function convertFileURLs(sourceCustom, fromEntityType, fromEntityId, toEntityType, toEntityId) { +function convertFileURLs(sourceCustom, fromEntityType, fromEntityId, toEntityType, toEntityId, campaign) { function convertText(text) { if (text) { @@ -22,7 +22,7 @@ function convertFileURLs(sourceCustom, fromEntityType, fromEntityId, toEntityTyp sourceCustom.html = convertText(sourceCustom.html); sourceCustom.text = convertText(sourceCustom.text); - if (sourceCustom.type === 'mosaico' || sourceCustom.type === 'mosaicoWithFsTemplate') { + if ((sourceCustom.type === 'mosaico' || sourceCustom.type === 'mosaicoWithFsTemplate') && campaign){ sourceCustom.data.model = convertText(sourceCustom.data.model); sourceCustom.data.model = convertText(sourceCustom.data.model); sourceCustom.data.metadata = convertText(sourceCustom.data.metadata); diff --git a/server/models/templates.js b/server/models/templates.js index 5a278a7d..0f311f77 100644 --- a/server/models/templates.js +++ b/server/models/templates.js @@ -77,7 +77,7 @@ async function create(context, entity) { if (entity.fromExistingEntity) { const existing = await getByIdTx(tx, context, entity.existingEntity, false); - + entity.type = existing.type; entity.tag_language = existing.tag_language; entity.data = existing.data; @@ -92,13 +92,11 @@ async function create(context, entity) { await shares.rebuildPermissionsTx(tx, { entityTypeId: 'template', entityId: id }); - //Returns an error - /*if (entity.fromExistingEntity) { + if (entity.fromExistingEntity) { await files.copyAllTx(tx, context, 'template', 'file', entity.existingEntity, 'template', 'file', id); - - convertFileURLs(entity, 'template', entity.existingEntity, 'template', id); + convertFileURLs(entity, 'template', entity.existingEntity, 'template', id, false); await tx('templates').update(filterObject(entity, allowedKeys)).where('id', id); - }*/ + } return id; }); From 2929048ebeba303e6c482f3f3c699acaba5c07fc Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Aug 2019 09:26:44 +0200 Subject: [PATCH 3/7] Fix --- server/models/campaigns.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/models/campaigns.js b/server/models/campaigns.js index 2e6aaa8f..a8f6e8f3 100644 --- a/server/models/campaigns.js +++ b/server/models/campaigns.js @@ -529,8 +529,7 @@ 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); + convertFileURLs(data.sourceCustom, copyFilesFrom.entityType, copyFilesFrom.entityId, 'campaign', id, true); await tx('campaigns') .update({ data: JSON.stringify(data) From c1a94046488255d44af8fefdff8975ba1f6a03a8 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Aug 2019 09:37:02 +0200 Subject: [PATCH 4/7] Verp campaign BUG fixed --- server/lib/message-sender.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/lib/message-sender.js b/server/lib/message-sender.js index ec90eefd..43e87ec6 100644 --- a/server/lib/message-sender.js +++ b/server/lib/message-sender.js @@ -347,16 +347,15 @@ class MessageSender { if (campaign) { const campaignAddress = [campaign.cid, list.cid, subscriptionGrouped.cid].join('.'); - if (this.useVerp) { envelope = { - from: campaignAddress + '@' + sendConfiguration.verp_hostname, + from: campaignAddress + '@' + this.sendConfiguration.verp_hostname, to: subscriptionGrouped.email }; } if (this.useVerpSenderHeader) { - sender = campaignAddress + '@' + sendConfiguration.verp_hostname; + sender = campaignAddress + '@' + this.sendConfiguration.verp_hostname; } headers['x-fbl'] = campaignAddress; From ee3fb1bbd19734fa38aefb598a7497a987506029 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 Aug 2019 11:38:07 +0200 Subject: [PATCH 5/7] Campaign tag language bug fixed --- client/src/campaigns/CUD.js | 3 ++- client/src/campaigns/Content.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/campaigns/CUD.js b/client/src/campaigns/CUD.js index c7d014d4..16978459 100644 --- a/client/src/campaigns/CUD.js +++ b/client/src/campaigns/CUD.js @@ -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); } } From 2202f228eba19f31135e82e2cb8cfa6ac9cdc006 Mon Sep 17 00:00:00 2001 From: Tomas Bures Date: Wed, 7 Aug 2019 11:25:47 +0200 Subject: [PATCH 6/7] Merge of PR #654 and some updates to it. --- server/lib/message-sender.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/lib/message-sender.js b/server/lib/message-sender.js index 43e87ec6..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) { @@ -347,15 +349,16 @@ class MessageSender { if (campaign) { const campaignAddress = [campaign.cid, list.cid, subscriptionGrouped.cid].join('.'); + if (this.useVerp) { envelope = { - from: campaignAddress + '@' + this.sendConfiguration.verp_hostname, + from: campaignAddress + '@' + sendConfiguration.verp_hostname, to: subscriptionGrouped.email }; } if (this.useVerpSenderHeader) { - sender = campaignAddress + '@' + this.sendConfiguration.verp_hostname; + sender = campaignAddress + '@' + sendConfiguration.verp_hostname; } headers['x-fbl'] = campaignAddress; @@ -388,7 +391,6 @@ class MessageSender { return; } - const sendConfiguration = this.sendConfiguration; const mailer = await mailers.getOrCreateMailer(sendConfiguration.id); await mailer.throttleWait(); From 30e03adf0cc4d2871027ebf07f00ef5ed31218a9 Mon Sep 17 00:00:00 2001 From: Tomas Bures Date: Wed, 7 Aug 2019 14:29:58 +0200 Subject: [PATCH 7/7] Fix for #619 Merged parts of PR #651 and fixed the rest --- client/src/campaigns/CUD.js | 2 +- client/src/templates/CUD.js | 47 +++++++++++++++++++--------------- server/lib/campaign-content.js | 4 +-- server/models/campaigns.js | 2 +- server/models/templates.js | 28 +++++++++++++++----- 5 files changed, 51 insertions(+), 32 deletions(-) diff --git a/client/src/campaigns/CUD.js b/client/src/campaigns/CUD.js index 16978459..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]}); } diff --git a/client/src/templates/CUD.js b/client/src/templates/CUD.js index b253f129..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,27 +155,28 @@ export default class CUD extends Component { state.setIn(['name', 'error'], t('nameMustNotBeEmpty')); } - const typeKey = state.getIn(['type', 'value']); - if (!typeKey && !state.getIn(['fromExistingEntity', 'value'])) { - state.setIn(['type', 'error'], t('typeMustBeSelected')); - }else{ - state.setIn(['type', 'error'], null); - } - - 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 && !state.getIn(['fromExistingEntity', 'value'])) { - 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/campaign-content.js b/server/lib/campaign-content.js index 1f6901d8..965b6bfb 100644 --- a/server/lib/campaign-content.js +++ b/server/lib/campaign-content.js @@ -1,6 +1,6 @@ 'use strict'; -function convertFileURLs(sourceCustom, fromEntityType, fromEntityId, toEntityType, toEntityId, campaign) { +function convertFileURLs(sourceCustom, fromEntityType, fromEntityId, toEntityType, toEntityId) { function convertText(text) { if (text) { @@ -22,7 +22,7 @@ function convertFileURLs(sourceCustom, fromEntityType, fromEntityId, toEntityTyp sourceCustom.html = convertText(sourceCustom.html); sourceCustom.text = convertText(sourceCustom.text); - if ((sourceCustom.type === 'mosaico' || sourceCustom.type === 'mosaicoWithFsTemplate') && campaign){ + if (sourceCustom.type === 'mosaico' || sourceCustom.type === 'mosaicoWithFsTemplate') { sourceCustom.data.model = convertText(sourceCustom.data.model); sourceCustom.data.model = convertText(sourceCustom.data.model); sourceCustom.data.metadata = convertText(sourceCustom.data.metadata); diff --git a/server/models/campaigns.js b/server/models/campaigns.js index a8f6e8f3..7c8c5bfa 100644 --- a/server/models/campaigns.js +++ b/server/models/campaigns.js @@ -529,7 +529,7 @@ 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, true); + convertFileURLs(data.sourceCustom, copyFilesFrom.entityType, copyFilesFrom.entityId, 'campaign', id); await tx('campaigns') .update({ data: JSON.stringify(data) diff --git a/server/models/templates.js b/server/models/templates.js index 0f311f77..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) { @@ -77,7 +75,7 @@ async function create(context, entity) { if (entity.fromExistingEntity) { const existing = await getByIdTx(tx, context, entity.existingEntity, false); - + entity.type = existing.type; entity.tag_language = existing.tag_language; entity.data = existing.data; @@ -87,15 +85,28 @@ 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 }); if (entity.fromExistingEntity) { await files.copyAllTx(tx, context, 'template', 'file', entity.existingEntity, 'template', 'file', id); - convertFileURLs(entity, 'template', entity.existingEntity, 'template', id, false); - 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; @@ -119,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 }); });