From bc818aaee2285537674e055db63f56ff9c4a6adf Mon Sep 17 00:00:00 2001 From: Tomas Bures Date: Thu, 27 Sep 2018 23:37:50 +0200 Subject: [PATCH] Bugfixes --- client/src/campaigns/Status.js | 29 +++++++++++++++-------------- client/src/campaigns/helpers.js | 3 ++- lib/mailers.js | 2 +- lib/subscription-mail-helpers.js | 4 ++-- lib/tools.js | 2 +- models/campaigns.js | 6 ++++-- models/fields.js | 8 ++++++-- models/forms.js | 2 +- models/shares.js | 2 +- routes/rest/campaigns.js | 2 +- routes/subscription.js | 2 +- 11 files changed, 35 insertions(+), 27 deletions(-) diff --git a/client/src/campaigns/Status.js b/client/src/campaigns/Status.js index 1856be59..fcec13a7 100644 --- a/client/src/campaigns/Status.js +++ b/client/src/campaigns/Status.js @@ -119,19 +119,18 @@ class SendControls extends Component { state.setIn(['date', 'error'], null); state.setIn(['time', 'error'], null); - if (!state.getIn(['sendLater', 'value'])) { - const dateValue = state.getIn(['date', 'value']); + if (state.getIn(['sendLater', 'value'])) { + const dateValue = state.getIn(['date', 'value']).trim(); if (!dateValue) { state.setIn(['date', 'error'], t('Date must not be empty')); - } else if (!moment.utc(dateValue, 'YYYY-MM-DD').isValid()) { + } else if (!moment(dateValue, 'YYYY-MM-DD', true).isValid()) { state.setIn(['date', 'error'], t('Date is invalid')); } - const timeValue = state.getIn(['time', 'value']); - const time = moment.utc(timeValue, 'HH:mm').isValid(); + const timeValue = state.getIn(['time', 'value']).trim(); if (!timeValue) { state.setIn(['time', 'error'], t('Time must not be empty')); - } else if (!time) { + } else if (!moment(timeValue, 'HH:mm', true).isValid()) { state.setIn(['time', 'error'], t('Time is invalid')); } } @@ -144,8 +143,8 @@ class SendControls extends Component { const date = moment(entity.scheduled); this.populateFormValues({ sendLater: true, - date: date.utc().format('YYYY-MM-DD'), - time: date.utc().format('HH:mm') + date: date.format('YYYY-MM-DD'), + time: date.format('HH:mm') }); } else { @@ -176,15 +175,15 @@ class SendControls extends Component { async scheduleAsync() { if (this.isFormWithoutErrors()) { const data = this.getFormValues(); - const date = moment.utc(data.date); - const time = moment.utc(date.time); + const date = moment(data.date, 'YYYY-MM-DD'); + const time = moment(data.time, 'HH:mm'); date.hour(time.hour()); date.minute(time.minute()); date.second(0); date.millisecond(0); - await this.postAndMaskStateError(`rest/campaign-start-at/${this.props.entity.id}/${date.toDate()}`); + await this.postAndMaskStateError(`rest/campaign-start-at/${this.props.entity.id}/${date.valueOf()}`); } else { this.showFormValidation(); @@ -214,7 +213,7 @@ class SendControls extends Component { if (entity.status === CampaignStatus.IDLE || entity.status === CampaignStatus.PAUSED || (entity.status === CampaignStatus.SCHEDULED && entity.scheduled)) { - const subscrInfo = entity.subscriptionsTotal === undefined ? '' : ` (${entity.subscriptionsTotal} ${t('subscribers')})`; + const subscrInfo = entity.subscriptionsTotal === undefined ? '' : ` (${entity.subscriptionsToSend} ${t('subscribers')})`; return (
@@ -223,7 +222,7 @@ class SendControls extends Component {
- + {this.getFormValue('sendLater') &&
@@ -254,13 +253,15 @@ class SendControls extends Component { ); } else if (entity.status === CampaignStatus.FINISHED) { + const subscrInfo = entity.subscriptionsTotal === undefined ? '' : ` (${entity.subscriptionsToSend} ${t('subscribers')})`; + return (
{t('All messages sent! Hit "Continue" if you you want to send this campaign to new subscribers.')} -
diff --git a/client/src/campaigns/helpers.js b/client/src/campaigns/helpers.js index f4fd10de..daf2d642 100644 --- a/client/src/campaigns/helpers.js +++ b/client/src/campaigns/helpers.js @@ -20,7 +20,8 @@ export function getCampaignLabels(t) { [CampaignStatus.FINISHED]: t('Finished'), [CampaignStatus.PAUSED]: t('Paused'), [CampaignStatus.INACTIVE]: t('Inactive'), - [CampaignStatus.ACTIVE]: t('Active') + [CampaignStatus.ACTIVE]: t('Active'), + [CampaignStatus.SENDING]: t('Sending') }; diff --git a/lib/mailers.js b/lib/mailers.js index aa1538f7..dae0466d 100644 --- a/lib/mailers.js +++ b/lib/mailers.js @@ -226,7 +226,7 @@ async function _createTransport(sendConfiguration) { transport.mailer = { throttleWait: bluebird.promisify(throttleWait), - sendTransationalMail: async (mail, template) => await _sendTransactionalMail(transport, mail, template), + sendTransactionalMail: async (mail, template) => await _sendTransactionalMail(transport, mail, template), sendMassMail: async (mail, template) => await _sendMail(transport, mail) }; diff --git a/lib/subscription-mail-helpers.js b/lib/subscription-mail-helpers.js index 45856cb7..9a59e2b6 100644 --- a/lib/subscription-mail-helpers.js +++ b/lib/subscription-mail-helpers.js @@ -1,6 +1,6 @@ 'use strict'; -const log = require('./log'); +const log = require('npmlog'); const fields = require('../models/fields'); const settings = require('../models/settings'); const {getTrustedUrl} = require('./urls'); @@ -128,7 +128,7 @@ async function _sendMail(list, email, template, subject, relativeUrls, subscript type: 'mjml' }; - if (list.default_form !== null) { + if (list.default_form) { const form = await forms.getById(contextHelpers.getAdminContext(), list.default_form); text.template = form['mail_' + template + '_text'] || text.template; diff --git a/lib/tools.js b/lib/tools.js index 087709ed..439fbcb8 100644 --- a/lib/tools.js +++ b/lib/tools.js @@ -40,7 +40,7 @@ async function getTemplate(template) { } if (template.type === 'mjml') { - const compiled = mjml.mjml2html(source); + const compiled = mjml(source); if (compiled.errors.length) { throw new Error(compiled.errors[0].message || compiled.errors[0]); diff --git a/models/campaigns.js b/models/campaigns.js index cbfa3895..dea75a4b 100644 --- a/models/campaigns.js +++ b/models/campaigns.js @@ -198,7 +198,7 @@ async function rawGetByTx(tx, key, id) { .select([ 'campaigns.id', 'campaigns.cid', 'campaigns.name', 'campaigns.description', 'campaigns.namespace', 'campaigns.status', 'campaigns.type', 'campaigns.source', 'campaigns.send_configuration', 'campaigns.from_name_override', 'campaigns.from_email_override', 'campaigns.reply_to_override', 'campaigns.subject_override', - 'campaigns.data', 'campaigns.click_tracking_disabled', 'campaigns.open_tracking_disabled', 'campaigns.unsubscribe_url', + 'campaigns.data', 'campaigns.click_tracking_disabled', 'campaigns.open_tracking_disabled', 'campaigns.unsubscribe_url', 'campaigns.scheduled', knex.raw(`GROUP_CONCAT(CONCAT_WS(\':\', campaign_lists.list, campaign_lists.segment) ORDER BY campaign_lists.id SEPARATOR \';\') as lists`) ]) .first(); @@ -682,6 +682,8 @@ async function _changeStatus(context, campaignId, permittedCurrentStates, newSta throw new interoperableErrors.InvalidStateError(invalidStateMessage); } + console.log(scheduled); + await tx('campaigns').where('id', campaignId).update({ status: newState, scheduled @@ -693,7 +695,7 @@ async function _changeStatus(context, campaignId, permittedCurrentStates, newSta async function start(context, campaignId, startAt) { - await _changeStatus(context, campaignId, [CampaignStatus.IDLE, CampaignStatus.PAUSED, CampaignStatus.FINISHED], CampaignStatus.SCHEDULED, 'Cannot start campaign until it is in IDLE or PAUSED state', startAt); + await _changeStatus(context, campaignId, [CampaignStatus.IDLE, CampaignStatus.SCHEDULED, CampaignStatus.PAUSED, CampaignStatus.FINISHED], CampaignStatus.SCHEDULED, 'Cannot start campaign until it is in IDLE or PAUSED state', startAt); } async function stop(context, campaignId) { diff --git a/models/fields.js b/models/fields.js index fcfa09a9..65c1aaee 100644 --- a/models/fields.js +++ b/models/fields.js @@ -96,6 +96,10 @@ fieldTypes.json = { parsePostValue: (field, value) => value, render: (field, value) => { try { + if (value === null || value.trim() === '') { + return ''; + } + let parsed = JSON.parse(value); if (Array.isArray(parsed)) { parsed = { @@ -224,7 +228,7 @@ fieldTypes['date'] = { getHbsType: field => 'typeDate' + field.settings.dateFormat.charAt(0).toUpperCase() + field.settings.dateFormat.slice(1), forHbs: (field, value) => formatDate(field.settings.dateFormat, value), parsePostValue: (field, value) => parseDate(field.settings.dateFormat, value), - render: (field, value) => formatDate(field.settings.dateFormat, value) + render: (field, value) => value !== null && value.trim() !== '' ? formatDate(field.settings.dateFormat, value) : '' }; fieldTypes['birthday'] = { @@ -239,7 +243,7 @@ fieldTypes['birthday'] = { getHbsType: field => 'typeBirthday' + field.settings.dateFormat.charAt(0).toUpperCase() + field.settings.dateFormat.slice(1), forHbs: (field, value) => formatBirthday(field.settings.dateFormat, value), parsePostValue: (field, value) => parseBirthday(field.settings.dateFormat, value), - render: (field, value) => formatBirthday(field.settings.dateFormat, value) + render: (field, value) => value !== null && value.trim() !== '' ? formatBirthday(field.settings.dateFormat, value) : '' }; const groupedTypes = Object.keys(fieldTypes).filter(key => fieldTypes[key].grouped); diff --git a/models/forms.js b/models/forms.js index b71d81ce..b6720cdd 100644 --- a/models/forms.js +++ b/models/forms.js @@ -217,7 +217,7 @@ function checkForMjmlErrors(form) { let compiled; try { - compiled = mjml.mjml2html(source); + compiled = mjml(source); } catch (err) { return err; } diff --git a/models/shares.js b/models/shares.js index 21f08d78..01b5800f 100644 --- a/models/shares.js +++ b/models/shares.js @@ -6,7 +6,7 @@ const { enforce } = require('../lib/helpers'); const dtHelpers = require('../lib/dt-helpers'); const entitySettings = require('../lib/entity-settings'); const interoperableErrors = require('../shared/interoperable-errors'); -const log = require('../lib/log'); +const log = require('npmlog'); const {getGlobalNamespaceId} = require('../shared/namespaces'); const {getAdminId} = require('../shared/users'); diff --git a/routes/rest/campaigns.js b/routes/rest/campaigns.js index 8935fe18..4a1900aa 100644 --- a/routes/rest/campaigns.js +++ b/routes/rest/campaigns.js @@ -69,7 +69,7 @@ router.postAsync('/campaign-start/:campaignId', passport.loggedIn, passport.csrf }); router.postAsync('/campaign-start-at/:campaignId/:dateTime', passport.loggedIn, passport.csrfProtection, async (req, res) => { - return res.json(await campaigns.start(req.context, req.params.campaignId, new Date(req.params.dateTime))); + return res.json(await campaigns.start(req.context, req.params.campaignId, new Date(Number.parseInt(req.params.dateTime)))); }); diff --git a/routes/subscription.js b/routes/subscription.js index fd39c08d..0f7eabf4 100644 --- a/routes/subscription.js +++ b/routes/subscription.js @@ -505,7 +505,7 @@ router.getAsync('/:lcid/unsubscribe/:ucid', passport.csrfProtection, async (req, const autoUnsubscribe = req.query.auto === 'yes'; if (autoUnsubscribe) { - await handleUnsubscribe(list, req.params.ucid, autoUnsubscribe, req.query.c, req.ip, res, next); + await handleUnsubscribe(list, req.params.ucid, autoUnsubscribe, req.query.c, req.ip, res); } else if (req.query.formTest || list.unsubscription_mode === lists.UnsubscriptionMode.ONE_STEP_WITH_FORM ||