diff --git a/assets/js/src/listing/listing.jsx b/assets/js/src/listing/listing.jsx
index 7f8b1d85e1..d9ef512579 100644
--- a/assets/js/src/listing/listing.jsx
+++ b/assets/js/src/listing/listing.jsx
@@ -298,7 +298,8 @@ const Listing = React.createClass({
filters: {},
filter: {},
selected_ids: [],
- selection: false
+ selection: false,
+ meta: {}
};
},
getParam: function(param) {
@@ -463,15 +464,21 @@ const Listing = React.createClass({
items: response.data || [],
filters: response.meta.filters || {},
groups: response.meta.groups || [],
- count: response.meta.count || 0
+ count: response.meta.count || 0,
+ meta: _.omit(response.meta, ['filters', 'groups', 'count'])
}, () => {
// if viewing an empty trash
if (this.state.group === 'trash' && response.meta.count === 0) {
// redirect to default group
this.handleGroup('all');
}
+
+ // trigger afterGetItems callback if specified
+ if (this.props.afterGetItems !== undefined) {
+ this.props.afterGetItems(this.state);
+ }
});
- }).fail(function(response) {
+ }).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
@@ -711,7 +718,7 @@ const Listing = React.createClass({
}.bind(this));
},
handleRenderItem: function(item, actions) {
- const render = this.props.onRenderItem(item, actions);
+ const render = this.props.onRenderItem(item, actions, this.state.meta);
return render.props.children;
},
handleRefreshItems: function() {
diff --git a/assets/js/src/newsletters/listings/mixins.jsx b/assets/js/src/newsletters/listings/mixins.jsx
index 3406e203f3..c7d687a4f7 100644
--- a/assets/js/src/newsletters/listings/mixins.jsx
+++ b/assets/js/src/newsletters/listings/mixins.jsx
@@ -1,7 +1,9 @@
import React from 'react'
+import ReactDOM from 'react-dom'
import MailPoet from 'mailpoet'
import classNames from 'classnames'
import jQuery from 'jquery'
+import ListingNotices from 'newsletters/listings/notices.jsx'
const _QueueMixin = {
pauseSending: function(newsletter) {
@@ -180,22 +182,23 @@ const _StatisticsMixin = {
}
const _MailerMixin = {
- resumeSending: function() {
- MailPoet.Ajax.post({
- endpoint: 'mailer',
- action: 'resumeSending'
- }).done(function() {
- jQuery('.mailpoet_sending_status.error').remove();
- MailPoet.Notice.success(MailPoet.I18n.t('mailerSendingResumedNotice'));
- // TODO: refresh listings to update the newsletter queue status
- }).fail((response) => {
- if (response.errors.length > 0) {
- MailPoet.Notice.error(
- response.errors.map(function(error) { return error.message; }),
- { scroll: true }
- );
- }
- });
+ checkMailerStatus: function(state) {
+ if (state.meta.mta_log.error) {
+ MailPoet.Notice.error(
+ '',
+ { static: true, id: 'mailpoet_mailer_error' }
+ );
+
+ ReactDOM.render((
+
+ ), jQuery('[data-id="mailpoet_mailer_error"]')[0]);
+
+ } else {
+ MailPoet.Notice.hide('mailpoet_mailer_error');
+ }
}
}
diff --git a/assets/js/src/newsletters/listings/notices.jsx b/assets/js/src/newsletters/listings/notices.jsx
index 64591a18aa..ed08bfa230 100644
--- a/assets/js/src/newsletters/listings/notices.jsx
+++ b/assets/js/src/newsletters/listings/notices.jsx
@@ -1,37 +1,47 @@
import React from "react";
import MailPoet from "mailpoet";
-import { MailerMixin } from 'newsletters/listings/mixins.jsx'
-
const ListingNotices = React.createClass({
- mixins: [MailerMixin],
- render() {
- // display sending error
- if (this.props.mailer_log.error) {
- let mailer_error_notice = null;
- if (this.props.mailer_log.error.operation === 'send') {
- mailer_error_notice =
- MailPoet.I18n.t('mailerSendErrorNotice')
- .replace('%$1s', this.props.mailer_config.method)
- .replace('%$2s', this.props.mailer_log.error.error_message);
- } else {
- mailer_error_notice =
- MailPoet.I18n.t('mailerConnectionErrorNotice')
- .replace('%$1s', this.props.mailer_log.error.error_message);
+ resumeSending() {
+ MailPoet.Ajax.post({
+ endpoint: 'mailer',
+ action: 'resumeSending'
+ }).done(function() {
+ MailPoet.Notice.hide('mailpoet_mailer_error');
+ MailPoet.Notice.success(MailPoet.I18n.t('mailerSendingResumedNotice'));
+ }).fail((response) => {
+ if (response.errors.length > 0) {
+ MailPoet.Notice.error(
+ response.errors.map(function(error) { return error.message; }),
+ { scroll: true }
+ );
}
- return (
-
- )
+ });
+ },
+ render() {
+ let mailer_error_notice;
+ if (this.props.mta_log.error.operation === 'send') {
+ mailer_error_notice =
+ MailPoet.I18n.t('mailerSendErrorNotice')
+ .replace('%$1s', this.props.mta_method)
+ .replace('%$2s', this.props.mta_log.error.error_message);
+ } else {
+ mailer_error_notice =
+ MailPoet.I18n.t('mailerConnectionErrorNotice')
+ .replace('%$1s', this.props.mta_log.error.error_message);
}
- return null;
+ return (
+
+ );
}
});
diff --git a/assets/js/src/newsletters/listings/notification.jsx b/assets/js/src/newsletters/listings/notification.jsx
index a52882f88e..85918c536c 100644
--- a/assets/js/src/newsletters/listings/notification.jsx
+++ b/assets/js/src/newsletters/listings/notification.jsx
@@ -4,7 +4,8 @@ import { createHashHistory } from 'history'
import Listing from 'listing/listing.jsx'
import ListingTabs from 'newsletters/listings/tabs.jsx'
-import ListingNotices from 'newsletters/listings/notices.jsx'
+
+import { MailerMixin } from 'newsletters/listings/mixins.jsx'
import classNames from 'classnames'
import jQuery from 'jquery'
@@ -18,8 +19,6 @@ import {
} from 'newsletters/scheduling/common.jsx'
const mailpoet_settings = window.mailpoet_settings || {};
-const mailpoet_mailer_log = mailpoet_settings.mta_log || {};
-const mailpoet_mailer_config = mailpoet_settings.mta || {};
const messages = {
onTrash: (response) => {
@@ -158,6 +157,7 @@ const newsletter_actions = [
];
const NewsletterListNotification = React.createClass({
+ mixins: [ MailerMixin ],
updateStatus: function(e) {
// make the event persist so that we can still override the selected value
// in the ajax callback
@@ -316,8 +316,6 @@ const NewsletterListNotification = React.createClass({
{MailPoet.I18n.t('pageTitle')} {MailPoet.I18n.t('new')}
-
-
);
diff --git a/assets/js/src/newsletters/listings/notification_history.jsx b/assets/js/src/newsletters/listings/notification_history.jsx
index 64ea560415..eaced5c474 100644
--- a/assets/js/src/newsletters/listings/notification_history.jsx
+++ b/assets/js/src/newsletters/listings/notification_history.jsx
@@ -6,14 +6,15 @@ import MailPoet from 'mailpoet'
import Listing from 'listing/listing.jsx'
import ListingTabs from 'newsletters/listings/tabs.jsx'
-import ListingNotices from 'newsletters/listings/notices.jsx'
-import { QueueMixin, StatisticsMixin } from 'newsletters/listings/mixins.jsx'
+import {
+ QueueMixin,
+ StatisticsMixin,
+ MailerMixin
+} from 'newsletters/listings/mixins.jsx'
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
const mailpoet_settings = window.mailpoet_settings || {};
-const mailpoet_mailer_log = mailpoet_settings.mta_log || {};
-const mailpoet_mailer_config = mailpoet_settings.mta || {};
const columns = [
{
@@ -53,7 +54,7 @@ const newsletter_actions = [
];
const NewsletterListNotificationHistory = React.createClass({
- mixins: [QueueMixin, StatisticsMixin],
+ mixins: [ QueueMixin, StatisticsMixin, MailerMixin ],
renderItem: function(newsletter, actions) {
const rowClasses = classNames(
'manage-column',
@@ -102,8 +103,6 @@ const NewsletterListNotificationHistory = React.createClass({
{MailPoet.I18n.t('pageTitle')} {MailPoet.I18n.t('new')}
-
-
);
diff --git a/assets/js/src/newsletters/listings/standard.jsx b/assets/js/src/newsletters/listings/standard.jsx
index 33467636ba..08e976df2f 100644
--- a/assets/js/src/newsletters/listings/standard.jsx
+++ b/assets/js/src/newsletters/listings/standard.jsx
@@ -6,14 +6,15 @@ import MailPoet from 'mailpoet'
import Listing from 'listing/listing.jsx'
import ListingTabs from 'newsletters/listings/tabs.jsx'
-import ListingNotices from 'newsletters/listings/notices.jsx'
-import { QueueMixin, StatisticsMixin } from 'newsletters/listings/mixins.jsx'
+import {
+ QueueMixin,
+ StatisticsMixin,
+ MailerMixin
+} from 'newsletters/listings/mixins.jsx'
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
const mailpoet_settings = window.mailpoet_settings || {};
-const mailpoet_mailer_log = mailpoet_settings.mta_log || {};
-const mailpoet_mailer_config = mailpoet_settings.mta || {};
const messages = {
onTrash: (response) => {
@@ -151,8 +152,8 @@ const newsletter_actions = [
];
const NewsletterListStandard = React.createClass({
- mixins: [QueueMixin, StatisticsMixin],
- renderItem: function(newsletter, actions) {
+ mixins: [ QueueMixin, StatisticsMixin, MailerMixin ],
+ renderItem: function(newsletter, actions, meta) {
const rowClasses = classNames(
'manage-column',
'column-primary',
@@ -175,7 +176,7 @@ const NewsletterListStandard = React.createClass({
{ actions }
- { this.renderQueueStatus(newsletter, mailpoet_mailer_log) }
+ { this.renderQueueStatus(newsletter, meta.mta_log) }
|
{ segments }
@@ -198,8 +199,6 @@ const NewsletterListStandard = React.createClass({
{MailPoet.I18n.t('pageTitle')} {MailPoet.I18n.t('new')}
-
-
);
diff --git a/assets/js/src/newsletters/listings/welcome.jsx b/assets/js/src/newsletters/listings/welcome.jsx
index 172336f5ac..e3f382da91 100644
--- a/assets/js/src/newsletters/listings/welcome.jsx
+++ b/assets/js/src/newsletters/listings/welcome.jsx
@@ -4,7 +4,8 @@ import { createHashHistory } from 'history'
import Listing from 'listing/listing.jsx'
import ListingTabs from 'newsletters/listings/tabs.jsx'
-import ListingNotices from 'newsletters/listings/notices.jsx'
+
+import { MailerMixin } from 'newsletters/listings/mixins.jsx'
import classNames from 'classnames'
import jQuery from 'jquery'
@@ -15,8 +16,6 @@ const mailpoet_roles = window.mailpoet_roles || {};
const mailpoet_segments = window.mailpoet_segments || {};
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
const mailpoet_settings = window.mailpoet_settings || {};
-const mailpoet_mailer_log = mailpoet_settings.mta_log || {};
-const mailpoet_mailer_config = mailpoet_settings.mta || {};
const messages = {
onTrash: (response) => {
@@ -155,6 +154,7 @@ const newsletter_actions = [
];
const NewsletterListWelcome = React.createClass({
+ mixins: [ MailerMixin ],
updateStatus: function(e) {
// make the event persist so that we can still override the selected value
// in the ajax callback
@@ -345,8 +345,6 @@ const NewsletterListWelcome = React.createClass({
{ MailPoet.I18n.t('pageTitle') } { MailPoet.I18n.t('new') }
-
-
);
diff --git a/assets/js/src/newsletters/newsletters.jsx b/assets/js/src/newsletters/newsletters.jsx
index 0ed787054e..fd82973843 100644
--- a/assets/js/src/newsletters/newsletters.jsx
+++ b/assets/js/src/newsletters/newsletters.jsx
@@ -27,7 +27,7 @@ const App = React.createClass({
const container = document.getElementById('newsletters_container');
if(container) {
- ReactDOM.render((
+ const mailpoet_listing = ReactDOM.render((
@@ -49,4 +49,6 @@ if(container) {
), container);
+
+ window.mailpoet_listing = mailpoet_listing;
}
diff --git a/assets/js/src/notice.js b/assets/js/src/notice.js
index 43abfdd3c4..668cbfe496 100644
--- a/assets/js/src/notice.js
+++ b/assets/js/src/notice.js
@@ -5,14 +5,14 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
MailPoet Notice:
description: Handles notices
- version: 0.2
+ version: 1.0
author: Jonathan Labreuille
company: Wysija
dependencies: jQuery
Usage:
- // success message (static: false)
+ // success message (static: false)
MailPoet.Notice.success('Yatta!');
// error message (static: false)
@@ -21,199 +21,206 @@ define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
// system message (static: true)
MailPoet.Notice.system('You need to updated ASAP!');
- Examples:
-
- MailPoet.Notice.success('- success #1 -');
- setTimeout(function() {
- MailPoet.Notice.success('- success #2 -');
- setTimeout(function() {
- MailPoet.Notice.error('- error -');
- setTimeout(function() {
- MailPoet.Notice.system('- system -');
-
- setTimeout(function() {
- MailPoet.Notice.hide();
- }, 2500);
- }, 300);
- }, 400);
- }, 500);
-
==================================================================================================*/
MailPoet.Notice = {
- version: 0.2,
- // default options
- defaults: {
- type: 'success',
- message: '',
- static: false,
- hideClose: false,
- id: null,
- positionAfter: false,
- scroll: false,
- timeout: 5000,
- onOpen: null,
- onClose: null
- },
- options: {},
- init: function(options) {
- // set options
- this.options = jQuery.extend({}, this.defaults, options);
+ version: 1.0,
+ // default options
+ defaults: {
+ type: 'success',
+ message: '',
+ static: false,
+ hideClose: false,
+ id: null,
+ positionAfter: false,
+ scroll: false,
+ timeout: 5000,
+ onOpen: null,
+ onClose: null
+ },
+ options: {},
+ init: function(options) {
+ // set options
+ this.options = jQuery.extend({}, this.defaults, options);
- // clone element
- this.element = jQuery('#mailpoet_notice_'+this.options.type).clone();
+ return this;
+ },
+ createNotice: function() {
+ // clone element
+ this.element = jQuery('#mailpoet_notice_'+this.options.type).clone();
- // add data-id to the element
- if (this.options.id) this.element.attr('data-id', 'notice_' + this.options.id);
-
- // remove id from clone
- this.element.removeAttr('id');
-
- // insert notice after its parent
- var positionAfter;
- if (typeof this.options.positionAfter === 'object') {
- positionAfter = this.options.positionAfter;
- } else if (typeof this.options.positionAfter === 'string') {
- positionAfter = jQuery(this.options.positionAfter);
- } else {
- positionAfter = jQuery('#mailpoet_notice_'+this.options.type);
- }
- positionAfter.after(this.element);
-
- // setup onClose callback
- var onClose = null;
- if(this.options.onClose !== null) {
- onClose = this.options.onClose;
- }
-
- // listen to remove event
- jQuery(this.element).on('close', function() {
- jQuery(this).fadeOut(200, function() {
- // on close callback
- if(onClose !== null) {
- onClose();
- }
- // remove notice
- jQuery(this).remove();
- });
- }.bind(this.element));
-
- // listen to message event
- jQuery(this.element).on('message', function(e, message) {
- MailPoet.Notice.setMessage(message);
- }.bind(this.element));
-
- return this;
- },
- isHTML: function(str) {
- var a = document.createElement('div');
- a.innerHTML = str;
- for(var c = a.childNodes, i = c.length; i--;) {
- if(c[i].nodeType == 1) return true;
- }
- return false;
- },
- setMessage: function(message) {
- // if it's not an html message, let's sugar coat the message with a fancy
- if(this.isHTML(message) === false) {
- message = ' '+message+' ';
- }
- // set message
- return this.element.html(message);
- },
- show: function(options) {
- // initialize
- this.init(options);
-
- // show notice
- this.showNotice();
-
- // return this;
- },
- showNotice: function() {
- // set message
- this.setMessage(this.options.message);
-
- // position notice
- this.element.insertAfter(jQuery('h2.title'));
-
- // set class name
- switch(this.options.type) {
- case 'success':
- this.element.addClass('updated');
- break;
- case 'system':
- this.element.addClass('update-nag');
- break;
- case 'error':
- this.element.addClass('error');
- break;
- }
-
- // make the notice appear
- this.element.fadeIn(200);
-
- // if scroll option is enabled, scroll to the notice
- if(this.options.scroll === true) {
- this.element.get(0).scrollIntoView(false);
- }
-
- // 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 if (this.options.hideClose === false) {
- this.element.append('');
- this.element.find('.mailpoet_notice_close').on('click', function() {
- jQuery(this).trigger('close');
- });
- }
-
- // call onOpen callback
- if(this.options.onOpen !== null) {
- this.options.onOpen(this.element);
- }
- },
- hide: function(all) {
- if(all !== undefined && all === true) {
- jQuery('.mailpoet_notice:not([id])').trigger('close');
- } else if (all !== undefined && jQuery.isArray(all)) {
- for (var id in all) {
- jQuery('[data-id="notice_' + all[id] + '"]')
- .trigger('close');
- }
- } if (all !== undefined) {
- jQuery('[data-id="notice_' + all + '"]')
- .trigger('close');
- } else {
- jQuery('.mailpoet_notice.updated:not([id]), .mailpoet_notice.error:not([id])')
- .trigger('close');
- }
- },
- error: function(message, options) {
- this.show(jQuery.extend({}, {
- type: 'error',
- message: ''+this.formatMessage(message)+' '
- }, options));
- },
- success: function(message, options) {
- this.show(jQuery.extend({}, {
- type: 'success',
- message: ''+this.formatMessage(message)+' '
- }, options));
- },
- system: function(message, options) {
- this.show(jQuery.extend({}, {
- type: 'system',
- static: true,
- message: ''+this.formatMessage(message)+' '
- }, options));
- },
- formatMessage: function(message) {
- if(Array.isArray(message)) {
- return message.join(' ');
- } else {
- return message;
- }
+ // add data-id to the element
+ if (this.options.id) {
+ this.element.attr(
+ 'data-id',
+ this.options.id
+ );
}
+
+ // remove id from clone
+ this.element.removeAttr('id');
+
+ // insert notice after its parent
+ var positionAfter;
+ if (typeof this.options.positionAfter === 'object') {
+ positionAfter = this.options.positionAfter;
+ } else if (typeof this.options.positionAfter === 'string') {
+ positionAfter = jQuery(this.options.positionAfter);
+ } else {
+ positionAfter = jQuery('#mailpoet_notice_'+this.options.type);
+ }
+ positionAfter.after(this.element);
+
+ // setup onClose callback
+ var onClose = null;
+ if (this.options.onClose !== null) {
+ onClose = this.options.onClose;
+ }
+
+ // listen to remove event
+ jQuery(this.element).on('close', function() {
+ jQuery(this).fadeOut(200, function() {
+ // on close callback
+ if (onClose !== null) {
+ onClose();
+ }
+ // remove notice
+ jQuery(this).remove();
+ });
+ }.bind(this.element));
+
+ // listen to message event
+ jQuery(this.element).on('setMessage', function(e, message) {
+ MailPoet.Notice.setMessage(message);
+ }.bind(this.element));
+
+ return this;
+ },
+ updateNotice: function() {
+ // update notice's message
+ jQuery('[data-id="'+this.options.id+'"').first().trigger(
+ 'setMessage', this.options.message
+ );
+ },
+ isHTML: function(str) {
+ var a = document.createElement('div');
+ a.innerHTML = str;
+ for (var c = a.childNodes, i = c.length; i--;) {
+ if (c[i].nodeType == 1) return true;
+ }
+ return false;
+ },
+ setMessage: function(message) {
+ message = this.formatMessage(message);
+
+ // if it's not an html message
+ // let's sugar coat the message with a fancy
+ if (this.isHTML(message) === false) {
+ message = ' '+message+' ';
+ }
+ // set message
+ return this.element.html(message);
+ },
+ formatMessage: function(message) {
+ if (Array.isArray(message)) {
+ return message.join(' ');
+ } else {
+ return message;
+ }
+ },
+ show: function(options) {
+ // initialize
+ this.init(options);
+
+ if (
+ this.options.id !== null
+ &&
+ jQuery('[data-id="'+this.options.id+'"').length > 0
+ ) {
+ this.updateNotice();
+ } else {
+ this.createNotice();
+ }
+ this.showNotice();
+ },
+ showNotice: function() {
+ // set message
+ this.setMessage(this.options.message);
+
+ // position notice
+ this.element.insertAfter(jQuery('h2.title'));
+
+ // set class name
+ switch (this.options.type) {
+ case 'success':
+ this.element.addClass('updated');
+ break;
+ case 'system':
+ this.element.addClass('update-nag');
+ break;
+ case 'error':
+ this.element.addClass('error');
+ break;
+ }
+
+ // make the notice appear
+ this.element.fadeIn(200);
+
+ // if scroll option is enabled, scroll to the notice
+ if (this.options.scroll === true) {
+ this.element.get(0).scrollIntoView(false);
+ }
+
+ // 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 if (this.options.hideClose === false) {
+ this.element.append('');
+ this.element.find('.mailpoet_notice_close').on('click', function() {
+ jQuery(this).trigger('close');
+ });
+ }
+
+ // call onOpen callback
+ if (this.options.onOpen !== null) {
+ this.options.onOpen(this.element);
+ }
+ },
+ hide: function(all) {
+ if (all !== undefined && all === true) {
+ // all notices
+ jQuery('.mailpoet_notice:not([id])').trigger('close');
+ } else if (all !== undefined && jQuery.isArray(all)) {
+ // array of ids
+ for (var id in all) {
+ jQuery('[data-id="' + all[id] + '"]').trigger('close');
+ }
+ } if (all !== undefined) {
+ // single id
+ jQuery('[data-id="' + all + '"]').trigger('close');
+ } else {
+ jQuery('.mailpoet_notice.updated:not([id]), .mailpoet_notice.error:not([id])')
+ .trigger('close');
+ }
+ },
+ error: function(message, options) {
+ this.show(jQuery.extend({}, {
+ type: 'error',
+ message: message
+ }, options));
+ },
+ success: function(message, options) {
+ this.show(jQuery.extend({}, {
+ type: 'success',
+ message: message
+ }, options));
+ },
+ system: function(message, options) {
+ this.show(jQuery.extend({}, {
+ type: 'system',
+ static: true,
+ message: message
+ }, options));
+ }
};
});
diff --git a/lib/API/Endpoints/Newsletters.php b/lib/API/Endpoints/Newsletters.php
index 2f5284b634..7d5eee8add 100644
--- a/lib/API/Endpoints/Newsletters.php
+++ b/lib/API/Endpoints/Newsletters.php
@@ -346,7 +346,9 @@ class Newsletters extends APIEndpoint {
return $this->successResponse($data, array(
'count' => $listing_data['count'],
'filters' => $listing_data['filters'],
- 'groups' => $listing_data['groups']
+ 'groups' => $listing_data['groups'],
+ 'mta_log' => Setting::getValue('mta_log'),
+ 'mta_method' => Setting::getValue('mta.method')
));
}
|