From 8d6b05a80e37b1534756ab8b29e07f3fe1a13ba2 Mon Sep 17 00:00:00 2001 From: Pavel Dohnal Date: Thu, 11 Apr 2019 14:12:22 +0200 Subject: [PATCH] Upload csv by file in React [MAILPOET-1808] --- .../src/subscribers/importExport/import.jsx | 64 ------------------- .../import/step_method_selection.jsx | 60 +++++------------ .../step_method_selection/method_upload.jsx | 52 ++++++++++++++- .../step_method_selection/process_csv.jsx | 39 +++++++++++ .../select_import_method.jsx | 4 +- .../import/step_data_manipulation.html | 2 +- .../import/step_method_selection.html | 24 ------- 7 files changed, 107 insertions(+), 138 deletions(-) create mode 100644 assets/js/src/subscribers/importExport/import/step_method_selection/process_csv.jsx diff --git a/assets/js/src/subscribers/importExport/import.jsx b/assets/js/src/subscribers/importExport/import.jsx index af34a2cd6a..99ac3fff54 100644 --- a/assets/js/src/subscribers/importExport/import.jsx +++ b/assets/js/src/subscribers/importExport/import.jsx @@ -87,41 +87,6 @@ jQuery(document).ready(() => { const mailChimpListsContainerElement = jQuery('#mailchimp_lists'); const mailChimpProcessButtonElement = jQuery('#method_mailchimp > div.mailpoet_method_process') .find('a.mailpoet_process'); - const uploadElement = jQuery('#file_local'); - const uploadProcessButtonElement = jQuery('#method_file > div.mailpoet_method_process') - .find('a.mailpoet_process'); - - function papaParserConfig(isFile) { - return { - skipEmptyLines: true, - error() { - MailPoet.Notice.hide(); - MailPoet.Notice.error(MailPoet.I18n.t('dataProcessingError')); - }, - complete(CSV) { - const sanitizedData = sanitizeCSVData(CSV.data); - if (sanitizedData) { - // since we assume that the header line is always present, we need - // to detect the header by checking if it contains a valid e-mail address - window.importData.step_method_selection = sanitizedData; - MailPoet.trackEvent('Subscribers import started', { - source: isFile ? 'file upload' : 'pasted data', - 'MailPoet Free version': window.mailpoet_version, - }); - router.navigate( - getMethodSelectionNextStepLink(window.importData.step_method_selection), - { trigger: true } - ); - } else { - MailPoet.Modal.loading(false); - let errorNotice = MailPoet.I18n.t('noValidRecords'); - errorNotice = errorNotice.replace('[link]', MailPoet.I18n.t('csvKBLink')); - errorNotice = errorNotice.replace('[/link]', ''); - MailPoet.Notice.error(errorNotice); - } - }, - }; - } function displayMailChimpLists(data) { const listSelectElement = mailChimpListsContainerElement.find('select'); @@ -152,35 +117,6 @@ jQuery(document).ready(() => { mailChimpListsContainerElement.show(); } - /* - * CSV file - */ - uploadElement.change((event) => { - const ext = event.currentTarget.value.match(/[^.]+$/); - MailPoet.Notice.hide(); - if (ext === null || ext[0].toLowerCase() !== 'csv') { - event.currentTarget.value.val(''); - MailPoet.Notice.error(MailPoet.I18n.t('wrongFileFormat')); - } - - toggleNextStepButton( - uploadProcessButtonElement, - (event.currentTarget.value.trim() !== '') ? 'on' : 'off' - ); - }); - - uploadProcessButtonElement.click(() => { - if (uploadElement.val().trim() !== '') { - // delay loading indicator for 10ms or else it's just too fast :) - MailPoet.Modal.loading(true); - setTimeout(() => { - uploadElement.parse({ - config: papaParserConfig(true), - }); - }, 10); - } - }); - /* * MailChimp */ diff --git a/assets/js/src/subscribers/importExport/import/step_method_selection.jsx b/assets/js/src/subscribers/importExport/import/step_method_selection.jsx index 7720bbde7c..edcd0531b8 100644 --- a/assets/js/src/subscribers/importExport/import/step_method_selection.jsx +++ b/assets/js/src/subscribers/importExport/import/step_method_selection.jsx @@ -1,13 +1,12 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; import MailPoet from 'mailpoet'; -import Papa from 'papaparse'; import PreviousNextStepButtons from './previous_next_step_buttons.jsx'; import SelectMethod from './step_method_selection/select_import_method.jsx'; import MethodPaste from './step_method_selection/method_paste.jsx'; import MethodUpload from './step_method_selection/method_upload.jsx'; import MethodMailChimp from './step_method_selection/method_mailchimp.jsx'; -import sanitizeCSVData from './sanitize_csv_data.jsx'; +import processCsv from './step_method_selection/process_csv.jsx'; const SUBSCRIBERS_LIMIT_FOR_VALIDATION = 500; @@ -39,49 +38,18 @@ function StepMethodSelection({ setCanGoNext(false); }; - function papaParserConfig(isFile) { - return { - skipEmptyLines: true, - error() { - MailPoet.Notice.hide(); - MailPoet.Notice.error(MailPoet.I18n.t('dataProcessingError')); - }, - complete(CSV) { - const sanitizedData = sanitizeCSVData(CSV.data); - if (sanitizedData) { - // since we assume that the header line is always present, we need - // to detect the header by checking if it contains a valid e-mail address - window.importData.step_method_selection = sanitizedData; - MailPoet.trackEvent('Subscribers import started', { - source: isFile ? 'file upload' : 'pasted data', - 'MailPoet Free version': window.mailpoet_version, - }); - navigate( - getNextStepLink(window.importData.step_method_selection), - { trigger: true } - ); - } else { - MailPoet.Modal.loading(false); - let errorNotice = MailPoet.I18n.t('noValidRecords'); - errorNotice = errorNotice.replace('[link]', MailPoet.I18n.t('csvKBLink')); - errorNotice = errorNotice.replace('[/link]', ''); - MailPoet.Notice.error(errorNotice); - } - }, - }; - } - const process = () => { - const pasteSize = encodeURI(csvData).split(/%..|./).length - 1; - MailPoet.Notice.hide(); - // get an approximate size of textarea paste in bytes - if (pasteSize > window.maxPostSizeBytes) { - MailPoet.Notice.error(MailPoet.I18n.t('maxPostSizeNotice')); - return; - } - // delay loading indicator for 10ms or else it's just too fast :) - MailPoet.Modal.loading(true); - Papa.parse(csvData, papaParserConfig(false)); + processCsv(csvData, (sanitizedData) => { + window.importData.step_method_selection = sanitizedData; + MailPoet.trackEvent('Subscribers import started', { + source: method === 'file-method' ? 'file upload' : 'pasted data', + 'MailPoet Free version': window.mailpoet_version, + }); + navigate( + getNextStepLink(window.importData.step_method_selection), + { trigger: true } + ); + }); }; const showNextButton = () => { @@ -112,10 +80,12 @@ function StepMethodSelection({ /> ) : null } - { method === 'csv-method' + { method === 'file-method' ? ( ) : null } diff --git a/assets/js/src/subscribers/importExport/import/step_method_selection/method_upload.jsx b/assets/js/src/subscribers/importExport/import/step_method_selection/method_upload.jsx index a4e378dc85..471f9cb176 100644 --- a/assets/js/src/subscribers/importExport/import/step_method_selection/method_upload.jsx +++ b/assets/js/src/subscribers/importExport/import/step_method_selection/method_upload.jsx @@ -1,21 +1,69 @@ import React from 'react'; import PropTypes from 'prop-types'; import MailPoet from 'mailpoet'; +import ReactStringReplace from 'react-string-replace'; + +const kbLink = 'http://docs.mailpoet.com/article/126-importing-subscribers-with-csv-files' + +const MethodUpload = ({ setInputValid, setInputInvalid, onValueChange }) => { + const onChange = (e) => { + const ext = e.target.value.match(/[^.]+$/); + MailPoet.Notice.hide(); + if (ext === null || ext[0].toLowerCase() !== 'csv') { + setInputInvalid(); + MailPoet.Notice.error(MailPoet.I18n.t('wrongFileFormat')); + onValueChange(''); + } else { + onValueChange(e.target.files[0]); + setInputValid(); + } + }; -const MethodUpload = ({ setInputValid }) => { return (
- MethodUpload + <> + +
); }; MethodUpload.propTypes = { setInputValid: PropTypes.func, + setInputInvalid: PropTypes.func, + onValueChange: PropTypes.func.isRequired, }; MethodUpload.defaultProps = { setInputValid: () => {}, + setInputInvalid: () => {}, }; export default MethodUpload; diff --git a/assets/js/src/subscribers/importExport/import/step_method_selection/process_csv.jsx b/assets/js/src/subscribers/importExport/import/step_method_selection/process_csv.jsx new file mode 100644 index 0000000000..0fd00fce96 --- /dev/null +++ b/assets/js/src/subscribers/importExport/import/step_method_selection/process_csv.jsx @@ -0,0 +1,39 @@ +import Papa from 'papaparse'; +import MailPoet from 'mailpoet'; +import sanitizeCSVData from '../sanitize_csv_data.jsx'; + +function papaParserConfig(done) { + return { + skipEmptyLines: true, + error() { + MailPoet.Notice.hide(); + MailPoet.Notice.error(MailPoet.I18n.t('dataProcessingError')); + }, + complete(CSV) { + const sanitizedData = sanitizeCSVData(CSV.data); + if (sanitizedData) { + done(sanitizedData); + } else { + MailPoet.Modal.loading(false); + let errorNotice = MailPoet.I18n.t('noValidRecords'); + errorNotice = errorNotice.replace('[link]', MailPoet.I18n.t('csvKBLink')); + errorNotice = errorNotice.replace('[/link]', ''); + MailPoet.Notice.error(errorNotice); + } + }, + }; +} + +const process = (csvData, done) => { + const pasteSize = encodeURI(csvData).split(/%..|./).length - 1; + MailPoet.Notice.hide(); + // get an approximate size of textarea paste in bytes + if (pasteSize > window.maxPostSizeBytes) { + MailPoet.Notice.error(MailPoet.I18n.t('maxPostSizeNotice')); + return; + } + MailPoet.Modal.loading(true); + Papa.parse(csvData, papaParserConfig(done)); +}; + +export default process; diff --git a/assets/js/src/subscribers/importExport/import/step_method_selection/select_import_method.jsx b/assets/js/src/subscribers/importExport/import/step_method_selection/select_import_method.jsx index 8601a76dd3..aced3dcca1 100644 --- a/assets/js/src/subscribers/importExport/import/step_method_selection/select_import_method.jsx +++ b/assets/js/src/subscribers/importExport/import/step_method_selection/select_import_method.jsx @@ -28,8 +28,8 @@ function SelectImportMethod({ name="select_method" data-automation-id="import-csv-method" id="import-csv-method" - checked={activeMethod === 'csv-method'} - onChange={() => onMethodChange('csv-method')} + checked={activeMethod === 'file-method'} + onChange={() => onMethodChange('file-method')} /> {MailPoet.I18n.t('methodUpload')} diff --git a/views/subscribers/importExport/import/step_data_manipulation.html b/views/subscribers/importExport/import/step_data_manipulation.html index 4ca2dd4eca..159b1af4c3 100644 --- a/views/subscribers/importExport/import/step_data_manipulation.html +++ b/views/subscribers/importExport/import/step_data_manipulation.html @@ -69,7 +69,7 @@ - + <%= __('Previous step') %>    diff --git a/views/subscribers/importExport/import/step_method_selection.html b/views/subscribers/importExport/import/step_method_selection.html index e4e7128725..ecdf125d14 100644 --- a/views/subscribers/importExport/import/step_method_selection.html +++ b/views/subscribers/importExport/import/step_method_selection.html @@ -1,29 +1,5 @@
- -
- - - - - - - -
- - - -
-
- -
-
-