Added delete button to entity lists.
This commit is contained in:
parent
bc818aaee2
commit
2b57396a5d
22 changed files with 312 additions and 67 deletions
|
@ -26,6 +26,11 @@ import {
|
|||
} from "../../../shared/campaigns";
|
||||
import {checkPermissions} from "../lib/permissions";
|
||||
import {getCampaignLabels} from "./helpers";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -42,6 +47,7 @@ export default class List extends Component {
|
|||
this.campaignStatusLabels = campaignStatusLabels;
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -145,6 +151,8 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, perms, data[0], data[1]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +160,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/campaigns`, t('Deleting campaign ...'), t('Campaign deleted'))}
|
||||
<Toolbar>
|
||||
{this.state.createPermitted &&
|
||||
<DropdownMenu className="btn-primary" label={t('Create Campaign')}>
|
||||
|
@ -164,7 +173,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Campaigns')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/campaigns-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/campaigns-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,11 @@ import {Table} from '../../lib/table';
|
|||
import {getTriggerTypes} from './helpers';
|
||||
import {Icon} from "../../lib/bootstrap-components";
|
||||
import mailtrainConfig from 'mailtrainConfig';
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -29,6 +34,7 @@ export default class List extends Component {
|
|||
this.eventLabels = eventLabels;
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
|
@ -59,6 +65,10 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
if (perms.includes('manageTriggers')) {
|
||||
tableDeleteDialogAddDeleteButton(actions, this, null, data[0], data[1]);
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +76,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/triggers/${this.props.campaign.id}`, t('Deleting trigger ...'), t('Trigger deleted'))}
|
||||
{mailtrainConfig.globalPermissions.includes('setupAutomation') && this.props.campaign.permissions.includes('manageTriggers') &&
|
||||
<Toolbar>
|
||||
<NavButton linkTo={`/campaigns/${this.props.campaign.id}/triggers/create`} className="btn-primary" icon="plus" label={t('Create Trigger')}/>
|
||||
|
@ -74,7 +85,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Triggers')}</Title>
|
||||
|
||||
<Table withHeader dataUrl={`rest/triggers-by-campaign-table/${this.props.campaign.id}`} columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl={`rest/triggers-by-campaign-table/${this.props.campaign.id}`} columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,8 +10,7 @@ import {
|
|||
import {withErrorHandling} from "./error-handling";
|
||||
import {Table} from "./table";
|
||||
import Dropzone from "react-dropzone";
|
||||
import {ModalDialog} from "./modals";
|
||||
import {Icon} from "./bootstrap-components";
|
||||
import {Icon, ModalDialog} from "./bootstrap-components";
|
||||
import axios from './axios';
|
||||
import styles from "./styles.scss";
|
||||
import {withPageHelpers} from "./page";
|
||||
|
|
|
@ -4,44 +4,72 @@ import React, { Component } from 'react';
|
|||
import axios, { HTTPMethod } from './axios';
|
||||
import { translate } from 'react-i18next';
|
||||
import PropTypes from 'prop-types';
|
||||
import {ModalDialog} from "./bootstrap-components";
|
||||
import {
|
||||
Icon,
|
||||
ModalDialog
|
||||
} from "./bootstrap-components";
|
||||
import {getUrl} from "./urls";
|
||||
import {withPageHelpers} from "./page";
|
||||
import styles from './styles.scss';
|
||||
|
||||
@translate()
|
||||
class RestActionModalDialog extends Component {
|
||||
@withPageHelpers
|
||||
export class RestActionModalDialog extends Component {
|
||||
static propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
message: PropTypes.string.isRequired,
|
||||
stateOwner: PropTypes.object.isRequired,
|
||||
stateOwner: PropTypes.object,
|
||||
visible: PropTypes.bool.isRequired,
|
||||
actionMethod: PropTypes.func.isRequired,
|
||||
actionUrl: PropTypes.string.isRequired,
|
||||
backUrl: PropTypes.string.isRequired,
|
||||
successUrl: PropTypes.string.isRequired,
|
||||
backUrl: PropTypes.string,
|
||||
successUrl: PropTypes.string,
|
||||
onBack: PropTypes.func,
|
||||
onSuccess: PropTypes.func,
|
||||
onPerformingAction: PropTypes.func,
|
||||
actionInProgressMsg: PropTypes.string.isRequired,
|
||||
actionDoneMsg: PropTypes.string.isRequired,
|
||||
onErrorAsync: PropTypes.func
|
||||
}
|
||||
|
||||
async hideModal() {
|
||||
this.props.stateOwner.navigateTo(this.props.backUrl);
|
||||
async hideModal(isBack) {
|
||||
if (this.props.backUrl) {
|
||||
this.props.stateOwner.navigateTo(this.props.backUrl);
|
||||
} else {
|
||||
if (isBack) {
|
||||
this.props.onBack();
|
||||
} else {
|
||||
this.props.onPerformingAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async performAction() {
|
||||
const t = this.props.t;
|
||||
const owner = this.props.stateOwner;
|
||||
const props = this.props;
|
||||
const t = props.t;
|
||||
const owner = props.stateOwner;
|
||||
|
||||
await this.hideModal();
|
||||
await this.hideModal(false);
|
||||
|
||||
try {
|
||||
owner.disableForm();
|
||||
owner.setFormStatusMessage('info', this.props.actionInProgressMsg);
|
||||
await axios.method(this.props.actionMethod, getUrl(this.props.actionUrl));
|
||||
if (!owner) {
|
||||
this.setFlashMessage('info', props.actionInProgressMsg);
|
||||
} else {
|
||||
owner.disableForm();
|
||||
owner.setFormStatusMessage('info', props.actionInProgressMsg);
|
||||
}
|
||||
|
||||
owner.navigateToWithFlashMessage(this.props.successUrl, 'success', this.props.actionDoneMsg);
|
||||
await axios.method(props.actionMethod, getUrl(props.actionUrl));
|
||||
|
||||
if (props.successUrl) {
|
||||
owner.navigateToWithFlashMessage(props.successUrl, 'success', props.actionDoneMsg);
|
||||
} else {
|
||||
props.onSuccess();
|
||||
this.setFlashMessage('success', props.actionDoneMsg);
|
||||
}
|
||||
} catch (err) {
|
||||
if (this.props.onErrorAsync) {
|
||||
await this.props.onErrorAsync(err);
|
||||
if (props.onErrorAsync) {
|
||||
await props.onErrorAsync(err);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
|
@ -52,8 +80,8 @@ class RestActionModalDialog extends Component {
|
|||
const t = this.props.t;
|
||||
|
||||
return (
|
||||
<ModalDialog hidden={!this.props.visible} title={this.props.title} onCloseAsync={::this.hideModal} buttons={[
|
||||
{ label: t('No'), className: 'btn-primary', onClickAsync: ::this.hideModal },
|
||||
<ModalDialog hidden={!this.props.visible} title={this.props.title} onCloseAsync={() => this.hideModal(true)} buttons={[
|
||||
{ label: t('No'), className: 'btn-primary', onClickAsync: () => this.hideModal(true) },
|
||||
{ label: t('Yes'), className: 'btn-danger', onClickAsync: ::this.performAction }
|
||||
]}>
|
||||
{this.props.message}
|
||||
|
@ -63,13 +91,17 @@ class RestActionModalDialog extends Component {
|
|||
}
|
||||
|
||||
@translate()
|
||||
class DeleteModalDialog extends Component {
|
||||
export class DeleteModalDialog extends Component {
|
||||
static propTypes = {
|
||||
stateOwner: PropTypes.object.isRequired,
|
||||
stateOwner: PropTypes.object,
|
||||
visible: PropTypes.bool.isRequired,
|
||||
deleteUrl: PropTypes.string.isRequired,
|
||||
backUrl: PropTypes.string.isRequired,
|
||||
successUrl: PropTypes.string.isRequired,
|
||||
backUrl: PropTypes.string,
|
||||
successUrl: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
onBack: PropTypes.func,
|
||||
onSuccess: PropTypes.func,
|
||||
onPerformingAction: PropTypes.func,
|
||||
deletingMsg: PropTypes.string.isRequired,
|
||||
deletedMsg: PropTypes.string.isRequired,
|
||||
onErrorAsync: PropTypes.func
|
||||
|
@ -78,16 +110,20 @@ class DeleteModalDialog extends Component {
|
|||
render() {
|
||||
const t = this.props.t;
|
||||
const owner = this.props.stateOwner;
|
||||
const name = this.props.name !== undefined ? this.props.name : (owner ? owner.getFormValue('name') : '');
|
||||
|
||||
return <RestActionModalDialog
|
||||
title={t('Confirm deletion')}
|
||||
message={t('Are you sure you want to delete "{{name}}"?', {name: owner.getFormValue('name')})}
|
||||
message={t('Are you sure you want to delete "{{name}}"?', {name})}
|
||||
stateOwner={this.props.stateOwner}
|
||||
visible={this.props.visible}
|
||||
actionMethod={HTTPMethod.DELETE}
|
||||
actionUrl={this.props.deleteUrl}
|
||||
backUrl={this.props.backUrl}
|
||||
successUrl={this.props.successUrl}
|
||||
onBack={this.props.onBack}
|
||||
onSuccess={this.props.onSuccess}
|
||||
onPerformingAction={this.props.onPerformingAction}
|
||||
actionInProgressMsg={this.props.deletingMsg}
|
||||
actionDoneMsg={this.props.deletedMsg}
|
||||
onErrorAsync={this.props.onErrorAsync}
|
||||
|
@ -95,9 +131,51 @@ class DeleteModalDialog extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export {
|
||||
ModalDialog,
|
||||
DeleteModalDialog,
|
||||
RestActionModalDialog
|
||||
export function tableDeleteDialogInit(owner) {
|
||||
owner.deleteDialogData = {};
|
||||
owner.state.deleteDialogShown = false;
|
||||
}
|
||||
|
||||
export function tableDeleteDialogAddDeleteButton(actions, owner, perms, id, name) {
|
||||
const t = owner.props.t;
|
||||
|
||||
if (!perms || perms.includes('delete')) {
|
||||
if (owner.deleteDialogData.id) {
|
||||
actions.push({
|
||||
label: <Icon className={styles.iconDisabled} icon="remove" title={t('Delete')}/>
|
||||
});
|
||||
} else {
|
||||
actions.push({
|
||||
label: <Icon icon="remove" title={t('Delete')}/>,
|
||||
action: () => {
|
||||
owner.deleteDialogData = {name, id};
|
||||
owner.setState({
|
||||
deleteDialogShown: true
|
||||
});
|
||||
owner.table.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function tableDeleteDialogRender(owner, deleteUrlBase, deletingMsg, deletedMsg) {
|
||||
function hide() {
|
||||
owner.deleteDialogData = {};
|
||||
owner.setState({ deleteDialogShown: false });
|
||||
owner.table.refresh();
|
||||
}
|
||||
|
||||
return (
|
||||
<DeleteModalDialog
|
||||
visible={owner.state.deleteDialogShown}
|
||||
name={owner.deleteDialogData.name}
|
||||
deleteUrl={deleteUrlBase + '/' + owner.deleteDialogData.id}
|
||||
onBack={hide}
|
||||
onPerformingAction={() => owner.setState({ deleteDialogShown: false })}
|
||||
onSuccess={hide}
|
||||
deletingMsg={deletingMsg}
|
||||
deletedMsg={deletedMsg}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -131,4 +131,8 @@
|
|||
.withElementInFullscreen {
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.iconDisabled {
|
||||
color: #888;
|
||||
}
|
|
@ -16,6 +16,7 @@ import { withPageHelpers } from './page'
|
|||
import { withErrorHandling, withAsyncErrorHandler } from './error-handling';
|
||||
import styles from "./styles.scss";
|
||||
import {getUrl} from "./urls";
|
||||
import {Table} from "./table";
|
||||
|
||||
const TreeSelectMode = {
|
||||
NONE: 0,
|
||||
|
@ -23,7 +24,7 @@ const TreeSelectMode = {
|
|||
MULTI: 2
|
||||
};
|
||||
|
||||
@translate()
|
||||
@translate(null, { withRef: true })
|
||||
@withPageHelpers
|
||||
@withErrorHandling
|
||||
class TreeTable extends Component {
|
||||
|
@ -46,6 +47,13 @@ class TreeTable extends Component {
|
|||
selectMode: TreeSelectMode.NONE
|
||||
}
|
||||
|
||||
refresh() {
|
||||
if (this.tree) {
|
||||
this.tree.reload(this.sanitizeTreeData(this.state.treeData));
|
||||
this.updateSelection();
|
||||
}
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
async loadData(dataUrl) {
|
||||
const response = await axios.get(getUrl(dataUrl));
|
||||
|
@ -323,6 +331,15 @@ class TreeTable extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Refreshes the table. This method is provided to allow programmatic refresh from a handler outside the table.
|
||||
The reference to the table can be obtained by ref.
|
||||
*/
|
||||
TreeTable.prototype.refresh = function() {
|
||||
this.getWrappedInstance().refresh();
|
||||
};
|
||||
|
||||
|
||||
export {
|
||||
TreeTable,
|
||||
TreeSelectMode
|
||||
|
|
|
@ -9,6 +9,11 @@ import axios from '../lib/axios';
|
|||
import {Link} from "react-router-dom";
|
||||
import {Icon} from "../lib/bootstrap-components";
|
||||
import {checkPermissions} from "../lib/permissions";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -19,6 +24,7 @@ export default class List extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -115,6 +121,8 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, perms, data[0], data[1]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -122,6 +130,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/lists`, t('Deleting list ...'), t('List deleted'))}
|
||||
{this.state.createPermitted &&
|
||||
<Toolbar>
|
||||
<NavButton linkTo="/lists/create" className="btn-primary" icon="plus" label={t('Create List')}/>
|
||||
|
@ -131,7 +140,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Lists')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/lists-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/lists-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,11 @@ import {Table} from '../lib/table';
|
|||
import {getTriggerTypes} from '../campaigns/triggers/helpers';
|
||||
import {Icon} from "../lib/bootstrap-components";
|
||||
import mailtrainConfig from 'mailtrainConfig';
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -27,6 +32,7 @@ export default class List extends Component {
|
|||
this.eventLabels = eventLabels;
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
|
@ -60,6 +66,10 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
if (perms.includes('manageTriggers')) {
|
||||
tableDeleteDialogAddDeleteButton(actions, this, null, campaignId + '/' + data[0], data[1]);
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -67,9 +77,10 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/triggers`, t('Deleting trigger ...'), t('Trigger deleted'))}
|
||||
<Title>{t('Triggers')}</Title>
|
||||
|
||||
<Table withHeader dataUrl={`rest/triggers-by-list-table/${this.props.list.id}`} columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl={`rest/triggers-by-list-table/${this.props.list.id}`} columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,11 @@ import { withErrorHandling } from '../../lib/error-handling';
|
|||
import { Table } from '../../lib/table';
|
||||
import { getFieldTypes } from './helpers';
|
||||
import {Icon} from "../../lib/bootstrap-components";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -18,6 +23,7 @@ export default class List extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
|
||||
this.fieldTypes = getFieldTypes(props.t);
|
||||
}
|
||||
|
@ -48,6 +54,8 @@ export default class List extends Component {
|
|||
label: <Icon icon="edit" title={t('Edit')}/>,
|
||||
link: `/lists/${this.props.list.id}/fields/${data[0]}/edit`
|
||||
});
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, null, data[0], data[1]);
|
||||
}
|
||||
|
||||
return actions;
|
||||
|
@ -57,6 +65,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/fields/${this.props.list.id}`, t('Deleting field ...'), t('Field deleted'))}
|
||||
{this.props.list.permissions.includes('manageFields') &&
|
||||
<Toolbar>
|
||||
<NavButton linkTo={`/lists/${this.props.list.id}/fields/create`} className="btn-primary" icon="plus" label={t('Create Field')}/>
|
||||
|
@ -65,7 +74,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Fields')}</Title>
|
||||
|
||||
<Table withHeader dataUrl={`rest/fields-table/${this.props.list.id}`} columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl={`rest/fields-table/${this.props.list.id}`} columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,11 @@ import { Table } from '../../lib/table';
|
|||
import axios from '../../lib/axios';
|
||||
import {Icon} from "../../lib/bootstrap-components";
|
||||
import {checkPermissions} from "../../lib/permissions";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -18,6 +23,7 @@ export default class List extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -64,6 +70,8 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, perms, data[0], data[1]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +79,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/forms`, t('Deleting form ...'), t('Form deleted'))}
|
||||
{this.state.createPermitted &&
|
||||
<Toolbar>
|
||||
<NavButton linkTo="/lists/forms/create" className="btn-primary" icon="plus" label={t('Create Custom Form')}/>
|
||||
|
@ -79,7 +88,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Forms')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/forms-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/forms-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -401,7 +401,7 @@ export default class CUD extends Component {
|
|||
backUrl={`/lists/${this.props.list.id}/imports/${this.props.entity.id}/edit`}
|
||||
successUrl={`/lists/${this.props.list.id}/imports`}
|
||||
deletingMsg={t('Deleting import ...')}
|
||||
deletedMsg={t('Field deleted')}/>
|
||||
deletedMsg={t('Import deleted')}/>
|
||||
}
|
||||
|
||||
<Title>{isEdit ? t('Edit Import') : t('Create Import')}</Title>
|
||||
|
|
|
@ -17,6 +17,11 @@ import {Icon} from "../../lib/bootstrap-components";
|
|||
import mailtrainConfig from 'mailtrainConfig';
|
||||
import moment from "moment";
|
||||
import {inProgress} from '../../../../shared/imports';
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -27,6 +32,7 @@ export default class List extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
|
||||
const {importSourceLabels, importStatusLabels} = getImportLabels(props.t);
|
||||
this.importSourceLabels = importSourceLabels;
|
||||
|
@ -72,6 +78,10 @@ export default class List extends Component {
|
|||
link: `/lists/${this.props.list.id}/imports/${data[0]}/status`
|
||||
});
|
||||
|
||||
if (this.props.list.permissions.includes('manageImports')) {
|
||||
tableDeleteDialogAddDeleteButton(actions, this, null, data[0], data[1]);
|
||||
}
|
||||
|
||||
return { refreshTimeout, actions };
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +89,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/imports/${this.props.list.id}`, t('Deleting import ...'), t('Import deleted'))}
|
||||
{mailtrainConfig.globalPermissions.includes('setupAutomation') && this.props.list.permissions.includes('manageImports') &&
|
||||
<Toolbar>
|
||||
<NavButton linkTo={`/lists/${this.props.list.id}/imports/create`} className="btn-primary" icon="plus" label={t('Create Import')}/>
|
||||
|
@ -87,7 +98,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Imports')}</Title>
|
||||
|
||||
<Table withHeader dataUrl={`rest/imports-table/${this.props.list.id}`} columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl={`rest/imports-table/${this.props.list.id}`} columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,11 @@ import {requiresAuthenticatedUser, withPageHelpers, Title, Toolbar, NavButton} f
|
|||
import { withErrorHandling } from '../../lib/error-handling';
|
||||
import { Table } from '../../lib/table';
|
||||
import {Icon} from "../../lib/bootstrap-components";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -17,6 +22,7 @@ export default class List extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
|
@ -40,6 +46,8 @@ export default class List extends Component {
|
|||
label: <Icon icon="edit" title={t('Edit')}/>,
|
||||
link: `/lists/${this.props.list.id}/segments/${data[0]}/edit`
|
||||
});
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, null, data[0], data[1]);
|
||||
}
|
||||
|
||||
return actions;
|
||||
|
@ -49,6 +57,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/segments/${this.props.list.id}`, t('Deleting segment ...'), t('Segment deleted'))}
|
||||
{this.props.list.permissions.includes('manageSegments') &&
|
||||
<Toolbar>
|
||||
<NavButton linkTo={`/lists/${this.props.list.id}/segments/create`} className="btn-primary" icon="plus" label={t('Create Segment')}/>
|
||||
|
@ -57,7 +66,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Segment')}</Title>
|
||||
|
||||
<Table withHeader dataUrl={`rest/segments-table/${this.props.list.id}`} columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl={`rest/segments-table/${this.props.list.id}`} columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@ import {Icon, Button} from "../../lib/bootstrap-components";
|
|||
import axios from '../../lib/axios';
|
||||
import {getFieldTypes, getSubscriptionStatusLabels} from './helpers';
|
||||
import {getUrl, getPublicUrl} from "../../lib/urls";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withForm
|
||||
|
@ -29,6 +34,7 @@ export default class List extends Component {
|
|||
const t = props.t;
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
|
||||
this.subscriptionStatusLabels = getSubscriptionStatusLabels(t);
|
||||
this.fieldTypes = getFieldTypes(t);
|
||||
|
@ -62,22 +68,16 @@ export default class List extends Component {
|
|||
this.updateSegmentSelection(nextProps);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
async deleteSubscription(id) {
|
||||
await axios.delete(getUrl(`rest/subscriptions/${this.props.list.id}/${id}`));
|
||||
this.blacklistTable.refresh();
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
async unsubscribeSubscription(id) {
|
||||
await axios.post(getUrl(`rest/subscriptions-unsubscribe/${this.props.list.id}/${id}`));
|
||||
this.blacklistTable.refresh();
|
||||
this.table.refresh();
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
async blacklistSubscription(email) {
|
||||
await axios.post(getUrl('rest/blacklist'), { email });
|
||||
this.blacklistTable.refresh();
|
||||
this.table.refresh();
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -132,10 +132,7 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
actions.push({
|
||||
label: <Icon icon="remove" title={t('Remove')}/>,
|
||||
action: () => this.deleteSubscription(data[0])
|
||||
});
|
||||
tableDeleteDialogAddDeleteButton(actions, this, null, data[0], data[2]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
@ -157,6 +154,7 @@ export default class List extends Component {
|
|||
// FIXME - presents segments in a data table as in campaign edit
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/subscriptions/${this.props.list.id}`, t('Deleting subscription ...'), t('Subscription deleted'))}
|
||||
<Toolbar>
|
||||
<a href={getPublicUrl(`subscription/${this.props.list.cid}`)} className="btn-default"><Button label={t('Subscription Form')} className="btn-default"/></a>
|
||||
<NavButton linkTo={`/lists/${this.props.list.id}/subscriptions/create`} className="btn-primary" icon="plus" label={t('Add Subscriber')}/>
|
||||
|
@ -175,7 +173,7 @@ export default class List extends Component {
|
|||
</div>
|
||||
|
||||
|
||||
<Table ref={node => this.blacklistTable = node} withHeader dataUrl={dataUrl} columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl={dataUrl} columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,11 @@ import { withErrorHandling, withAsyncErrorHandler } from '../lib/error-handling'
|
|||
import axios from '../lib/axios';
|
||||
import {Icon} from "../lib/bootstrap-components";
|
||||
import {checkPermissions} from "../lib/permissions";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withErrorHandling
|
||||
|
@ -18,6 +23,7 @@ export default class List extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -44,6 +50,7 @@ export default class List extends Component {
|
|||
|
||||
const actions = node => {
|
||||
const actions = [];
|
||||
console.log(node);
|
||||
|
||||
if (node.data.permissions.includes('edit')) {
|
||||
actions.push({
|
||||
|
@ -59,11 +66,14 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, node.data.permissions, node.key, node.key);
|
||||
|
||||
return actions;
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/namespaces`, t('Deleting namespace ...'), t('Namespace deleted'))}
|
||||
{this.state.createPermitted &&
|
||||
<Toolbar>
|
||||
<NavButton linkTo="/namespaces/create" className="btn-primary" icon="plus" label={t('Create Namespace')}/>
|
||||
|
@ -72,7 +82,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Namespaces')}</Title>
|
||||
|
||||
<TreeTable withHeader withDescription dataUrl="rest/namespaces-tree" actions={actions} />
|
||||
<TreeTable ref={node => this.table = node} withHeader withDescription dataUrl="rest/namespaces-tree" actions={actions} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,11 @@ import { ReportState } from '../../../shared/reports';
|
|||
import {Icon} from "../lib/bootstrap-components";
|
||||
import {checkPermissions} from "../lib/permissions";
|
||||
import {getUrl} from "../lib/urls";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withErrorHandling
|
||||
|
@ -21,6 +26,7 @@ export default class List extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -159,6 +165,8 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, perms, data[0], data[1]);
|
||||
|
||||
return { refreshTimeout, actions };
|
||||
}
|
||||
}
|
||||
|
@ -167,6 +175,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/reports`, t('Deleting report ...'), t('Report deleted'))}
|
||||
<Toolbar>
|
||||
{this.state.createPermitted &&
|
||||
<NavButton linkTo="/reports/create" className="btn-primary" icon="plus" label={t('Create Report')}/>
|
||||
|
@ -178,7 +187,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Reports')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/reports-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/reports-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,11 @@ import axios from '../../lib/axios';
|
|||
import moment from 'moment';
|
||||
import mailtrainConfig from 'mailtrainConfig';
|
||||
import {checkPermissions} from "../../lib/permissions";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -20,6 +25,7 @@ export default class List extends Component {
|
|||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -68,6 +74,8 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, perms, data[0], data[1]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +83,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/reports/templates`, t('Deleting report template ...'), t('Report template deleted'))}
|
||||
{this.state.createPermitted &&
|
||||
<Toolbar>
|
||||
<DropdownMenu className="btn-primary" label={t('Create Report Template')}>
|
||||
|
@ -88,7 +97,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Report Templates')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/report-templates-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/report-templates-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,11 @@ import axios from '../lib/axios';
|
|||
import moment from 'moment';
|
||||
import {getMailerTypes} from './helpers';
|
||||
import {checkPermissions} from "../lib/permissions";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../lib/modals";
|
||||
|
||||
|
||||
@translate()
|
||||
|
@ -32,6 +37,7 @@ export default class List extends Component {
|
|||
this.mailerTypes = getMailerTypes(props.t);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -82,6 +88,8 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, perms, data[0], data[1]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -89,6 +97,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/send-configurations`, t('Deleting send configuration ...'), t('Send configuration deleted'))}
|
||||
{this.state.createPermitted &&
|
||||
<Toolbar>
|
||||
<NavButton linkTo="/send-configurations/create" className="btn-primary" icon="plus" label={t('Create Send Configuration')}/>
|
||||
|
@ -97,7 +106,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Send Configurations')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/send-configurations-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/send-configurations-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,11 @@ import {Table} from '../lib/table';
|
|||
import moment from 'moment';
|
||||
import {getTemplateTypes} from './helpers';
|
||||
import {checkPermissions} from "../lib/permissions";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -30,6 +35,7 @@ export default class List extends Component {
|
|||
this.templateTypes = getTemplateTypes(props.t);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -95,6 +101,8 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, perms, data[0], data[1]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +110,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/templates`, t('Deleting template ...'), t('Template deleted'))}
|
||||
<Toolbar>
|
||||
{this.state.createPermitted &&
|
||||
<NavButton linkTo="/templates/create" className="btn-primary" icon="plus" label={t('Create Template')}/>
|
||||
|
@ -113,7 +122,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Templates')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/templates-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/templates-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,11 @@ import axios from '../../lib/axios';
|
|||
import moment from 'moment';
|
||||
import { getTemplateTypes } from './helpers';
|
||||
import {checkPermissions} from "../../lib/permissions";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../../lib/modals";
|
||||
|
||||
|
||||
@translate()
|
||||
|
@ -23,6 +28,7 @@ export default class List extends Component {
|
|||
this.templateTypes = getTemplateTypes(props.t);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
@withAsyncErrorHandler
|
||||
|
@ -86,6 +92,8 @@ export default class List extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, perms, data[0], data[1]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +101,7 @@ export default class List extends Component {
|
|||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/mosaico-templates`, t('Deleting Mosaico template ...'), t('Mosaico template deleted'))}
|
||||
{this.state.createPermitted &&
|
||||
<Toolbar>
|
||||
<DropdownMenu className="btn-primary" label={t('Create Mosaico Template')}>
|
||||
|
@ -104,7 +113,7 @@ export default class List extends Component {
|
|||
|
||||
<Title>{t('Mosaico Templates')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/mosaico-templates-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/mosaico-templates-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,11 @@ import {NavButton, requiresAuthenticatedUser, Title, Toolbar, withPageHelpers} f
|
|||
import {Table} from "../lib/table";
|
||||
import mailtrainConfig from "mailtrainConfig";
|
||||
import {Icon} from "../lib/bootstrap-components";
|
||||
import {
|
||||
tableDeleteDialogAddDeleteButton,
|
||||
tableDeleteDialogInit,
|
||||
tableDeleteDialogRender
|
||||
} from "../lib/modals";
|
||||
|
||||
@translate()
|
||||
@withPageHelpers
|
||||
|
@ -13,6 +18,9 @@ import {Icon} from "../lib/bootstrap-components";
|
|||
export default class List extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {};
|
||||
tableDeleteDialogInit(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -33,27 +41,35 @@ export default class List extends Component {
|
|||
columns.push({ data: 4, title: "Role" });
|
||||
|
||||
columns.push({
|
||||
actions: data => [
|
||||
{
|
||||
actions: data => {
|
||||
const actions = [];
|
||||
|
||||
actions.push({
|
||||
label: <Icon icon="edit" title={t('Edit')}/>,
|
||||
link: `/users/${data[0]}/edit`
|
||||
},
|
||||
{
|
||||
});
|
||||
|
||||
actions.push({
|
||||
label: <Icon icon="share" title={t('Share')}/>,
|
||||
link: `/users/${data[0]}/shares`
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
tableDeleteDialogAddDeleteButton(actions, this, null, data[0], data[1]);
|
||||
|
||||
return actions;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{tableDeleteDialogRender(this, `rest/users`, t('Deleting user ...'), t('User deleted'))}
|
||||
<Toolbar>
|
||||
<NavButton linkTo="/users/create" className="btn-primary" icon="plus" label={t('Create User')}/>
|
||||
</Toolbar>
|
||||
|
||||
<Title>{t('Users')}</Title>
|
||||
|
||||
<Table withHeader dataUrl="rest/users-table" columns={columns} />
|
||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/users-table" columns={columns} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -578,7 +578,7 @@ async function _removeAndGetTx(tx, context, listId, existing) {
|
|||
throw new interoperableErrors.NotFoundError();
|
||||
}
|
||||
|
||||
await tx(getSubscriptionTableName(listId)).where('id', id).del();
|
||||
await tx(getSubscriptionTableName(listId)).where('id', existing.id).del();
|
||||
|
||||
if (existing.status === SubscriptionStatus.SUBSCRIBED) {
|
||||
await tx('lists').where('id', listId).decrement('subscribers', 1);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue