Work on sending campaigns. Campaign status page half-way done, but does not work yet.

This commit is contained in:
Tomas Bures 2018-09-10 00:55:44 +02:00
parent 67d7129f7b
commit d1fa4f4211
66 changed files with 1653 additions and 525 deletions

View file

@ -31,6 +31,7 @@ export default class API extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.loadAccessToken();
}

View file

@ -42,6 +42,7 @@ export default class Account extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.loadFormValues();
}

View file

@ -60,6 +60,7 @@ export default class Account extends Component {
password2: ''
});
// noinspection JSIgnoredPromiseFromCall
this.validateResetToken();
}

View file

@ -45,12 +45,13 @@ import {getUrl} from "../lib/urls";
import {
campaignOverridables,
CampaignSource,
CampaignStatus,
CampaignType
} from "../../../shared/campaigns";
import moment from 'moment';
import {getMailerTypes} from "../send-configurations/helpers";
import {ResourceType} from "../lib/mosaico";
import {getCampaignTypeLabels} from "./helpers";
import {getCampaignLabels} from "./helpers";
@translate()
@withForm
@ -66,7 +67,8 @@ export default class CUD extends Component {
this.templateTypes = getTemplateTypes(props.t, 'data_sourceCustom_', ResourceType.CAMPAIGN);
this.mailerTypes = getMailerTypes(props.t);
this.campaignTypes = getCampaignTypeLabels(t);
const { campaignTypeLabels } = getCampaignLabels(t);
this.campaignTypeLabels = campaignTypeLabels;
this.createTitles = {
[CampaignType.REGULAR]: t('Create Regular Campaign'),
@ -134,6 +136,7 @@ export default class CUD extends Component {
onSendConfigurationChanged(newState, key, oldValue, sendConfigurationId) {
newState.sendConfiguration = null;
// noinspection JSIgnoredPromiseFromCall
this.fetchSendConfiguration(sendConfigurationId);
}
@ -167,7 +170,7 @@ export default class CUD extends Component {
}
for (const overridable of campaignOverridables) {
data[overridable + '_overriden'] = !!data[overridable + '_override'];
data[overridable + '_overriden'] = data[overridable + '_override'] === null;
}
const lsts = [];
@ -184,9 +187,14 @@ export default class CUD extends Component {
}
data.lists = lsts;
// noinspection JSIgnoredPromiseFromCall
this.fetchSendConfiguration(data.send_configuration);
});
if (this.props.entity.status === CampaignStatus.SENDING) {
this.disableForm();
}
} else {
const data = {};
for (const overridable of campaignOverridables) {
@ -620,7 +628,7 @@ export default class CUD extends Component {
const campaignsColumns = [
{ data: 1, title: t('Name') },
{ data: 2, title: t('Description') },
{ data: 3, title: t('Type'), render: data => this.campaignTypes[data] },
{ data: 3, title: t('Type'), render: data => this.campaignTypeLabels[data] },
{ data: 4, title: t('Created'), render: data => moment(data).fromNow() },
{ data: 5, title: t('Namespace') }
];
@ -671,6 +679,12 @@ export default class CUD extends Component {
<Title>{isEdit ? this.editTitles[this.getFormValue('type')] : this.createTitles[this.getFormValue('type')]}</Title>
{isEdit && this.props.entity.status === CampaignStatus.SENDING &&
<div className={`alert alert-info`} role="alert">
{t('Form cannot be edited because the campaign is currently being sent out. Wait till the sending is finished and refresh.')}
</div>
}
<Form stateOwner={this} onSubmitAsync={::this.submitHandler}>
<InputField id="name" label={t('Name')}/>
<TextArea id="description" label={t('Description')}/>

View file

@ -25,7 +25,7 @@ import {
CampaignType
} from "../../../shared/campaigns";
import {checkPermissions} from "../lib/permissions";
import {getCampaignTypeLabels} from "./helpers";
import {getCampaignLabels} from "./helpers";
@translate()
@withPageHelpers
@ -37,15 +37,9 @@ export default class List extends Component {
const t = props.t;
this.campaignStatuses = {
[CampaignStatus.IDLE]: t('Idle'),
[CampaignStatus.FINISHED]: t('Finished'),
[CampaignStatus.PAUSED]: t('Paused'),
[CampaignStatus.INACTIVE]: t('Inactive'),
[CampaignStatus.ACTIVE]: t('Active')
};
this.campaignTypes = getCampaignTypeLabels(t);
const { campaignTypeLabels, campaignStatusLabels } = getCampaignLabels(t);
this.campaignTypeLabels = campaignTypeLabels;
this.campaignStatusLabels = campaignStatusLabels;
this.state = {};
}
@ -65,6 +59,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}
@ -74,7 +69,7 @@ export default class List extends Component {
const columns = [
{ data: 1, title: t('Name') },
{ data: 2, title: t('Description') },
{ data: 3, title: t('Type'), render: data => this.campaignTypes[data] },
{ data: 3, title: t('Type'), render: data => this.campaignTypeLabels[data] },
{
data: 4,
title: t('Status'),
@ -87,7 +82,7 @@ export default class List extends Component {
return t('Sending');
}
} else {
return this.campaignStatuses[data];
return this.campaignStatusLabels[data];
}
}
},
@ -100,6 +95,13 @@ export default class List extends Component {
const campaignType = data[3];
const campaignSource = data[6];
if (perms.includes('viewStats')) {
actions.push({
label: <Icon icon="send" title={t('Status')}/>,
link: `/campaigns/${data[0]}/status`
});
}
if (perms.includes('edit')) {
actions.push({
label: <Icon icon="edit" title={t('Edit')}/>,

View file

@ -0,0 +1,387 @@
'use strict';
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {translate} from 'react-i18next';
import {
requiresAuthenticatedUser,
Title,
withPageHelpers
} from '../lib/page';
import {
AlignedRow,
ButtonRow,
CheckBox,
DatePicker,
Form,
InputField,
TableSelect,
withForm
} from '../lib/form';
import {
withAsyncErrorHandler,
withErrorHandling
} from '../lib/error-handling';
import {getCampaignLabels} from './helpers';
import {Table} from "../lib/table";
import {Button} from "../lib/bootstrap-components";
import axios from "../lib/axios";
import {getUrl} from "../lib/urls";
import interoperableErrors from '../../../shared/interoperable-errors';
import {CampaignStatus} from "../../../shared/campaigns";
import moment from 'moment';
import campaignsStyles from "./styles.scss";
@translate()
@withForm
@withPageHelpers
@withErrorHandling
@requiresAuthenticatedUser
class TestUser extends Component {
constructor(props) {
super(props);
this.initForm();
}
static propTypes = {
entity: PropTypes.object.isRequired
}
localValidateFormValues(state) {
const t = this.props.t;
if (!state.getIn(['testUser', 'value'])) {
state.setIn(['testUser', 'error'], t('Subscription has to be selected to show the campaign for a test user.'))
} else {
state.setIn(['testUser', 'error'], null);
}
}
componentDidMount() {
this.populateFormValues({
testUser: null,
});
}
async previewAsync() {
if (this.isFormWithoutErrors()) {
const data = this.getFormValues();
// FIXME - navigate to campaign preview
} else {
this.showFormValidation();
}
}
render() {
const t = this.props.t;
const testUsersColumns = [
{ data: 1, title: t('Email') },
{ data: 4, title: t('List ID') },
{ data: 5, title: t('List') },
{ data: 6, title: t('Segment') },
{ data: 7, title: t('List namespace') }
];
return (
<Form stateOwner={this}>
<TableSelect id="testUser" label={t('Preview campaign as')} withHeader dropdown dataUrl={`rest/campaigns-test-users-table/${this.props.entity.id}`} columns={testUsersColumns} selectionLabelIndex={1} />
<ButtonRow>
<Button className="btn-primary" label={t('Preview')} onClickAsync={::this.previewAsync}/>
</ButtonRow>
</Form>
);
}
}
@translate()
@withForm
@withPageHelpers
@withErrorHandling
@requiresAuthenticatedUser
class SendControls extends Component {
constructor(props) {
super(props);
this.initForm();
}
static propTypes = {
entity: PropTypes.object.isRequired,
refreshEntity: PropTypes.func.isRequired
}
localValidateFormValues(state) {
const t = this.props.t;
state.setIn(['date', 'error'], null);
state.setIn(['time', 'error'], null);
if (!state.getIn(['sendLater', 'value'])) {
const dateValue = state.getIn(['date', 'value']);
if (!dateValue) {
state.setIn(['date', 'error'], t('Date must not be empty'));
} else if (!moment.utc(dateValue, 'YYYY-MM-DD').isValid()) {
state.setIn(['date', 'error'], t('Date is invalid'));
}
const timeValue = state.getIn(['time', 'value']);
const time = moment.utc(timeValue, 'HH:mm').isValid();
if (!timeValue) {
state.setIn(['time', 'error'], t('Time must not be empty'));
} else if (!time) {
state.setIn(['time', 'error'], t('Time is invalid'));
}
}
}
componentDidMount() {
const entity = this.props.entity;
if (entity.scheduled) {
const date = moment(entity.scheduled);
this.populateFormValues({
sendLater: true,
date: date.utc().format('YYYY-MM-DD'),
time: date.utc().format('HH:mm')
});
} else {
this.populateFormValues({
sendLater: false,
date: '',
time: ''
});
}
}
async refreshEntity() {
await this.props.refreshEntity();
}
async postAndMaskStateError(url) {
try {
await axios.post(getUrl(url));
} catch (err) {
if (err instanceof interoperableErrors.InvalidStateError) {
// Just mask the fact that it's not possible to start anything and refresh instead.
} else {
throw err;
}
}
}
async scheduleAsync() {
if (this.isFormWithoutErrors()) {
const data = this.getFormValues();
const date = moment.utc(data.date);
const time = moment.utc(date.time);
date.hour(time.hour());
date.minute(time.minute());
date.second(0);
date.millisecond(0);
await this.postAndMaskStateError(`rest/campaign-start-at/${this.props.entity.id}/${date.toDate()}`);
} else {
this.showFormValidation();
}
await this.refreshEntity();
}
async startAsync() {
await this.postAndMaskStateError(`rest/campaign-start/${this.props.entity.id}`);
await this.refreshEntity();
}
async stopAsync() {
await this.postAndMaskStateError(`rest/campaign-stop/${this.props.entity.id}`);
await this.refreshEntity();
}
async resetAsync() {
await this.postAndMaskStateError(`rest/campaign-reset/${this.props.entity.id}`);
await this.refreshEntity();
}
render() {
const t = this.props.t;
const entity = this.props.entity;
if (entity.status === CampaignStatus.IDLE || entity.status === CampaignStatus.PAUSED || (entity.status === CampaignStatus.SCHEDULED && entity.scheduled)) {
const subscrInfo = entity.subscriptionsTotal === undefined ? '' : ` (${entity.subscriptionsTotal} ${t('subscribers')})`;
return (
<div>
<AlignedRow label={t('Send status')}>
{entity.scheduled ? t('Campaign is scheduled for delivery.') : t('Campaign is ready to be sent out.')}
</AlignedRow>
<Form stateOwner={this}>
<CheckBox id="sendLater" label={t('Send later')} text={t('Schedule deliver at particular date/time')}/>
{this.getFormValue('sendLater') &&
<div>
<DatePicker id="date" label={t('Date')} />
<InputField id="time" label={t('Time')} help={t('Enter 24-hour time in format HH:MM (e.g. 13:48)')}/>
</div>
}
</Form>
<ButtonRow className={campaignsStyles.sendButtonRow}>
{this.getFormValue('sendLater') ?
<Button className="btn-primary" icon="send" label={(entity.scheduled ? t('Reschedule send') : t('Schedule send')) + subscrInfo} onClickAsync={::this.scheduleAsync}/>
:
<Button className="btn-primary" icon="send" label={t('Send') + subscrInfo} onClickAsync={::this.startAsync}/>
}
</ButtonRow>
</div>
);
} else if (entity.status === CampaignStatus.SENDING || (entity.status === CampaignStatus.SCHEDULED && !entity.scheduled)) {
return (
<div>
<div>
{t('Campaign is being sent out.')}
</div>
<ButtonRow>
<Button className="btn-primary" icon="stop" label={t('Stop')} onClickAsync={::this.pauseAsync}/>
</ButtonRow>
</div>
);
} else if (entity.status === CampaignStatus.FINISHED) {
return (
<div>
<div>
{t('All messages sent! Hit "Continue" if you you want to send this campaign to new subscribers.')}
</div>
<ButtonRow>
<Button className="btn-primary" icon="play" label={t('Continue')} onClickAsync={::this.startAsync}/>
<Button className="btn-primary" icon="refresh" label={t('Reset')} onClickAsync={::this.resetAsync}/>
</ButtonRow>
</div>
);
} else {
return null;
}
}
}
@translate()
@withPageHelpers
@withErrorHandling
@requiresAuthenticatedUser
export default class Status extends Component {
constructor(props) {
super(props);
const t = props.t;
this.state = {
entity: props.entity,
sendConfiguration: null
};
const { campaignTypeLabels, campaignStatusLabels } = getCampaignLabels(t);
this.campaignTypeLabels = campaignTypeLabels;
this.campaignStatusLabels = campaignStatusLabels;
this.refreshTimeoutHandler = ::this.periodicRefreshTask;
this.refreshTimeoutId = 0;
}
static propTypes = {
entity: PropTypes.object
}
@withAsyncErrorHandler
async refreshEntity() {
let resp;
resp = await axios.get(getUrl(`rest/campaigns-stats/${this.props.entity.id}`));
const entity = resp.data;
resp = await axios.get(getUrl(`rest/send-configurations-public/${entity.send_configuration}`));
const sendConfiguration = resp.data;
this.setState({
entity,
sendConfiguration
});
}
async periodicRefreshTask() {
// The periodic task runs all the time, so that we don't have to worry about starting/stopping it as a reaction to the buttons.
await this.refreshEntity();
if (this.refreshTimeoutHandler) { // For some reason the task gets rescheduled if server is restarted while the page is shown. That why we have this check here.
this.refreshTimeoutId = setTimeout(this.refreshTimeoutHandler, 2000);
}
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.periodicRefreshTask();
}
componentWillUnmount() {
clearTimeout(this.refreshTimeoutId);
this.refreshTimeoutHandler = null;
}
render() {
const t = this.props.t;
const entity = this.state.entity;
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>);
};
addOverridable('from_name', t('"From" name'));
addOverridable('from_email', t('"From" email address'));
addOverridable('reply_to', t('"Reply-to" email address'));
addOverridable('subject', t('"Subject" line'));
} else {
sendSettings = <AlignedRow>{t('Loading send configuration ...')}</AlignedRow>
}
const listsColumns = [
{ data: 1, title: t('Name') },
{ data: 2, title: t('ID'), render: data => <code>{data}</code> },
{ data: 3, title: t('Namespace') },
{ data: 4, title: t('Segment') }
];
return (
<div>
<Title>{t('Campaign Status')}</Title>
<AlignedRow label={t('Name')}>{entity.name}</AlignedRow>
<AlignedRow label={t('Subscribers')}>{entity.subscriptionsTotal === undefined ? t('computing ...') : entity.subscriptionsTotal}</AlignedRow>
<AlignedRow label={t('Status')}>{this.campaignStatusLabels[entity.status]}</AlignedRow>
{sendSettings}
<AlignedRow label={t('Target lists/segments')}>
<Table withHeader dataUrl={`rest/lists-with-segment-by-campaign-table/${this.props.entity.id}`} columns={listsColumns} />
</AlignedRow>
<hr/>
<TestUser entity={entity}/>
<hr/>
<SendControls entity={entity} refreshEntity={::this.refreshEntity}/>
</div>
);
}
}

View file

@ -1,8 +1,11 @@
'use strict';
import {CampaignType} from "../../../shared/campaigns";
import {
CampaignStatus,
CampaignType
} from "../../../shared/campaigns";
export function getCampaignTypeLabels(t) {
export function getCampaignLabels(t) {
const campaignTypeLabels = {
[CampaignType.REGULAR]: t('Regular'),
@ -10,5 +13,19 @@ export function getCampaignTypeLabels(t) {
[CampaignType.RSS]: t('RSS')
};
return campaignTypeLabels;
const campaignStatusLabels = {
[CampaignStatus.IDLE]: t('Idle'),
[CampaignStatus.SCHEDULED]: t('Scheduled'),
[CampaignStatus.PAUSED]: t('Paused'),
[CampaignStatus.FINISHED]: t('Finished'),
[CampaignStatus.PAUSED]: t('Paused'),
[CampaignStatus.INACTIVE]: t('Inactive'),
[CampaignStatus.ACTIVE]: t('Active')
};
return {
campaignStatusLabels,
campaignTypeLabels
};
}

View file

@ -2,6 +2,7 @@
import React from 'react';
import Status from './Status';
import CampaignsCUD from './CUD';
import Content from './Content';
import CampaignsList from './List';
@ -29,6 +30,12 @@ function getMenus(t) {
},
link: params => `/campaigns/${params.campaignId}/edit`,
navs: {
status: {
title: t('Status'),
link: params => `/campaigns/${params.campaignId}/status`,
visible: resolved => resolved.campaign.permissions.includes('viewStats'),
panelRender: props => <Status entity={props.resolved.campaign} />
},
':action(edit|delete)': {
title: t('Edit'),
link: params => `/campaigns/${params.campaignId}/edit`,

View file

@ -32,7 +32,11 @@
}
}
.newEntry{
.newEntry {
text-align: right;
margin-bottom: 15px;
}
.sendButtonRow {
margin-top: 10px;
}

View file

@ -30,7 +30,7 @@ import {
Event
} from '../../../../shared/triggers';
import moment from 'moment';
import {getCampaignTypeLabels} from "../helpers";
import {getCampaignLabels} from "../helpers";
@translate()
@ -44,7 +44,7 @@ export default class CUD extends Component {
this.state = {};
this.campaignTypes = getCampaignTypeLabels(props.t);
this.campaignTypeLabels = getCampaignLabels(props.t);
const {entityLabels, eventLabels} = getTriggerTypes(props.t);
this.entityLabels = entityLabels;
@ -186,7 +186,7 @@ export default class CUD extends Component {
const campaignsColumns = [
{ data: 1, title: t('Name') },
{ data: 2, title: t('Description') },
{ data: 3, title: t('Type'), render: data => this.campaignTypes[data] },
{ data: 3, title: t('Type'), render: data => this.campaignTypeLabels[data] },
{ data: 4, title: t('Created'), render: data => moment(data).fromNow() },
{ data: 5, title: t('Namespace') }
];

View file

@ -249,6 +249,7 @@ class ModalDialog extends Component {
// are capture, converted to onClose callback and prevented. It's up to the parent to decide whether to
// hide the modal or not.
if (!this.props.hidden) {
// noinspection JSIgnoredPromiseFromCall
this.onClose();
evt.preventDefault();
}

View file

@ -185,6 +185,7 @@ class RouteContent extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.resolve(this.props);
}
@ -193,6 +194,7 @@ class RouteContent extends Component {
componentWillReceiveProps(nextProps) {
if (this.props.match.params !== nextProps.match.params && needsResolve(this.props.route, nextProps.route, this.props.match, nextProps.match)) {
// noinspection JSIgnoredPromiseFromCall
this.resolve(nextProps);
}
}
@ -279,6 +281,7 @@ class SectionContent extends Component {
}
this.historyUnlisten = props.history.listen((location, action) => {
// noinspection JSIgnoredPromiseFromCall
this.closeFlashMessage();
})
}

View file

@ -154,6 +154,7 @@ class Table extends Component {
}
}
// noinspection JSIgnoredPromiseFromCall
this.notifySelection(this.props.onSelectionDataAsync, this.selectionMap);
}
}
@ -278,6 +279,7 @@ class Table extends Component {
if (self.props.selectMode === TableSelectMode.SINGLE) {
if (selectionMap.size !== 1 || !selectionMap.has(rowKey)) {
// noinspection JSIgnoredPromiseFromCall
self.notifySelection(self.props.onSelectionChangedAsync, new Map([[rowKey, data]]));
}
@ -290,6 +292,7 @@ class Table extends Component {
newSelMap.set(rowKey, data);
}
// noinspection JSIgnoredPromiseFromCall
self.notifySelection(self.props.onSelectionChangedAsync, newSelMap);
}
});
@ -321,6 +324,7 @@ class Table extends Component {
clearTimeout(this.refreshTimeoutId);
});
// noinspection JSIgnoredPromiseFromCall
this.fetchAndNotifySelectionData();
}
@ -344,6 +348,8 @@ class Table extends Component {
});
this.updateSelectInfo();
// noinspection JSIgnoredPromiseFromCall
this.fetchAndNotifySelectionData();
}
@ -375,6 +381,8 @@ class Table extends Component {
async deselectAll(evt) {
evt.preventDefault();
// noinspection JSIgnoredPromiseFromCall
this.notifySelection(this.props.onSelectionChangedAsync, new Map());
}

View file

@ -82,6 +82,7 @@ class TreeTable extends Component {
treeData: nextProps.data
});
} else if (nextProps.dataUrl && this.props.dataUrl !== nextProps.dataUrl) {
// noinspection JSIgnoredPromiseFromCall
this.loadData(next.props.dataUrl);
}
}
@ -107,6 +108,7 @@ class TreeTable extends Component {
componentDidMount() {
if (!this.props.data && this.props.dataUrl) {
// noinspection JSIgnoredPromiseFromCall
this.loadData(this.props.dataUrl);
}
@ -229,6 +231,7 @@ class TreeTable extends Component {
const selection = this.destringifyKey(this.tree.getActiveNode().key);
if (selection !== this.props.selection) {
// noinspection JSIgnoredPromiseFromCall
this.onSelectionChanged(selection);
}
}
@ -252,6 +255,7 @@ class TreeTable extends Component {
}
if (updated) {
// noinspection JSIgnoredPromiseFromCall
this.onSelectionChanged(selection);
}
}

View file

@ -125,6 +125,7 @@ export class UntrustedContentHost extends Component {
scheduleRefreshAccessToken() {
this.refreshAccessTokenTimeout = setTimeout(() => {
// noinspection JSIgnoredPromiseFromCall
this.refreshAccessToken();
this.scheduleRefreshAccessToken();
}, 60 * 1000);
@ -136,6 +137,7 @@ export class UntrustedContentHost extends Component {
}
if (!this.state.hasAccessToken) {
// noinspection JSIgnoredPromiseFromCall
this.refreshAccessToken();
}
}

View file

@ -36,6 +36,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}

View file

@ -35,6 +35,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}

