- Updates Migrator with new column for Segments
- Updates Segmnets tests - Updates MailPoet's Notice.js with additional options - Updates Import's router, WP menu bootstrap logic, client- and server-side logic
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -47,6 +47,8 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
type: 'success',
|
||||
message: '',
|
||||
static: false,
|
||||
hideClose: false,
|
||||
addCustomClass: false,
|
||||
scroll: false,
|
||||
timeout: 2000,
|
||||
onOpen: null,
|
||||
@ -60,6 +62,9 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
// clone element
|
||||
this.element = jQuery('#mailpoet_notice_'+this.options.type).clone();
|
||||
|
||||
// add custom identifier class to the element
|
||||
if (this.options.addCustomClass) this.element.addClass('mailpoet_'+this.options.addCustomClass);
|
||||
|
||||
// remove id from clone
|
||||
this.element.removeAttr('id');
|
||||
|
||||
@ -73,7 +78,6 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
}
|
||||
|
||||
// listen to remove event
|
||||
var element = this.element;
|
||||
jQuery(this.element).on('close', function() {
|
||||
jQuery(this).fadeOut(200, function() {
|
||||
// on close callback
|
||||
@ -148,7 +152,7 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
// if the notice is not static, it has to disappear after a timeout
|
||||
if(this.options.static === false) {
|
||||
this.element.delay(this.options.timeout).trigger('close');
|
||||
} else {
|
||||
} else if (this.options.hideClose === false) {
|
||||
this.element.append('<a href="javascript:;" class="mailpoet_notice_close"><span class="dashicons dashicons-dismiss"></span></a>');
|
||||
this.element.find('.mailpoet_notice_close').on('click', function() {
|
||||
jQuery(this).trigger('close');
|
||||
@ -163,6 +167,14 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
hide: function(all) {
|
||||
if(all !== undefined && all === true) {
|
||||
jQuery('.mailpoet_notice:not([id])').trigger('close');
|
||||
} else if (all !== undefined && jQuery.isArray(all)) {
|
||||
for (var noticeClass in all) {
|
||||
jQuery('.mailpoet_'+all[noticeClass])
|
||||
.trigger('close');
|
||||
}
|
||||
} if (all !== undefined) {
|
||||
jQuery('.mailpoet_'+noticeClass)
|
||||
.trigger('close');
|
||||
} else {
|
||||
jQuery('.mailpoet_notice.updated:not([id]), .mailpoet_notice.error:not([id])')
|
||||
.trigger('close');
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
namespace MailPoet\Config;
|
||||
use MailPoet\Import\Import;
|
||||
use \MailPoet\Import\BootstrapMenu;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Form;
|
||||
@ -214,13 +214,14 @@ class Menu {
|
||||
}
|
||||
|
||||
function import() {
|
||||
$import = new Import();
|
||||
$data = $import->bootstrapImportMenu();
|
||||
$import = new BootstrapMenu();
|
||||
$data = $import->bootstrap();
|
||||
echo $this->renderer->render('import.html', $data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function formEditor() {
|
||||
$id = (isset($_GET['id']) ? (int)$_GET['id'] : 0);
|
||||
$form = Form::findOne($id);
|
||||
|
106
lib/Import/BootstrapMenu.php
Normal file
106
lib/Import/BootstrapMenu.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php namespace MailPoet\Import;
|
||||
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
class BootstrapMenu {
|
||||
|
||||
function __construct() {
|
||||
$this->subscriberFields = $this->getSubscriberFields();
|
||||
$this->subscriberCustomFields = $this->getSubscriberCustomFields();
|
||||
$this->segments = $this->getSegments();
|
||||
}
|
||||
|
||||
function getSubscriberFields() {
|
||||
return array(
|
||||
'subscriber_email' => __("Email"),
|
||||
'subscriber_firstname' => __("First name"),
|
||||
'subscriber_lastname' => __("Last name"),
|
||||
/* 'subscriber_confirmed_ip' => __("IP address"),
|
||||
'subscriber_confirmed_at' => __("Subscription date"),*/
|
||||
'subscriber_state' => __("Status")
|
||||
);
|
||||
}
|
||||
|
||||
function getSegments() {
|
||||
return Segment::findArray();
|
||||
}
|
||||
|
||||
function getSubscriberCustomFields() {
|
||||
return CustomField::findArray();
|
||||
}
|
||||
|
||||
function formatSubscriberFields() {
|
||||
return array_map(function ($fieldId, $fieldName) {
|
||||
return array(
|
||||
'id' => $fieldId,
|
||||
'name' => $fieldName,
|
||||
'type' => ($fieldId === 'subscriber_confirmed_at') ? 'date' : null,
|
||||
'custom' => false
|
||||
);
|
||||
}, array_keys($this->subscriberFields), $this->subscriberFields);
|
||||
}
|
||||
|
||||
function formatSubscriberCustomFields() {
|
||||
return array_map(function ($field) {
|
||||
return array(
|
||||
'id' => $field['id'],
|
||||
'name' => $field['name'],
|
||||
'label' => $field['name'],
|
||||
'type' => $field['type'],
|
||||
'custom' => true
|
||||
);
|
||||
}, $this->subscriberCustomFields);
|
||||
}
|
||||
|
||||
function formatSubscriberFieldsSelect2() {
|
||||
$select2Fields = array(
|
||||
array(
|
||||
'name' => __("Actions"),
|
||||
'children' => array(
|
||||
array(
|
||||
'id' => 'ignore',
|
||||
'name' => __("Ignore column..."),
|
||||
),
|
||||
array(
|
||||
'id' => 'create',
|
||||
'name' => __("Create new column...")
|
||||
),
|
||||
)
|
||||
),
|
||||
array(
|
||||
'name' => __("System columns"),
|
||||
'children' => $this->formatSubscriberFields()
|
||||
)
|
||||
);
|
||||
if($this->subscriberCustomFields) {
|
||||
array_push($select2Fields, array(
|
||||
'name' => __("User columns"),
|
||||
'children' => $this->formatSubscriberCustomFields()
|
||||
));
|
||||
}
|
||||
return $select2Fields;
|
||||
}
|
||||
|
||||
function bootstrap() {
|
||||
$data['segments'] = array_map(function ($segment) {
|
||||
return array(
|
||||
'id' => $segment['id'],
|
||||
'name' => $segment['name'],
|
||||
);
|
||||
}, $this->getSegments());
|
||||
|
||||
$data['subscriberFields'] = array_merge(
|
||||
$this->formatSubscriberFields(),
|
||||
$this->formatSubscriberCustomFields()
|
||||
);
|
||||
|
||||
$data['subscriberFieldsSelect2'] = $this->formatSubscriberFieldsSelect2();
|
||||
|
||||
$data = array_map('json_encode', $data);
|
||||
$data['maxPostSizeBytes'] = Helpers::getMaxPostSize('bytes');
|
||||
$data['maxPostSize'] = Helpers::getMaxPostSize();
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -1,106 +1,71 @@
|
||||
<?php namespace MailPoet\Import;
|
||||
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
class Import {
|
||||
|
||||
function getSegments() {
|
||||
return Segment::findArray();
|
||||
public function __construct($data) {
|
||||
$this->subscribersData = $data['subscribers'];
|
||||
$this->segments = $data['segments'];
|
||||
$this->updateSubscribers = $data['updateSubscribers'];
|
||||
$this->subscriberFields = $this->getSubscriberFields();
|
||||
$this->subscriberCustomFields = $this->getCustomSubscriberFields();
|
||||
$this->currentTime = time();
|
||||
$this->profilerStart = microtime(true);
|
||||
}
|
||||
|
||||
function getSubscriberCustomFields() {
|
||||
return CustomField::findArray();
|
||||
function process() {
|
||||
// :)
|
||||
return array(
|
||||
'status' => 'success',
|
||||
'count' => count($this->subscribersData['subscriber_email'])
|
||||
);
|
||||
if(in_array('subscriber_status', $subscriberFields)) {
|
||||
$this->subscribersData['subscriber_state'] = $this->filterSubscriberState(
|
||||
$this->subscribersData['subscriber_state']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getSubscriberFields() {
|
||||
return array(
|
||||
'subscriber_email' => __("Email"),
|
||||
'subscriber_firstname' => __("First name"),
|
||||
'subscriber_lastname' => __("Last name"),
|
||||
'subscriber_confirmed_ip' => __("IP address"),
|
||||
'subscriber_confirmed_at' => __("Subscription date"),
|
||||
'subscriber_state' => __("Status")
|
||||
);
|
||||
}
|
||||
|
||||
function formatSubscriberFields($subscriberFields) {
|
||||
return array_map(function ($fieldId, $fieldName) {
|
||||
return array(
|
||||
'id' => $fieldId,
|
||||
'name' => $fieldName,
|
||||
'type' => ($fieldId === 'subscriber_confirmed_at') ? 'date' : null,
|
||||
'custom' => false
|
||||
);
|
||||
}, array_keys($subscriberFields), $subscriberFields);
|
||||
}
|
||||
|
||||
function formatSubscriberCustomFields($subscriberCustomFields) {
|
||||
return array_map(function ($field) {
|
||||
return array(
|
||||
'id' => $field['id'],
|
||||
'name' => $field['name'],
|
||||
'label' => $field['name'],
|
||||
'type' => $field['type'],
|
||||
'custom' => true
|
||||
);
|
||||
}, $subscriberCustomFields);
|
||||
if(!is_int($field)) return $field;
|
||||
}, array_keys($this->subscribersData));
|
||||
}
|
||||
|
||||
function formatSelect2Fields($subscriberFields, $subscriberCustomFields) {
|
||||
$data = array(
|
||||
array(
|
||||
'name' => __("Actions"),
|
||||
'children' => array(
|
||||
array(
|
||||
'id' => 'ignore',
|
||||
'name' => __("Ignore column..."),
|
||||
),
|
||||
array(
|
||||
'id' => 'create',
|
||||
'name' => __("Create new column...")
|
||||
),
|
||||
)
|
||||
function getCustomSubscriberFields() {
|
||||
return array_map(function ($field) {
|
||||
if(is_int($field)) return $field;
|
||||
}, array_keys($this->subscribersData));
|
||||
}
|
||||
|
||||
function filterSubscriberState($data) {
|
||||
$states = array(
|
||||
'subscribed' => array(
|
||||
'subscribed',
|
||||
'confirmed',
|
||||
1,
|
||||
'1',
|
||||
'true'
|
||||
),
|
||||
array(
|
||||
'name' => __("System columns"),
|
||||
'children' => $subscriberFields
|
||||
'unsubscribed' => array(
|
||||
'unsubscribed',
|
||||
-1,
|
||||
'-1',
|
||||
'false'
|
||||
)
|
||||
);
|
||||
|
||||
if($subscriberCustomFields) {
|
||||
array_push($data, array(
|
||||
'name' => __("User columns"),
|
||||
'children' => $subscriberCustomFields
|
||||
));
|
||||
}
|
||||
return $data;
|
||||
return array_map(function ($state) use ($states) {
|
||||
if(in_array(strtolower($state), $states['subscribed'])) {
|
||||
return 1;
|
||||
}
|
||||
if(in_array(strtolower($state), $states['unsubscribed'])) {
|
||||
return -1;
|
||||
}
|
||||
return 1; // make "subscribed" a default state
|
||||
}, $data);
|
||||
}
|
||||
|
||||
function bootstrapImportMenu() {
|
||||
$data['segments'] = array_map(function ($segment) {
|
||||
return array(
|
||||
'id' => $segment['id'],
|
||||
'name' => $segment['name'],
|
||||
'text' => $segment['name']
|
||||
);
|
||||
}, $this->getSegments());
|
||||
|
||||
$data['subscriberFields'] = $this->formatSubscriberFields(
|
||||
$this->getSubscriberFields()
|
||||
);
|
||||
|
||||
$data['subscriberCustomFields'] = $this->formatSubscriberCustomFields(
|
||||
$this->getSubscriberCustomFields()
|
||||
);
|
||||
|
||||
$data['select2Fields'] = $this->formatSelect2Fields(
|
||||
$data['subscriberFields'],
|
||||
$data['subscriberCustomFields']
|
||||
);
|
||||
|
||||
$data['maximumParseSize'] = Helpers::get_maximum_post_size();
|
||||
return array_map('json_encode', $data);
|
||||
function timeExecution() {
|
||||
$profilerEnd = microtime(true);
|
||||
return ($profilerEnd - $this->profilerStart) / 60;
|
||||
}
|
||||
}
|
155
lib/Import/MailChimp.php
Normal file
155
lib/Import/MailChimp.php
Normal file
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
namespace MailPoet\Import;
|
||||
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
class MailChimp {
|
||||
public function __construct($APIKey, $lists = false) {
|
||||
$this->APIKey = $this->getAPIKey($APIKey);
|
||||
$this->maxPostSize = Helpers::getMaxPostSize('bytes');
|
||||
$this->dataCenter = $this->getDataCenter();
|
||||
$this->lists = $lists;
|
||||
$this->listsURL = 'https://%s.api.mailchimp.com/2.0/lists/list?apikey=%s';
|
||||
$this->exportURL = 'https://%s.api.mailchimp.com/export/1.0/list/?apikey=%s&id=%s';
|
||||
}
|
||||
|
||||
public function getLists() {
|
||||
if(!$this->APIKey || !$this->dataCenter) {
|
||||
return $this->processError('API');
|
||||
}
|
||||
|
||||
$connection = @fopen(sprintf($this->listsURL, $this->dataCenter, $this->APIKey), 'r');
|
||||
|
||||
if(!$connection) {
|
||||
return $this->processError('connection');
|
||||
} else {
|
||||
$response = '';
|
||||
while (!feof($connection)) {
|
||||
$buffer = fgets($connection, 4096);
|
||||
if(trim($buffer) !== '') {
|
||||
$response .= $buffer;
|
||||
}
|
||||
}
|
||||
fclose($connection);
|
||||
}
|
||||
|
||||
$response = json_decode($response);
|
||||
|
||||
if(!$response) {
|
||||
return $this->processError('API');
|
||||
}
|
||||
|
||||
foreach ($response->data as $list) {
|
||||
$lists[] = array(
|
||||
'id' => $list->id,
|
||||
'name' => $list->name
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'status' => 'success',
|
||||
'data' => $lists
|
||||
);
|
||||
}
|
||||
|
||||
public function getSubscribers() {
|
||||
if(!$this->APIKey || !$this->dataCenter) {
|
||||
return $this->processError('API');
|
||||
}
|
||||
|
||||
if(!is_array($this->lists)) {
|
||||
return $this->processError('lists');
|
||||
}
|
||||
|
||||
$bytesFetched = 0;
|
||||
foreach ($this->lists as $list) {
|
||||
$url = sprintf($this->exportURL, $this->dataCenter, $this->APIKey, $list);
|
||||
$connection = @fopen($url, 'r');
|
||||
if(!$connection) {
|
||||
return $this->processError('connection');
|
||||
} else {
|
||||
$i = 0;
|
||||
$header = array();
|
||||
while (!feof($connection)) {
|
||||
$buffer = fgets($connection, 4096);
|
||||
if(trim($buffer) !== '') {
|
||||
$obj = json_decode($buffer);
|
||||
if($i === 0) {
|
||||
$header = $obj;
|
||||
if(is_object($header) && isset($header->error)) {
|
||||
return $this->processError('API');
|
||||
}
|
||||
if(!isset($headerHash)) {
|
||||
$headerHash = md5(implode(',', $header));
|
||||
} else {
|
||||
if(md5(implode(',', $header) !== $headerHash)) {
|
||||
return $this->processError('headers');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$subscribers[] = $obj;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
$bytesFetched += strlen($buffer);
|
||||
if($bytesFetched > $this->maxPostSize) {
|
||||
return $this->processError('size');
|
||||
|
||||
}
|
||||
}
|
||||
fclose($connection);
|
||||
}
|
||||
}
|
||||
|
||||
if(!count($subscribers)) {
|
||||
return $this->processError('subscribers');
|
||||
|
||||
}
|
||||
|
||||
return array(
|
||||
'status' => 'success',
|
||||
'data' => $subscribers,
|
||||
'invalid' => false,
|
||||
'duplicate' => false,
|
||||
'header' => $header,
|
||||
'count' => count($subscribers)
|
||||
);
|
||||
}
|
||||
|
||||
private function getDataCenter() {
|
||||
// double parantheses: http://phpsadness.com/sad/51
|
||||
return ($this->APIKey) ? end((explode('-', $this->APIKey))) : false;
|
||||
}
|
||||
|
||||
private function getAPIKey($APIKey) {
|
||||
return (preg_match('/[a-zA-Z0-9]{32}-[a-zA-Z0-9]{3,}/', $APIKey)) ? $APIKey : false;
|
||||
}
|
||||
|
||||
private function processError($error) {
|
||||
switch ($error) {
|
||||
case 'API':
|
||||
$message = __('Invalid API key.');
|
||||
break;
|
||||
case 'connection':
|
||||
$message = __('Could not connect to your MailChimp account.');
|
||||
break;
|
||||
case 'headers':
|
||||
$message = __('The selected lists do not have matching columns (headers).');
|
||||
break;
|
||||
case 'size':
|
||||
$message = __('Information received from MailChimp is too large for processing. Please limit the number of lists.');
|
||||
break;
|
||||
case 'subscribers':
|
||||
$message = __('Did not find any active subscribers.');
|
||||
break;
|
||||
case 'lists':
|
||||
$message = __('Did not find any valid lists');
|
||||
break;
|
||||
}
|
||||
return array(
|
||||
'status' => 'error',
|
||||
'message' => $message
|
||||
);
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Import\MailChimp;
|
||||
use MailPoet\Models\CustomField;
|
||||
use MailPoet\Models\Segment;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -15,4 +17,40 @@ class Import {
|
||||
$mailChimp = new MailChimp($data['api_key'], $data['lists']);
|
||||
wp_send_json($mailChimp->getSubscribers());
|
||||
}
|
||||
|
||||
function addSegment($data) {
|
||||
$segment = Segment::createOrUpdate($data, $returnObject = true);
|
||||
wp_send_json(
|
||||
(!is_array($segment)) ?
|
||||
array(
|
||||
'status' => 'error',
|
||||
'message' => $segment
|
||||
) :
|
||||
array(
|
||||
'status' => 'success',
|
||||
'segment' => $segment
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function addCustomField($data) {
|
||||
$customField = CustomField::create();
|
||||
$customField->hydrate($data);
|
||||
$result = $customField->save();
|
||||
wp_send_json(
|
||||
(!$result) ?
|
||||
array(
|
||||
'status' => 'error'
|
||||
) :
|
||||
array(
|
||||
'status' => 'success',
|
||||
'customField' => $customField->asArray()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function process($data) {
|
||||
$import = new \MailPoet\Import\Import(json_decode($data, true));
|
||||
wp_send_json($import->process());
|
||||
}
|
||||
}
|
@ -73,29 +73,23 @@ class Helpers {
|
||||
return $jqueryui_format;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine maximum post size in bytes
|
||||
*/
|
||||
static function get_maximum_post_size() {
|
||||
$maximum_post_size = ini_get('post_max_size');
|
||||
$maximum_post_size_bytes = (int) $maximum_post_size;
|
||||
$unit = strtolower($maximum_post_size[strlen($maximum_post_size) - 1]);
|
||||
static function getMaxPostSize($bytes = false) {
|
||||
$maxPostSize = ini_get('post_max_size');
|
||||
if (!$bytes) return $maxPostSize;
|
||||
$maxPostSizeBytes = (int) $maxPostSize;
|
||||
$unit = strtolower($maxPostSize[strlen($maxPostSize) - 1]);
|
||||
switch ($unit) {
|
||||
case 'g':
|
||||
$maximum_post_size_bytes *= 1024;
|
||||
case 'm':
|
||||
$maximum_post_size_bytes *= 1024;
|
||||
case 'k':
|
||||
$maximum_post_size_bytes *= 1024;
|
||||
case 'g':
|
||||
$maxPostSizeBytes *= 1024;
|
||||
case 'm':
|
||||
$maxPostSizeBytes *= 1024;
|
||||
case 'k':
|
||||
$maxPostSizeBytes *= 1024;
|
||||
}
|
||||
|
||||
return $maximum_post_size_bytes;
|
||||
return $maxPostSizeBytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flatten multidimensional array
|
||||
*/
|
||||
static function flatten_array($array) {
|
||||
static function flattenArray($array) {
|
||||
return call_user_func_array(
|
||||
'array_merge_recursive', array_map('array_values', $array)
|
||||
);
|
||||
|
@ -11,6 +11,7 @@ class SegmentCest {
|
||||
$this->before_time = time();
|
||||
$this->data = array(
|
||||
'name' => 'some name',
|
||||
'description' => 'some description'
|
||||
);
|
||||
|
||||
$this->segment = Segment::create();
|
||||
@ -22,6 +23,20 @@ class SegmentCest {
|
||||
expect($this->saved)->equals(true);
|
||||
}
|
||||
|
||||
function itCanHaveName() {
|
||||
expect($this->segment->name)->equals($this->data['name']);
|
||||
}
|
||||
|
||||
function nameMustBeUnique() {
|
||||
$segment = Segment::create();
|
||||
$segment->hydrate($this->data);
|
||||
expect($segment->save())->contains('Duplicate');
|
||||
}
|
||||
|
||||
function itCanHaveDescription() {
|
||||
expect($this->segment->description)->equals($this->data['description']);
|
||||
}
|
||||
|
||||
function itHasToBeValid() {
|
||||
expect($this->saved)->equals(true);
|
||||
$empty_model = Segment::create();
|
||||
|
@ -5,8 +5,8 @@
|
||||
<h2 class="title"><%= __('Import') %></h2>
|
||||
<!-- STEP 1: method selection -->
|
||||
<% include 'import/step1.html' %>
|
||||
<!-- STEP 2: subscriber manipulation -->
|
||||
|
||||
<!-- STEP 2: subscriber data manipulation -->
|
||||
<% include 'import/step2.html' %>
|
||||
<!-- STEP 3: results -->
|
||||
</div>
|
||||
|
||||
@ -15,17 +15,53 @@
|
||||
<%= localize({
|
||||
'noMailChimpLists': __('No active lists found.'),
|
||||
'serverError': __('Server error:'),
|
||||
'select': __('Select')
|
||||
'select': __('Select'),
|
||||
'maxPostSizeNotice': __('Your CSV is over %s, and too big to process. Please split the file in two, or more.')|replace({'%s': maxPostSize}),
|
||||
'dataProcessingError': __("Your data couldn't be processed. Please make sure it is in the proper format."),
|
||||
'noValidRecords': __('No valid records were found.'),
|
||||
'importNoticeSkipped': __('%1$s records were skipped due to problems.'),
|
||||
'importNoticeInvalid': __('%1$s emails are not valid : %2$s.'),
|
||||
'importNoticeDuplicate': __('%1$s emails appear more than once in your file : %2$s.'),
|
||||
'hideDetails': __('Hide details.'),
|
||||
'showDetails': __('Show more details.'),
|
||||
'listSelectionRequired': __('You need to select at least one list.'),
|
||||
'addNewList': __('Add new list'),
|
||||
'addNewColumuserColumnsn': __('Add new list'),
|
||||
'userColumns': __('User columns'),
|
||||
'selectedValueAlreadyMatched': __('The selected value is already matched to another column.'),
|
||||
'confirmCorrespondingColumn': __('Can you confirm that this column is corresponding to that field?'),
|
||||
'columnContainInvalidElement': __('One of the columns contains an invalid email. Please fix before continuing.'),
|
||||
'january': __('January'),
|
||||
'february': __('February'),
|
||||
'march': __('March'),
|
||||
'april': __('April'),
|
||||
'may': __('May'),
|
||||
'june': __('June'),
|
||||
'july': __('July'),
|
||||
'august': __('August'),
|
||||
'september': __('September'),
|
||||
'october': __('October'),
|
||||
'november': __('November'),
|
||||
'december': __('December'),
|
||||
'noDateFieldMatch': __("Do not match as a 'date field' if most of the rows for that column return the same error."),
|
||||
'emptyDate': __('Date cannot be empty'),
|
||||
'verifyDateMatch': __('Verify that the date in blue matches the original one'),
|
||||
'pm': __('pm'),
|
||||
'am': __('am'),
|
||||
'dateMatchError': __('Error matching date.'),
|
||||
'columnContainsInvalidDate': __('One of the columns contains an invalid date. Please fix before continuing.'),
|
||||
'listCreateError': __('Error adding a new segment:'),
|
||||
'columnContainsInvalidElement': __('One of the columns contains an invalid email. Please fix before continuing.'),
|
||||
'customFieldCreateError': __('Custom field could not be created.')
|
||||
}) %>
|
||||
|
||||
<script type="text/javascript">
|
||||
var
|
||||
maximum_parse_size = <%= maximumParseSize %>,
|
||||
maximum_parse_notice = "<%= __('Your CSV is over %s, and too big to process. Please split the file in two, or more.')|replace({'%s': maximumParseSize}) %>",
|
||||
data_container = {},
|
||||
mailpoet_columns_select2 = <%= select2Fields|raw %>,
|
||||
maxPostSize = '<%= maxPostSize %>',
|
||||
importData = {},
|
||||
mailpoet_columns_select2 = <%= subscriberFieldsSelect2|raw %>,
|
||||
mailpoet_columns = <%= subscriberFields|raw %>,
|
||||
mailpoet_lists = <%= segments|raw %>,
|
||||
email_regex = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])+.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
||||
mailpoetLists = <%= segments|raw %>,
|
||||
emailRegex = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-_]{0,61}[a-zA-Z0-9])+.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
||||
</script>
|
||||
<% endblock %>
|
@ -1,4 +1,4 @@
|
||||
<div id="step_1" class="mailpoet_hidden">
|
||||
<div id="step1" class="mailpoet_hidden">
|
||||
<div class="inside">
|
||||
<!-- Method selection -->
|
||||
<table class="mailpoet_subscribers form-table">
|
||||
@ -76,7 +76,7 @@
|
||||
<td>
|
||||
<input type="file" id="file_local">
|
||||
|
||||
<%= __( 'total max upload file size : %s' )|replace({'%s': maximumParseSize}) %>
|
||||
<%= __( 'total max upload file size : %s' )|replace({'%s': maxPostSize}) %>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -109,7 +109,7 @@
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<select class ="mailchimp_lists_select" multiple="multiple"></select>
|
||||
<select class="mailchimp_lists_select" data-placeholder="<%= __('Select') %>" multiple="multiple"></select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -143,12 +143,11 @@
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<a href="javascript:;"
|
||||
class="button-primary wysija mailpoet_process"><%= ('Next step') %> </a>
|
||||
class="button-primary disabled wysija mailpoet_process"><%= ('Next step') %> </a>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
</div>
|
||||
</div>
|
216
views/import/step2.html
Normal file
216
views/import/step2.html
Normal file
@ -0,0 +1,216 @@
|
||||
<div id="step2" class="mailpoet_hidden">
|
||||
<div id="subscribers_data_parse_results">
|
||||
<!-- Template data -->
|
||||
</div>
|
||||
|
||||
<script id="subscribers_data_parse_results_template" type="text/x-handlebars-template">
|
||||
<div class="notice">
|
||||
<ul>
|
||||
<li>{{{notice}}}</li>
|
||||
<li><a class="mailpoet_subscribers_data_parse_results_details_show"
|
||||
href="javascript:;"><%= __('Show more details.') %></a></li>
|
||||
</ul>
|
||||
<div class="mailpoet_subscribers_data_parse_results_details mailpoet_hidden">
|
||||
<hr>
|
||||
<ul>
|
||||
{{#if duplicate}}
|
||||
<li>{{{duplicate}}}</li>
|
||||
{{/if}}
|
||||
{{#if invalid}}
|
||||
<li>{{{invalid}}}</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<div class="inside">
|
||||
<br>
|
||||
<!-- Subscribers Data -->
|
||||
<div id="subscribers_data">
|
||||
<table class="mailpoet_subscribers widefat fixed">
|
||||
<!-- Template data -->
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<table class="mailpoet_subscribers form-table">
|
||||
<tbody>
|
||||
<!-- MP3 Segments -->
|
||||
<tr class="mailpoet_segments mailpoet_hidden">
|
||||
<th scope="row">
|
||||
<label>
|
||||
<%= __('Pick one or many segments') %>
|
||||
<p class="description"><%= __('Pick the segments you want to import those subscribers to.') %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<select id="mailpoet_segments_select" data-placeholder="<%= __('Select') %>" multiple="multiple"></select>
|
||||
<a href="javascript:;" class="mailpoet_create_segment"><%= __('Create new list') %></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="mailpoet_no_segments mailpoet_hidden">
|
||||
<th scope="row">
|
||||
<%=
|
||||
__('To add subscribers to a mailing segment, [link]create a list[/link].')
|
||||
|replace({
|
||||
'[link]': '<a href="javascript:;" class="mailpoet_create_segment">',
|
||||
'[/link]': '</a>'
|
||||
})
|
||||
|raw
|
||||
%>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label>
|
||||
<%= __("Update existing subscribers' information") %>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<label>
|
||||
<input type="radio" name="subscriber_update_option" value="yes"
|
||||
checked><span><%= __('Yes') %></span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="subscriber_update_option"
|
||||
value="no"><span><%= __('No') %></span>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<a href="javascript:;" id="step_2_process"
|
||||
class="button-primary wysija disabled"><%= __('Next step') %> </a>
|
||||
</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- subscribers data template -->
|
||||
<script id="subscribers_data_template" type="text/x-handlebars-template">
|
||||
<thead>
|
||||
<th>
|
||||
<%= __('Match data') %>
|
||||
</th>
|
||||
{{#show_and_match_columns .}}
|
||||
{{#.}}
|
||||
<th>
|
||||
<select class="mailpoet_subscribers_column_data_match" data-column-id="{{column_id}}" id="column_{{@index}}">
|
||||
</th>
|
||||
{{/.}}
|
||||
{{/show_and_match_columns}}
|
||||
</thead>
|
||||
<tbody>
|
||||
{{> subscribers_data_template_partial}}
|
||||
</tbody>
|
||||
</script>
|
||||
|
||||
<script id="subscribers_data_template_partial" type="text/x-handlebars-template">
|
||||
{{#if header}}
|
||||
<tr class="mailpoet_header">
|
||||
<td></td>
|
||||
{{#header}}
|
||||
<td>
|
||||
{{this}}
|
||||
</td>
|
||||
{{/header}}
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#subscribers}}
|
||||
<tr>
|
||||
<td>
|
||||
{{show_real_index @index}}
|
||||
</td>
|
||||
{{#.}}
|
||||
<td>
|
||||
{{{this}}}
|
||||
</td>
|
||||
{{/.}}
|
||||
</tr>
|
||||
{{/subscribers}}
|
||||
</script>
|
||||
|
||||
<!-- New segment template -->
|
||||
<script id="new_segment_template" type="text/x-handlebars-template">
|
||||
<p>
|
||||
<label><%= __('Name') %>:</label>
|
||||
<input id="new_segment_name" type="text" name="name"/>
|
||||
</p>
|
||||
<p class="mailpoet_validation_error" data-error="segment_name_required">
|
||||
<%= __('You need to specify a name') %>
|
||||
</p>
|
||||
<p class="mailpoet_validation_error" data-error="segment_name_not_unique">
|
||||
<%= __('This name is already taken') %>
|
||||
</p>
|
||||
<p>
|
||||
<label><%= __('Description') %>:</label>
|
||||
<br/>
|
||||
<textarea id="new_segment_description" cols="40" rows="3" name="description"/>
|
||||
</p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<p class="mailpoet_align_right">
|
||||
<input type="submit" value="<%= __('Done') %>" id="new_segment_process"
|
||||
class="button-primary "/>
|
||||
<input type="submit" value="<%= __('Cancel') %>" id="new_segment_cancel"
|
||||
class="button-primary"/>
|
||||
</p>
|
||||
|
||||
</form>
|
||||
</script>
|
||||
|
||||
<!-- New column template -->
|
||||
<script id="new_column_template" type="text/x-handlebars-template">
|
||||
<p>
|
||||
<label><%= __('Field type') %>:</label>
|
||||
<select id="new_column_type" name="type">
|
||||
<option value="">--</option>
|
||||
<option value="input">
|
||||
<%= __('Text Input') %>
|
||||
</option>
|
||||
<option value="textarea">
|
||||
<%= __('Text Area') %>
|
||||
</option>
|
||||
<option value="radio">
|
||||
<%= __('Radio buttons') %>
|
||||
</option>
|
||||
<option value="checkbox">
|
||||
<%= __('Checkbox') %>
|
||||
</option>
|
||||
<option value="select">
|
||||
<%= __('Select') %>
|
||||
</option>
|
||||
<option value="date">
|
||||
<%= __('Date') %>
|
||||
</option>
|
||||
</select>
|
||||
</p>
|
||||
<p class="mailpoet_validation_error" data-error="type_required">
|
||||
<%= __('You need to select a type') %>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label><%= __('Field name') %>:</label>
|
||||
<input id="new_column_name" type="text" name="name" value="{{ name }}"/>
|
||||
</p>
|
||||
<p class="mailpoet_validation_error" data-error="name_required">
|
||||
<%= __('You need to specify a name') %>
|
||||
</p>
|
||||
<p class="mailpoet_validation_error" data-error="name_not_unique">
|
||||
<%= __('This name is already taken') %>
|
||||
</p>
|
||||
|
||||
<hr/>
|
||||
|
||||
<p class="mailpoet_align_right">
|
||||
<input type="submit" value="<%= __('Done') %>" id="new_column_process"
|
||||
class="button-primary "/>
|
||||
<input type="submit" value="<%= __('Cancel') %>" id="new_column_cancel"
|
||||
class="button-primary"/>
|
||||
</p>
|
||||
|
||||
</form>
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user