diff --git a/assets/js/src/subscribers/importExport/import-old.jsx b/assets/js/src/subscribers/importExport/import-old.jsx index 2049d5b01a..7cbd07ad10 100644 --- a/assets/js/src/subscribers/importExport/import-old.jsx +++ b/assets/js/src/subscribers/importExport/import-old.jsx @@ -158,269 +158,6 @@ jQuery(document).ready(() => { ? data : new Handlebars.SafeString(Handlebars.Utils.escapeExpression(data)))); - // start array index from 1 - Handlebars.registerHelper('calculate_index', (rawIndex) => { - const index = parseInt(rawIndex, 10); - // display filler data (e.g., ellipsis) if we've reached the maximum number of rows and - // subscribers count is greater than the maximum number of rows we're displaying - if (index === maxRowsToShow && subscribers.subscribersCount > (maxRowsToShow + 1)) { - fillerPosition = index; - return filler; - } - if (index === (subscribers.subscribers.length - 1)) { - // if we're on the last line, show the total count of subscribers data - return subscribers.subscribersCount.toLocaleString(); - } - return index + 1; - }); - - // reduce subscribers object if the total length is greater than the - // maximum number of defined rows - if (subscribers.subscribersCount > (maxRowsToShow + 1)) { - subscribers.subscribers.splice( - maxRowsToShow, subscribers.subscribersCount - (maxRowsToShow + 1), - fillerArray - ); - } - - // filter subscribers' data to detect dates, emails, etc. - function filterSubscribers() { - const subscribersClone = jQuery.extend(true, {}, subscribers); - let preventNextStep = false; - jQuery( - '[data-id="notice_invalidEmail"], [data-id="notice_invalidDate"]' - ) - .remove(); - const displayedColumns = jQuery.map( - jQuery('.mailpoet_subscribers_column_data_match'), (element, elementIndex) => { - const columnId = jQuery(element).data('column-id'); - const validationRule = jQuery(element).data('validation-rule'); - jQuery(element).val(columnId).trigger('change'); - return { - id: columnId, - index: elementIndex, - validationRule, - element, - }; - } - ); - // iterate through the object of mailpoet columns - jQuery.map(window.mailpoetColumns, (column) => { - let firstRowData; - let validationRule; - let testedFormat; - let allowedDateFormats; - // check if the column id matches the selected id of one of the - // subscriber's data columns - const matchedColumn = _.find( - displayedColumns, - data => data.id === column.id - ); - // EMAIL filter: if the first value in the column doesn't have a valid - // email, hide the next button - if (column.id === 'email') { - if (!window.mailpoet_email_regex.test( - subscribersClone.subscribers[0][matchedColumn.index] - ) - ) { - preventNextStep = true; - if (!jQuery('[data-id="notice_invalidEmail"]').length) { - MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidElement'), { - static: true, - scroll: true, - hideClose: true, - id: 'invalidEmail', - }); - } - } else { - MailPoet.Notice.hide('invalidEmail'); - } - } - // DATE filter: if column type is date, check if we can recognize it - if (column.type === 'date' && matchedColumn) { - allowedDateFormats = [ - Moment.ISO_8601, - 'YYYY/MM/DD', - 'MM/DD/YYYY', - 'DD/MM/YYYY', - 'YYYY/MM/DD', - 'YYYY/DD/MM', - 'MM/YYYY', - 'YYYY/MM', - 'YYYY', - ]; - firstRowData = subscribersClone.subscribers[0][matchedColumn.index]; - validationRule = false; - // check if date exists - if (firstRowData.trim() === '') { - subscribersClone.subscribers[0][matchedColumn.index] = `${MailPoet.I18n.t('emptyFirstRowDate')} `; - preventNextStep = true; - } else { - Object.keys(allowedDateFormats).forEach((format) => { - testedFormat = allowedDateFormats[format]; - if (Moment(firstRowData, testedFormat, true).isValid()) { - validationRule = (typeof (testedFormat) === 'function') - ? 'datetime' - : testedFormat; - // set validation on the column element - jQuery(matchedColumn.element).data('validation-rule', validationRule); - return; - } - if (validationRule === 'datetime') { - validationRule = Moment.ISO_8601; - } - }); - } - jQuery.map(subscribersClone.subscribers, (dataSubscribers, index) => { - const data = dataSubscribers; - const rowData = data[matchedColumn.index]; - const date = Moment(rowData, testedFormat, true); - if (index === fillerPosition || rowData.trim() === '') return; - // validate date - if (date.isValid()) { - data[matchedColumn.index] = new Handlebars.SafeString( - `${Handlebars.Utils.escapeExpression(data[matchedColumn.index])}${MailPoet.Date.format(date)} ` - ); - } else { - data[matchedColumn.index] = new Handlebars.SafeString( - `${Handlebars.Utils.escapeExpression(data[matchedColumn.index])}${new Handlebars.SafeString(MailPoet.I18n.t('dateMatchError'))} ` - ); - preventNextStep = true; - } - }); - if (preventNextStep && !jQuery('.mailpoet_invalidDate').length) { - MailPoet.Notice.error(MailPoet.I18n.t('columnContainsInvalidDate'), { - static: true, - scroll: true, - hideClose: true, - id: 'invalidDate', - }); - } - } - }); - // refresh table with susbcribers' data - jQuery('#subscribers_data > table > tbody') - .html(subscribersDataTemplatePartial(subscribersClone)); - - if (preventNextStep) { - toggleNextStepButton('off'); - } else if (!jQuery('.mailpoet_notice.error:visible').length - && segmentSelectElement.val()) { - toggleNextStepButton('on'); - } - } - - // render template - jQuery('#subscribers_data > table').html(subscribersDataTemplate(subscribers)); - - // filter displayed data - jQuery('select.mailpoet_subscribers_column_data_match') - .select2({ - data: window.mailpoetColumnsSelect2, - width: '15em', - templateResult(item) { - return item.name; - }, - templateSelection(item) { - return item.name; - }, - }) - .on('select2:selecting', (selectEvent) => { - const selectElement = selectEvent.currentTarget; - const selectedOptionId = selectEvent.params.args.data.id; - // CREATE CUSTOM FIELD - if (selectedOptionId === 'create') { - selectEvent.preventDefault(); - jQuery(selectElement).select2('close'); - MailPoet.Modal.popup({ - title: MailPoet.I18n.t('addNewField'), - template: jQuery('#form_template_field_form').html(), - }); - jQuery('#form_field_new').parsley().on('form:submit', () => { - // get data - const data = jQuery('#form_field_new').mailpoetSerializeObject(); - - // save custom field - MailPoet.Ajax.post({ - api_version: window.mailpoet_api_version, - endpoint: 'customFields', - action: 'save', - data, - }).done((response) => { - const newColumnData = { - id: response.data.id, - name: response.data.name, - type: response.data.type, - params: response.data.params, - custom: true, - }; - // if this is the first custom column, create an "optgroup" - if (window.mailpoetColumnsSelect2.length === 2) { - window.mailpoetColumnsSelect2.push({ - name: MailPoet.I18n.t('userColumns'), - children: [], - }); - } - window.mailpoetColumnsSelect2[2].children.push(newColumnData); - window.mailpoetColumns.push(newColumnData); - jQuery('select.mailpoet_subscribers_column_data_match') - .each(() => { - jQuery(selectElement) - .html('') - .select2('destroy') - .select2({ - data: window.mailpoetColumnsSelect2, - width: '15em', - templateResult(item) { - return item.name; - }, - templateSelection(item) { - return item.name; - }, - }); - }); - jQuery(selectElement).data('column-id', newColumnData.id); - jQuery(selectElement).data('validation-rule', false); - filterSubscribers(); - // close popup - MailPoet.Modal.close(); - }).fail((response) => { - if (response.errors.length > 0) { - MailPoet.Notice.error( - response.errors.map(error => error.message), - { positionAfter: '#field_name' } - ); - } - }); - return false; - }); - } else { - // CHANGE COLUMN - // check for duplicate values in all select options - jQuery('select.mailpoet_subscribers_column_data_match') - .each(() => { - const element = selectElement; - const elementId = jQuery(element).val(); - // if another column has the same value and it's not an 'ignore', - // prompt user - if (elementId === selectedOptionId - && elementId !== 'ignore') { - if (confirm(`${MailPoet.I18n.t('selectedValueAlreadyMatched')} ${MailPoet.I18n.t('confirmCorrespondingColumn')}`)) { // eslint-disable-line - jQuery(element).data('column-id', 'ignore'); - } else { - selectEvent.preventDefault(); - jQuery(selectElement).select2('close'); - } - } - }); - } - }) - .on('select2:select', (selectEvent) => { - const selectElement = selectEvent.currentTarget; - const selectedOptionId = selectEvent.params.data.id; - jQuery(selectElement).data('column-id', selectedOptionId); - filterSubscribers(); - }); nextStepButton.off().on('click', (event) => { diff --git a/assets/js/src/subscribers/importExport/import/step_data_manipulation.jsx b/assets/js/src/subscribers/importExport/import/step_data_manipulation.jsx index 574476ff4e..24f6905f6b 100644 --- a/assets/js/src/subscribers/importExport/import/step_data_manipulation.jsx +++ b/assets/js/src/subscribers/importExport/import/step_data_manipulation.jsx @@ -4,6 +4,7 @@ import { withRouter } from 'react-router-dom'; import PreviousNextStepButtons from './previous_next_step_buttons.jsx'; import Warnings from './step_data_manipulation/warnings.jsx'; import MatchTable from './step_data_manipulation/match_table.jsx'; +import SelectSegment from './step_data_manipulation/select_segment.jsx'; function getPreviousStepLink(importData, subscribersLimitForValidation) { if (importData === undefined) { @@ -46,6 +47,7 @@ function StepDataManipulation({ subscribers={stepMethodSelectionData.subscribers} header={stepMethodSelectionData.header} /> + { + jQuery('select.mailpoet_subscribers_column_data_match') + .select2({ + data: window.mailpoetColumnsSelect2, + width: '15em', + templateResult(item) { + return item.name; + }, + templateSelection(item) { + return item.name; + }, + }) + .on('select2:selecting', (selectEvent) => { + const selectElement = selectEvent.currentTarget; + const selectedOptionId = selectEvent.params.args.data.id; + // CREATE CUSTOM FIELD + if (selectedOptionId === 'create') { + selectEvent.preventDefault(); + jQuery(selectElement).select2('close'); + MailPoet.Modal.popup({ + title: MailPoet.I18n.t('addNewField'), + template: jQuery('#form_template_field_form').html(), + }); + jQuery('#form_field_new').parsley().on('form:submit', () => { + // get data + const data = jQuery('#form_field_new').mailpoetSerializeObject(); + + // save custom field + MailPoet.Ajax.post({ + api_version: window.mailpoet_api_version, + endpoint: 'customFields', + action: 'save', + data, + }).done((response) => { + const newColumnData = { + id: response.data.id, + name: response.data.name, + type: response.data.type, + params: response.data.params, + custom: true, + }; + // if this is the first custom column, create an "optgroup" + if (window.mailpoetColumnsSelect2.length === 2) { + window.mailpoetColumnsSelect2.push({ + name: MailPoet.I18n.t('userColumns'), + children: [], + }); + } + window.mailpoetColumnsSelect2[2].children.push(newColumnData); + window.mailpoetColumns.push(newColumnData); + jQuery('select.mailpoet_subscribers_column_data_match') + .each(() => { + jQuery(selectElement) + .html('') + .select2('destroy') + .select2({ + data: window.mailpoetColumnsSelect2, + width: '15em', + templateResult(item) { + return item.name; + }, + templateSelection(item) { + return item.name; + }, + }); + }); + jQuery(selectElement).data('column-id', newColumnData.id); + jQuery(selectElement).data('validation-rule', false); + const columnIndex = jQuery(selectElement).data('column-index'); + selectColumnType(newColumnData.id, columnIndex); + // close popup + MailPoet.Modal.close(); + }).fail((response) => { + if (response.errors.length > 0) { + MailPoet.Notice.error( + response.errors.map(error => error.message), + { positionAfter: '#field_name' } + ); + } + }); + return false; + }); + } else { + // CHANGE COLUMN + // check for duplicate values in all select options + jQuery('select.mailpoet_subscribers_column_data_match') + .each(() => { + const element = selectElement; + const elementId = jQuery(element).val(); + // if another column has the same value and it's not an 'ignore', + // prompt user + if (elementId === selectedOptionId + && elementId !== 'ignore') { + if (confirm(`${MailPoet.I18n.t('selectedValueAlreadyMatched')} ${MailPoet.I18n.t('confirmCorrespondingColumn')}`)) { // eslint-disable-line + jQuery(element).data('column-id', 'ignore'); + } else { + selectEvent.preventDefault(); + jQuery(selectElement).select2('close'); + } + } + }); + } + }) + .on('select2:select', (selectEvent) => { + const selectElement = selectEvent.currentTarget; + const selectedOptionId = selectEvent.params.data.id; + jQuery(selectElement).data('column-id', selectedOptionId); + const columnIndex = jQuery(selectElement).data('column-index'); + selectColumnType(selectedOptionId, columnIndex); + }); + jQuery.map( + jQuery('.mailpoet_subscribers_column_data_match'), (element) => { + const columnId = jQuery(element).data('column-id'); + jQuery(element).val(columnId).trigger('change'); + } + ); +}; diff --git a/assets/js/src/subscribers/importExport/import/step_data_manipulation/match_table.jsx b/assets/js/src/subscribers/importExport/import/step_data_manipulation/match_table.jsx index c45a6d127e..a66757c5f4 100644 --- a/assets/js/src/subscribers/importExport/import/step_data_manipulation/match_table.jsx +++ b/assets/js/src/subscribers/importExport/import/step_data_manipulation/match_table.jsx @@ -1,106 +1,120 @@ -import React from 'react'; +import React, { useLayoutEffect } from 'react'; import PropTypes from 'prop-types'; import MailPoet from 'mailpoet'; +import _ from 'underscore'; +import generateColumnSelection from './generate_column_selection.jsx'; import matchColumns from './match_columns.jsx'; const MAX_SUBSCRIBERS_SHOWN = 10; -function ColumnDataMatch({ columnTypes }) { - return ( - - {MailPoet.I18n.t('matchData')} - {/* eslint-disable-next-line react/no-array-index-key */} - {columnTypes.map((columnType, i) => {columnType.column_id})} - - ); -} - -ColumnDataMatch.propTypes = { - columnTypes: PropTypes.arrayOf(PropTypes.shape({ column_id: PropTypes.string })).isRequired, -}; - -function Header({ header }) { - return ( - - - {header.map(headerName => {headerName})} - - ); -} - -Header.propTypes = { - header: PropTypes.arrayOf(PropTypes.string).isRequired, -}; - -function Subscriber({ subscriber, index }) { - return ( - <> - {index} - {/* eslint-disable-next-line react/no-array-index-key */} - {subscriber.map((field, i) => {field})} - - ); -} - -Subscriber.propTypes = { - subscriber: PropTypes.arrayOf(PropTypes.string).isRequired, - index: PropTypes.node.isRequired, -}; - -function Subscribers({ subscribers, subscribersCount }) { - const filler = '. . .'; - const fillerArray = Array(subscribers[0].length).fill(filler); - return ( - <> - { - subscribers - .slice(0, MAX_SUBSCRIBERS_SHOWN) - .map((subscriber, i) => ( - - - - )) - } - { - subscribersCount > MAX_SUBSCRIBERS_SHOWN + 1 - ? - : null - } - { - subscribersCount > MAX_SUBSCRIBERS_SHOWN - ? ( - - - - ) - : null - } - - ); -} - -Subscribers.propTypes = { - subscribersCount: PropTypes.number.isRequired, - subscribers: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)).isRequired, -}; - function MatchTable({ subscribersCount, subscribers, header, }) { - const matchedColumnTypes = matchColumns(subscribers, header); + let selectedColumns = []; + + useLayoutEffect(() => { + generateColumnSelection((selectedOptionId, columnIndex) => { + selectedColumns[columnIndex] = selectedOptionId; + }); + }); + + function ColumnDataMatch() { + const matchedColumnTypes = matchColumns(subscribers, header); + selectedColumns = _.pluck(matchedColumnTypes, 'column_id'); + return ( + + {MailPoet.I18n.t('matchData')} + { + matchedColumnTypes.map((columnType, i) => { + return ( + // eslint-disable-next-line react/no-array-index-key + +