View file

@ -27,7 +27,7 @@ import {
withErrorHandling
} from '../../lib/error-handling';
import {DeleteModalDialog} from "../../lib/modals";
import {getImportTypes} from './helpers';
import {getImportLabels} from './helpers';
import {
ImportSource,
inProgress,
@ -62,7 +62,7 @@ export default class CUD extends Component {
this.state = {};
const {importSourceLabels, mappingTypeLabels} = getImportTypes(props.t);
const {importSourceLabels, mappingTypeLabels} = getImportLabels(props.t);
this.importSourceLabels = importSourceLabels;

View file

@ -12,7 +12,7 @@ import {
} from '../../lib/page';
import {withErrorHandling} from '../../lib/error-handling';
import {Table} from '../../lib/table';
import {getImportTypes} from './helpers';
import {getImportLabels} from './helpers';
import {Icon} from "../../lib/bootstrap-components";
import mailtrainConfig from 'mailtrainConfig';
import moment from "moment";
@ -28,7 +28,7 @@ export default class List extends Component {
this.state = {};
const {importSourceLabels, importStatusLabels} = getImportTypes(props.t);
const {importSourceLabels, importStatusLabels} = getImportLabels(props.t);
this.importSourceLabels = importSourceLabels;
this.importStatusLabels = importStatusLabels;
}

View file

@ -13,7 +13,7 @@ import {
withAsyncErrorHandler,
withErrorHandling
} from '../../lib/error-handling';
import {getImportTypes} from './helpers';
import {getImportLabels} from './helpers';
import axios from "../../lib/axios";
import {getUrl} from "../../lib/urls";
import moment from "moment";
@ -32,7 +32,7 @@ export default class Status extends Component {
entity: props.entity
};
const {importSourceLabels, importStatusLabels, runStatusLabels} = getImportTypes(props.t);
const {importSourceLabels, importStatusLabels, runStatusLabels} = getImportLabels(props.t);
this.importSourceLabels = importSourceLabels;
this.importStatusLabels = importStatusLabels;
this.runStatusLabels = runStatusLabels;
@ -69,6 +69,7 @@ export default class Status extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.periodicRefreshTask();
}

View file

@ -17,7 +17,7 @@ import {
withAsyncErrorHandler,
withErrorHandling
} from '../../lib/error-handling';
import {getImportTypes} from './helpers';
import {getImportLabels} from './helpers';
import {
prepFinishedAndNotInProgress,
runInProgress,
@ -46,7 +46,7 @@ export default class Status extends Component {
entity: props.entity
};
const {importSourceLabels, importStatusLabels, runStatusLabels} = getImportTypes(props.t);
const {importSourceLabels, importStatusLabels, runStatusLabels} = getImportLabels(props.t);
this.importSourceLabels = importSourceLabels;
this.importStatusLabels = importStatusLabels;
this.runStatusLabels = runStatusLabels;
@ -77,6 +77,7 @@ export default class Status extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.periodicRefreshTask();
}

View file

@ -3,7 +3,7 @@
import React from 'react';
import {ImportSource, MappingType, ImportStatus, RunStatus} from '../../../../shared/imports';
export function getImportTypes(t) {
export function getImportLabels(t) {
const importSourceLabels = {
[ImportSource.CSV_FILE]: t('CSV file'),

View file

@ -85,6 +85,7 @@ export default class CUD extends Component {
}
if (!this.isEditGlobal()) {
// noinspection JSIgnoredPromiseFromCall
this.loadTreeData();
}
}

View file

@ -35,6 +35,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}

View file

@ -50,6 +50,7 @@ export default class CUD extends Component {
state.formState = state.formState.setIn(['data', 'user_fields', 'value'], '');
if (newVal) {
// noinspection JSIgnoredPromiseFromCall
this.fetchUserFields(newVal);
}
}

View file

@ -51,6 +51,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}

View file

@ -34,6 +34,7 @@ export default class Output extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.loadOutput();
}

View file

@ -35,6 +35,7 @@ export default class View extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.loadContent();
}

View file

@ -37,6 +37,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}

View file

@ -49,6 +49,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}

View file

@ -56,6 +56,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}

View file

@ -40,6 +40,7 @@ export default class List extends Component {
}
componentDidMount() {
// noinspection JSIgnoredPromiseFromCall
this.fetchPermissions();
}