@@ -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 ||