Bugfixes
This commit is contained in:
parent
1448d9e914
commit
bc818aaee2
11 changed files with 35 additions and 27 deletions
|
@ -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 (
|
||||
<div>
|
||||
|
@ -223,7 +222,7 @@ class SendControls extends Component {
|
|||
</AlignedRow>
|
||||
|
||||
<Form stateOwner={this}>
|
||||
<CheckBox id="sendLater" label={t('Send later')} text={t('Schedule deliver at particular date/time')}/>
|
||||
<CheckBox id="sendLater" label={t('Send later')} text={t('Schedule delivery at a particular date/time')}/>
|
||||
{this.getFormValue('sendLater') &&
|
||||
<div>
|
||||
<DatePicker id="date" label={t('Date')} />
|
||||
|
@ -254,13 +253,15 @@ class SendControls extends Component {
|
|||
);
|
||||
|
||||
} else if (entity.status === CampaignStatus.FINISHED) {
|
||||
const subscrInfo = entity.subscriptionsTotal === undefined ? '' : ` (${entity.subscriptionsToSend} ${t('subscribers')})`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AlignedRow label={t('Send status')}>
|
||||
{t('All messages sent! Hit "Continue" if you you want to send this campaign to new subscribers.')}
|
||||
</AlignedRow>
|
||||
<ButtonRow>
|
||||
<Button className="btn-primary" icon="play" label={t('Continue')} onClickAsync={::this.startAsync}/>
|
||||
<Button className="btn-primary" icon="play" label={t('Continue') + subscrInfo} onClickAsync={::this.startAsync}/>
|
||||
<Button className="btn-primary" icon="refresh" label={t('Reset')} onClickAsync={::this.resetAsync}/>
|
||||
</ButtonRow>
|
||||
</div>
|
||||
|
|
|
@ -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')
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -217,7 +217,7 @@ function checkForMjmlErrors(form) {
|
|||
let compiled;
|
||||
|
||||
try {
|
||||
compiled = mjml.mjml2html(source);
|
||||
compiled = mjml(source);
|
||||
} catch (err) {
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -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))));
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -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 ||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue