Add a green box in stats for recently sent newsletters, add help KB link [MAILPOET-877]
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
$excellent-badge-color = #2993ab
|
$excellent-badge-color = #2993ab
|
||||||
$good-badge-color = #f0b849
|
$good-badge-color = #f0b849
|
||||||
$bad-badge-color = #d54e21
|
$bad-badge-color = #d54e21
|
||||||
|
$green-badge-color = #55bd56
|
||||||
$grey-stat-color = #707070
|
$grey-stat-color = #707070
|
||||||
|
|
||||||
#newsletters_container
|
#newsletters_container
|
||||||
@ -39,6 +40,10 @@ $grey-stat-color = #707070
|
|||||||
&_hidden
|
&_hidden
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
|
&_link_small
|
||||||
|
text-decoration: underline !important
|
||||||
|
font-size: 0.75rem
|
||||||
|
|
||||||
.mailpoet_badge
|
.mailpoet_badge
|
||||||
padding: 4px 6px 3px 6px
|
padding: 4px 6px 3px 6px
|
||||||
color: #FFFFFF
|
color: #FFFFFF
|
||||||
@ -57,3 +62,6 @@ $grey-stat-color = #707070
|
|||||||
|
|
||||||
&_bad
|
&_bad
|
||||||
background: $bad-badge-color
|
background: $bad-badge-color
|
||||||
|
|
||||||
|
&_green
|
||||||
|
background: $green-badge-color
|
||||||
|
@ -10,7 +10,7 @@ class Badge extends React.Component {
|
|||||||
this.props.size ? `mailpoet_badge_size_${this.props.size}` : ''
|
this.props.size ? `mailpoet_badge_size_${this.props.size}` : ''
|
||||||
);
|
);
|
||||||
|
|
||||||
const tooltip = this.props.tooltip.replace(/\n/g, '<br />') || false;
|
const tooltip = this.props.tooltip ? this.props.tooltip.replace(/\n/g, '<br />') : false;
|
||||||
// tooltip ID must be unique, defaults to tooltip text
|
// tooltip ID must be unique, defaults to tooltip text
|
||||||
const tooltipId = this.props.tooltipId || tooltip;
|
const tooltipId = this.props.tooltipId || tooltip;
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import ReactStringReplace from 'react-string-replace'
|
|||||||
import { Link } from 'react-router'
|
import { Link } from 'react-router'
|
||||||
import MailPoet from 'mailpoet'
|
import MailPoet from 'mailpoet'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
import moment from 'moment'
|
||||||
import jQuery from 'jquery'
|
import jQuery from 'jquery'
|
||||||
import Hooks from 'wp-js-hooks'
|
import Hooks from 'wp-js-hooks'
|
||||||
import StatsBadge from 'newsletters/badges/stats.jsx'
|
import StatsBadge from 'newsletters/badges/stats.jsx'
|
||||||
@ -143,14 +144,14 @@ const _QueueMixin = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const _StatisticsMixin = {
|
const _StatisticsMixin = {
|
||||||
renderStatistics: function(newsletter, sentCondition) {
|
renderStatistics: function(newsletter, sent_condition, current_time) {
|
||||||
if (sentCondition === undefined) {
|
if (sent_condition === undefined) {
|
||||||
// condition for standard and post notification listings
|
// condition for standard and post notification listings
|
||||||
sentCondition = newsletter.statistics
|
sent_condition = newsletter.statistics
|
||||||
&& newsletter.queue
|
&& newsletter.queue
|
||||||
&& newsletter.queue.status !== 'scheduled'
|
&& newsletter.queue.status !== 'scheduled'
|
||||||
}
|
}
|
||||||
if (!sentCondition) {
|
if (!sent_condition) {
|
||||||
return (
|
return (
|
||||||
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
||||||
);
|
);
|
||||||
@ -177,8 +178,19 @@ const _StatisticsMixin = {
|
|||||||
const percentage_opened_display = MailPoet.Num.toLocaleFixed(percentage_opened, 1);
|
const percentage_opened_display = MailPoet.Num.toLocaleFixed(percentage_opened, 1);
|
||||||
const percentage_unsubscribed_display = MailPoet.Num.toLocaleFixed(percentage_unsubscribed, 1);
|
const percentage_unsubscribed_display = MailPoet.Num.toLocaleFixed(percentage_unsubscribed, 1);
|
||||||
|
|
||||||
|
// green box for newsletters that were just sent
|
||||||
|
const show_stats_timeout = 6; // in hours
|
||||||
|
const newsletter_date = newsletter.queue.scheduled_at || newsletter.queue.created_at;
|
||||||
|
const sent_hours_ago = moment(current_time).diff(moment(newsletter_date), 'hours');
|
||||||
|
const too_early_for_stats = sent_hours_ago < show_stats_timeout;
|
||||||
|
|
||||||
|
const improveStatsKBLink = 'http://beta.docs.mailpoet.com/article/190-whats-a-good-email-open-rate';
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
if (total_sent >= 20 && newsletter.statistics.opened >= 5) {
|
if (total_sent >= 20
|
||||||
|
&& newsletter.statistics.opened >= 5
|
||||||
|
&& !too_early_for_stats
|
||||||
|
) {
|
||||||
// display stats with badges
|
// display stats with badges
|
||||||
content = (
|
content = (
|
||||||
<div className="mailpoet_stats_text">
|
<div className="mailpoet_stats_text">
|
||||||
@ -206,27 +218,65 @@ const _StatisticsMixin = {
|
|||||||
} else {
|
} else {
|
||||||
// display simple stats
|
// display simple stats
|
||||||
content = (
|
content = (
|
||||||
<span className="mailpoet_stats_text">
|
<div>
|
||||||
{ percentage_opened_display }%,
|
<span className="mailpoet_stats_text">
|
||||||
{ " " }
|
{ percentage_opened_display }%,
|
||||||
{ percentage_clicked_display }%
|
{ " " }
|
||||||
<span className="mailpoet_stat_hidden">
|
{ percentage_clicked_display }%
|
||||||
, { percentage_unsubscribed_display }%
|
<span className="mailpoet_stat_hidden">
|
||||||
|
, { percentage_unsubscribed_display }%
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
{ too_early_for_stats && (
|
||||||
|
<div className="mailpoet_badge mailpoet_badge_green">
|
||||||
|
{MailPoet.I18n.t('checkBackInHours')
|
||||||
|
.replace('%$1d', show_stats_timeout - sent_hours_ago)}
|
||||||
|
</div>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (total_sent > 0 && params.link) {
|
let after_content;
|
||||||
|
if (percentage_opened < 5
|
||||||
|
&& sent_hours_ago >= 24
|
||||||
|
&& total_sent >= 10
|
||||||
|
) {
|
||||||
|
// help link for bad open rate
|
||||||
|
after_content = (
|
||||||
|
<div>
|
||||||
|
<a
|
||||||
|
href={improveStatsKBLink}
|
||||||
|
target="_blank"
|
||||||
|
className="mailpoet_stat_link_small"
|
||||||
|
>
|
||||||
|
{MailPoet.I18n.t('improveThisLinkText')}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total_sent > 0 && !too_early_for_stats && params.link) {
|
||||||
|
// wrap content in a link
|
||||||
return (
|
return (
|
||||||
<Link
|
<div>
|
||||||
key={ `stats-${newsletter.id}` }
|
<Link
|
||||||
to={ params.link }
|
key={ `stats-${newsletter.id}` }
|
||||||
>{ content }</Link>
|
to={ params.link }
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</Link>
|
||||||
|
{after_content}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return (
|
||||||
|
<div>
|
||||||
|
{content}
|
||||||
|
{after_content}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ const NewsletterListNotificationHistory = React.createClass({
|
|||||||
</td>
|
</td>
|
||||||
{ (mailpoet_tracking_enabled === true) ? (
|
{ (mailpoet_tracking_enabled === true) ? (
|
||||||
<td className="column" data-colname={ MailPoet.I18n.t('statistics') }>
|
<td className="column" data-colname={ MailPoet.I18n.t('statistics') }>
|
||||||
{ this.renderStatistics(newsletter) }
|
{ this.renderStatistics(newsletter, undefined, meta.current_time) }
|
||||||
</td>
|
</td>
|
||||||
) : null }
|
) : null }
|
||||||
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
||||||
|
@ -184,7 +184,7 @@ const NewsletterListStandard = React.createClass({
|
|||||||
</td>
|
</td>
|
||||||
{ (mailpoet_tracking_enabled === true) ? (
|
{ (mailpoet_tracking_enabled === true) ? (
|
||||||
<td className="column" data-colname={ MailPoet.I18n.t('statistics') }>
|
<td className="column" data-colname={ MailPoet.I18n.t('statistics') }>
|
||||||
{ this.renderStatistics(newsletter) }
|
{ this.renderStatistics(newsletter, undefined, meta.current_time) }
|
||||||
</td>
|
</td>
|
||||||
) : null }
|
) : null }
|
||||||
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
||||||
|
@ -372,7 +372,8 @@ class Newsletters extends APIEndpoint {
|
|||||||
'filters' => $listing_data['filters'],
|
'filters' => $listing_data['filters'],
|
||||||
'groups' => $listing_data['groups'],
|
'groups' => $listing_data['groups'],
|
||||||
'mta_log' => Setting::getValue('mta_log'),
|
'mta_log' => Setting::getValue('mta_log'),
|
||||||
'mta_method' => Setting::getValue('mta.method')
|
'mta_method' => Setting::getValue('mta.method'),
|
||||||
|
'current_time' => current_time('mysql')
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +99,8 @@
|
|||||||
'openedStatTooltip': __('Above 30% is excellent.\\nBetween 15 and 30% is good.\\nUnder 15% is bad.'),
|
'openedStatTooltip': __('Above 30% is excellent.\\nBetween 15 and 30% is good.\\nUnder 15% is bad.'),
|
||||||
'clickedStatTooltip': __('Above 3% is excellent.\\nBetween 1 and 3% is good.\\nUnder 1% is bad.'),
|
'clickedStatTooltip': __('Above 3% is excellent.\\nBetween 1 and 3% is good.\\nUnder 1% is bad.'),
|
||||||
'unsubscribedStatTooltip': __('Under 1% is excellent.\\nBetween 1 and 3% is good.\\nOver 3% is bad.'),
|
'unsubscribedStatTooltip': __('Under 1% is excellent.\\nBetween 1 and 3% is good.\\nOver 3% is bad.'),
|
||||||
|
'checkBackInHours': __('Nice job! Check back in %$1d hour(s) for more stats.'),
|
||||||
|
'improveThisLinkText': __('What can I do to improve this?'),
|
||||||
|
|
||||||
'templateFileMalformedError': __('This template file appears to be damaged. Please try another one.'),
|
'templateFileMalformedError': __('This template file appears to be damaged. Please try another one.'),
|
||||||
'importTemplateTitle': __('Import a template'),
|
'importTemplateTitle': __('Import a template'),
|
||||||
|
Reference in New Issue
Block a user