Move mailer error below tabs
This commit is contained in:
committed by
M. Shull
parent
569ac522cf
commit
71634e65a8
@@ -12,6 +12,7 @@ import ListingSearch from 'listing/search.jsx';
|
|||||||
import ListingGroups from 'listing/groups.jsx';
|
import ListingGroups from 'listing/groups.jsx';
|
||||||
import ListingFilters from 'listing/filters.jsx';
|
import ListingFilters from 'listing/filters.jsx';
|
||||||
import ListingItems from 'listing/listing_items.jsx';
|
import ListingItems from 'listing/listing_items.jsx';
|
||||||
|
import MailerError from 'listing/notices.jsx';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
const Listing = createReactClass({ // eslint-disable-line react/prefer-es6-class
|
const Listing = createReactClass({ // eslint-disable-line react/prefer-es6-class
|
||||||
@@ -636,97 +637,100 @@ const Listing = createReactClass({ // eslint-disable-line react/prefer-es6-class
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
{ groups }
|
{ this.state.meta.mta_method && <MailerError {...this.state.meta} /> }
|
||||||
{ search }
|
<div>
|
||||||
<div className="tablenav top clearfix">
|
{ groups }
|
||||||
<ListingBulkActions
|
{ search }
|
||||||
count={this.state.count}
|
<div className="tablenav top clearfix">
|
||||||
bulk_actions={bulkActions}
|
<ListingBulkActions
|
||||||
selection={this.state.selection}
|
count={this.state.count}
|
||||||
selected_ids={this.state.selected_ids}
|
bulk_actions={bulkActions}
|
||||||
onBulkAction={this.handleBulkAction}
|
|
||||||
/>
|
|
||||||
<ListingFilters
|
|
||||||
filters={this.state.filters}
|
|
||||||
filter={this.state.filter}
|
|
||||||
group={this.state.group}
|
|
||||||
onBeforeSelectFilter={this.props.onBeforeSelectFilter || null}
|
|
||||||
onSelectFilter={this.handleFilter}
|
|
||||||
onEmptyTrash={this.handleEmptyTrash}
|
|
||||||
/>
|
|
||||||
{extraActions}
|
|
||||||
<ListingPages
|
|
||||||
count={this.state.count}
|
|
||||||
page={this.state.page}
|
|
||||||
limit={this.state.limit}
|
|
||||||
onSetPage={this.handleSetPage}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<table className={tableClasses}>
|
|
||||||
<thead>
|
|
||||||
<ListingHeader
|
|
||||||
onSort={this.handleSort}
|
|
||||||
onSelectItems={this.handleSelectItems}
|
|
||||||
selection={this.state.selection}
|
selection={this.state.selection}
|
||||||
sort_by={sortBy}
|
selected_ids={this.state.selected_ids}
|
||||||
sort_order={sortOrder}
|
onBulkAction={this.handleBulkAction}
|
||||||
|
/>
|
||||||
|
<ListingFilters
|
||||||
|
filters={this.state.filters}
|
||||||
|
filter={this.state.filter}
|
||||||
|
group={this.state.group}
|
||||||
|
onBeforeSelectFilter={this.props.onBeforeSelectFilter || null}
|
||||||
|
onSelectFilter={this.handleFilter}
|
||||||
|
onEmptyTrash={this.handleEmptyTrash}
|
||||||
|
/>
|
||||||
|
{extraActions}
|
||||||
|
<ListingPages
|
||||||
|
count={this.state.count}
|
||||||
|
page={this.state.page}
|
||||||
|
limit={this.state.limit}
|
||||||
|
onSetPage={this.handleSetPage}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<table className={tableClasses}>
|
||||||
|
<thead>
|
||||||
|
<ListingHeader
|
||||||
|
onSort={this.handleSort}
|
||||||
|
onSelectItems={this.handleSelectItems}
|
||||||
|
selection={this.state.selection}
|
||||||
|
sort_by={sortBy}
|
||||||
|
sort_order={sortOrder}
|
||||||
|
columns={columns}
|
||||||
|
is_selectable={bulkActions.length > 0}
|
||||||
|
/>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<ListingItems
|
||||||
|
onRenderItem={this.handleRenderItem}
|
||||||
|
getListingItemKey={this.props.getListingItemKey}
|
||||||
|
onDeleteItem={this.handleDeleteItem}
|
||||||
|
onRestoreItem={this.handleRestoreItem}
|
||||||
|
onTrashItem={this.handleTrashItem}
|
||||||
|
onRefreshItems={this.handleRefreshItems}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
is_selectable={bulkActions.length > 0}
|
is_selectable={bulkActions.length > 0}
|
||||||
/>
|
onSelectItem={this.handleSelectItem}
|
||||||
</thead>
|
onSelectAll={this.handleSelectAll}
|
||||||
|
|
||||||
<ListingItems
|
|
||||||
onRenderItem={this.handleRenderItem}
|
|
||||||
getListingItemKey={this.props.getListingItemKey}
|
|
||||||
onDeleteItem={this.handleDeleteItem}
|
|
||||||
onRestoreItem={this.handleRestoreItem}
|
|
||||||
onTrashItem={this.handleTrashItem}
|
|
||||||
onRefreshItems={this.handleRefreshItems}
|
|
||||||
columns={columns}
|
|
||||||
is_selectable={bulkActions.length > 0}
|
|
||||||
onSelectItem={this.handleSelectItem}
|
|
||||||
onSelectAll={this.handleSelectAll}
|
|
||||||
selection={this.state.selection}
|
|
||||||
selected_ids={this.state.selected_ids}
|
|
||||||
loading={this.state.loading}
|
|
||||||
group={this.state.group}
|
|
||||||
count={this.state.count}
|
|
||||||
limit={this.state.limit}
|
|
||||||
item_actions={itemActions}
|
|
||||||
messages={messages}
|
|
||||||
items={items}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<tfoot>
|
|
||||||
<ListingHeader
|
|
||||||
onSort={this.handleSort}
|
|
||||||
onSelectItems={this.handleSelectItems}
|
|
||||||
selection={this.state.selection}
|
selection={this.state.selection}
|
||||||
sort_by={sortBy}
|
selected_ids={this.state.selected_ids}
|
||||||
sort_order={sortOrder}
|
loading={this.state.loading}
|
||||||
columns={columns}
|
group={this.state.group}
|
||||||
is_selectable={bulkActions.length > 0}
|
count={this.state.count}
|
||||||
|
limit={this.state.limit}
|
||||||
|
item_actions={itemActions}
|
||||||
|
messages={messages}
|
||||||
|
items={items}
|
||||||
/>
|
/>
|
||||||
</tfoot>
|
|
||||||
|
|
||||||
</table>
|
<tfoot>
|
||||||
<div className="tablenav bottom">
|
<ListingHeader
|
||||||
<ListingBulkActions
|
onSort={this.handleSort}
|
||||||
count={this.state.count}
|
onSelectItems={this.handleSelectItems}
|
||||||
bulk_actions={bulkActions}
|
selection={this.state.selection}
|
||||||
selection={this.state.selection}
|
sort_by={sortBy}
|
||||||
selected_ids={this.state.selected_ids}
|
sort_order={sortOrder}
|
||||||
onBulkAction={this.handleBulkAction}
|
columns={columns}
|
||||||
/>
|
is_selectable={bulkActions.length > 0}
|
||||||
<ListingPages
|
/>
|
||||||
count={this.state.count}
|
</tfoot>
|
||||||
page={this.state.page}
|
|
||||||
limit={this.state.limit}
|
</table>
|
||||||
onSetPage={this.handleSetPage}
|
<div className="tablenav bottom">
|
||||||
/>
|
<ListingBulkActions
|
||||||
|
count={this.state.count}
|
||||||
|
bulk_actions={bulkActions}
|
||||||
|
selection={this.state.selection}
|
||||||
|
selected_ids={this.state.selected_ids}
|
||||||
|
onBulkAction={this.handleBulkAction}
|
||||||
|
/>
|
||||||
|
<ListingPages
|
||||||
|
count={this.state.count}
|
||||||
|
page={this.state.page}
|
||||||
|
limit={this.state.limit}
|
||||||
|
onSetPage={this.handleSetPage}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
111
assets/js/src/listing/notices.jsx
Normal file
111
assets/js/src/listing/notices.jsx
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import MailPoet from 'mailpoet';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import ReactStringReplace from 'react-string-replace';
|
||||||
|
|
||||||
|
const resumeMailerSending = () => {
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
api_version: window.mailpoet_api_version,
|
||||||
|
endpoint: 'mailer',
|
||||||
|
action: 'resumeSending',
|
||||||
|
}).done(() => {
|
||||||
|
MailPoet.Notice.success(MailPoet.I18n.t('mailerSendingResumedNotice'));
|
||||||
|
window.mailpoet_listing.forceUpdate();
|
||||||
|
}).fail((response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(error => error.message),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function MailerError(props) {
|
||||||
|
if (props.mta_log.error && props.mta_log.status === 'paused' && props.mta_log.error.operation !== 'authorization') {
|
||||||
|
if (props.mta_log.error.operation === 'migration') {
|
||||||
|
return (
|
||||||
|
<div className="mailpoet_notice notice notice-warning">
|
||||||
|
<p>{ props.mta_log.error.error_message }</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = props.mta_log.error.error_message;
|
||||||
|
const code = props.mta_log.error.error_code;
|
||||||
|
if (code) {
|
||||||
|
message += message ? ', ' : '';
|
||||||
|
message += MailPoet.I18n.t('mailerErrorCode').replace('%$1s', code);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="mailpoet_notice notice notice-error">
|
||||||
|
<p>
|
||||||
|
{
|
||||||
|
props.mta_log.error.operation === 'send'
|
||||||
|
? MailPoet.I18n.t('mailerSendErrorNotice').replace('%$1s', props.mta_method)
|
||||||
|
: MailPoet.I18n.t('mailerConnectionErrorNotice')
|
||||||
|
}
|
||||||
|
:
|
||||||
|
{' '}
|
||||||
|
<i>{ message }</i>
|
||||||
|
</p>
|
||||||
|
{ props.mta_method === 'PHPMail' ? <PHPMailerCheckSettingsNotice /> : <MailerCheckSettingsNotice /> }
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
href="javascript:;"
|
||||||
|
className="button button-primary"
|
||||||
|
onClick={resumeMailerSending}
|
||||||
|
>
|
||||||
|
{ MailPoet.I18n.t('mailerResumeSendingButton') }
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MailerError.propTypes = {
|
||||||
|
mta_method: PropTypes.string.isRequired,
|
||||||
|
mta_log: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
};
|
||||||
|
|
||||||
|
const PHPMailerCheckSettingsNotice = () => (
|
||||||
|
<Fragment>
|
||||||
|
<p>{ MailPoet.I18n.t('mailerSendErrorCheckConfiguration') }</p>
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
{
|
||||||
|
ReactStringReplace(
|
||||||
|
MailPoet.I18n.t('mailerSendErrorUseSendingService'),
|
||||||
|
/<b>(.*?)<\/b>/g,
|
||||||
|
(match, key) => <b key={key}>{ match }</b>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
href="https://www.mailpoet.com/free-plan/?utm_source=plugin&utm_campaign=sending-error"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
{ MailPoet.I18n.t('mailerSendErrorSignUpForSendingService') }
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
const MailerCheckSettingsNotice = () => (
|
||||||
|
<p>
|
||||||
|
{
|
||||||
|
ReactStringReplace(
|
||||||
|
MailPoet.I18n.t('mailerCheckSettingsNotice'),
|
||||||
|
/\[link\](.*?)\[\/link\]/g,
|
||||||
|
match => <a href="?page=mailpoet-settings#mta" key="check-sending">{ match }</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default MailerError;
|
@@ -407,134 +407,6 @@ const MailerMixin = {
|
|||||||
jQuery('[data-id="mailpoet_authorization_error"]').slideUp();
|
jQuery('[data-id="mailpoet_authorization_error"]').slideUp();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
state.meta.mta_log.error
|
|
||||||
&& state.meta.mta_log.status === 'paused'
|
|
||||||
&& state.meta.mta_log.error.operation !== 'authorization'
|
|
||||||
) {
|
|
||||||
const errorType = MailerMixin.getMailerErrorType(state);
|
|
||||||
let container = jQuery('[data-id="mailpoet_mailer_error"]')[0];
|
|
||||||
if (!container) {
|
|
||||||
MailPoet.Notice[errorType](
|
|
||||||
'',
|
|
||||||
{ static: true, id: 'mailpoet_mailer_error' }
|
|
||||||
);
|
|
||||||
container = jQuery('[data-id="mailpoet_mailer_error"]')[0];
|
|
||||||
}
|
|
||||||
ReactDOM.render(
|
|
||||||
MailerMixin.getMailerError(state),
|
|
||||||
container
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
MailPoet.Notice.hide('mailpoet_mailer_error');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getMailerError(state) {
|
|
||||||
if (state.meta.mta_log.error.operation === 'migration') {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<p>{ state.meta.mta_log.error.error_message }</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// offer MSS when PHPMail is failing
|
|
||||||
let mailerErrorCheckSettings;
|
|
||||||
if (state.meta.mta_method === 'PHPMail') {
|
|
||||||
mailerErrorCheckSettings = (
|
|
||||||
<>
|
|
||||||
<p>{ MailPoet.I18n.t('mailerSendErrorCheckConfiguration') }</p>
|
|
||||||
<br />
|
|
||||||
<p>
|
|
||||||
{
|
|
||||||
ReactStringReplace(
|
|
||||||
MailPoet.I18n.t('mailerSendErrorUseSendingService'),
|
|
||||||
/<b>(.*?)<\/b>/g,
|
|
||||||
(match, key) => <b key={key}>{ match }</b>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
href="https://www.mailpoet.com/free-plan/?utm_source=plugin&utm_campaign=sending-error"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{ MailPoet.I18n.t('mailerSendErrorSignUpForSendingService') }
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
mailerErrorCheckSettings = (
|
|
||||||
<p>
|
|
||||||
{
|
|
||||||
ReactStringReplace(
|
|
||||||
MailPoet.I18n.t('mailerCheckSettingsNotice'),
|
|
||||||
/\[link\](.*?)\[\/link\]/g,
|
|
||||||
match => <a href="?page=mailpoet-settings#mta" key="check-sending">{ match }</a>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// append error code if available
|
|
||||||
let mailerErrorMessage = state.meta.mta_log.error.error_message;
|
|
||||||
if (state.meta.mta_log.error.error_code) {
|
|
||||||
mailerErrorMessage += mailerErrorMessage ? ', ' : '';
|
|
||||||
mailerErrorMessage += MailPoet.I18n.t('mailerErrorCode').replace('%$1s', state.meta.mta_log.error.error_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
{
|
|
||||||
state.meta.mta_log.error.operation === 'send'
|
|
||||||
? MailPoet.I18n.t('mailerSendErrorNotice').replace('%$1s', state.meta.mta_method)
|
|
||||||
: MailPoet.I18n.t('mailerConnectionErrorNotice')
|
|
||||||
}
|
|
||||||
:
|
|
||||||
{' '}
|
|
||||||
<i>{ mailerErrorMessage }</i>
|
|
||||||
</p>
|
|
||||||
{ mailerErrorCheckSettings }
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
className="button button-primary"
|
|
||||||
onClick={MailerMixin.resumeMailerSending}
|
|
||||||
>
|
|
||||||
{ MailPoet.I18n.t('mailerResumeSendingButton') }
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getMailerErrorType(state) {
|
|
||||||
if (state.meta.mta_log.error.operation === 'migration') {
|
|
||||||
return 'system';
|
|
||||||
}
|
|
||||||
return 'error';
|
|
||||||
},
|
|
||||||
resumeMailerSending() {
|
|
||||||
MailPoet.Ajax.post({
|
|
||||||
api_version: window.mailpoet_api_version,
|
|
||||||
endpoint: 'mailer',
|
|
||||||
action: 'resumeSending',
|
|
||||||
}).done(() => {
|
|
||||||
MailPoet.Notice.hide('mailpoet_mailer_error');
|
|
||||||
MailPoet.Notice.success(MailPoet.I18n.t('mailerSendingResumedNotice'));
|
|
||||||
window.mailpoet_listing.forceUpdate();
|
|
||||||
}).fail((response) => {
|
|
||||||
if (response.errors.length > 0) {
|
|
||||||
MailPoet.Notice.error(
|
|
||||||
response.errors.map(error => error.message),
|
|
||||||
{ scroll: true }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -18,7 +18,7 @@ class NewsletterSendingErrorCest {
|
|||||||
$settings->withSendingError($errorMessage);
|
$settings->withSendingError($errorMessage);
|
||||||
|
|
||||||
$I->amOnMailpoetPage('Emails');
|
$I->amOnMailpoetPage('Emails');
|
||||||
$I->waitForElement('.mailpoet_notice.notice-error div');
|
$I->waitForElement('div.mailpoet_notice.notice-error');
|
||||||
$I->see('Sending has been paused due to a technical issue with SMTP: ' . $errorMessage, '.notice-error p');
|
$I->see('Sending has been paused due to a technical issue with SMTP: ' . $errorMessage, '.notice-error p');
|
||||||
$I->see('Check your sending method settings.', '.notice-error p');
|
$I->see('Check your sending method settings.', '.notice-error p');
|
||||||
$I->see('Resume sending', '.notice-error p');
|
$I->see('Resume sending', '.notice-error p');
|
||||||
@@ -40,7 +40,7 @@ class NewsletterSendingErrorCest {
|
|||||||
$settings->withSendingError($errorMessage);
|
$settings->withSendingError($errorMessage);
|
||||||
|
|
||||||
$I->amOnMailpoetPage('Emails');
|
$I->amOnMailpoetPage('Emails');
|
||||||
$I->waitForElement('.mailpoet_notice.notice-error div');
|
$I->waitForElement('div.mailpoet_notice.notice-error');
|
||||||
$I->see('Sending has been paused due to a technical issue with PHPMail: ' . $errorMessage, '.notice-error p');
|
$I->see('Sending has been paused due to a technical issue with PHPMail: ' . $errorMessage, '.notice-error p');
|
||||||
$I->see('Please check your sending method configuration, you may need to consult with your hosting company.', '.notice-error p');
|
$I->see('Please check your sending method configuration, you may need to consult with your hosting company.', '.notice-error p');
|
||||||
$I->see('The easy alternative is to send emails with MailPoet Sending Service instead, like thousands of other users do.', '.notice-error p');
|
$I->see('The easy alternative is to send emails with MailPoet Sending Service instead, like thousands of other users do.', '.notice-error p');
|
||||||
|
Reference in New Issue
Block a user