'use strict'; import React, {Component} from 'react'; import PropTypes from 'prop-types'; import { withTranslation } from '../../lib/i18n'; import { NavButton, requiresAuthenticatedUser, Title, withPageHelpers } from '../../lib/page'; import { Button, ButtonRow, CheckBox, Dropdown, Fieldset, Form, FormSendMethod, InputField, StaticField, TextArea, withForm } from '../../lib/form'; import { withAsyncErrorHandler, withErrorHandling } from '../../lib/error-handling'; import {DeleteModalDialog} from "../../lib/modals"; import {getImportLabels} from './helpers'; import { ImportSource, inProgress, MappingType, prepInProgress, runInProgress } from '../../../../shared/imports'; import axios from "../../lib/axios"; import {getUrl} from "../../lib/urls"; import listStyles from "../styles.scss"; import styles from "../../lib/styles.scss"; function truncate(str, len, ending = '...') { str = str.trim(); if (str.length > len) { return str.substring(0, len - ending.length) + ending; } else { return str; } } @withTranslation() @withForm @withPageHelpers @withErrorHandling @requiresAuthenticatedUser export default class CUD extends Component { constructor(props) { super(props); this.state = {}; const {importSourceLabels, mappingTypeLabels} = getImportLabels(props.t); this.importSourceLabels = importSourceLabels; this.importSourceOptions = [ {key: ImportSource.CSV_FILE, label: importSourceLabels[ImportSource.CSV_FILE]}, // {key: ImportSource.LIST, label: importSourceLabels[ImportSource.LIST]} ]; this.mappingOptions = [ {key: MappingType.BASIC_SUBSCRIBE, label: mappingTypeLabels[MappingType.BASIC_SUBSCRIBE]}, {key: MappingType.BASIC_UNSUBSCRIBE, label: mappingTypeLabels[MappingType.BASIC_UNSUBSCRIBE]}, ]; this.refreshTimeoutHandler = ::this.refreshEntity; this.refreshTimeoutId = 0; this.initForm(); } static propTypes = { action: PropTypes.string.isRequired, list: PropTypes.object, fieldsGrouped: PropTypes.array, entity: PropTypes.object } initFromEntity(entity) { this.getFormValuesFromEntity(entity, data => { data.settings = data.settings || {}; const mapping = data.mapping || {}; if (data.source === ImportSource.CSV_FILE) { data.csvFileName = data.settings.csv.originalname; data.csvDelimiter = data.settings.csv.delimiter; } const mappingSettings = mapping.settings || {}; data.mapping_settings_checkEmails = 'checkEmails' in mappingSettings ? !!mappingSettings.checkEmails : true; const mappingFlds = mapping.fields || {}; for (const field of this.props.fieldsGrouped) { if (field.column) { const colMapping = mappingFlds[field.column] || {}; data['mapping_fields_' + field.column + '_column'] = colMapping.column || ''; } else { for (const option of field.settings.options) { const col = field.groupedOptions[option.key].column; const colMapping = mappingFlds[col] || {}; data['mapping_fields_' + col + '_column'] = colMapping.column || ''; } } } const emailMapping = mappingFlds.email || {}; data.mapping_fields_email_column = emailMapping.column || ''; }); if (inProgress(entity.status)) { this.refreshTimeoutId = setTimeout(this.refreshTimeoutHandler, 1000); } } componentDidMount() { if (this.props.entity) { this.initFromEntity(this.props.entity); } else { this.populateFormValues({ name: '', description: '', source: ImportSource.CSV_FILE, csvFileName: '', csvDelimiter: ',', }); } } componentWillUnmount() { clearTimeout(this.refreshTimeoutId); } @withAsyncErrorHandler async refreshEntity() { const resp = await axios.get(getUrl(`rest/imports/${this.props.list.id}/${this.props.entity.id}`)); this.initFromEntity(resp.data); } localValidateFormValues(state) { const t = this.props.t; const isEdit = !!this.props.entity; const source = Number.parseInt(state.getIn(['source', 'value'])); for (const key of state.keys()) { state.setIn([key, 'error'], null); } if (!state.getIn(['name', 'value'])) { state.setIn(['name', 'error'], t('nameMustNotBeEmpty')); } if (!isEdit) { if (source === ImportSource.CSV_FILE) { if (!this.csvFile || this.csvFile.files.length === 0) { state.setIn(['csvFileName', 'error'], t('fileMustBeSelected')); } if (!state.getIn(['csvDelimiter', 'value']).trim()) { state.setIn(['csvDelimiter', 'error'], t('csvDelimiterMustNotBeEmpty')); } } } else { const mappingType = Number.parseInt(state.getIn(['mapping_type', 'value'])); if (mappingType === MappingType.BASIC_SUBSCRIBE || mappingType === MappingType.BASIC_UNSUBSCRIBE) { if (!state.getIn(['mapping_fields_email_column', 'value'])) { state.setIn(['mapping_fields_email_column', 'error'], t('emailMappingHasToBeProvided')); } } } } async submitHandler() { const t = this.props.t; const isEdit = !!this.props.entity; let sendMethod, url; if (this.props.entity) { sendMethod = FormSendMethod.PUT; url = `rest/imports/${this.props.list.id}/${this.props.entity.id}` } else { sendMethod = FormSendMethod.POST; url = `rest/imports/${this.props.list.id}` } try { this.disableForm(); this.setFormStatusMessage('info', t('saving')); const submitResponse = await this.validateAndSendFormValuesToURL(sendMethod, url, data => { data.source = Number.parseInt(data.source); data.settings = {}; const formData = new FormData(); if (!isEdit) { if (data.source === ImportSource.CSV_FILE) { data.settings.csv = {}; formData.append('csvFile', this.csvFile.files[0]); data.settings.csv.delimiter = data.csvDelimiter.trim(); } } else { data.mapping_type = Number.parseInt(data.mapping_type); const mapping = { fields: {}, settings: {} }; if (data.mapping_type === MappingType.BASIC_SUBSCRIBE) { mapping.settings.checkEmails = data.mapping_settings_checkEmails; for (const field of this.props.fieldsGrouped) { if (field.column) { const colMapping = data['mapping_fields_' + field.column + '_column']; if (colMapping) { mapping.fields[field.column] = { column: colMapping }; } } else { for (const option of field.settings.options) { const col = field.groupedOptions[option.key].column; const colMapping = data['mapping_fields_' + col + '_column']; if (colMapping) { mapping.fields[col] = { column: colMapping }; } } } } } if (data.mapping_type === MappingType.BASIC_SUBSCRIBE || data.mapping_type === MappingType.BASIC_UNSUBSCRIBE) { mapping.fields.email = { column: data.mapping_fields_email_column }; } data.mapping = mapping; } for (const key in data) { if (key.startsWith('mapping_fields') || key.startsWith('mapping_settings')) { delete data[key]; } } delete data.csvFile; delete data.csvDelimiter; delete data.sampleRow; formData.append('entity', JSON.stringify(data)); return formData; }); if (submitResponse) { if (!isEdit) { this.navigateTo(`/lists/${this.props.list.id}/imports/${submitResponse}/edit`); } else { this.navigateToWithFlashMessage(`/lists/${this.props.list.id}/imports/${this.props.entity.id}/status`, 'success', t('importSaved')); } } else { this.enableForm(); this.setFormStatusMessage('warning', t('thereAreErrorsInTheFormPleaseFixThemAnd')); } } catch (error) { throw error; } } onFileSelected(evt, x) { if (!this.getFormValue('name') && this.csvFile.files.length > 0) { this.updateFormValue('name', this.csvFile.files[0].name); } this.scheduleFormRevalidate(); } render() { const t = this.props.t; const isEdit = !!this.props.entity; const source = Number.parseInt(this.getFormValue('source')); const status = this.getFormValue('status'); const settings = this.getFormValue('settings'); let settingsEdit = null; if (source === ImportSource.CSV_FILE) { if (isEdit) { settingsEdit =