diff --git a/assets/css/src/progress_bar.styl b/assets/css/src/progress_bar.styl
index f2fcb5b03f..b711fca67c 100644
--- a/assets/css/src/progress_bar.styl
+++ b/assets/css/src/progress_bar.styl
@@ -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)
\ No newline at end of file
+.mailpoet_progress_complete
+ .mailpoet_progress_bar
+ background-color: #fecf23
+ background-image: linear-gradient(top, #fecf23, #fd9215)
\ No newline at end of file
diff --git a/assets/js/src/form/fields/text.jsx b/assets/js/src/form/fields/text.jsx
index 825209d77c..04fac47d08 100644
--- a/assets/js/src/form/fields/text.jsx
+++ b/assets/js/src/form/fields/text.jsx
@@ -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}
+ />
);
}
});
diff --git a/assets/js/src/listing/listing.jsx b/assets/js/src/listing/listing.jsx
index d7495133b1..a74d42ed2c 100644
--- a/assets/js/src/listing/listing.jsx
+++ b/assets/js/src/listing/listing.jsx
@@ -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) {
diff --git a/assets/js/src/newsletters/list.jsx b/assets/js/src/newsletters/list.jsx
index 00f6ac0936..1accdd3ba0 100644
--- a/assets/js/src/newsletters/list.jsx
+++ b/assets/js/src/newsletters/list.jsx
@@ -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 (
Not sent yet.
);
} 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 = (
+
+ Sent to {
+ item.queue.count_processed - item.queue.count_failed
+ } out of { item.queue.count_total }.
+
+ );
+ } else {
+ label = (
+
+ { item.queue.count_processed } / { item.queue.count_total }
+
+ Resume
+ Pause
+
+ );
+ }
+
return (
-
-
+
+
+
+ { percentage + "%" }
+
- { item.queue.count_processed } / { item.queue.count_total }
+
+ { label }
+
);
}
@@ -194,7 +260,8 @@ define(
columns={columns}
bulk_actions={ bulk_actions }
item_actions={ item_actions }
- messages={ messages } />
+ messages={ messages }
+ auto_refresh={ true } />
);
}
diff --git a/assets/js/src/newsletters/send.jsx b/assets/js/src/newsletters/send.jsx
index d4476481f7..0c9bcbc2d1 100644
--- a/assets/js/src/newsletters/send.jsx
+++ b/assets/js/src/newsletters/send.jsx
@@ -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("
")
+ MailPoet.Notice.success(
+ 'The newsletter is being sent...'
);
} else {
- MailPoet.Notice.error(
- 'An error occurred while trying to send. '+
- 'Check your settings.'
- );
+ if(response.errors) {
+ MailPoet.Notice.error(
+ response.errors.join("
")
+ );
+ } else {
+ MailPoet.Notice.error(
+ 'An error occurred while trying to send. '+
+ 'Check your settings.'
+ );
+ }
}
- }
- }.bind(this));
+ }.bind(this));
+ }
+ },
+ componentDidMount: function() {
+ if(this.isMounted()) {
+ jQuery('#mailpoet_newsletter').parsley();
+ }
},
render: function() {
return (
diff --git a/assets/js/src/settings/tabs.js b/assets/js/src/settings/tabs.js
index a81318cd00..860581c9c4 100644
--- a/assets/js/src/settings/tabs.js
+++ b/assets/js/src/settings/tabs.js
@@ -36,7 +36,7 @@ define(
} else {
// hide DKIM option when using MailPoet's API
jQuery('#mailpoet_mta_dkim')[
- (method === 'mailpoet')
+ (method === 'MailPoet')
? 'hide'
: 'show'
]();
diff --git a/lib/Config/Menu.php b/lib/Config/Menu.php
index b20a0696b8..1d0aaac4e5 100644
--- a/lib/Config/Menu.php
+++ b/lib/Config/Menu.php
@@ -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(),
diff --git a/lib/Models/Newsletter.php b/lib/Models/Newsletter.php
index 09ef11774e..02135b6adb 100644
--- a/lib/Models/Newsletter.php
+++ b/lib/Models/Newsletter.php
@@ -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 . '%');
}
diff --git a/lib/Models/SendingQueue.php b/lib/Models/SendingQueue.php
index d1c9762132..9a5bcf405b 100644
--- a/lib/Models/SendingQueue.php
+++ b/lib/Models/SendingQueue.php
@@ -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();
+ }
}
\ No newline at end of file
diff --git a/lib/Router/Queue.php b/lib/Router/Queue.php
index 4a2ae14b3b..c20eacd7f7 100644
--- a/lib/Router/Queue.php
+++ b/lib/Router/Queue.php
@@ -92,6 +92,8 @@ class Queue {
);
}
+
+
function addQueues($data) {
$result = array_map(function ($queueData) {
$queue = SendingQueue::create();
diff --git a/lib/Router/SendingQueue.php b/lib/Router/SendingQueue.php
index 2cb67e0c89..6f493a0b5c 100644
--- a/lib/Router/SendingQueue.php
+++ b/lib/Router/SendingQueue.php
@@ -1,13 +1,14 @@
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) {
diff --git a/lib/Settings/Hosts.php b/lib/Settings/Hosts.php
index 95264d047c..fc9d125543 100644
--- a/lib/Settings/Hosts.php
+++ b/lib/Settings/Hosts.php
@@ -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,
diff --git a/package.json b/package.json
index d90d3231b0..9a2955db2e 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/views/settings/mta.html b/views/settings/mta.html
index 426b00197c..cca8431a19 100644
--- a/views/settings/mta.html
+++ b/views/settings/mta.html
@@ -17,6 +17,7 @@
name="mta[method]"
value="<%= settings.mta.method %>"
/>
+
- class="mailpoet_active"<% endif %>
+ data-method="MailPoet"
+ <% if(settings.mta.method == 'MailPoet') %>class="mailpoet_active"<% endif %>
>
<%= __('Configure') %>
+ href="#mta/MailPoet"><%= __('Configure') %>
-
<%= __('Open a free account with MailPoet, and get:') %>
@@ -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 %>"
/>
@@ -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
diff --git a/webpack.config.js b/webpack.config.js
index 86be7a7b05..ade6c14f97 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -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',