mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-19 00:11:49 +03:00
848b2d82a1
no issue This pull request removes the `suppressionList` feature flag and all its dependencies from the codebase. It makes the suppression list feature the default and consistent behavior for all email events and newsletters. It simplifies the UI, logic, and data related to email events and newsletters. It affects several files in the `ghost/admin/app`, `ghost/core/core`, and `ghost/members-api` directories.
339 lines
9.9 KiB
JavaScript
339 lines
9.9 KiB
JavaScript
import Helper from '@ember/component/helper';
|
||
import moment from 'moment-timezone';
|
||
import {getNonDecimal, getSymbol} from 'ghost-admin/utils/currency';
|
||
import {ghPluralize} from 'ghost-admin/helpers/gh-pluralize';
|
||
import {inject as service} from '@ember/service';
|
||
|
||
export default class ParseMemberEventHelper extends Helper {
|
||
@service feature;
|
||
@service utils;
|
||
@service membersUtils;
|
||
|
||
compute([event, hasMultipleNewsletters]) {
|
||
const subject = event.data.member.name || event.data.member.email;
|
||
const icon = this.getIcon(event);
|
||
const action = this.getAction(event, hasMultipleNewsletters);
|
||
const info = this.getInfo(event);
|
||
const description = this.getDescription(event);
|
||
|
||
const join = this.getJoin(event);
|
||
const object = this.getObject(event);
|
||
const url = this.getURL(event);
|
||
const route = this.getRoute(event);
|
||
const timestamp = moment(event.data.created_at);
|
||
const source = this.getSource(event);
|
||
|
||
return {
|
||
memberId: event.data.member_id ?? event.data.member?.id,
|
||
member: event.data.member,
|
||
emailId: event.data.email_id,
|
||
email: event.data.email,
|
||
icon,
|
||
subject,
|
||
action,
|
||
join,
|
||
object,
|
||
source,
|
||
info,
|
||
description,
|
||
url,
|
||
route,
|
||
timestamp
|
||
};
|
||
}
|
||
|
||
/* internal helper functions */
|
||
getIcon(event) {
|
||
let icon;
|
||
|
||
if (event.type === 'login_event') {
|
||
icon = 'logged-in';
|
||
}
|
||
|
||
if (event.type === 'payment_event') {
|
||
icon = 'subscriptions';
|
||
}
|
||
|
||
if (event.type === 'newsletter_event') {
|
||
if (event.data.subscribed) {
|
||
icon = 'subscribed-to-email';
|
||
} else {
|
||
icon = 'unsubscribed-from-email';
|
||
}
|
||
}
|
||
|
||
if (event.type === 'subscription_event') {
|
||
icon = 'subscriptions';
|
||
|
||
if (event.data.type === 'canceled') {
|
||
icon = 'canceled-subscription';
|
||
}
|
||
}
|
||
|
||
if (event.type === 'signup_event' || (event.type === 'subscription_event' && event.data.type === 'created' && event.data.signup)) {
|
||
icon = 'signed-up';
|
||
}
|
||
|
||
if (event.type === 'email_opened_event') {
|
||
icon = 'opened-email';
|
||
}
|
||
|
||
if (event.type === 'email_sent_event') {
|
||
icon = 'sent-email';
|
||
}
|
||
|
||
if (event.type === 'email_delivered_event') {
|
||
icon = 'received-email';
|
||
}
|
||
|
||
if (event.type === 'email_failed_event') {
|
||
icon = 'email-delivery-failed';
|
||
}
|
||
|
||
if (event.type === 'email_complaint_event') {
|
||
icon = 'email-delivery-spam';
|
||
}
|
||
|
||
if (event.type === 'comment_event') {
|
||
icon = 'comment';
|
||
}
|
||
|
||
if (event.type === 'click_event' || event.type === 'aggregated_click_event') {
|
||
icon = 'click';
|
||
}
|
||
|
||
if (event.type === 'feedback_event') {
|
||
if (event.data.score === 1) {
|
||
icon = 'more-like-this';
|
||
} else {
|
||
icon = 'less-like-this';
|
||
}
|
||
}
|
||
|
||
return 'event-' + icon;
|
||
}
|
||
|
||
getAction(event, hasMultipleNewsletters) {
|
||
if (event.type === 'signup_event' || (event.type === 'subscription_event' && event.data.type === 'created' && event.data.signup)) {
|
||
return 'signed up';
|
||
}
|
||
|
||
if (event.type === 'login_event') {
|
||
return 'logged in';
|
||
}
|
||
|
||
if (event.type === 'payment_event') {
|
||
return 'made payment';
|
||
}
|
||
|
||
if (event.type === 'newsletter_event') {
|
||
let newsletter = 'newsletter';
|
||
if (hasMultipleNewsletters && event.data.newsletter && event.data.newsletter.name) {
|
||
newsletter = event.data.newsletter.name;
|
||
}
|
||
|
||
if (event.data.subscribed) {
|
||
return 'subscribed to ' + newsletter;
|
||
} else {
|
||
return 'unsubscribed from ' + newsletter;
|
||
}
|
||
}
|
||
|
||
if (event.type === 'subscription_event') {
|
||
if (event.data.type === 'created') {
|
||
return 'started paid subscription';
|
||
}
|
||
if (event.data.type === 'updated') {
|
||
return 'changed paid subscription';
|
||
}
|
||
if (event.data.type === 'canceled') {
|
||
return 'canceled paid subscription';
|
||
}
|
||
if (event.data.type === 'reactivated') {
|
||
return 'reactivated paid subscription';
|
||
}
|
||
if (event.data.type === 'expired') {
|
||
return 'ended paid subscription';
|
||
}
|
||
|
||
return 'changed paid subscription';
|
||
}
|
||
|
||
if (event.type === 'email_opened_event') {
|
||
return 'opened email';
|
||
}
|
||
|
||
if (event.type === 'email_sent_event') {
|
||
return 'sent email';
|
||
}
|
||
|
||
if (event.type === 'email_delivered_event') {
|
||
return 'received email';
|
||
}
|
||
|
||
if (event.type === 'email_failed_event') {
|
||
return 'bounced email';
|
||
}
|
||
|
||
if (event.type === 'email_complaint_event') {
|
||
return 'email flagged as spam';
|
||
}
|
||
|
||
if (event.type === 'comment_event') {
|
||
if (event.data.parent) {
|
||
return 'replied to comment';
|
||
}
|
||
return 'commented';
|
||
}
|
||
|
||
if (event.type === 'click_event') {
|
||
return 'clicked link in email';
|
||
}
|
||
|
||
if (event.type === 'aggregated_click_event') {
|
||
if (event.data.count.clicks <= 1) {
|
||
return 'clicked link in email';
|
||
}
|
||
return `clicked ${ghPluralize(event.data.count.clicks, 'link')} in email`;
|
||
}
|
||
|
||
if (event.type === 'feedback_event') {
|
||
if (event.data.score === 1) {
|
||
return 'more like this';
|
||
}
|
||
return 'less like this';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* When we need to append the action and object in one sentence, you can add extra words here.
|
||
* E.g.,
|
||
* action: 'Signed up'.
|
||
* object: 'My blog post'
|
||
* When both words need to get appended, we'll add 'on'
|
||
* -> do this by returning 'on' in getJoin()
|
||
* This string is not added when action and object are in a separete table column, or when the getObject/getURL is empty
|
||
*/
|
||
getJoin() {
|
||
return '–';
|
||
}
|
||
|
||
/**
|
||
* Clickable object, shown between action and info, or in a separate column in some views
|
||
*/
|
||
getObject(event) {
|
||
if (event.type === 'signup_event' || event.type === 'subscription_event') {
|
||
if (event.data.attribution?.title) {
|
||
return event.data.attribution.title;
|
||
}
|
||
}
|
||
|
||
if (event.type === 'comment_event') {
|
||
if (event.data.post) {
|
||
return event.data.post.title;
|
||
}
|
||
}
|
||
|
||
if (event.type === 'click_event' || event.type === 'feedback_event') {
|
||
if (event.data.post) {
|
||
return event.data.post.title;
|
||
}
|
||
}
|
||
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* Clickable object, shown between action and info, or in a separate column in some views
|
||
*/
|
||
getSource(event) {
|
||
if (event.data?.attribution?.referrer_source) {
|
||
return {
|
||
name: event.data.attribution.referrer_source,
|
||
url: event.data.attribution.referrer_url ?? null
|
||
};
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
getInfo(event) {
|
||
if (event.type === 'subscription_event') {
|
||
let mrrDelta = getNonDecimal(event.data.mrr_delta, event.data.currency);
|
||
if (mrrDelta === 0) {
|
||
return;
|
||
}
|
||
const symbol = getSymbol(event.data.currency);
|
||
|
||
if (event.data.type === 'created') {
|
||
const sign = mrrDelta > 0 ? '' : '-';
|
||
const tierName = this.membersUtils.hasMultipleTiers ? (event.data.tierName ?? 'Paid') : 'Paid';
|
||
return `${tierName} ${sign}${symbol}${Math.abs(mrrDelta)}/month`;
|
||
}
|
||
const sign = mrrDelta > 0 ? '+' : '-';
|
||
return `MRR ${sign}${symbol}${Math.abs(mrrDelta)}`;
|
||
}
|
||
|
||
if (event.type === 'signup_event' && this.membersUtils.paidMembersEnabled) {
|
||
return 'Free';
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
getDescription(event) {
|
||
if (event.type === 'click_event') {
|
||
// Clean URL
|
||
try {
|
||
return this.utils.cleanTrackedUrl(event.data.link.to, true);
|
||
} catch (e) {
|
||
// Invalid URL
|
||
}
|
||
return event.data.link.to;
|
||
}
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* Make the object clickable
|
||
*/
|
||
getURL(event) {
|
||
if (['comment_event', 'click_event', 'feedback_event'].includes(event.type)) {
|
||
if (event.data.post) {
|
||
return event.data.post.url;
|
||
}
|
||
}
|
||
|
||
if (['signup_event', 'subscription_event'].includes(event.type)) {
|
||
if (event.data.attribution && event.data.attribution.url) {
|
||
return event.data.attribution.url;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* Get internal route props for a clickable object
|
||
*/
|
||
getRoute(event) {
|
||
if (['comment_event', 'click_event', 'feedback_event'].includes(event.type)) {
|
||
if (event.data.post) {
|
||
return {
|
||
name: 'posts.analytics',
|
||
model: event.data.post.id
|
||
};
|
||
}
|
||
}
|
||
|
||
if (['signup_event', 'subscription_event'].includes(event.type)) {
|
||
if (event.data.attribution_type === 'post') {
|
||
return {
|
||
name: 'posts.analytics',
|
||
model: event.data.attribution_id
|
||
};
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
}
|