Merge branch 'pull/564' into development

This commit is contained in:
Tomas Bures 2019-03-26 22:55:00 +01:00
commit dcb7168322
24 changed files with 1216 additions and 52 deletions

View file

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

View file

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

View file

@ -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'));

View file

@ -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>
);
);
}
}
}

View file

@ -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)
};

View file

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

View file

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

View file

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

View file

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