forked from MichaelYick/mailpoet
Remove old files
[MAILPOET-2791]
This commit is contained in:
parent
f9a3da175d
commit
3128b24070
@ -1,50 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import ReactTooltip from 'react-tooltip';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
function Badge(props) {
|
|
||||||
const badgeClasses = classNames(
|
|
||||||
'mailpoet_badge',
|
|
||||||
props.type ? `mailpoet_badge_${props.type}` : ''
|
|
||||||
);
|
|
||||||
|
|
||||||
const tooltip = props.tooltip ? props.tooltip.replace(/\n/g, '<br />') : false;
|
|
||||||
// tooltip ID must be unique, defaults to tooltip text
|
|
||||||
const tooltipId = props.tooltipId || tooltip;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<span
|
|
||||||
className={badgeClasses}
|
|
||||||
data-tip={tooltip}
|
|
||||||
data-for={tooltipId}
|
|
||||||
>
|
|
||||||
{props.name}
|
|
||||||
</span>
|
|
||||||
{ tooltip && (
|
|
||||||
<ReactTooltip
|
|
||||||
place="right"
|
|
||||||
multiline
|
|
||||||
id={tooltipId}
|
|
||||||
/>
|
|
||||||
) }
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Badge.propTypes = {
|
|
||||||
name: PropTypes.string.isRequired,
|
|
||||||
tooltip: PropTypes.string,
|
|
||||||
tooltipId: PropTypes.string,
|
|
||||||
type: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
Badge.defaultProps = {
|
|
||||||
type: undefined,
|
|
||||||
tooltipId: undefined,
|
|
||||||
tooltip: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default Badge;
|
|
@ -1,121 +0,0 @@
|
|||||||
import MailPoet from 'mailpoet';
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import Badge from './badge.jsx';
|
|
||||||
|
|
||||||
const badges = {
|
|
||||||
excellent: {
|
|
||||||
name: MailPoet.I18n.t('excellentBadgeName'),
|
|
||||||
tooltipTitle: MailPoet.I18n.t('excellentBadgeTooltip'),
|
|
||||||
},
|
|
||||||
good: {
|
|
||||||
name: MailPoet.I18n.t('goodBadgeName'),
|
|
||||||
tooltipTitle: MailPoet.I18n.t('goodBadgeTooltip'),
|
|
||||||
},
|
|
||||||
bad: {
|
|
||||||
name: MailPoet.I18n.t('badBadgeName'),
|
|
||||||
tooltipTitle: MailPoet.I18n.t('badBadgeTooltip'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const stats = {
|
|
||||||
opened: {
|
|
||||||
badgeRanges: [30, 10, 0],
|
|
||||||
badgeTypes: [
|
|
||||||
'excellent',
|
|
||||||
'good',
|
|
||||||
'bad',
|
|
||||||
],
|
|
||||||
tooltipText: MailPoet.I18n.t('openedStatTooltip'),
|
|
||||||
},
|
|
||||||
clicked: {
|
|
||||||
badgeRanges: [3, 1, 0],
|
|
||||||
badgeTypes: [
|
|
||||||
'excellent',
|
|
||||||
'good',
|
|
||||||
'bad',
|
|
||||||
],
|
|
||||||
tooltipText: MailPoet.I18n.t('clickedStatTooltip'),
|
|
||||||
},
|
|
||||||
unsubscribed: {
|
|
||||||
badgeRanges: [3, 1, 0],
|
|
||||||
badgeTypes: [
|
|
||||||
'bad',
|
|
||||||
'good',
|
|
||||||
'excellent',
|
|
||||||
],
|
|
||||||
tooltipText: MailPoet.I18n.t('unsubscribedStatTooltip'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
class StatsBadge extends React.Component {
|
|
||||||
static getBadgeType(stat, rate) {
|
|
||||||
const len = stat.badgeRanges.length;
|
|
||||||
for (let i = 0; i < len; i += 1) {
|
|
||||||
if (rate > stat.badgeRanges[i]) {
|
|
||||||
return stat.badgeTypes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// rate must be zero at this point
|
|
||||||
return stat.badgeTypes[len - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const stat = stats[this.props.stat] || null;
|
|
||||||
if (!stat) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rate = this.props.rate;
|
|
||||||
if (rate < 0 || rate > 100) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const badgeType = StatsBadge.getBadgeType(stat, rate);
|
|
||||||
const badge = badges[badgeType] || null;
|
|
||||||
if (!badge) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tooltipText = `${badge.tooltipTitle}\n\n${stat.tooltipText}`;
|
|
||||||
const tooltipId = this.props.tooltipId || null;
|
|
||||||
|
|
||||||
const content = (
|
|
||||||
<Badge
|
|
||||||
type={badgeType}
|
|
||||||
name={badge.name}
|
|
||||||
tooltip={tooltipText}
|
|
||||||
tooltipId={tooltipId}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.props.headline) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<span className={`mailpoet_stat_${badgeType}`}>
|
|
||||||
{this.props.headline}
|
|
||||||
</span>
|
|
||||||
{' '}
|
|
||||||
{content}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatsBadge.propTypes = {
|
|
||||||
stat: PropTypes.string.isRequired,
|
|
||||||
rate: PropTypes.number.isRequired,
|
|
||||||
tooltipId: PropTypes.string,
|
|
||||||
headline: PropTypes.string,
|
|
||||||
};
|
|
||||||
|
|
||||||
StatsBadge.defaultProps = {
|
|
||||||
headline: '',
|
|
||||||
tooltipId: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default StatsBadge;
|
|
@ -1,95 +0,0 @@
|
|||||||
import MailPoet from 'mailpoet';
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Tags from 'common/tag/tags';
|
|
||||||
|
|
||||||
function formatAddress(address, name) {
|
|
||||||
let addressString = '';
|
|
||||||
if (address) {
|
|
||||||
addressString = (name) ? `${name} <${address}>` : address;
|
|
||||||
}
|
|
||||||
return addressString;
|
|
||||||
}
|
|
||||||
|
|
||||||
function NewsletterStatsInfo(props) {
|
|
||||||
const { newsletter } = props;
|
|
||||||
|
|
||||||
const newsletterDate = newsletter.queue.scheduled_at || newsletter.queue.created_at;
|
|
||||||
|
|
||||||
const senderAddress = formatAddress(
|
|
||||||
newsletter.sender_address || '',
|
|
||||||
newsletter.sender_name || ''
|
|
||||||
);
|
|
||||||
const replyToAddress = formatAddress(
|
|
||||||
newsletter.reply_to_address || '',
|
|
||||||
newsletter.reply_to_name || ''
|
|
||||||
);
|
|
||||||
|
|
||||||
const segments = newsletter.segments || [];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="mailpoet_stat_spaced">
|
|
||||||
<a
|
|
||||||
href={newsletter.preview_url}
|
|
||||||
className="button-secondary"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{MailPoet.I18n.t('statsPreviewNewsletter')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
{MailPoet.I18n.t('statsDateSent')}
|
|
||||||
:
|
|
||||||
{' '}
|
|
||||||
{MailPoet.Date.format(newsletterDate)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{ segments.length && (
|
|
||||||
<>
|
|
||||||
<div className="mailpoet-gap" />
|
|
||||||
<div>
|
|
||||||
{`${MailPoet.I18n.t('statsToSegments')}: `}
|
|
||||||
<Tags segments={segments} dimension="large" />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) }
|
|
||||||
|
|
||||||
<div className="mailpoet-gap" />
|
|
||||||
|
|
||||||
<div>
|
|
||||||
{`${MailPoet.I18n.t('statsFromAddress')}: `}
|
|
||||||
{ senderAddress }
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{replyToAddress && (
|
|
||||||
<>
|
|
||||||
<div className="mailpoet-gap" />
|
|
||||||
<div>
|
|
||||||
{`${MailPoet.I18n.t('statsReplyToAddress')}: `}
|
|
||||||
{ replyToAddress }
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
NewsletterStatsInfo.propTypes = {
|
|
||||||
newsletter: PropTypes.shape({
|
|
||||||
queue: PropTypes.shape({
|
|
||||||
scheduled_at: PropTypes.string,
|
|
||||||
created_at: PropTypes.string,
|
|
||||||
}).isRequired,
|
|
||||||
sender_address: PropTypes.string,
|
|
||||||
sender_name: PropTypes.string,
|
|
||||||
reply_to_address: PropTypes.string,
|
|
||||||
preview_url: PropTypes.string,
|
|
||||||
reply_to_name: PropTypes.string,
|
|
||||||
segments: PropTypes.array,
|
|
||||||
}).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NewsletterStatsInfo;
|
|
@ -1,124 +0,0 @@
|
|||||||
import Hooks from 'wp-js-hooks';
|
|
||||||
import MailPoet from 'mailpoet';
|
|
||||||
import React from 'react';
|
|
||||||
import StatsBadge from 'newsletters/badges/stats.jsx';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
const NewsletterGeneralStats = ({ newsletter }) => {
|
|
||||||
const totalSent = newsletter.total_sent || 0;
|
|
||||||
let percentageClicked = 0;
|
|
||||||
let percentageOpened = 0;
|
|
||||||
let percentageUnsubscribed = 0;
|
|
||||||
if (totalSent > 0) {
|
|
||||||
percentageClicked = (newsletter.statistics.clicked * 100) / totalSent;
|
|
||||||
percentageOpened = (newsletter.statistics.opened * 100) / totalSent;
|
|
||||||
percentageUnsubscribed = (newsletter.statistics.unsubscribed * 100) / totalSent;
|
|
||||||
}
|
|
||||||
// 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);
|
|
||||||
const headlineOpened = `${percentageOpenedDisplay}% ${MailPoet.I18n.t('percentageOpened')}`;
|
|
||||||
const headlineClicked = `${percentageClickedDisplay}% ${MailPoet.I18n.t('percentageClicked')}`;
|
|
||||||
const headlineUnsubscribed = `${percentageUnsubscribedDisplay}% ${MailPoet.I18n.t('percentageUnsubscribed')}`;
|
|
||||||
const statsKBLink = 'https://kb.mailpoet.com/article/190-whats-a-good-email-open-rate';
|
|
||||||
// thresholds to display badges
|
|
||||||
const minNewslettersSent = 20;
|
|
||||||
const minNewslettersOpened = 5;
|
|
||||||
let statsContent;
|
|
||||||
if (totalSent >= minNewslettersSent
|
|
||||||
&& newsletter.statistics.opened >= minNewslettersOpened
|
|
||||||
) {
|
|
||||||
// display stats with badges
|
|
||||||
statsContent = (
|
|
||||||
<div className="mailpoet_stat_grey">
|
|
||||||
<div className="mailpoet_stat_big mailpoet_stat_spaced">
|
|
||||||
<StatsBadge
|
|
||||||
stat="opened"
|
|
||||||
rate={percentageOpened}
|
|
||||||
headline={headlineOpened}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mailpoet_stat_big mailpoet_stat_spaced">
|
|
||||||
<StatsBadge
|
|
||||||
stat="clicked"
|
|
||||||
rate={percentageClicked}
|
|
||||||
headline={headlineClicked}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{Hooks.applyFilters('mailpoet_newsletters_revenues_stats', null, newsletter.statistics.revenue)}
|
|
||||||
<div>
|
|
||||||
<StatsBadge
|
|
||||||
stat="unsubscribed"
|
|
||||||
rate={percentageUnsubscribed}
|
|
||||||
headline={headlineUnsubscribed}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// display stats without badges
|
|
||||||
statsContent = (
|
|
||||||
<div className="mailpoet_stat_grey">
|
|
||||||
<div className="mailpoet_stat_big mailpoet_stat_spaced">
|
|
||||||
{headlineOpened}
|
|
||||||
</div>
|
|
||||||
<div className="mailpoet_stat_big mailpoet_stat_spaced">
|
|
||||||
{headlineClicked}
|
|
||||||
</div>
|
|
||||||
{Hooks.applyFilters('mailpoet_newsletters_revenues_stats', null, newsletter.statistics.revenue)}
|
|
||||||
<div>
|
|
||||||
{headlineUnsubscribed}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<p className="mailpoet_stat_grey mailpoet_stat_big">
|
|
||||||
{MailPoet.I18n.t('statsTotalSent')}
|
|
||||||
{' '}
|
|
||||||
{parseInt(totalSent, 10).toLocaleString()}
|
|
||||||
</p>
|
|
||||||
{statsContent}
|
|
||||||
{ newsletter.ga_campaign && (
|
|
||||||
<p>
|
|
||||||
{MailPoet.I18n.t('googleAnalytics')}
|
|
||||||
{': '}
|
|
||||||
{ newsletter.ga_campaign }
|
|
||||||
</p>
|
|
||||||
) }
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
href={statsKBLink}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
data-beacon-article="58f671152c7d3a057f8858e8"
|
|
||||||
>
|
|
||||||
{MailPoet.I18n.t('readMoreOnStats')}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
NewsletterGeneralStats.propTypes = {
|
|
||||||
newsletter: PropTypes.shape({
|
|
||||||
ga_campaign: PropTypes.string,
|
|
||||||
total_sent: PropTypes.number,
|
|
||||||
statistics: PropTypes.shape({
|
|
||||||
clicked: PropTypes.number,
|
|
||||||
opened: PropTypes.number,
|
|
||||||
unsubscribed: PropTypes.number,
|
|
||||||
revenue: PropTypes.shape({
|
|
||||||
currency: PropTypes.string.isRequired,
|
|
||||||
value: PropTypes.number.isRequired,
|
|
||||||
formatted: PropTypes.string.isRequired,
|
|
||||||
count: PropTypes.number.isRequired,
|
|
||||||
}),
|
|
||||||
}).isRequired,
|
|
||||||
}).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NewsletterGeneralStats;
|
|
@ -115,13 +115,6 @@ const baseConfig = {
|
|||||||
'babel-loader'
|
'babel-loader'
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
include: path.resolve(__dirname, 'assets/js/src/newsletters/badges/stats.jsx'),
|
|
||||||
use: [
|
|
||||||
'expose-loader?' + globalPrefix + '.StatsBadge',
|
|
||||||
'babel-loader',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
include: path.resolve(__dirname, 'assets/js/src/help-tooltip.jsx'),
|
include: path.resolve(__dirname, 'assets/js/src/help-tooltip.jsx'),
|
||||||
use: [
|
use: [
|
||||||
@ -203,7 +196,6 @@ const adminConfig = {
|
|||||||
'help-tooltip.jsx',
|
'help-tooltip.jsx',
|
||||||
'listing/listing.jsx',
|
'listing/listing.jsx',
|
||||||
'common/index.ts',
|
'common/index.ts',
|
||||||
'newsletters/badges/stats.jsx',
|
|
||||||
],
|
],
|
||||||
admin: 'webpack_admin_index.jsx',
|
admin: 'webpack_admin_index.jsx',
|
||||||
newsletter_editor: 'newsletter_editor/webpack_index.jsx',
|
newsletter_editor: 'newsletter_editor/webpack_index.jsx',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user