Paste functionality

[MAILPOET-1808]
This commit is contained in:
Pavel Dohnal
2019-04-11 13:32:21 +02:00
committed by M. Shull
parent a685f1632b
commit bd5d62304d
3 changed files with 69 additions and 82 deletions

View File

@@ -81,17 +81,7 @@ jQuery(document).ready(() => {
);
}
return;
// render process button for each method
const methodProcessContainerTemplate = Handlebars.compile(jQuery('#method_process_template').html());
jQuery('.mailpoet_method_process').html(methodProcessContainerTemplate());
// define reusable variables
const currentStepE = jQuery(window.location.hash);
const methodSelectionElement = jQuery('#select_method');
const pasteInputElement = jQuery('#paste_input');
const pasteInputPlaceholderElement = pasteInputElement.data('placeholder').replace(/\\n/g, '\n');
const pasteProcessButtonElement = jQuery('#method_paste > div.mailpoet_method_process')
.find('a.mailpoet_process');
const mailChimpKeyInputElement = jQuery('#mailchimp_key');
const mailChimpKeyVerifyButtonElement = jQuery('#mailchimp_key_verify');
const mailChimpListsContainerElement = jQuery('#mailchimp_lists');
@@ -101,35 +91,6 @@ jQuery(document).ready(() => {
const uploadProcessButtonElement = jQuery('#method_file > div.mailpoet_method_process')
.find('a.mailpoet_process');
// define method change behavior
methodSelectionElement.change(() => {
const availableMethods = jQuery(':radio[name="select_method"]');
const selectedMethod = availableMethods.index(availableMethods.filter(':checked'));
MailPoet.Notice.hide();
// hide all methods
currentStepE.find('.inside')
.children('div[id^="method_"]')
.hide();
// show selected method
currentStepE.find('.inside')
.children(`div[id^="method_"]:eq(${selectedMethod})`)
.show()
.find('table')
.show();
});
// start step 1
showCurrentStep();
function toggleNextStepButton(element, condition) {
const disabled = 'button-disabled';
if (condition === 'on') {
element.closest('table a').removeClass(disabled);
return;
}
element.closest('table a').addClass(disabled);
}
function papaParserConfig(isFile) {
return {
skipEmptyLines: true,
@@ -191,47 +152,6 @@ jQuery(document).ready(() => {
mailChimpListsContainerElement.show();
}
/*
* Paste
*/
pasteInputElement
.attr('value', pasteInputPlaceholderElement).css('color', '#999')
.focus((event) => {
if (jQuery(event.currentTarget).val() === pasteInputPlaceholderElement) {
jQuery(event.currentTarget).attr('value', '').css('color', '#222');
}
})
.blur((event) => {
if (jQuery(event.currentTarget).val() === '') {
jQuery(event.currentTarget).attr('value', pasteInputPlaceholderElement).css('color', '#999');
}
toggleNextStepButton(
pasteProcessButtonElement,
(event.currentTarget.value.trim() !== '') ? 'on' : 'off'
);
})
.keyup((event) => {
toggleNextStepButton(
pasteProcessButtonElement,
(event.currentTarget.value.trim() !== '') ? 'on' : 'off'
);
});
pasteProcessButtonElement.click(() => {
const pasteSize = encodeURI(pasteInputElement.val()).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);
setTimeout(() => {
Papa.parse(pasteInputElement.val(), papaParserConfig(false));
}, 10);
});
/*
* CSV file
*/

View File

@@ -1,16 +1,35 @@
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';
const SUBSCRIBERS_LIMIT_FOR_VALIDATION = 500;
const getNextStepLink = (importData) => {
if (importData === undefined) {
return 'step_data_manipulation';
}
if (importData.subscribersCount === undefined) {
return 'step_data_manipulation';
}
if (importData.subscribersCount < SUBSCRIBERS_LIMIT_FOR_VALIDATION) {
return 'step_data_manipulation';
}
return 'step_input_validation';
};
function StepMethodSelection({
navigate,
}) {
const [canGoNext, setCanGoNext] = useState(false);
const [method, setMethod] = useState(undefined);
const [csvData, setCsvData] = useState('');
const setInputValid = () => {
setCanGoNext(true);
@@ -20,13 +39,58 @@ 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]', '</a>');
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));
};
const showNextButton = () => {
if (method) {
return (
<PreviousNextStepButtons
canGoNext={canGoNext}
hidePrevious
onNextAction={() => navigate('step_data_manipulation', { trigger: true })}
onNextAction={process}
/>
);
}
@@ -42,6 +106,7 @@ function StepMethodSelection({
{ method === 'paste-method'
? (
<MethodPaste
onValueChange={setCsvData}
setInputValid={setInputValid}
setInputInvalid={setInputInValid}
/>

View File

@@ -7,13 +7,14 @@ const kbLink = 'http://docs.mailpoet.com/article/126-importing-subscribers-with-
const placeholder = 'Email, First Name, Last Name\njohn@doe.com, John, Doe\nmary@smith.com, Mary, Smith\njohnny@walker.com, Johnny, Walker';
const MethodPaste = ({ setInputValid, setInputInvalid }) => {
const MethodPaste = ({ setInputValid, setInputInvalid, onValueChange }) => {
const onChange = (e) => {
if (e.target.value) {
setInputValid();
} else {
setInputInvalid();
}
onValueChange(e.target.value);
};
return (
@@ -53,6 +54,7 @@ const MethodPaste = ({ setInputValid, setInputInvalid }) => {
MethodPaste.propTypes = {
setInputValid: PropTypes.func,
setInputInvalid: PropTypes.func,
onValueChange: PropTypes.func.isRequired,
};
MethodPaste.defaultProps = {