Merge branch 'pull/564' into development
This commit is contained in:
commit
dcb7168322
24 changed files with 1216 additions and 52 deletions
26
client/package-lock.json
generated
26
client/package-lock.json
generated
|
@ -4470,7 +4470,8 @@
|
|||
},
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -4488,11 +4489,13 @@
|
|||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -4505,15 +4508,18 @@
|
|||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -4616,7 +4622,8 @@
|
|||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -4626,6 +4633,7 @@
|
|||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -4638,6 +4646,7 @@
|
|||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -4743,7 +4752,8 @@
|
|||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -4858,6 +4868,7 @@
|
|||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -4875,6 +4886,7 @@
|
|||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
|
|
@ -229,6 +229,7 @@ export default class CUD extends Component {
|
|||
[lstPrefix + 'list']: null,
|
||||
[lstPrefix + 'segment']: null,
|
||||
[lstPrefix + 'useSegmentation']: false,
|
||||
[lstPrefix + 'work_list_current_namespace']: false,
|
||||
lists: [lstUid],
|
||||
|
||||
send_configuration: null,
|
||||
|
@ -236,6 +237,8 @@ export default class CUD extends Component {
|
|||
|
||||
click_tracking_disabled: false,
|
||||
open_tracking_disabled: false,
|
||||
work_send_config_current_namespace: false,
|
||||
work_template_current_namespace: false,
|
||||
|
||||
unsubscribe_url: '',
|
||||
|
||||
|
@ -521,12 +524,18 @@ export default class CUD extends Component {
|
|||
const lstsEditEntries = [];
|
||||
const lsts = this.getFormValue('lists') || [];
|
||||
let lstOrderIdx = 0;
|
||||
|
||||
const currentNamespace = this.getFormValue('namespace');
|
||||
const useNamespaceSendConfig = this.getFormValue('work_send_config_current_namespace');
|
||||
const useNamespaceTemplate = this.getFormValue('work_template_current_namespace');
|
||||
|
||||
for (const lstUid of lsts) {
|
||||
const prefix = 'lists_' + lstUid + '_';
|
||||
const lstOrderIdxClosure = lstOrderIdx;
|
||||
|
||||
const selectedList = this.getFormValue(prefix + 'list');
|
||||
|
||||
const useNamespaceLists = this.getFormValue(prefix + 'work_list_current_namespace');
|
||||
|
||||
lstsEditEntries.push(
|
||||
<div key={lstUid} className={campaignsStyles.entry + ' ' + campaignsStyles.entryWithButtons}>
|
||||
<div className={campaignsStyles.entryButtons}>
|
||||
|
@ -562,8 +571,13 @@ export default class CUD extends Component {
|
|||
}
|
||||
</div>
|
||||
<div className={campaignsStyles.entryContent}>
|
||||
<TableSelect id={prefix + 'list'} label={t('list')} withHeader dropdown dataUrl='rest/lists-table' columns={listsColumns} selectionLabelIndex={1} />
|
||||
|
||||
<CheckBox id={prefix + "work_list_current_namespace"} label={t('namespaceFiltering')} text={t('workWithCampaignNamespace')}/>
|
||||
{useNamespaceLists &&
|
||||
<TableSelect id={prefix + 'list'} label={t('list')} withHeader dropdown dataUrl={`rest/users-table-byNamespace/${currentNamespace}`} columns={listsColumns} selectionLabelIndex={1} />
|
||||
}
|
||||
{!useNamespaceLists &&
|
||||
<TableSelect id={prefix + 'list'} label={t('list')} withHeader dropdown dataUrl={`rest/lists-table`} columns={listsColumns} selectionLabelIndex={1} />
|
||||
}
|
||||
{(campaignTypeKey === CampaignType.REGULAR || campaignTypeKey === CampaignType.RSS) &&
|
||||
<div>
|
||||
<CheckBox id={prefix + 'useSegmentation'} label={t('segment')} text={t('useAParticularSegment')}/>
|
||||
|
@ -608,13 +622,21 @@ export default class CUD extends Component {
|
|||
sendSettings = [];
|
||||
|
||||
const addOverridable = (id, label) => {
|
||||
sendSettings.push(<CheckBox key={id + '_overriden'} id={id + '_overriden'} label={label} text={t('override')}/>);
|
||||
|
||||
if (this.getFormValue(id + '_overriden')) {
|
||||
sendSettings.push(<InputField key={id + '_override'} id={id + '_override'}/>);
|
||||
} else {
|
||||
if(this.state.sendConfiguration[id + '_overridable'] == 1){
|
||||
if (this.getFormValue(id + '_overriden')) {
|
||||
sendSettings.push(<InputField label={t(label)} key={id + '_override'} id={id + '_override'}/>);
|
||||
} else {
|
||||
sendSettings.push(
|
||||
<StaticField key={id + '_original'} label={t(label)} id={id + '_original'} className={styles.formDisabled}>
|
||||
{this.state.sendConfiguration[id]}
|
||||
</StaticField>
|
||||
);
|
||||
}
|
||||
sendSettings.push(<CheckBox key={id + '_overriden'} id={id + '_overriden'} text={t('override')} overrideFormat={true}/>);
|
||||
}
|
||||
else{
|
||||
sendSettings.push(
|
||||
<StaticField key={id + '_original'} id={id + '_original'} className={styles.formDisabled}>
|
||||
<StaticField key={id + '_original'} label={t(label)} id={id + '_original'} className={styles.formDisabled}>
|
||||
{this.state.sendConfiguration[id]}
|
||||
</StaticField>
|
||||
);
|
||||
|
@ -659,7 +681,13 @@ export default class CUD extends Component {
|
|||
|
||||
// The "key" property here and in the TableSelect below is to tell React that these tables are different and should be rendered by different instances. Otherwise, React will use
|
||||
// only one instance, which fails because Table does not handle updates in "columns" property
|
||||
templateEdit = <TableSelect key="templateSelect" id="data_sourceTemplate" label={t('template')} withHeader dropdown dataUrl='rest/templates-table' columns={templatesColumns} selectionLabelIndex={1} help={help}/>;
|
||||
if(useNamespaceTemplate){
|
||||
templateEdit = <TableSelect key="templateSelect" id="data_sourceTemplate" label={t('template')} withHeader dropdown dataUrl={`rest/templates-table-byNamespace/${currentNamespace}`} columns={templatesColumns} selectionLabelIndex={1} help={help}/>;
|
||||
}
|
||||
else{
|
||||
templateEdit = <TableSelect key="templateSelect" id="data_sourceTemplate" label={t('template')} withHeader dropdown dataUrl='rest/templates-table' columns={templatesColumns} selectionLabelIndex={1} help={help}/>;
|
||||
}
|
||||
|
||||
|
||||
} else if (!isEdit && sourceTypeKey === CampaignSource.CUSTOM_FROM_CAMPAIGN) {
|
||||
const campaignsColumns = [
|
||||
|
@ -731,12 +759,20 @@ export default class CUD extends Component {
|
|||
|
||||
{lstsEdit}
|
||||
|
||||
<hr/>
|
||||
<Title>{t('sendSettings')}</Title>
|
||||
|
||||
<TableSelect id="send_configuration" label={t('sendConfiguration')} withHeader dropdown dataUrl='rest/send-configurations-table' columns={sendConfigurationsColumns} selectionLabelIndex={1} />
|
||||
<CheckBox id="work_send_config_current_namespace" label={t('namespaceFiltering')} text={t('workWithCampaignNamespace')}/>
|
||||
|
||||
{useNamespaceSendConfig &&
|
||||
<TableSelect id="send_configuration" label={t('sendConfiguration')} withHeader dropdown dataUrl={`rest/send-configurations-table-byNamespace/${currentNamespace}`} columns={sendConfigurationsColumns} selectionLabelIndex={1} />
|
||||
}
|
||||
{!useNamespaceSendConfig &&
|
||||
<TableSelect id="send_configuration" label={t('sendConfiguration')} withHeader dropdown dataUrl={`rest/send-configurations-table`} columns={sendConfigurationsColumns} selectionLabelIndex={1} />
|
||||
}
|
||||
|
||||
|
||||
{sendSettings}
|
||||
|
||||
|
||||
<InputField id="unsubscribe_url" label={t('customUnsubscribeUrl')}/>
|
||||
|
||||
<hr/>
|
||||
|
@ -744,10 +780,12 @@ export default class CUD extends Component {
|
|||
<CheckBox id="open_tracking_disabled" text={t('disableOpenedTracking')}/>
|
||||
<CheckBox id="click_tracking_disabled" text={t('disableClickedTracking')}/>
|
||||
|
||||
{sourceEdit && <hr/> }
|
||||
<Title>{t('template')}</Title>
|
||||
|
||||
{sourceEdit}
|
||||
|
||||
<CheckBox id="work_template_current_namespace" label={t('namespaceFiltering')} text={t('workWithCampaignNamespace')}/>
|
||||
|
||||
{templateEdit}
|
||||
|
||||
<ButtonRow>
|
||||
|
|
|
@ -225,6 +225,18 @@ class SendControls extends Component {
|
|||
await this.refreshEntity();
|
||||
}
|
||||
|
||||
async confirmStart() {
|
||||
const t = this.props.t;
|
||||
this.actionDialog(
|
||||
t('confirmLaunch'),
|
||||
t('doYouWantToLaunchTheCampaign?All'),
|
||||
async () => {
|
||||
await this.startAsync();
|
||||
await this.refreshEntity();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async resetAsync() {
|
||||
const t = this.props.t;
|
||||
this.actionDialog(
|
||||
|
@ -306,7 +318,7 @@ class SendControls extends Component {
|
|||
{this.getFormValue('sendLater') ?
|
||||
<Button className="btn-primary" icon="send" label={(entity.scheduled ? t('rescheduleSend') : t('scheduleSend')) + subscrInfo} onClickAsync={::this.scheduleAsync}/>
|
||||
:
|
||||
<Button className="btn-primary" icon="send" label={t('send') + subscrInfo} onClickAsync={::this.startAsync}/>
|
||||
<Button className="btn-primary" icon="send" label={t('send') + subscrInfo} onClickAsync={::this.confirmStart}/>
|
||||
}
|
||||
{entity.status === CampaignStatus.PAUSED && <LinkButton className="btn-secondary" icon="signal" label={t('viewStatistics')} to={`/campaigns/${entity.id}/statistics`}/>}
|
||||
</ButtonRow>
|
||||
|
@ -335,7 +347,7 @@ class SendControls extends Component {
|
|||
{t('allMessagesSent!HitContinueIfYouYouWant')}
|
||||
</AlignedRow>
|
||||
<ButtonRow>
|
||||
<Button className="btn-primary" icon="play" label={t('continue') + subscrInfo} onClickAsync={::this.startAsync}/>
|
||||
<Button className="btn-primary" icon="play" label={t('continue') + subscrInfo} onClickAsync={::this.confirmStart}/>
|
||||
<Button className="btn-primary" icon="refresh" label={t('reset')} onClickAsync={::this.resetAsync}/>
|
||||
<LinkButton className="btn-secondary" icon="signal" label={t('viewStatistics')} to={`/campaigns/${entity.id}/statistics`}/>
|
||||
</ButtonRow>
|
||||
|
@ -443,11 +455,17 @@ export default class Status extends Component {
|
|||
let sendSettings;
|
||||
if (this.state.sendConfiguration) {
|
||||
sendSettings = [];
|
||||
|
||||
|
||||
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 && entity[id + '_override'] != null){
|
||||
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_email', t('fromEmailAddress'));
|
||||
addOverridable('reply_to', t('replytoEmailAddress'));
|
||||
|
|
|
@ -339,7 +339,8 @@ class CheckBox extends Component {
|
|||
text: PropTypes.string.isRequired,
|
||||
label: PropTypes.string,
|
||||
help: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
format: PropTypes.string
|
||||
format: PropTypes.string,
|
||||
overrideFormat: PropTypes.bool
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -347,15 +348,28 @@ class CheckBox extends Component {
|
|||
const owner = this.getFormStateOwner();
|
||||
const id = this.props.id;
|
||||
const htmlId = 'form_' + id;
|
||||
const overrideFormat = this.props.overrideFormat;
|
||||
|
||||
const className = owner.addFormValidationClass('form-check-input', id);
|
||||
|
||||
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
|
||||
if(overrideFormat){
|
||||
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
|
||||
<div className={styles.overrideCheckboxForm}>
|
||||
<input className={className} type="checkbox" checked={owner.getFormValue(id)} id={htmlId} aria-describedby={htmlId + '_help'} onChange={evt => owner.updateFormValue(id, !owner.getFormValue(id))}/>
|
||||
<label className={styles.checkboxText} htmlFor={htmlId}>{props.text}</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else{
|
||||
return wrapInput(id, htmlId, owner, props.format, '', props.label, props.help,
|
||||
<div className="form-group form-check my-2">
|
||||
<input className={className} type="checkbox" checked={owner.getFormValue(id)} id={htmlId} aria-describedby={htmlId + '_help'} onChange={evt => owner.updateFormValue(id, !owner.getFormValue(id))}/>
|
||||
<label className="form-check-label" htmlFor={htmlId}>{props.text}</label>
|
||||
<label className={styles.checkboxText} htmlFor={htmlId}>{props.text}</label>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,12 @@ import {convertToFake, getLang} from '../../../shared/langs';
|
|||
import {createComponentMixin} from "./decorator-helpers";
|
||||
|
||||
import lang_en_US_common from "../../../locales/en-US/common";
|
||||
import lang_es_ES_common from "../../../locales/es-ES/common";
|
||||
|
||||
|
||||
const resourcesCommon = {
|
||||
'en-US': lang_en_US_common,
|
||||
'es-ES': lang_es_ES_common,
|
||||
'fk-FK': convertToFake(lang_en_US_common)
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
Button,
|
||||
DismissibleAlert,
|
||||
DropdownActionLink,
|
||||
ButtonDropdown,
|
||||
Icon
|
||||
} from "./bootstrap-components";
|
||||
import mailtrainConfig
|
||||
|
@ -696,4 +697,5 @@ export function getLanguageChooser(t) {
|
|||
);
|
||||
|
||||
return languageChooser;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,16 @@
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
.checkboxText{
|
||||
padding-top: 3px;
|
||||
}
|
||||
.overrideCheckboxForm{
|
||||
position: relative;
|
||||
margin-top: -15px;
|
||||
margin-bottom: 30px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.dropZone{
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
|
|
|
@ -108,7 +108,7 @@ class Root extends Component {
|
|||
<ul className="navbar-nav mt-navbar-nav-left">
|
||||
{topLevelMenu}
|
||||
<NavDropdown label={t('administration')}>
|
||||
<DropdownLink to="/users">{t('users')}</DropdownLink>
|
||||
{mailtrainConfig.globalPermissions.manageUserList && <DropdownLink to="/users">{t('users')}</DropdownLink>}
|
||||
<DropdownLink to="/namespaces">{t('namespaces')}</DropdownLink>
|
||||
{mailtrainConfig.globalPermissions.manageSettings && <DropdownLink to="/settings">{t('globalSettings')}</DropdownLink>}
|
||||
<DropdownLink to="/send-configurations">{t('sendConfigurations')}</DropdownLink>
|
||||
|
|
|
@ -231,13 +231,13 @@ export default class CUD extends Component {
|
|||
|
||||
<Fieldset label={t('emailHeader')}>
|
||||
<InputField id="from_email" label={t('defaultFromEmail')}/>
|
||||
<CheckBox id="from_email_overridable" text={t('overridable')}/>
|
||||
<CheckBox id="from_email_overridable" text={t('overridable')} overrideFormat={true}/>
|
||||
<InputField id="from_name" label={t('defaultFromName')}/>
|
||||
<CheckBox id="from_name_overridable" text={t('overridable')}/>
|
||||
<CheckBox id="from_name_overridable" text={t('overridable')} overrideFormat={true}/>
|
||||
<InputField id="reply_to" label={t('defaultReplytoEmail')}/>
|
||||
<CheckBox id="reply_to_overridable" text={t('overridable')}/>
|
||||
<CheckBox id="reply_to_overridable" text={t('overridable')} overrideFormat={true}/>
|
||||
<InputField id="subject" label={t('subject')}/>
|
||||
<CheckBox id="subject_overridable" text={t('overridable')}/>
|
||||
<CheckBox id="subject_overridable" text={t('overridable')} overrideFormat={true}/>
|
||||
<InputField id="x_mailer" label={t('xMailer')}/>
|
||||
</Fieldset>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue