diff --git a/assets/css/src/components/_importExport.scss b/assets/css/src/components/_importExport.scss index 047f0f39eb..c0e67b7528 100644 --- a/assets/css/src/components/_importExport.scss +++ b/assets/css/src/components/_importExport.scss @@ -99,6 +99,10 @@ tr { } } +.mailpoet_subscribers_data_parse_results_details_show { + cursor: pointer; +} + .mailpoet_import_validation_step { display: flex; flex-direction: column; diff --git a/assets/js/src/subscribers/importExport/import-old.jsx b/assets/js/src/subscribers/importExport/import-old.jsx index 9354f279f1..54f0ac0fb0 100644 --- a/assets/js/src/subscribers/importExport/import-old.jsx +++ b/assets/js/src/subscribers/importExport/import-old.jsx @@ -11,97 +11,19 @@ import StepInputValidation from './import/step_input_validation.jsx'; import StepMethodSelection from './import/step_method_selection.jsx'; import StepResults from './import/step_results.jsx'; -const SUBSCRIBERS_LIMIT_FOR_VALIDATION = 500; - -function getDataManipulationPreviousStepLink(importData) { - if (importData === undefined) { - return 'step_method_selection'; - } - if (importData.subscribersCount === undefined) { - return 'step_method_selection'; - } - if (importData.subscribersCount < SUBSCRIBERS_LIMIT_FOR_VALIDATION) { - return 'step_method_selection'; - } - return 'step_input_validation'; -} jQuery(document).ready(() => { - if (!jQuery('#mailpoet_subscribers_import').length) { - return; - } - jQuery('input[name="select_method"]').attr('checked', false); - // configure router - const router = new (Backbone.Router.extend({ - routes: { - '': 'home', - step_method_selection: 'step_method_selection', - step_input_validation: 'step_input_validation', - step_data_manipulation: 'step_data_manipulation', - step_results: 'step_results', - }, - home() { - this.navigate('step_method_selection', { trigger: true }); - }, - }))(); - - function showCurrentStep() { - MailPoet.Notice.hide(); - MailPoet.Modal.loading(false); - jQuery('#mailpoet_subscribers_import > div[id^="step"]').hide(); - jQuery(window.location.hash).show(); - } - - router.on('route:step_method_selection', () => { - showCurrentStep(); - - const container = document.getElementById('step_method_selection'); - - if (container) { - ReactDOM.render( - , - container - ); - } - }); - - router.on('route:step_input_validation', () => { - if (typeof (window.importData.step_method_selection) === 'undefined') { - router.navigate('step_method_selection', { trigger: true }); - return; - } - showCurrentStep(); - const container = document.getElementById('step_input_validation'); - - if (container) { - ReactDOM.render( - , - container - ); - } - }); router.on('route:step_data_manipulation', () => { let fillerPosition; - let importResults; - let duplicates; - if (typeof (window.importData.step_method_selection) === 'undefined') { - router.navigate('step_method_selection', { trigger: true }); - return; - } + // define reusable variables const nextStepButton = jQuery('#next_step'); - const previousStepButton = jQuery('#return_to_previous'); + // create a copy of subscribers object for further manipulation const subscribers = jQuery.extend(true, {}, window.importData.step_method_selection); const subscribersDataTemplate = Handlebars.compile(jQuery('#subscribers_data_template').html()); const subscribersDataTemplatePartial = Handlebars.compile(jQuery('#subscribers_data_template_partial').html()); - const subscribersDataParseResultsTemplate = Handlebars.compile(jQuery('#subscribers_data_parse_results_template').html()); const segmentSelectElement = jQuery('#mailpoet_segments_select'); const maxRowsToShow = 10; const filler = '. . .'; @@ -110,8 +32,6 @@ jQuery(document).ready(() => { const fillerArray = Array(...new Array(subscribers.subscribers[0].length)) .map(String.prototype.valueOf, filler); - showCurrentStep(); - function toggleNextStepButton(condition) { const disabled = 'button-disabled'; if (condition === 'on') { @@ -125,61 +45,6 @@ jQuery(document).ready(() => { jQuery('#subscribers_data_parse_results:visible').html(''); jQuery('#subscribers_data_import_results:visible').hide(); - // show parse statistics if any duplicate/invalid records were found - if (subscribers.invalid.length || subscribers.duplicate.length || subscribers.role.length) { - // count repeating e-mails inside duplicate array and present them in - // 'email (xN)' format - duplicates = {}; - subscribers.duplicate.forEach((subscriberEmail) => { - duplicates[subscriberEmail] = (duplicates[subscriberEmail] || 0) + 1; - }); - subscribers.duplicate = []; - Object.keys(duplicates).forEach((email) => { - if (duplicates[email] > 1) { - subscribers.duplicate.push(`${email} (x${duplicates[email]})`); - } else { - subscribers.duplicate.push(email); - } - }); - - importResults = { - notice: MailPoet.I18n.t('importNoticeSkipped').replace( - '%1$s', - `${subscribers.invalid.length + subscribers.duplicate.length + subscribers.role.length}` - ), - invalid: (subscribers.invalid.length) - ? MailPoet.I18n.t('importNoticeInvalid') - .replace('%1$s', `${subscribers.invalid.length.toLocaleString()}`) - .replace('%2$s', subscribers.invalid.join(', ')) - : null, - duplicate: (subscribers.duplicate.length) - ? MailPoet.I18n.t('importNoticeDuplicate') - .replace('%1$s', `${subscribers.duplicate.length}`) - .replace('%2$s', subscribers.duplicate.join(', ')) - : null, - role: (subscribers.role.length) - ? MailPoet.I18n.t('importNoticeRoleBased') - .replace('%1$s', `${subscribers.role.length.toLocaleString()}`) - .replace('%2$s', subscribers.role.join(', ')) - .replace( - /\[link](.+)\[\/link]/, - '$1' - ) - : null, - }; - jQuery('#subscribers_data_parse_results').html( - subscribersDataParseResultsTemplate(importResults) - ); - } - - jQuery('.mailpoet_subscribers_data_parse_results_details_show') - .click(function detailsClick() { - const details = jQuery('.mailpoet_subscribers_data_parse_results_details'); - details.toggle(); - jQuery(this).text((details.is(':visible')) - ? MailPoet.I18n.t('hideDetails') - : MailPoet.I18n.t('showDetails')); - }); // show available segments if (window.mailpoetSegments.length) { @@ -610,12 +475,6 @@ jQuery(document).ready(() => { filterSubscribers(); }); - previousStepButton.off().on('click', () => { - router.navigate( - getDataManipulationPreviousStepLink(window.importData.step_method_selection), - { trigger: true } - ); - }); nextStepButton.off().on('click', (event) => { const columns = {}; 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 cdf289c2d9..03554fd5d2 100644 --- a/assets/js/src/subscribers/importExport/import/step_data_manipulation.jsx +++ b/assets/js/src/subscribers/importExport/import/step_data_manipulation.jsx @@ -2,6 +2,7 @@ import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import { withRouter } from 'react-router-dom'; import PreviousNextStepButtons from './previous_next_step_buttons.jsx'; +import Warnings from './step_data_manipulation/warnings.jsx'; function getPreviousStepLink(importData, subscribersLimitForValidation) { if (importData === undefined) { @@ -32,6 +33,9 @@ function StepDataManipulation({ return ( <> + ( diff --git a/assets/js/src/subscribers/importExport/import/step_data_manipulation/warnings.jsx b/assets/js/src/subscribers/importExport/import/step_data_manipulation/warnings.jsx index e69de29bb2..762a10df4c 100644 --- a/assets/js/src/subscribers/importExport/import/step_data_manipulation/warnings.jsx +++ b/assets/js/src/subscribers/importExport/import/step_data_manipulation/warnings.jsx @@ -0,0 +1,117 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import MailPoet from 'mailpoet'; +import ReactStringReplace from 'react-string-replace'; +import classNames from 'classnames'; + +const getSingleWarning = (warningTranslation, subscribers) => { + let warning = ''; + if (subscribers.length) { + warning = ReactStringReplace( + warningTranslation.replace('%2$s', subscribers.join(', ')), + '%1$s', + () => {subscribers.length.toLocaleString()} + ); + warning =

{warning}

; + } + return warning; +}; + +const Warnings = ({ + stepMethodSelectionData, +}) => { + const { invalid, duplicate, role } = stepMethodSelectionData; + + const [detailsShown, setDetailsShown] = useState(false); + + const detailClasses = classNames( + 'mailpoet_subscribers_data_parse_results_details', + { mailpoet_hidden: !detailsShown }, + ); + + const invalidWarning = getSingleWarning(MailPoet.I18n.t('importNoticeInvalid'), invalid); + + const duplicateWarning = getSingleWarning(MailPoet.I18n.t('importNoticeDuplicate'), duplicate); + + let roleBasedWarning = ''; + if (role.length) { + roleBasedWarning = ReactStringReplace( + MailPoet.I18n.t('importNoticeRoleBased'), + /(%1\$s|\[link\].*\[\/link\]|%2\$s)/, + (match) => { + if (match === '%1$s') return {role.length.toLocaleString()}; + if (match === '%2$s') return role.join(', '); + return ( + + {match.replace('[link]', '').replace('[/link]', '')} + + ); + } + ); + roleBasedWarning =

{roleBasedWarning}

; + } + + if ( + invalid.length + || duplicate.length + || role.length + ) { + const allWarningsCount = invalid.length + duplicate.length + role.length; + return ( +
+

+ {ReactStringReplace(MailPoet.I18n.t('importNoticeSkipped'), '%1$s', () => ( + {allWarningsCount.toLocaleString()} + ))} + {' '} + setDetailsShown(!detailsShown)} + role="button" + tabIndex={0} + onKeyDown={(event) => { + if ((['keydown', 'keypress'].includes(event.type) && ['Enter', ' '].includes(event.key)) + ) { + event.preventDefault(); + setDetailsShown(!detailsShown); + } + }} + > + {MailPoet.I18n.t('showMoreDetails')} + +

+
+
+ {invalidWarning} + {duplicateWarning} + {roleBasedWarning} +
+
+ ); + } + return null; +}; + +Warnings.propTypes = { + stepMethodSelectionData: PropTypes.shape({ + duplicate: PropTypes.arrayOf(PropTypes.string), + invalid: PropTypes.arrayOf(PropTypes.string), + role: PropTypes.arrayOf(PropTypes.string), + }), +}; + +Warnings.defaultProps = { + stepMethodSelectionData: { + invalid: [], + duplicate: [], + role: [], + }, +}; + +export default Warnings; diff --git a/views/subscribers/importExport/import.html b/views/subscribers/importExport/import.html index 749f3107fb..3e039baf4c 100644 --- a/views/subscribers/importExport/import.html +++ b/views/subscribers/importExport/import.html @@ -105,6 +105,7 @@ 'methodMailChimpVerify': __('Verify'), 'methodMailChimpSelectList': __('Select list(s)'), 'methodMailChimpSelectPlaceholder': _x('Select', 'Verb'), +'showMoreDetails': __('Show more details'), 'pasteLabel': __('Copy and paste your subscribers from Excel/Spreadsheets'), 'pasteDescription': __('This file needs to be formatted in a CSV style (comma-separated-values.) Look at some [link]examples on our support site[/link].'), 'methodSelectionHead': __('How would you like to import subscribers?') diff --git a/views/subscribers/importExport/import/step_data_manipulation.html b/views/subscribers/importExport/import/step_data_manipulation.html index 9a22717042..0bbeed47e4 100644 --- a/views/subscribers/importExport/import/step_data_manipulation.html +++ b/views/subscribers/importExport/import/step_data_manipulation.html @@ -3,23 +3,6 @@ -