Campaign status show send settings Bug
This commit is contained in:
parent
4b1b1a380d
commit
1a61067ff9
9 changed files with 119 additions and 26 deletions
|
@ -12,7 +12,8 @@ import {
|
||||||
requiresAuthenticatedUser,
|
requiresAuthenticatedUser,
|
||||||
Title,
|
Title,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
withPageHelpers
|
withPageHelpers,
|
||||||
|
getNamespaceChooser
|
||||||
} from '../lib/page';
|
} from '../lib/page';
|
||||||
import {
|
import {
|
||||||
withAsyncErrorHandler,
|
withAsyncErrorHandler,
|
||||||
|
@ -75,8 +76,12 @@ export default class List extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
const t = this.props.t;
|
const t = this.props.t;
|
||||||
|
var pathname = window.location.href;
|
||||||
|
var url = new URL(pathname);
|
||||||
|
var namespace = url.searchParams.get("namespace");
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ data: 1, title: t('name') },
|
{ data: 1, title: t('name') },
|
||||||
{ data: 2, title: t('id'), render: data => <code>{data}</code> },
|
{ data: 2, title: t('id'), render: data => <code>{data}</code> },
|
||||||
|
@ -108,6 +113,7 @@ export default class List extends Component {
|
||||||
const status = data[5];
|
const status = data[5];
|
||||||
const campaignSource = data[7];
|
const campaignSource = data[7];
|
||||||
|
|
||||||
|
|
||||||
if (perms.includes('viewStats')) {
|
if (perms.includes('viewStats')) {
|
||||||
actions.push({
|
actions.push({
|
||||||
label: <Icon icon="envelope" title={t('status')}/>,
|
label: <Icon icon="envelope" title={t('status')}/>,
|
||||||
|
@ -172,6 +178,7 @@ export default class List extends Component {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{tableRestActionDialogRender(this)}
|
{tableRestActionDialogRender(this)}
|
||||||
|
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
{this.state.createPermitted &&
|
{this.state.createPermitted &&
|
||||||
<ButtonDropdown buttonClassName="btn-primary" menuClassName="dropdown-menu-right" label={t('createCampaign')}>
|
<ButtonDropdown buttonClassName="btn-primary" menuClassName="dropdown-menu-right" label={t('createCampaign')}>
|
||||||
|
@ -182,10 +189,19 @@ export default class List extends Component {
|
||||||
}
|
}
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
||||||
<Title>{t('campaigns')}</Title>
|
<Toolbar>
|
||||||
|
{getNamespaceChooser(t)}
|
||||||
|
</Toolbar>
|
||||||
|
|
||||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/campaigns-table" columns={columns} />
|
<Title>{t('campaigns')}</Title>
|
||||||
|
{!namespace &&
|
||||||
|
<Table ref={node => this.table = node} withHeader dataUrl="rest/campaigns-table" columns={columns} />
|
||||||
|
}
|
||||||
|
{!!namespace &&
|
||||||
|
<Table ref={node => this.table = node} withHeader dataUrl={`rest/campaigns-namespace/${namespace}`} columns={columns} />
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -443,11 +443,17 @@ export default class Status extends Component {
|
||||||
let sendSettings;
|
let sendSettings;
|
||||||
if (this.state.sendConfiguration) {
|
if (this.state.sendConfiguration) {
|
||||||
sendSettings = [];
|
sendSettings = [];
|
||||||
|
|
||||||
const addOverridable = (id, label) => {
|
const addOverridable = (id, label) => {
|
||||||
sendSettings.push(<AlignedRow key={id} label={label}>{entity[id + '_override'] === null ? this.state.sendConfiguration[id] : entity[id + '_override']}</AlignedRow>);
|
if(this.state.sendConfiguration[id + '_overridable'] == 1){
|
||||||
|
sendSettings.push(<AlignedRow key={id} label={label}>{entity[id + '_override']}</AlignedRow>);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
sendSettings.push(<AlignedRow key={id} label={label}>{this.state.sendConfiguration[id]}</AlignedRow>);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
addOverridable('from_name', t('fromName'));
|
addOverridable('from_name', t('fromName'));
|
||||||
addOverridable('from_email', t('fromEmailAddress'));
|
addOverridable('from_email', t('fromEmailAddress'));
|
||||||
addOverridable('reply_to', t('replytoEmailAddress'));
|
addOverridable('reply_to', t('replytoEmailAddress'));
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
Button,
|
Button,
|
||||||
DismissibleAlert,
|
DismissibleAlert,
|
||||||
DropdownActionLink,
|
DropdownActionLink,
|
||||||
|
ButtonDropdown,
|
||||||
Icon
|
Icon
|
||||||
} from "./bootstrap-components";
|
} from "./bootstrap-components";
|
||||||
import mailtrainConfig
|
import mailtrainConfig
|
||||||
|
@ -696,4 +697,22 @@ export function getLanguageChooser(t) {
|
||||||
);
|
);
|
||||||
|
|
||||||
return languageChooser;
|
return languageChooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNamespaceChooser(t) {
|
||||||
|
|
||||||
|
const namespaceOptions = [];
|
||||||
|
namespaceOptions.push(
|
||||||
|
<DropdownLink to={`/campaigns`}>{t('All')}</DropdownLink>,
|
||||||
|
<DropdownLink to={`/campaigns?namespace=1`}>{t('Root')}</DropdownLink>
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
const namespaceChooser = (
|
||||||
|
<ButtonDropdown buttonClassName="btn-primary" menuClassName="dropdown-menu-right" label={t('namespaceFilter')}>
|
||||||
|
{namespaceOptions}
|
||||||
|
</ButtonDropdown>
|
||||||
|
);
|
||||||
|
|
||||||
|
return namespaceChooser;
|
||||||
}
|
}
|
|
@ -198,6 +198,7 @@
|
||||||
"triggers": "Triggers",
|
"triggers": "Triggers",
|
||||||
"share": "Share",
|
"share": "Share",
|
||||||
"createCampaign": "Create Campaign",
|
"createCampaign": "Create Campaign",
|
||||||
|
"namespaceFilter": "Namespace filtering",
|
||||||
"regular": "Regular",
|
"regular": "Regular",
|
||||||
"rss": "RSS",
|
"rss": "RSS",
|
||||||
"triggered": "Triggered",
|
"triggered": "Triggered",
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
{
|
{
|
||||||
"welcomeToMailtrain": "Bienvenido a Mailtrain...",
|
"welcomeToMailtrain": "Bienvenido a Mailtrain...",
|
||||||
"personalAccessToken": "Personal access token",
|
"personalAccessToken": "Token de acceso personal",
|
||||||
"accessTokenNotYetGenerated": "Access token not yet generated",
|
"accessTokenNotYetGenerated": "El token de acceso aun no se ha generado",
|
||||||
"api": "API",
|
"api": "API",
|
||||||
"resetAccessToken": "Reset Access Token",
|
"resetAccessToken": "Reiniciar token de acceso",
|
||||||
"generateAccessToken": "Generate Access Token",
|
"generateAccessToken": "Generar token de acceso",
|
||||||
"notesAboutTheApi": "Notes about the API",
|
"notesAboutTheApi": "Notas sobre la API",
|
||||||
"addSubscription": "Add subscription",
|
"addSubscription": "Añadir suscripcion",
|
||||||
"thisApiCallEitherInsertsANewSubscription": "This API call either inserts a new subscription or updates existing. Fields not included are left as is, so if you update only LAST_NAME value, then FIRST_NAME is kept untouched for an existing subscription.",
|
"thisApiCallEitherInsertsANewSubscription": "Esta llamada a la API inserta una nueva suscripción o actualiza las existentes. Los campos no incluidos se dejan como están, por lo que si actualiza solo el valor de LAST_NAME, FIRST_NAME se mantiene intacto para una suscripción existente.",
|
||||||
"arguments": "arguments",
|
"arguments": "argumentos",
|
||||||
"yourPersonalAccessToken": "your personal access token",
|
"yourPersonalAccessToken": "tu token de acceso personal",
|
||||||
"subscribersEmailAddress": "subscriber's email address",
|
"subscribersEmailAddress": "email del suscriptor",
|
||||||
"required": "required",
|
"required": "requerido",
|
||||||
"subscribersFirstName": "subscriber's first name",
|
"subscribersFirstName": "nombre del suscriptor",
|
||||||
"subscribersLastName": "subscriber's last name",
|
"subscribersLastName": "apellidos del suscriptor",
|
||||||
"subscribersTimezoneEgEuropeTallinnPstOr": "subscriber's timezone (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). If not set defaults to \"UTC\"",
|
"subscribersTimezoneEgEuropeTallinnPstOr": "zona horaria del suscriptor (eg. \"Europe/Tallinn\", \"PST\" or \"UTC\"). Si no, asigna por defecto a \"UTC\"",
|
||||||
"customFieldValueUseYesnoForOptionGroup": "custom field value. Use yes/no for option group values (checkboxes, radios, drop downs)",
|
"customFieldValueUseYesnoForOptionGroup": "valor de campo personalizado. Usa si/no para opciones grupales (checkboxes, radios, drop downs)",
|
||||||
"additionalPostArguments": "Additional POST arguments",
|
"additionalPostArguments": "argumentos POST adicionales",
|
||||||
"setToYesIfYouWantToMakeSureTheEmailIs": "set to \"yes\" if you want to make sure the email is marked as subscribed even if it was previously marked as unsubscribed. If the email was already unsubscribed/blocked then subscription status is not changed",
|
"setToYesIfYouWantToMakeSureTheEmailIs": "set to \"yes\" if you want to make sure the email is marked as subscribed even if it was previously marked as unsubscribed. If the email was already unsubscribed/blocked then subscription status is not changed",
|
||||||
"setToYesIfYouWantToSendConfirmationEmail": "set to \"yes\" if you want to send confirmation email to the subscriber before actually marking as subscribed",
|
"setToYesIfYouWantToSendConfirmationEmail": "set to \"yes\" if you want to send confirmation email to the subscriber before actually marking as subscribed",
|
||||||
"example": "Example",
|
"example": "Ejemplo",
|
||||||
"removeSubscription": "Remove subscription",
|
"removeSubscription": "Eliminar suscripción",
|
||||||
"thisApiCallMarksASubscriptionAs": "This API call marks a subscription as unsubscribed",
|
"thisApiCallMarksASubscriptionAs": "This API call marks a subscription as unsubscribed",
|
||||||
"deleteSubscription": "Delete subscription",
|
"deleteSubscription": "Delete subscription",
|
||||||
"thisApiCallDeletesASubscription": "This API call deletes a subscription",
|
"thisApiCallDeletesASubscription": "This API call deletes a subscription",
|
||||||
|
@ -198,6 +198,7 @@
|
||||||
"triggers": "Triggers",
|
"triggers": "Triggers",
|
||||||
"share": "Share",
|
"share": "Share",
|
||||||
"createCampaign": "Create Campaign",
|
"createCampaign": "Create Campaign",
|
||||||
|
"namespaceFilter": "Namespace filtering",
|
||||||
"regular": "Regular",
|
"regular": "Regular",
|
||||||
"rss": "RSS",
|
"rss": "RSS",
|
||||||
"triggered": "Triggered",
|
"triggered": "Triggered",
|
||||||
|
|
|
@ -76,6 +76,19 @@ async function listDTAjax(context, params) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function listByNamespaceDTAjax(context, namespaceId, params) {
|
||||||
|
return await dtHelpers.ajaxListWithPermissions(
|
||||||
|
context,
|
||||||
|
[{ entityTypeId: 'campaign', requiredOperations: ['view'] }],
|
||||||
|
params,
|
||||||
|
builder => builder.from('campaigns')
|
||||||
|
.innerJoin('namespaces', 'namespaces.id', 'campaigns.namespace')
|
||||||
|
.where('namespaces.id', namespaceId)
|
||||||
|
.whereNull('campaigns.parent'),
|
||||||
|
['campaigns.id', 'campaigns.name', 'campaigns.cid', 'campaigns.description', 'campaigns.type', 'campaigns.status', 'campaigns.scheduled', 'campaigns.source', 'campaigns.created', 'namespaces.name']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function listChildrenDTAjax(context, campaignId, params) {
|
async function listChildrenDTAjax(context, campaignId, params) {
|
||||||
return await dtHelpers.ajaxListWithPermissions(
|
return await dtHelpers.ajaxListWithPermissions(
|
||||||
context,
|
context,
|
||||||
|
@ -730,9 +743,9 @@ async function changeStatusByCampaignCidAndSubscriptionIdTx(tx, context, campaig
|
||||||
])
|
])
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (!message) {
|
//if (!message) {
|
||||||
throw new Error('Invalid campaign.')
|
throw new Error('Invalid campaign.')
|
||||||
}
|
//}
|
||||||
|
|
||||||
await _changeStatusByMessageTx(tx, context, message, subscriptionStatus);
|
await _changeStatusByMessageTx(tx, context, message, subscriptionStatus);
|
||||||
}
|
}
|
||||||
|
@ -934,6 +947,7 @@ module.exports.Content = Content;
|
||||||
module.exports.hash = hash;
|
module.exports.hash = hash;
|
||||||
|
|
||||||
module.exports.listDTAjax = listDTAjax;
|
module.exports.listDTAjax = listDTAjax;
|
||||||
|
module.exports.listByNamespaceDTAjax = listByNamespaceDTAjax;
|
||||||
module.exports.listChildrenDTAjax = listChildrenDTAjax;
|
module.exports.listChildrenDTAjax = listChildrenDTAjax;
|
||||||
module.exports.listWithContentDTAjax = listWithContentDTAjax;
|
module.exports.listWithContentDTAjax = listWithContentDTAjax;
|
||||||
module.exports.listOthersWhoseListsAreIncludedDTAjax = listOthersWhoseListsAreIncludedDTAjax;
|
module.exports.listOthersWhoseListsAreIncludedDTAjax = listOthersWhoseListsAreIncludedDTAjax;
|
||||||
|
|
|
@ -53,6 +53,33 @@ async function listDTAjax(context, params) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function listByNamespaceDTAjax(context, params) {
|
||||||
|
const campaignEntityType = entitySettings.getEntityType('campaign');
|
||||||
|
|
||||||
|
return await dtHelpers.ajaxListWithPermissions(
|
||||||
|
context,
|
||||||
|
[{ entityTypeId: 'list', requiredOperations: ['view'] }],
|
||||||
|
params,
|
||||||
|
builder => builder
|
||||||
|
.from('lists')
|
||||||
|
.innerJoin('namespaces', 'namespaces.id', 'lists.namespace'),
|
||||||
|
['lists.id', 'lists.name', 'lists.cid', 'lists.subscribers', 'lists.description', 'namespaces.name',
|
||||||
|
{
|
||||||
|
name: 'triggerCount',
|
||||||
|
query: builder =>
|
||||||
|
builder.from('campaigns')
|
||||||
|
.innerJoin('campaign_lists', 'campaigns.id', 'campaign_lists.campaign')
|
||||||
|
.innerJoin('triggers', 'campaigns.id', 'triggers.campaign')
|
||||||
|
.innerJoin(campaignEntityType.permissionsTable, 'campaigns.id', `${campaignEntityType.permissionsTable}.entity`)
|
||||||
|
.whereRaw('campaign_lists.list = lists.id')
|
||||||
|
.where(`${campaignEntityType.permissionsTable}.operation`, 'viewTriggers')
|
||||||
|
.count()
|
||||||
|
.as('triggerCount')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function listWithSegmentByCampaignDTAjax(context, campaignId, params) {
|
async function listWithSegmentByCampaignDTAjax(context, campaignId, params) {
|
||||||
return await dtHelpers.ajaxListWithPermissions(
|
return await dtHelpers.ajaxListWithPermissions(
|
||||||
context,
|
context,
|
||||||
|
@ -260,6 +287,7 @@ async function remove(context, id) {
|
||||||
module.exports.UnsubscriptionMode = UnsubscriptionMode;
|
module.exports.UnsubscriptionMode = UnsubscriptionMode;
|
||||||
module.exports.hash = hash;
|
module.exports.hash = hash;
|
||||||
module.exports.listDTAjax = listDTAjax;
|
module.exports.listDTAjax = listDTAjax;
|
||||||
|
module.exports.listByNamespaceDTAjax = listByNamespaceDTAjax;
|
||||||
module.exports.listWithSegmentByCampaignDTAjax = listWithSegmentByCampaignDTAjax;
|
module.exports.listWithSegmentByCampaignDTAjax = listWithSegmentByCampaignDTAjax;
|
||||||
module.exports.getByIdTx = getByIdTx;
|
module.exports.getByIdTx = getByIdTx;
|
||||||
module.exports.getById = getById;
|
module.exports.getById = getById;
|
||||||
|
|
|
@ -19,6 +19,10 @@ router.postAsync('/campaigns-others-by-list-table/:campaignId/:listIds', passpor
|
||||||
return res.json(await campaigns.listOthersWhoseListsAreIncludedDTAjax(req.context, castToInteger(req.params.campaignId), req.params.listIds.split(';').map(x => castToInteger(x)), req.body));
|
return res.json(await campaigns.listOthersWhoseListsAreIncludedDTAjax(req.context, castToInteger(req.params.campaignId), req.params.listIds.split(';').map(x => castToInteger(x)), req.body));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.postAsync('/campaigns-namespace/:namespaceId', passport.loggedIn, async (req, res) => {
|
||||||
|
return res.json(await campaigns.listByNamespaceDTAjax(req.context, castToInteger(req.params.namespaceId), req.body));
|
||||||
|
});
|
||||||
|
|
||||||
router.postAsync('/campaigns-children/:campaignId', passport.loggedIn, async (req, res) => {
|
router.postAsync('/campaigns-children/:campaignId', passport.loggedIn, async (req, res) => {
|
||||||
return res.json(await campaigns.listChildrenDTAjax(req.context, castToInteger(req.params.campaignId), req.body));
|
return res.json(await campaigns.listChildrenDTAjax(req.context, castToInteger(req.params.campaignId), req.body));
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,10 @@ router.postAsync('/lists-table', passport.loggedIn, async (req, res) => {
|
||||||
return res.json(await lists.listDTAjax(req.context, req.body));
|
return res.json(await lists.listDTAjax(req.context, req.body));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.postAsync('/users-table-byNamespace/:namespaceId', passport.loggedIn, async (req, res) => {
|
||||||
|
return res.json(await lists.listDTAjax(req.context, 1));
|
||||||
|
});
|
||||||
|
|
||||||
router.postAsync('/lists-with-segment-by-campaign-table/:campaignId', passport.loggedIn, async (req, res) => {
|
router.postAsync('/lists-with-segment-by-campaign-table/:campaignId', passport.loggedIn, async (req, res) => {
|
||||||
return res.json(await lists.listWithSegmentByCampaignDTAjax(req.context, castToInteger(req.params.campaignId), req.body));
|
return res.json(await lists.listWithSegmentByCampaignDTAjax(req.context, castToInteger(req.params.campaignId), req.body));
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue