Rewrite renderStatistics as a React component
This commit is contained in:
committed by
M. Shull
parent
d9857731ea
commit
b1d521f929
@ -1,247 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import ReactStringReplace from 'react-string-replace';
|
import ReactStringReplace from 'react-string-replace';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import MailPoet from 'mailpoet';
|
import MailPoet from 'mailpoet';
|
||||||
import moment from 'moment';
|
|
||||||
import jQuery from 'jquery';
|
import jQuery from 'jquery';
|
||||||
import Hooks from 'wp-js-hooks';
|
|
||||||
import StatsBadge from 'newsletters/badges/stats.jsx';
|
|
||||||
import HelpTooltip from 'help-tooltip.jsx';
|
|
||||||
|
|
||||||
function trackStatsCTAClicked() {
|
export const trackStatsCTAClicked = () => {
|
||||||
MailPoet.trackEvent(
|
MailPoet.trackEvent(
|
||||||
'User has clicked a CTA to view detailed stats',
|
'User has clicked a CTA to view detailed stats',
|
||||||
{ 'MailPoet Free version': window.mailpoet_version }
|
{ 'MailPoet Free version': window.mailpoet_version }
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
function wrapInLink(content, params, id, totalSent) {
|
|
||||||
if (totalSent <= 0 || !params.link) {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.externalLink) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
key={`stats-${id}`}
|
|
||||||
href={params.link}
|
|
||||||
onClick={params.onClick || null}
|
|
||||||
>
|
|
||||||
{content}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
key={`stats-${id}`}
|
|
||||||
to={params.link}
|
|
||||||
onClick={params.onClick || null}
|
|
||||||
>
|
|
||||||
{content}
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const addStatsCTALink = (params) => {
|
|
||||||
if (window.mailpoet_premium_active) {
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
const newParams = params;
|
|
||||||
newParams.link = 'admin.php?page=mailpoet-premium';
|
|
||||||
newParams.externalLink = true;
|
|
||||||
newParams.onClick = trackStatsCTAClicked;
|
|
||||||
return newParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const renderStatistics = (newsletter, isSent, currentTime) => {
|
|
||||||
let sent = isSent;
|
|
||||||
if (sent === undefined) {
|
|
||||||
// condition for standard and post notification listings
|
|
||||||
sent = newsletter.statistics
|
|
||||||
&& newsletter.queue
|
|
||||||
&& newsletter.queue.status !== 'scheduled';
|
|
||||||
}
|
|
||||||
if (!sent) {
|
|
||||||
return (
|
|
||||||
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let params = {};
|
|
||||||
Hooks.addFilter('mailpoet_newsletters_listing_stats_before', 'mailpoet', addStatsCTALink);
|
|
||||||
params = Hooks.applyFilters('mailpoet_newsletters_listing_stats_before', params, newsletter);
|
|
||||||
|
|
||||||
// welcome emails provide explicit total_sent value
|
|
||||||
const totalSent = Number((newsletter.total_sent || newsletter.queue.count_processed));
|
|
||||||
|
|
||||||
let percentageClicked = 0;
|
|
||||||
let percentageOpened = 0;
|
|
||||||
let percentageUnsubscribed = 0;
|
|
||||||
let revenue = null;
|
|
||||||
|
|
||||||
if (totalSent > 0) {
|
|
||||||
percentageClicked = (newsletter.statistics.clicked * 100) / totalSent;
|
|
||||||
percentageOpened = (newsletter.statistics.opened * 100) / totalSent;
|
|
||||||
percentageUnsubscribed = (newsletter.statistics.unsubscribed * 100) / totalSent;
|
|
||||||
revenue = newsletter.statistics.revenue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// format to 1 decimal place
|
|
||||||
const percentageClickedDisplay = MailPoet.Num.toLocaleFixed(percentageClicked, 1);
|
|
||||||
const percentageOpenedDisplay = MailPoet.Num.toLocaleFixed(percentageOpened, 1);
|
|
||||||
const percentageUnsubscribedDisplay = MailPoet.Num.toLocaleFixed(percentageUnsubscribed, 1);
|
|
||||||
|
|
||||||
let showStatsTimeout;
|
|
||||||
let newsletterDate;
|
|
||||||
let sentHoursAgo;
|
|
||||||
let tooEarlyForStats;
|
|
||||||
let showKbLink;
|
|
||||||
if (currentTime !== undefined) {
|
|
||||||
// standard emails and post notifications:
|
|
||||||
// display green box for newsletters that were just sent
|
|
||||||
showStatsTimeout = 6; // in hours
|
|
||||||
newsletterDate = newsletter.queue.scheduled_at || newsletter.queue.created_at;
|
|
||||||
sentHoursAgo = moment(currentTime).diff(moment(newsletterDate), 'hours');
|
|
||||||
tooEarlyForStats = sentHoursAgo < showStatsTimeout;
|
|
||||||
showKbLink = true;
|
|
||||||
} else {
|
|
||||||
// welcome emails: no green box and KB link
|
|
||||||
tooEarlyForStats = false;
|
|
||||||
showKbLink = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const improveStatsKBLink = 'http://beta.docs.mailpoet.com/article/191-how-to-improve-my-open-and-click-rates';
|
|
||||||
|
|
||||||
// thresholds to display badges
|
|
||||||
const minNewslettersSent = 20;
|
|
||||||
const minNewsletterOpens = 5;
|
|
||||||
|
|
||||||
let openedAndClickedStats;
|
|
||||||
if (totalSent >= minNewslettersSent
|
|
||||||
&& newsletter.statistics.opened >= minNewsletterOpens
|
|
||||||
&& !tooEarlyForStats
|
|
||||||
) {
|
|
||||||
// display stats with badges
|
|
||||||
openedAndClickedStats = (
|
|
||||||
<div className="mailpoet_stats_text">
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
{ percentageOpenedDisplay }
|
|
||||||
%
|
|
||||||
{' '}
|
|
||||||
</span>
|
|
||||||
<StatsBadge
|
|
||||||
stat="opened"
|
|
||||||
rate={percentageOpened}
|
|
||||||
tooltipId={`opened-${newsletter.id}`}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span>
|
|
||||||
{ percentageClickedDisplay }
|
|
||||||
%
|
|
||||||
{' '}
|
|
||||||
</span>
|
|
||||||
<StatsBadge
|
|
||||||
stat="clicked"
|
|
||||||
rate={percentageClicked}
|
|
||||||
tooltipId={`clicked-${newsletter.id}`}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="mailpoet_stat_hidden">
|
|
||||||
{ percentageUnsubscribedDisplay }
|
|
||||||
%
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// display simple stats
|
|
||||||
openedAndClickedStats = (
|
|
||||||
<div>
|
|
||||||
<span className="mailpoet_stats_text">
|
|
||||||
{ percentageOpenedDisplay }
|
|
||||||
%,
|
|
||||||
{ ' ' }
|
|
||||||
{ percentageClickedDisplay }
|
|
||||||
%
|
|
||||||
<span className="mailpoet_stat_hidden">
|
|
||||||
,
|
|
||||||
{' '}
|
|
||||||
{ percentageUnsubscribedDisplay }
|
|
||||||
%
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const wrapContentInLink = (content, idPrefix) => wrapInLink(
|
|
||||||
content,
|
|
||||||
params,
|
|
||||||
`${idPrefix}-${newsletter.id}`,
|
|
||||||
totalSent
|
|
||||||
);
|
|
||||||
|
|
||||||
const content = (
|
|
||||||
<>
|
|
||||||
{ wrapContentInLink(openedAndClickedStats, 'opened-and-clicked') }
|
|
||||||
{ revenue !== null && revenue.value > 0 && (
|
|
||||||
<div className="mailpoet_stats_text">
|
|
||||||
{ wrapContentInLink(revenue.formatted, 'revenue') }
|
|
||||||
{' '}
|
|
||||||
<HelpTooltip
|
|
||||||
tooltip={MailPoet.I18n.t('revenueStatsTooltip')}
|
|
||||||
place="left"
|
|
||||||
tooltipId="helpTooltipStatsRevenue"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) }
|
|
||||||
{ tooEarlyForStats && wrapContentInLink(
|
|
||||||
(
|
|
||||||
<div className="mailpoet_badge mailpoet_badge_green">
|
|
||||||
{MailPoet.I18n.t('checkBackInHours').replace('%$1d', showStatsTimeout - sentHoursAgo)}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
'check-back'
|
|
||||||
) }
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
// thresholds to display bad open rate help
|
|
||||||
const maxPercentageOpened = 5;
|
|
||||||
const minSentHoursAgo = 24;
|
|
||||||
const minTotalSent = 10;
|
|
||||||
|
|
||||||
let afterContent;
|
|
||||||
if (showKbLink
|
|
||||||
&& percentageOpened < maxPercentageOpened
|
|
||||||
&& sentHoursAgo >= minSentHoursAgo
|
|
||||||
&& totalSent >= minTotalSent
|
|
||||||
) {
|
|
||||||
// help link for bad open rate
|
|
||||||
afterContent = (
|
|
||||||
<div>
|
|
||||||
<a
|
|
||||||
href={improveStatsKBLink}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="mailpoet_stat_link_small"
|
|
||||||
>
|
|
||||||
{MailPoet.I18n.t('improveThisLinkText')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{content}
|
|
||||||
{afterContent}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addStatsCTAAction = (actions) => {
|
export const addStatsCTAAction = (actions) => {
|
||||||
|
@ -12,8 +12,8 @@ import ListingHeading from 'newsletters/listings/heading.jsx';
|
|||||||
import FeatureAnnouncement from 'announcements/feature_announcement.jsx';
|
import FeatureAnnouncement from 'announcements/feature_announcement.jsx';
|
||||||
|
|
||||||
import QueueStatus from 'newsletters/listings/queue_status.jsx';
|
import QueueStatus from 'newsletters/listings/queue_status.jsx';
|
||||||
|
import Statistics from 'newsletters/listings/statistics.jsx';
|
||||||
import {
|
import {
|
||||||
renderStatistics,
|
|
||||||
addStatsCTAAction,
|
addStatsCTAAction,
|
||||||
checkCronStatus,
|
checkCronStatus,
|
||||||
checkMailerStatus,
|
checkMailerStatus,
|
||||||
@ -102,7 +102,7 @@ const NewsletterListNotificationHistory = createReactClass({ // eslint-disable-l
|
|||||||
</td>
|
</td>
|
||||||
{ (mailpoetTrackingEnabled === true) ? (
|
{ (mailpoetTrackingEnabled === true) ? (
|
||||||
<td className="column" data-colname={MailPoet.I18n.t('statistics')}>
|
<td className="column" data-colname={MailPoet.I18n.t('statistics')}>
|
||||||
{ renderStatistics(newsletter, undefined, meta.current_time) }
|
<Statistics newsletter={newsletter} currentTime={meta.current_time} />
|
||||||
</td>
|
</td>
|
||||||
) : null }
|
) : null }
|
||||||
<td className="column-date" data-colname={MailPoet.I18n.t('sentOn')}>
|
<td className="column-date" data-colname={MailPoet.I18n.t('sentOn')}>
|
||||||
|
@ -11,8 +11,8 @@ import ListingTabs from 'newsletters/listings/tabs.jsx';
|
|||||||
import ListingHeading from 'newsletters/listings/heading.jsx';
|
import ListingHeading from 'newsletters/listings/heading.jsx';
|
||||||
import FeatureAnnouncement from 'announcements/feature_announcement.jsx';
|
import FeatureAnnouncement from 'announcements/feature_announcement.jsx';
|
||||||
import QueueStatus from 'newsletters/listings/queue_status.jsx';
|
import QueueStatus from 'newsletters/listings/queue_status.jsx';
|
||||||
|
import Statistics from 'newsletters/listings/statistics.jsx';
|
||||||
import {
|
import {
|
||||||
renderStatistics,
|
|
||||||
addStatsCTAAction,
|
addStatsCTAAction,
|
||||||
checkCronStatus,
|
checkCronStatus,
|
||||||
checkMailerStatus,
|
checkMailerStatus,
|
||||||
@ -213,7 +213,7 @@ const NewsletterListStandard = createReactClass({ // eslint-disable-line react/p
|
|||||||
</td>
|
</td>
|
||||||
{ (mailpoetTrackingEnabled === true) ? (
|
{ (mailpoetTrackingEnabled === true) ? (
|
||||||
<td className="column" data-colname={MailPoet.I18n.t('statistics')}>
|
<td className="column" data-colname={MailPoet.I18n.t('statistics')}>
|
||||||
{ renderStatistics(newsletter, undefined, meta.current_time) }
|
<Statistics newsletter={newsletter} currentTime={meta.current_time} />
|
||||||
</td>
|
</td>
|
||||||
) : null }
|
) : null }
|
||||||
<td className="column-date" data-colname={MailPoet.I18n.t('sentOn')}>
|
<td className="column-date" data-colname={MailPoet.I18n.t('sentOn')}>
|
||||||
|
264
assets/js/src/newsletters/listings/statistics.jsx
Normal file
264
assets/js/src/newsletters/listings/statistics.jsx
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
import MailPoet from 'mailpoet';
|
||||||
|
import Hooks from 'wp-js-hooks';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import HelpTooltip from 'help-tooltip.jsx';
|
||||||
|
import StatsBadge from 'newsletters/badges/stats.jsx';
|
||||||
|
import { trackStatsCTAClicked } from 'newsletters/listings/mixins.jsx';
|
||||||
|
|
||||||
|
const wrapInLink = (content, params, id, totalSent) => {
|
||||||
|
if (totalSent <= 0 || !params.link) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.externalLink) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={`stats-${id}`}
|
||||||
|
href={params.link}
|
||||||
|
onClick={params.onClick || null}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={`stats-${id}`}
|
||||||
|
to={params.link}
|
||||||
|
onClick={params.onClick || null}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addStatsCTALink = (params) => {
|
||||||
|
if (window.mailpoet_premium_active) {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
const newParams = params;
|
||||||
|
newParams.link = 'admin.php?page=mailpoet-premium';
|
||||||
|
newParams.externalLink = true;
|
||||||
|
newParams.onClick = trackStatsCTAClicked;
|
||||||
|
return newParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Statistics = ({ newsletter, isSent, currentTime }) => {
|
||||||
|
let sent = isSent;
|
||||||
|
if (sent === undefined) {
|
||||||
|
// condition for standard and post notification listings
|
||||||
|
sent = newsletter.statistics
|
||||||
|
&& newsletter.queue
|
||||||
|
&& newsletter.queue.status !== 'scheduled';
|
||||||
|
}
|
||||||
|
if (!sent) {
|
||||||
|
return (
|
||||||
|
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let params = {};
|
||||||
|
Hooks.addFilter('mailpoet_newsletters_listing_stats_before', 'mailpoet', addStatsCTALink);
|
||||||
|
params = Hooks.applyFilters('mailpoet_newsletters_listing_stats_before', params, newsletter);
|
||||||
|
|
||||||
|
// welcome emails provide explicit total_sent value
|
||||||
|
const totalSent = Number((newsletter.total_sent || newsletter.queue.count_processed));
|
||||||
|
|
||||||
|
let percentageClicked = 0;
|
||||||
|
let percentageOpened = 0;
|
||||||
|
let percentageUnsubscribed = 0;
|
||||||
|
let revenue = null;
|
||||||
|
|
||||||
|
if (totalSent > 0) {
|
||||||
|
percentageClicked = (newsletter.statistics.clicked * 100) / totalSent;
|
||||||
|
percentageOpened = (newsletter.statistics.opened * 100) / totalSent;
|
||||||
|
percentageUnsubscribed = (newsletter.statistics.unsubscribed * 100) / totalSent;
|
||||||
|
revenue = newsletter.statistics.revenue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// format to 1 decimal place
|
||||||
|
const percentageClickedDisplay = MailPoet.Num.toLocaleFixed(percentageClicked, 1);
|
||||||
|
const percentageOpenedDisplay = MailPoet.Num.toLocaleFixed(percentageOpened, 1);
|
||||||
|
const percentageUnsubscribedDisplay = MailPoet.Num.toLocaleFixed(percentageUnsubscribed, 1);
|
||||||
|
|
||||||
|
let showStatsTimeout;
|
||||||
|
let newsletterDate;
|
||||||
|
let sentHoursAgo;
|
||||||
|
let tooEarlyForStats;
|
||||||
|
let showKbLink;
|
||||||
|
if (currentTime !== undefined) {
|
||||||
|
// standard emails and post notifications:
|
||||||
|
// display green box for newsletters that were just sent
|
||||||
|
showStatsTimeout = 6; // in hours
|
||||||
|
newsletterDate = newsletter.queue.scheduled_at || newsletter.queue.created_at;
|
||||||
|
sentHoursAgo = moment(currentTime).diff(moment(newsletterDate), 'hours');
|
||||||
|
tooEarlyForStats = sentHoursAgo < showStatsTimeout;
|
||||||
|
showKbLink = true;
|
||||||
|
} else {
|
||||||
|
// welcome emails: no green box and KB link
|
||||||
|
tooEarlyForStats = false;
|
||||||
|
showKbLink = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const improveStatsKBLink = 'http://beta.docs.mailpoet.com/article/191-how-to-improve-my-open-and-click-rates';
|
||||||
|
|
||||||
|
// thresholds to display badges
|
||||||
|
const minNewslettersSent = 20;
|
||||||
|
const minNewsletterOpens = 5;
|
||||||
|
|
||||||
|
let openedAndClickedStats;
|
||||||
|
if (totalSent >= minNewslettersSent
|
||||||
|
&& newsletter.statistics.opened >= minNewsletterOpens
|
||||||
|
&& !tooEarlyForStats
|
||||||
|
) {
|
||||||
|
// display stats with badges
|
||||||
|
openedAndClickedStats = (
|
||||||
|
<div className="mailpoet_stats_text">
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
{percentageOpenedDisplay}
|
||||||
|
%
|
||||||
|
{' '}
|
||||||
|
</span>
|
||||||
|
<StatsBadge
|
||||||
|
stat="opened"
|
||||||
|
rate={percentageOpened}
|
||||||
|
tooltipId={`opened-${newsletter.id}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
{percentageClickedDisplay}
|
||||||
|
%
|
||||||
|
{' '}
|
||||||
|
</span>
|
||||||
|
<StatsBadge
|
||||||
|
stat="clicked"
|
||||||
|
rate={percentageClicked}
|
||||||
|
tooltipId={`clicked-${newsletter.id}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="mailpoet_stat_hidden">
|
||||||
|
{percentageUnsubscribedDisplay}
|
||||||
|
%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// display simple stats
|
||||||
|
openedAndClickedStats = (
|
||||||
|
<div>
|
||||||
|
<span className="mailpoet_stats_text">
|
||||||
|
{percentageOpenedDisplay}
|
||||||
|
%,
|
||||||
|
{' '}
|
||||||
|
{percentageClickedDisplay}
|
||||||
|
%
|
||||||
|
<span className="mailpoet_stat_hidden">
|
||||||
|
,
|
||||||
|
{' '}
|
||||||
|
{percentageUnsubscribedDisplay}
|
||||||
|
%
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapContentInLink = (content, idPrefix) => wrapInLink(
|
||||||
|
content,
|
||||||
|
params,
|
||||||
|
`${idPrefix}-${newsletter.id}`,
|
||||||
|
totalSent
|
||||||
|
);
|
||||||
|
|
||||||
|
const content = (
|
||||||
|
<>
|
||||||
|
{wrapContentInLink(openedAndClickedStats, 'opened-and-clicked')}
|
||||||
|
{revenue !== null && revenue.value > 0 && (
|
||||||
|
<div className="mailpoet_stats_text">
|
||||||
|
{wrapContentInLink(revenue.formatted, 'revenue')}
|
||||||
|
{' '}
|
||||||
|
<HelpTooltip
|
||||||
|
tooltip={MailPoet.I18n.t('revenueStatsTooltip')}
|
||||||
|
place="left"
|
||||||
|
tooltipId="helpTooltipStatsRevenue"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{tooEarlyForStats && wrapContentInLink(
|
||||||
|
(
|
||||||
|
<div className="mailpoet_badge mailpoet_badge_green">
|
||||||
|
{MailPoet.I18n.t('checkBackInHours').replace('%$1d', showStatsTimeout - sentHoursAgo)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
'check-back'
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
// thresholds to display bad open rate help
|
||||||
|
const maxPercentageOpened = 5;
|
||||||
|
const minSentHoursAgo = 24;
|
||||||
|
const minTotalSent = 10;
|
||||||
|
|
||||||
|
let afterContent;
|
||||||
|
if (showKbLink
|
||||||
|
&& percentageOpened < maxPercentageOpened
|
||||||
|
&& sentHoursAgo >= minSentHoursAgo
|
||||||
|
&& totalSent >= minTotalSent
|
||||||
|
) {
|
||||||
|
// help link for bad open rate
|
||||||
|
afterContent = (
|
||||||
|
<div>
|
||||||
|
<a
|
||||||
|
href={improveStatsKBLink}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="mailpoet_stat_link_small"
|
||||||
|
>
|
||||||
|
{MailPoet.I18n.t('improveThisLinkText')}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{content}
|
||||||
|
{afterContent}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
Statistics.propTypes = {
|
||||||
|
newsletter: PropTypes.shape({
|
||||||
|
id: PropTypes.number.isRequired,
|
||||||
|
queue: PropTypes.shape({
|
||||||
|
status: PropTypes.string,
|
||||||
|
count_processed: PropTypes.number.isRequired,
|
||||||
|
count_total: PropTypes.number.isRequired,
|
||||||
|
created_at: PropTypes.instanceOf(Date),
|
||||||
|
scheduled_at: PropTypes.instanceOf(Date),
|
||||||
|
}),
|
||||||
|
total_sent: PropTypes.number,
|
||||||
|
statistics: PropTypes.shape({
|
||||||
|
clicked: PropTypes.number,
|
||||||
|
opened: PropTypes.number,
|
||||||
|
unsubscribed: PropTypes.number,
|
||||||
|
revenue: PropTypes.number,
|
||||||
|
}),
|
||||||
|
}).isRequired,
|
||||||
|
isSent: PropTypes.bool,
|
||||||
|
currentTime: PropTypes.instanceOf(Date),
|
||||||
|
};
|
||||||
|
Statistics.defaultProps = {
|
||||||
|
isSent: undefined,
|
||||||
|
currentTime: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Statistics;
|
@ -8,8 +8,8 @@ import ListingTabs from 'newsletters/listings/tabs.jsx';
|
|||||||
import ListingHeading from 'newsletters/listings/heading.jsx';
|
import ListingHeading from 'newsletters/listings/heading.jsx';
|
||||||
import FeatureAnnouncement from 'announcements/feature_announcement.jsx';
|
import FeatureAnnouncement from 'announcements/feature_announcement.jsx';
|
||||||
|
|
||||||
|
import Statistics from 'newsletters/listings/statistics.jsx';
|
||||||
import {
|
import {
|
||||||
renderStatistics,
|
|
||||||
addStatsCTAAction,
|
addStatsCTAAction,
|
||||||
checkCronStatus,
|
checkCronStatus,
|
||||||
checkMailerStatus,
|
checkMailerStatus,
|
||||||
@ -332,10 +332,10 @@ const NewsletterListWelcome = createReactClass({ // eslint-disable-line react/pr
|
|||||||
</td>
|
</td>
|
||||||
{ (mailpoetTrackingEnabled === true) ? (
|
{ (mailpoetTrackingEnabled === true) ? (
|
||||||
<td className="column" data-colname={MailPoet.I18n.t('statistics')}>
|
<td className="column" data-colname={MailPoet.I18n.t('statistics')}>
|
||||||
{ renderStatistics(
|
<Statistics
|
||||||
newsletter,
|
newsletter={newsletter}
|
||||||
newsletter.total_sent > 0 && newsletter.statistics
|
isSent={newsletter.total_sent > 0 && newsletter.statistics}
|
||||||
) }
|
/>
|
||||||
</td>
|
</td>
|
||||||
) : null }
|
) : null }
|
||||||
<td className="column-date" data-colname={MailPoet.I18n.t('lastModifiedOn')}>
|
<td className="column-date" data-colname={MailPoet.I18n.t('lastModifiedOn')}>
|
||||||
|
Reference in New Issue
Block a user