Status update of newsletters completed

- duplicate newsletter now includes options as well
- fixed NaN issue in statistics when newsletter is being sent
- use constant for scheduled (and put it as the sendingQueue Model level)
This commit is contained in:
Jonathan Labreuille
2016-06-16 20:01:53 +02:00
parent 744455f0df
commit aa3a46b941
7 changed files with 122 additions and 69 deletions

View File

@ -94,12 +94,12 @@ const bulk_actions = [
}
];
const item_actions = [
const newsletter_actions = [
{
name: 'view',
link: function(item) {
link: function(newsletter) {
return (
<a href={ item.preview_url } target="_blank">
<a href={ newsletter.preview_url } target="_blank">
{MailPoet.I18n.t('preview')}
</a>
);
@ -107,9 +107,9 @@ const item_actions = [
},
{
name: 'edit',
link: function(item) {
link: function(newsletter) {
return (
<a href={ `?page=mailpoet-newsletter-editor&id=${ item.id }` }>
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
{MailPoet.I18n.t('edit')}
</a>
);
@ -118,11 +118,11 @@ const item_actions = [
{
name: 'duplicate',
label: MailPoet.I18n.t('duplicate'),
onClick: function(item, refresh) {
onClick: function(newsletter, refresh) {
return MailPoet.Ajax.post({
endpoint: 'newsletters',
action: 'duplicate',
data: item.id
data: newsletter.id
}).done(function(response) {
if (response !== false && response.subject !== undefined) {
MailPoet.Notice.success(
@ -141,77 +141,77 @@ const item_actions = [
];
const NewsletterListStandard = React.createClass({
pauseSending: function(item) {
pauseSending: function(newsletter) {
MailPoet.Ajax.post({
endpoint: 'sendingQueue',
action: 'pause',
data: item.id
data: newsletter.id
}).done(function() {
jQuery('#resume_'+item.id).show();
jQuery('#pause_'+item.id).hide();
jQuery('#resume_'+newsletter.id).show();
jQuery('#pause_'+newsletter.id).hide();
});
},
resumeSending: function(item) {
resumeSending: function(newsletter) {
MailPoet.Ajax.post({
endpoint: 'sendingQueue',
action: 'resume',
data: item.id
data: newsletter.id
}).done(function() {
jQuery('#pause_'+item.id).show();
jQuery('#resume_'+item.id).hide();
jQuery('#pause_'+newsletter.id).show();
jQuery('#resume_'+newsletter.id).hide();
});
},
renderStatus: function(item) {
if(!item.queue) {
renderStatus: function(newsletter) {
if (!newsletter.queue) {
return (
<span>{MailPoet.I18n.t('notSentYet')}</span>
);
} else {
if (item.queue.status === 'scheduled') {
if (newsletter.queue.status === 'scheduled') {
return (
<span>{MailPoet.I18n.t('scheduledFor')} { MailPoet.Date.format(item.queue.scheduled_at) } </span>
<span>{MailPoet.I18n.t('scheduledFor')} { MailPoet.Date.format(newsletter.queue.scheduled_at) } </span>
)
}
const progressClasses = classNames(
'mailpoet_progress',
{ 'mailpoet_progress_complete': item.queue.status === 'completed'}
{ 'mailpoet_progress_complete': newsletter.queue.status === 'completed'}
);
// calculate percentage done
const percentage = Math.round(
(item.queue.count_processed * 100) / (item.queue.count_total)
(newsletter.queue.count_processed * 100) / (newsletter.queue.count_total)
);
let label;
if(item.queue.status === 'completed') {
if (newsletter.queue.status === 'completed') {
label = (
<span>
{
MailPoet.I18n.t('newsletterQueueCompleted')
.replace("%$1d", item.queue.count_processed - item.queue.count_failed)
.replace("%$2d", item.queue.count_total)
.replace("%$1d", newsletter.queue.count_processed - newsletter.queue.count_failed)
.replace("%$2d", newsletter.queue.count_total)
}
</span>
);
} else {
label = (
<span>
{ item.queue.count_processed } / { item.queue.count_total }
{ newsletter.queue.count_processed } / { newsletter.queue.count_total }
&nbsp;&nbsp;
<a
id={ 'resume_'+item.id }
id={ 'resume_'+newsletter.id }
className="button"
style={{ display: (item.queue.status === 'paused') ? 'inline-block': 'none' }}
style={{ display: (newsletter.queue.status === 'paused') ? 'inline-block': 'none' }}
href="javascript:;"
onClick={ this.resumeSending.bind(null, item) }
onClick={ this.resumeSending.bind(null, newsletter) }
>{MailPoet.I18n.t('resume')}</a>
<a
id={ 'pause_'+item.id }
id={ 'pause_'+newsletter.id }
className="button mailpoet_pause"
style={{ display: (item.queue.status === null) ? 'inline-block': 'none' }}
style={{ display: (newsletter.queue.status === null) ? 'inline-block': 'none' }}
href="javascript:;"
onClick={ this.pauseSending.bind(null, item) }
onClick={ this.pauseSending.bind(null, newsletter) }
>{MailPoet.I18n.t('pause')}</a>
</span>
);
@ -242,15 +242,22 @@ const NewsletterListStandard = React.createClass({
if (newsletter.statistics && newsletter.queue && newsletter.queue.status !== 'scheduled') {
const total_sent = ~~(newsletter.queue.count_processed);
const percentage_clicked = Math.round(
let percentage_clicked = 0;
let percentage_opened = 0;
let percentage_unsubscribed = 0;
if (total_sent > 0) {
percentage_clicked = Math.round(
(~~(newsletter.statistics.clicked) * 100) / total_sent
);
const percentage_opened = Math.round(
percentage_opened = Math.round(
(~~(newsletter.statistics.opened) * 100) / total_sent
);
const percentage_unsubscribed = Math.round(
percentage_unsubscribed = Math.round(
(~~(newsletter.statistics.unsubscribed) * 100) / total_sent
);
}
return (
<span>
@ -318,7 +325,7 @@ const NewsletterListStandard = React.createClass({
onRenderItem={this.renderItem}
columns={columns}
bulk_actions={ bulk_actions }
item_actions={ item_actions }
item_actions={ newsletter_actions }
messages={ messages }
auto_refresh={ true }
/>

View File

@ -105,8 +105,9 @@ define(
}
}).done((response) => {
this.setState({ loading: false });
if(response.result === true) {
this.context.router.push('/');
this.context.router.push(`/${ this.state.item.type || '' }`);
MailPoet.Notice.success(response.data.message);
} else {
if(response.errors) {
@ -133,7 +134,7 @@ define(
this.setState({ loading: false });
if(response.result === true) {
this.context.router.push('/');
this.context.router.push(`/${ this.state.item.type || '' }`);
MailPoet.Notice.success(
MailPoet.I18n.t('newsletterUpdated')
);

View File

@ -322,6 +322,10 @@ class SendingQueue {
if(!$queue->count_to_process) {
$queue->processed_at = current_time('mysql');
$queue->status = SendingQueueModel::STATUS_COMPLETED;
// set newsletter status to sent
$newsletter = Newsletter::findOne($queue->newsletter_id);
$newsletter->setStatus(Newsletter::STATUS_SENT);
}
$queue->subscribers = serialize((array) $queue->subscribers);
$queue->save();

View File

@ -86,12 +86,24 @@ class Newsletter extends Model {
foreach($segments as $segment) {
$relation = NewsletterSegment::create();
$relation->segment_id = $segment['id'];
$relation->newsletter_id = $duplicate->id();
$result = $relation->save();
$relation->newsletter_id = $duplicate->id;
$relation->save();
}
}
// TODO: duplicate options (if need be)
// duplicate options
$options = NewsletterOption::where('newsletter_id', $this->id)
->findArray();
if(!empty($options)) {
foreach($options as $option) {
$relation = NewsletterOption::create();
$relation->newsletter_id = $duplicate->id;
$relation->option_field_id = $option['option_field_id'];
$relation->value = $option['value'];
$relation->save();
}
}
}
return $duplicate;

View File

@ -7,6 +7,8 @@ class SendingQueue extends Model {
public static $_table = MP_SENDING_QUEUES_TABLE;
const STATUS_COMPLETED = 'completed';
const STATUS_SCHEDULED = 'scheduled';
const STATUS_PAUSED = 'paused';
function __construct() {
parent::__construct();
@ -16,7 +18,7 @@ class SendingQueue extends Model {
if($this->count_processed === $this->count_total) {
return false;
} else {
$this->set('status', 'paused');
$this->set('status', STATUS_PAUSED);
$this->save();
return ($this->getErrors() === false && $this->id() > 0);
}
@ -26,14 +28,14 @@ class SendingQueue extends Model {
if($this->count_processed === $this->count_total) {
return $this->complete();
} else {
$this->set_expr('status', 'NULL');
$this->setExpr('status', 'NULL');
$this->save();
return ($this->getErrors() === false && $this->id() > 0);
}
}
function complete() {
$this->set('status', 'completed');
$this->set('status', self::STATUS_COMPLETED);
$this->save();
return ($this->getErrors() === false && $this->id() > 0);
}

View File

@ -182,7 +182,7 @@ class Scheduler {
if($existing_queue) return;
$queue = SendingQueue::create();
$queue->newsletter_id = $newsletter->id;
$queue->status = 'scheduled';
$queue->status = self::STATUS_SCHEDULED;
$queue->scheduled_at = $next_run_date;
$queue->save();
return $queue;

View File

@ -9,12 +9,14 @@ use MailPoet\Models\Setting;
use MailPoet\Models\Subscriber;
use MailPoet\Models\SubscriberSegment;
use MailPoet\Newsletter\Scheduler\Scheduler;
use MailPoet\Models\SendingQueue as SendingQueueModel;
use MailPoet\Util\Helpers;
if(!defined('ABSPATH')) exit;
class SendingQueue {
function add($data) {
// check that the sending method has been configured properly
try {
new Mailer(false);
} catch(\Exception $e) {
@ -24,59 +26,81 @@ class SendingQueue {
);
}
// check that the newsletter exists
$newsletter = Newsletter::filter('filterWithOptions')
->findOne($data['newsletter_id']);
if(!$newsletter) {
if($newsletter === false) {
return array(
'result' => false,
'errors' => array(__('Newsletter does not exist.'))
'errors' => array(__('This newsletter does not exist.'))
);
}
if($newsletter->type === Newsletter::TYPE_WELCOME) {
// set welcome email active
$result = $newsletter->setStatus(Newsletter::STATUS_ACTIVE);
$errors = $result->getErrors();
if(!empty($errors)) {
return array(
'result' => false,
'errors' => $errors
);
} else {
return array(
'result' => true,
'data' => array(
'message' => __('Your welcome notification is activated.')
'message' => __('Your welcome email has been activated.')
)
);
}
} else if($newsletter->type === Newsletter::TYPE_NOTIFICATION) {
// Post Notifications
$newsletter = Scheduler::processPostNotificationSchedule($newsletter->id);
Scheduler::createPostNotificationQueue($newsletter);
// set post notification active
$newsletter->setStatus(Newsletter::STATUS_ACTIVE);
}
$queue = \MailPoet\Models\SendingQueue::whereNull('status')
$queue = SendingQueueModel::whereNull('status')
->where('newsletter_id', $newsletter->id)
->findOne();
if(!empty($queue)) {
return array(
'result' => false,
'errors' => array(__('Send operation is already in progress.'))
'errors' => array(__('This newsletter is already being sent.'))
);
}
$queue = \MailPoet\Models\SendingQueue::where('status', 'scheduled')
->where('newsletter_id', $newsletter->id)
$queue = SendingQueueModel::where('newsletter_id', $newsletter->id)
->where('status', SendingQueueModel::STATUS_SCHEDULED)
->findOne();
if(!$queue) {
$queue = \MailPoet\Models\SendingQueue::create();
$queue = SendingQueueModel::create();
$queue->newsletter_id = $newsletter->id;
}
if($newsletter->type === 'notification') {
if($newsletter->type === Newsletter::TYPE_NOTIFICATION) {
$queue->scheduled_at = Scheduler::getNextRunDate($newsletter->schedule);
$queue->status = 'scheduled';
$queue->status = SendingQueueModel::STATUS_SCHEDULED;
$queue->save();
return array(
'result' => true,
'data' => array(
'message' => __('Your post notifications are activated.')
'message' => __('Your post notification has been activated.')
)
);
}
if((bool)$newsletter->isScheduled) {
$queue->status = 'scheduled';
// set newsletter status
$newsletter->setStatus(Newsletter::STATUS_SCHEDULED);
// set queue status
$queue->status = SendingQueueModel::STATUS_SCHEDULED;
$queue->scheduled_at = Scheduler::scheduleFromTimestamp(
$newsletter->scheduledAt
);
@ -104,6 +128,9 @@ class SendingQueue {
);
$queue->count_total = $queue->count_to_process = count($subscribers);
// set newsletter status
$newsletter->setStatus(Newsletter::STATUS_SENDING);
$message = __('The newsletter is being sent...');
}
$queue->save();