- "Channels" feature
- Shoutout config param rendered on the homepage
- "Clone" feature for campaigns
This commit is contained in:
Tomas Bures 2020-07-17 14:53:48 +02:00
parent 00432e6cfe
commit d170548cfa
25 changed files with 1009 additions and 525 deletions

View file

@ -16,8 +16,8 @@ const dependencyHelpers = require('../lib/dependency-helpers');
const {EntityActivityType, CampaignActivityType} = require('../../shared/activity-log');
const activityLog = require('../lib/activity-log');
const allowedKeys = ['name', 'description', 'namespace', 'cpg_name', 'cpg_description',
'send_configuration', 'from_name_override', 'from_email_override', 'reply_to_override', 'subject', 'data', 'click_tracking_disabled', 'open_tracking_disabled', 'unsubscribe_url', 'source'];
const allowedKeys = new Set(['name', 'description', 'namespace', 'cpg_name', 'cpg_description',
'send_configuration', 'from_name_override', 'from_email_override', 'reply_to_override', 'subject', 'data', 'click_tracking_disabled', 'open_tracking_disabled', 'unsubscribe_url', 'source']);
function hash(entity) {
@ -43,12 +43,27 @@ async function listDTAjax(context, params) {
);
}
async function _getByTx(tx, key, id, withPermissions = true) {
async function listWithCreateCampaignPermissionDTAjax(context, params) {
return await dtHelpers.ajaxListWithPermissions(
context,
[{ entityTypeId: 'channel', requiredOperations: ['createCampaign'] }],
params,
builder => {
builder = builder.from('channels')
.innerJoin('namespaces', 'namespaces.id', 'channels.namespace');
return builder;
},
['channels.id', 'channels.name', 'channels.cid', 'channels.description', 'namespaces.name']
);
}
async function _getByTx(tx, context, key, id, withPermissions = true) {
const entity = await tx('channels').where('channels.' + key, id)
.leftJoin('channel_lists', 'channels.id', 'channel_lists.channel')
.groupBy('channels.id')
.select([
'channels.id', 'channels.name', 'channels.cid', 'channels.description', 'channels.namespace', 'channels.source',
'channels.id', 'channels.name', 'channels.cid', 'channels.description', 'channels.namespace', 'channels.cpg_name', 'channels.cpg_description', 'channels.source',
'channels.send_configuration', 'channels.from_name_override', 'channels.from_email_override', 'channels.reply_to_override', 'channels.subject',
'channels.data', 'channels.click_tracking_disabled', 'channels.open_tracking_disabled', 'channels.unsubscribe_url',
knex.raw(`GROUP_CONCAT(CONCAT_WS(\':\', channel_lists.list, channel_lists.segment) ORDER BY channel_lists.id SEPARATOR \';\') as lists`)
@ -82,7 +97,7 @@ async function _getByTx(tx, key, id, withPermissions = true) {
async function getByIdTx(tx, context, id, withPermissions = true) {
await shares.enforceEntityPermissionTx(tx, context, 'channel', id, 'view');
return await _getByTx(tx, 'id', id, withPermissions);
return await _getByTx(tx, context, 'id', id, withPermissions);
}
async function getById(context, id, withPermissions = true) {
@ -97,12 +112,13 @@ async function _validateAndPreprocess(tx, context, entity, isCreate) {
if (entity.source !== null) {
enforce(Number.isInteger(entity.source));
if (entity.source === CampaignSource.CUSTOM_FROM_TEMPLATE) {
if (entity.source === CampaignSource.TEMPLATE || entity.source === CampaignSource.CUSTOM_FROM_TEMPLATE) {
await shares.enforceEntityPermissionTx(tx, context, 'template', entity.data.sourceTemplate, 'view');
} else if (entity.source === CampaignSource.CUSTOM_FROM_CAMPAIGN) {
await shares.enforceEntityPermissionTx(tx, context, 'campaign', entity.data.sourceCampaign, 'view');
} else if (entity.source === CampaignSource.CUSTOM) {
enforce(allTagLanguages.includes(entity.data.sourceCustom.tag_language), `Invalid tag language '${entity.data.sourceCustom.tag_language}'`);
} else if (entity.source === CampaignSource.URL) {
} else {
enforce(false, 'Unknown channel source');
}
@ -156,7 +172,7 @@ async function updateWithConsistencyCheck(context, entity) {
await knex.transaction(async tx => {
await shares.enforceEntityPermissionTx(tx, context, 'channel', entity.id, 'edit');
const existing = await _getByTx(tx, 'id', entity.id, false);
const existing = await _getByTx(tx, context, 'id', entity.id, false);
const existingHash = hash(existing);
if (existingHash !== entity.originalHash) {
@ -166,7 +182,7 @@ async function updateWithConsistencyCheck(context, entity) {
await _validateAndPreprocess(tx, context, entity, false);
let filteredEntity = filterObject(entity, allowedKeys);
await namespaceHelpers.validateMove(context, entity, existing, 'channel', 'createCampaign', 'delete');
await namespaceHelpers.validateMoveTx(tx, context, entity, existing, 'channel', 'createCampaign', 'delete');
await tx('channel_lists').where('channel', entity.id).del();
await tx('channel_lists').insert(entity.lists.map(x => ({channel: entity.id, ...x})));
@ -197,8 +213,8 @@ async function remove(context, id) {
module.exports.hash = hash;
module.exports.listDTAjax = listDTAjax;
module.exports.listWithCreateCampaignPermissionDTAjax = listWithCreateCampaignPermissionDTAjax;
module.exports.getByIdTx = getByIdTx;
module.exports.getById = getById;
module.exports.create = create;