'use strict'; import React, {Component} from 'react'; import PropTypes from 'prop-types'; import { Trans } from 'react-i18next'; import { withTranslation } from '../../lib/i18n'; import { NavButton, requiresAuthenticatedUser, Title, withPageHelpers } from '../../lib/page' import { ACEEditor, Button, ButtonRow, Dropdown, Form, FormSendMethod, InputField, TextArea, withForm } from '../../lib/form'; import {withErrorHandling} from '../../lib/error-handling'; import { NamespaceSelect, validateNamespace } from '../../lib/namespace'; import {DeleteModalDialog} from "../../lib/modals"; import mailtrainConfig from 'mailtrainConfig'; import 'brace/mode/javascript'; import 'brace/mode/json'; import 'brace/mode/handlebars'; @withTranslation() @withForm @withPageHelpers @withErrorHandling @requiresAuthenticatedUser export default class CUD extends Component { constructor(props) { super(props); this.state = {}; this.initForm(); } static propTypes = { action: PropTypes.string.isRequired, wizard: PropTypes.string, entity: PropTypes.object } componentDidMount() { if (this.props.entity) { this.getFormValuesFromEntity(this.props.entity); } else { const wizard = this.props.wizard; if (wizard === 'subscribers-all') { this.populateFormValues({ name: '', description: 'Generates a campaign report listing all subscribers along with their statistics.', namespace: mailtrainConfig.user.namespace, mime_type: 'text/html', user_fields: '[\n' + ' {\n' + ' "id": "campaign",\n' + ' "name": "Campaign",\n' + ' "type": "campaign",\n' + ' "minOccurences": 1,\n' + ' "maxOccurences": 1\n' + ' }\n' + ']', js: 'const results = await campaigns.getResults(inputs.campaign, ["*"]);\n' + 'render({ results });', hbs: '

{{title}}

\n' + '\n' + '
\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{#if results}}\n' + ' \n' + ' {{#each results}}\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{/each}}\n' + ' \n' + ' {{/if}}\n' + '
\n' + ' {{#translate}}Email{{/translate}}\n' + ' \n' + ' {{#translate}}Tracker Count{{/translate}}\n' + '
\n' + ' {{email}}\n' + ' \n' + ' {{tracker_count}}\n' + '
\n' + '
' }); } else if (wizard === 'subscribers-grouped') { this.populateFormValues({ name: '', description: 'Generates a campaign report with results are aggregated by some "Country" custom field.', namespace: mailtrainConfig.user.namespace, mime_type: 'text/html', user_fields: '[\n' + ' {\n' + ' "id": "campaign",\n' + ' "name": "Campaign",\n' + ' "type": "campaign",\n' + ' "minOccurences": 1,\n' + ' "maxOccurences": 1\n' + ' }\n' + ']', js: 'const results = await campaigns.getResults(inputs.campaign, ["merge_country"], query =>\n' + ' query.count("* AS count_all")\n' + ' .select(knex.raw("SUM(IF(tracker.count IS NULL, 0, 1)) AS count_opened"))\n' + ' .groupBy("merge_country")\n' + ');\n' + '\n' + 'for (const row of results) {\n' + ' row.percentage = Math.round((row.count_opened / row.count_all) * 100);\n' + '}\n' + '\n' + 'render({ results });', hbs: '

{{title}}

\n' + '\n' + '
\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{#if results}}\n' + ' \n' + ' {{#each results}}\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' {{/each}}\n' + ' \n' + ' {{/if}}\n' + '
\n' + ' {{#translate}}Country{{/translate}}\n' + ' \n' + ' {{#translate}}Opened{{/translate}}\n' + ' \n' + ' {{#translate}}All{{/translate}}\n' + ' \n' + ' {{#translate}}Percentage{{/translate}}\n' + '
\n' + ' {{merge_country}}\n' + ' \n' + ' {{count_opened}}\n' + ' \n' + ' {{count_all}}\n' + ' \n' + ' {{percentage}}%\n' + '
\n' + '
' }); } else if (wizard === 'export-list-csv') { this.populateFormValues({ name: '', description: 'Exports a list as a CSV file.', namespace: mailtrainConfig.user.namespace, mime_type: 'text/csv', user_fields: '[\n' + ' {\n' + ' "id": "list",\n' + ' "name": "List",\n' + ' "type": "list",\n' + ' "minOccurences": 1,\n' + ' "maxOccurences": 1\n' + ' }\n' + ']', js: 'const results = await subscriptions.list(inputs.list.id);\n' + 'render({ results });', hbs: '{{#each results}}\n' + '{{firstName}},{{lastName}},{{email}}\n' + '{{/each}}' }); } else { this.populateFormValues({ name: '', description: '', namespace: mailtrainConfig.user.namespace, mime_type: 'text/html', user_fields: '', js: '', hbs: '' }); } } } localValidateFormValues(state) { const t = this.props.t; if (!state.getIn(['name', 'value'])) { state.setIn(['name', 'error'], t('nameMustNotBeEmpty')); } else { state.setIn(['name', 'error'], null); } if (!state.getIn(['mime_type', 'value'])) { state.setIn(['mime_type', 'error'], t('mimeTypeMustBeSelected')); } else { state.setIn(['mime_type', 'error'], null); } try { const userFields = JSON.parse(state.getIn(['user_fields', 'value'])); state.setIn(['user_fields', 'error'], null); } catch (err) { if (err instanceof SyntaxError) { state.setIn(['user_fields', 'error'], t('syntaxErrorInTheUserFieldsSpecification')); } } validateNamespace(t, state); } async submitAndStay() { await this.formHandleChangedError(async () => await this.doSubmit(true)); } async submitAndLeave() { await this.formHandleChangedError(async () => await this.doSubmit(false)); } async doSubmit(stay) { const t = this.props.t; let sendMethod, url; if (this.props.entity) { sendMethod = FormSendMethod.PUT; url = `rest/report-templates/${this.props.entity.id}` } else { sendMethod = FormSendMethod.POST; url = 'rest/report-templates' } this.disableForm(); this.setFormStatusMessage('info', t('saving')); const submitSuccessful = await this.validateAndSendFormValuesToURL(sendMethod, url); if (submitSuccessful) { if (stay) { await this.getFormValuesFromURL(`rest/report-templates/${this.props.entity.id}`); this.enableForm(); this.setFormStatusMessage('success', t('reportTemplateSaved')); } else { this.navigateToWithFlashMessage('/reports/templates', 'success', t('reportTemplateSaved')); } } else { this.enableForm(); this.setFormStatusMessage('warning', t('thereAreErrorsInTheFormPleaseFixThemAnd')); } } render() { const t = this.props.t; const isEdit = !!this.props.entity; const canDelete = isEdit && this.props.entity.permissions.includes('delete'); return (
{canDelete && } {isEdit ? t('editReportTemplate') : t('createReportTemplate')}