Sending Progress
- improved progress bar styles (with completed status) - add pause/resume buttons - fixed method case in settings.mta for MailPoet & SMTP Providers - fixed parsley dependency - added validation on from name & address on step 3
This commit is contained in:
committed by
MrCasual
parent
9b011c0281
commit
4a2bbe3f88
@ -5,17 +5,25 @@
|
||||
width: 100%
|
||||
margin: 0
|
||||
border-radius: 5px
|
||||
position: relative
|
||||
|
||||
.mailpoet_progress span
|
||||
.mailpoet_progress_label
|
||||
position: absolute
|
||||
width: 100%
|
||||
text-align: center
|
||||
display: inline-block
|
||||
margin: 2px 0 0 0
|
||||
|
||||
.mailpoet_progress_bar
|
||||
position: absolute
|
||||
display: inline-block
|
||||
height: 100%
|
||||
border-radius: 3px
|
||||
box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset
|
||||
|
||||
.blue span
|
||||
background-color: #34c2e3
|
||||
background-image: linear-gradient(top, #34c2e3, darken(#34c2e3, 20%))
|
||||
|
||||
.orange span
|
||||
background-color: #fecf23
|
||||
background-image: linear-gradient(top, #fecf23, #fd9215)
|
||||
.mailpoet_progress_complete
|
||||
.mailpoet_progress_bar
|
||||
background-color: #fecf23
|
||||
background-image: linear-gradient(top, #fecf23, #fd9215)
|
@ -20,7 +20,9 @@ function(
|
||||
value={ this.props.item[this.props.field.name] }
|
||||
placeholder={ this.props.field.placeholder }
|
||||
defaultValue={ this.props.field.defaultValue }
|
||||
onChange={ this.props.onValueChange } />
|
||||
onChange={ this.props.onValueChange }
|
||||
{...this.props.field.validation}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -397,6 +397,12 @@ define(
|
||||
if(this.isMounted()) {
|
||||
const params = this.props.params || {}
|
||||
this.initWithParams(params)
|
||||
|
||||
if(this.props.auto_refresh) {
|
||||
jQuery(document).on('heartbeat-tick.mailpoet', function(e, data) {
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
},
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
|
@ -123,23 +123,89 @@ define(
|
||||
];
|
||||
|
||||
var NewsletterList = React.createClass({
|
||||
pauseSending: function(item) {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'pause',
|
||||
data: item.id
|
||||
}).done(function() {
|
||||
jQuery('#resume_'+item.id).show();
|
||||
jQuery('#pause_'+item.id).hide();
|
||||
});
|
||||
},
|
||||
resumeSending: function(item) {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'resume',
|
||||
data: item.id
|
||||
}).done(function() {
|
||||
jQuery('#pause_'+item.id).show();
|
||||
jQuery('#resume_'+item.id).hide();
|
||||
});
|
||||
},
|
||||
renderStatus: function(item) {
|
||||
if(item.queue === null) {
|
||||
return (
|
||||
<span>Not sent yet.</span>
|
||||
);
|
||||
} else {
|
||||
var progressClasses = classNames(
|
||||
'mailpoet_progress',
|
||||
{ 'mailpoet_progress_complete': item.queue.status === 'completed'}
|
||||
);
|
||||
|
||||
// calculate percentage done
|
||||
var percentage = Math.round(
|
||||
(item.queue.count_processed * 100) / (item.queue.count_total)
|
||||
);
|
||||
|
||||
var label = false;
|
||||
|
||||
if(item.queue.status === 'completed') {
|
||||
label = (
|
||||
<span>
|
||||
Sent to {
|
||||
item.queue.count_processed - item.queue.count_failed
|
||||
} out of { item.queue.count_total }.
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
label = (
|
||||
<span>
|
||||
{ item.queue.count_processed } / { item.queue.count_total }
|
||||
|
||||
<a
|
||||
id={ 'resume_'+item.id }
|
||||
className="button"
|
||||
style={{ display: (item.queue.status === 'paused') ? 'inline-block': 'none' }}
|
||||
href="javascript:;"
|
||||
onClick={ this.resumeSending.bind(null, item) }
|
||||
>Resume</a>
|
||||
<a
|
||||
id={ 'pause_'+item.id }
|
||||
className="button mailpoet_pause"
|
||||
style={{ display: (item.queue.status === null) ? 'inline-block': 'none' }}
|
||||
href="javascript:;"
|
||||
onClick={ this.pauseSending.bind(null, item) }
|
||||
>Pause</a>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mailpoet_progress blue">
|
||||
<span style={ { width: percentage + "%"} }></span>
|
||||
<div className={ progressClasses }>
|
||||
<span
|
||||
className="mailpoet_progress_bar"
|
||||
style={ { width: percentage + "%"} }
|
||||
></span>
|
||||
<span className="mailpoet_progress_label">
|
||||
{ percentage + "%" }
|
||||
</span>
|
||||
</div>
|
||||
{ item.queue.count_processed } / { item.queue.count_total }
|
||||
<p style={{ textAlign:'center' }}>
|
||||
{ label }
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -194,7 +260,8 @@ define(
|
||||
columns={columns}
|
||||
bulk_actions={ bulk_actions }
|
||||
item_actions={ item_actions }
|
||||
messages={ messages } />
|
||||
messages={ messages }
|
||||
auto_refresh={ true } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -48,14 +48,21 @@ define(
|
||||
name: 'from_name',
|
||||
type: 'text',
|
||||
placeholder: 'John Doe',
|
||||
defaultValue: settings.from_name
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.name : '',
|
||||
validation: {
|
||||
'data-parsley-required': true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'from_email',
|
||||
type: 'text',
|
||||
placeholder: 'john.doe@email.com',
|
||||
defaultValue: settings.from_address
|
||||
},
|
||||
defaultValue: (settings.sender !== undefined) ? settings.sender.address : '',
|
||||
validation: {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-type': 'email'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -93,33 +100,40 @@ define(
|
||||
Router.History
|
||||
],
|
||||
handleSend: function() {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'addQueue',
|
||||
data: {
|
||||
newsletter_id: this.props.params.id,
|
||||
segments: jQuery('#mailpoet_segments').val()
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response === true) {
|
||||
//this.history.pushState(null, '/');
|
||||
if(jQuery('#mailpoet_newsletter').parsley().validate() === true) {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'sendingQueue',
|
||||
action: 'add',
|
||||
data: {
|
||||
newsletter_id: this.props.params.id,
|
||||
segments: jQuery('#mailpoet_segments').val()
|
||||
}
|
||||
}).done(function(response) {
|
||||
if(response.result === true) {
|
||||
this.history.pushState(null, '/');
|
||||
|
||||
MailPoet.Notice.success(
|
||||
'The newsletter has been sent!'
|
||||
);
|
||||
} else {
|
||||
if(response.errors) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.join("<br />")
|
||||
MailPoet.Notice.success(
|
||||
'The newsletter is being sent...'
|
||||
);
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
'An error occurred while trying to send. '+
|
||||
'<a href="?page=mailpoet-settings">Check your settings.</a>'
|
||||
);
|
||||
if(response.errors) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.join("<br />")
|
||||
);
|
||||
} else {
|
||||
MailPoet.Notice.error(
|
||||
'An error occurred while trying to send. '+
|
||||
'<a href="?page=mailpoet-settings">Check your settings.</a>'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
componentDidMount: function() {
|
||||
if(this.isMounted()) {
|
||||
jQuery('#mailpoet_newsletter').parsley();
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -36,7 +36,7 @@ define(
|
||||
} else {
|
||||
// hide DKIM option when using MailPoet's API
|
||||
jQuery('#mailpoet_mta_dkim')[
|
||||
(method === 'mailpoet')
|
||||
(method === 'MailPoet')
|
||||
? 'hide'
|
||||
: 'show'
|
||||
]();
|
||||
|
@ -320,20 +320,27 @@ class Menu {
|
||||
}
|
||||
|
||||
function newsletters() {
|
||||
add_filter('heartbeat_received', array($this, 'getQueueStatus'), 10, 3);
|
||||
|
||||
global $wp_roles;
|
||||
|
||||
$data = array();
|
||||
|
||||
$data['segments'] = Segment::findArray();
|
||||
$settings = Setting::findArray();
|
||||
$data['settings'] = array();
|
||||
foreach ($settings as $setting) {
|
||||
$data['settings'][$setting['name']] = $setting['value'];
|
||||
}
|
||||
$data['settings'] = Setting::getAll();
|
||||
$data['roles'] = $wp_roles->get_names();
|
||||
echo $this->renderer->render('newsletters.html', $data);
|
||||
}
|
||||
|
||||
function getQueueStatus($response, $data, $screen_id) {
|
||||
if(isset($data['mailpoet'])) {
|
||||
$response['mailpoet'] = array(
|
||||
'hello' => 'world'
|
||||
);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
function newletterEditor() {
|
||||
$data = array();
|
||||
wp_enqueue_media();
|
||||
@ -364,7 +371,7 @@ class Menu {
|
||||
$data = array(
|
||||
'form' => $form,
|
||||
'pages' => Pages::getAll(),
|
||||
'segments' => Segment::getPublished()
|
||||
'segments' => Segment::getPublic()
|
||||
->findArray(),
|
||||
'styles' => FormRenderer::getStyles($form),
|
||||
'date_types' => Block\Date::getDateTypes(),
|
||||
|
@ -43,6 +43,12 @@ class Newsletter extends Model {
|
||||
)->select_expr(MP_NEWSLETTER_OPTION_TABLE.'.value');
|
||||
}
|
||||
|
||||
function getQueue() {
|
||||
return SendingQueue::where('newsletter_id', $this->id)
|
||||
->orderByDesc('updated_at')
|
||||
->findOne();
|
||||
}
|
||||
|
||||
static function search($orm, $search = '') {
|
||||
return $orm->where_like('subject', '%' . $search . '%');
|
||||
}
|
||||
|
@ -9,4 +9,27 @@ class SendingQueue extends Model {
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function pause() {
|
||||
if($this->count_processed === $this->count_total) {
|
||||
return false;
|
||||
} else {
|
||||
$this->set('status', 'paused');
|
||||
return $this->save();
|
||||
}
|
||||
}
|
||||
|
||||
function resume() {
|
||||
if($this->count_processed === $this->count_total) {
|
||||
return $this->complete();
|
||||
} else {
|
||||
$this->set_expr('status', 'NULL');
|
||||
return $this->save();
|
||||
}
|
||||
}
|
||||
|
||||
function complete() {
|
||||
$this->set('status', 'completed');
|
||||
return $this->save();
|
||||
}
|
||||
}
|
@ -92,6 +92,8 @@ class Queue {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function addQueues($data) {
|
||||
$result = array_map(function ($queueData) {
|
||||
$queue = SendingQueue::create();
|
||||
|
@ -1,13 +1,14 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Util\Helpers;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
class SendingQueue {
|
||||
function addQueue($data) {
|
||||
function add($data) {
|
||||
$queue = \MailPoet\Models\SendingQueue::where('newsletter_id', $data['newsletter_id'])
|
||||
->whereNull('status')
|
||||
->findArray();
|
||||
@ -18,6 +19,7 @@ class SendingQueue {
|
||||
'errors' => array(__('Send operation is already in progress.'))
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
$queue = \MailPoet\Models\SendingQueue::create();
|
||||
$queue->newsletter_id = $data['newsletter_id'];
|
||||
@ -39,18 +41,60 @@ class SendingQueue {
|
||||
)
|
||||
);
|
||||
$queue->count_total = $queue->count_to_process = count($subscriber_ids);
|
||||
$queue->save();
|
||||
wp_send_json(
|
||||
!$queue->save() ?
|
||||
$result = $queue->save();
|
||||
if($result === false) {
|
||||
$errors = array(__('Queue could not be created.'));
|
||||
|
||||
if(!empty($queue->getValidationErrors())) {
|
||||
$errors = array_merge($errors, $queue->getValidationErrors());
|
||||
}
|
||||
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => false,
|
||||
'errors' => array(__('Queue could not be created.'))
|
||||
) :
|
||||
'errors' => $errors
|
||||
)
|
||||
);
|
||||
} else {
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => true,
|
||||
'data' => array($queue->id)
|
||||
)
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function pause($newsletter_id) {
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
$result = false;
|
||||
|
||||
if($newsletter !== false) {
|
||||
$queue = $newsletter->getQueue();
|
||||
if($queue !== false && $queue->id() > 0) {
|
||||
$result = $queue->pause();
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json(array(
|
||||
'result' => $result
|
||||
));
|
||||
}
|
||||
|
||||
function resume($newsletter_id) {
|
||||
$newsletter = Newsletter::findOne($newsletter_id);
|
||||
$result = false;
|
||||
|
||||
if($newsletter !== false) {
|
||||
$queue = $newsletter->getQueue();
|
||||
if($queue !== false && $queue->id() > 0) {
|
||||
$result = $queue->resume();
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json(array(
|
||||
'result' => $result
|
||||
));
|
||||
}
|
||||
|
||||
function addQueues($data) {
|
||||
|
@ -3,25 +3,25 @@ namespace MailPoet\Settings;
|
||||
|
||||
class Hosts {
|
||||
private static $_smtp = array(
|
||||
'amazon' => array(
|
||||
'AmazonSES' => array(
|
||||
'name' => 'Amazon SES',
|
||||
'api' => false,
|
||||
'emails' => 100,
|
||||
'interval' => 5
|
||||
),
|
||||
'elasticemail' => array(
|
||||
'ElasticEmail' => array(
|
||||
'name' => 'ElasticEmail',
|
||||
'api' => true,
|
||||
'emails' => 100,
|
||||
'interval' => 5
|
||||
),
|
||||
'mailgun' => array(
|
||||
'MailGun' => array(
|
||||
'name' => 'MailGun',
|
||||
'api' => false,
|
||||
'emails' => 100,
|
||||
'interval' => 5
|
||||
),
|
||||
'sendgrid' => array(
|
||||
'SendGrid' => array(
|
||||
'name' => 'SendGrid',
|
||||
'api' => true,
|
||||
'emails' => 100,
|
||||
|
@ -24,7 +24,7 @@
|
||||
"moment": "^2.10.3",
|
||||
"napa": "^1.2.0",
|
||||
"papaparse": "4.1.1",
|
||||
"parsley": "^0.1.0",
|
||||
"parsleyjs": "^2.1.2",
|
||||
"react": "^0.14.1",
|
||||
"react-checkbox-group": "0.2.2",
|
||||
"react-dom": "^0.14.1",
|
||||
|
@ -17,6 +17,7 @@
|
||||
name="mta[method]"
|
||||
value="<%= settings.mta.method %>"
|
||||
/>
|
||||
|
||||
<!-- mta: sending frequency -->
|
||||
<input
|
||||
type="hidden"
|
||||
@ -51,8 +52,8 @@
|
||||
<!-- smtp: available sending methods -->
|
||||
<ul class="mailpoet_sending_methods clearfix">
|
||||
<li
|
||||
data-method="mailpoet"
|
||||
<% if(settings.mta.method == 'mailpoet') %>class="mailpoet_active"<% endif %>
|
||||
data-method="MailPoet"
|
||||
<% if(settings.mta.method == 'MailPoet') %>class="mailpoet_active"<% endif %>
|
||||
>
|
||||
<h3>
|
||||
<img
|
||||
@ -76,7 +77,7 @@
|
||||
<div class="mailpoet_actions">
|
||||
<a
|
||||
class="button-secondary"
|
||||
href="#mta/mailpoet"><%= __('Configure') %></a>
|
||||
href="#mta/MailPoet"><%= __('Configure') %></a>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
@ -125,7 +126,7 @@
|
||||
<!-- Sending Method: MailPoet -->
|
||||
<div
|
||||
class="mailpoet_sending_method"
|
||||
data-method="mailpoet"
|
||||
data-method="MailPoet"
|
||||
style="display:none;"
|
||||
>
|
||||
<h3><%= __('Open a free account with MailPoet, and get:') %></h3>
|
||||
@ -165,8 +166,8 @@
|
||||
type="text"
|
||||
id="mailpoet_api_key"
|
||||
size="40"
|
||||
name="api_key"
|
||||
value="<%= settings.api_key %>"
|
||||
name="mta[api_key]"
|
||||
value="<%= settings.mta.api_key %>"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -666,7 +667,6 @@
|
||||
)
|
||||
? $('.mailpoet_sending_method:visible').data('method')
|
||||
: $('#mta_method').val();
|
||||
|
||||
alert(
|
||||
'Sending a test email to: '+recipient+
|
||||
' using sending method: '+mta_method
|
||||
|
@ -77,7 +77,7 @@ baseConfig = {
|
||||
{
|
||||
include: /html2canvas.js$/,
|
||||
loader: 'expose-loader?html2canvas',
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@ -92,7 +92,8 @@ config.push(_.extend({}, baseConfig, {
|
||||
'ajax',
|
||||
'modal',
|
||||
'notice',
|
||||
'jquery.serialize_object'
|
||||
'jquery.serialize_object',
|
||||
'parsleyjs'
|
||||
],
|
||||
admin: [
|
||||
'subscribers/subscribers.jsx',
|
||||
|
Reference in New Issue
Block a user