mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-24 03:14:03 +03:00
Added donation events to activity feeds (#17632)
fixes TryGhost/Product#3698 fixes TryGhost/Product#3699
This commit is contained in:
parent
374bfc405c
commit
874552bdbe
@ -93,8 +93,18 @@
|
||||
{{#let (parse-member-event event eventsFetcher.hasMultipleNewsletters) as |parsedEvent|}}
|
||||
<div class="gh-dashboard-list-item member-details">
|
||||
<div class="gh-dashboard-list-item-sub">
|
||||
<GhMemberAvatar @member={{parsedEvent.member}} @containerClass="w8 h8 mr3 flex-shrink-0" />
|
||||
<LinkTo class="gh-dashboard-list-text" @route="member" @model="{{parsedEvent.memberId}}" data-test-dashboard-member-activity-item>{{parsedEvent.subject}}</LinkTo>
|
||||
{{#if parsedEvent.member}}
|
||||
<GhMemberAvatar @member={{parsedEvent.member}} @containerClass="w8 h8 mr3 flex-shrink-0" />
|
||||
<LinkTo class="gh-dashboard-list-text" @route="member" @model="{{parsedEvent.memberId}}" data-test-dashboard-member-activity-item>{{parsedEvent.subject}}</LinkTo>
|
||||
{{else}}
|
||||
{{#if parsedEvent.email}}
|
||||
<GhMemberAvatar @name={{parsedEvent.subject}} @containerClass="w8 h8 mr3 flex-shrink-0" />
|
||||
<a class="gh-dashboard-list-text" href="mailto:{{parsedEvent.email}}" target="_blank" rel="noopener noreferrer" title="{{parsedEvent.email}}">{{parsedEvent.subject}}</a>
|
||||
{{else}}
|
||||
<GhMemberAvatar @name={{parsedEvent.subject}} @containerClass="w8 h8 mr3 flex-shrink-0" />
|
||||
<span class="gh-dashboard-list-text">{{parsedEvent.subject}}</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="gh-dashboard-list-item-sub">
|
||||
{{svg-jar parsedEvent.icon }}
|
||||
|
@ -13,9 +13,9 @@ const stringToHslColor = function (str, saturation, lightness) {
|
||||
|
||||
export default class GhMemberAvatarComponent extends Component {
|
||||
get memberName() {
|
||||
let {member} = this.args;
|
||||
let {member, name} = this.args;
|
||||
|
||||
return member?.name || member?.email || 'NM';
|
||||
return member?.name || member?.email || name || 'NM';
|
||||
}
|
||||
|
||||
get avatarImage() {
|
||||
|
@ -45,8 +45,18 @@
|
||||
{{#let (parse-member-event event) as |parsedEvent|}}
|
||||
<div class="gh-dashboard-list-item">
|
||||
<div class="gh-dashboard-list-item-sub">
|
||||
<GhMemberAvatar @member={{parsedEvent.member}} @containerClass="w6 h6 mr3 flex-shrink-0" />
|
||||
<LinkTo class="gh-dashboard-list-text" @route="member" @model="{{parsedEvent.memberId}}" @query={{hash postAnalytics=@post.id}}>{{parsedEvent.subject}}</LinkTo>
|
||||
{{#if parsedEvent.member}}
|
||||
<GhMemberAvatar @member={{parsedEvent.member}} @containerClass="w6 h6 mr3 flex-shrink-0" />
|
||||
<LinkTo class="gh-dashboard-list-text" @route="member" @model="{{parsedEvent.memberId}}" @query={{hash postAnalytics=@post.id}}>{{parsedEvent.subject}}</LinkTo>
|
||||
{{else}}
|
||||
{{#if parsedEvent.email}}
|
||||
<GhMemberAvatar @name={{parsedEvent.subject}} @containerClass="w6 h6 mr3 flex-shrink-0" />
|
||||
<a class="gh-dashboard-list-text" href="mailto:{{parsedEvent.email}}" target="_blank" rel="noopener noreferrer" title="{{parsedEvent.email}}">{{parsedEvent.subject}}</a>
|
||||
{{else}}
|
||||
<GhMemberAvatar @name={{parsedEvent.subject}} @containerClass="w6 h6 mr3 flex-shrink-0" />
|
||||
<span class="gh-dashboard-list-text">{{parsedEvent.subject}}</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="gh-dashboard-list-item-sub">
|
||||
{{svg-jar parsedEvent.icon }}
|
||||
|
@ -10,7 +10,7 @@ export default class ParseMemberEventHelper extends Helper {
|
||||
@service membersUtils;
|
||||
|
||||
compute([event, hasMultipleNewsletters]) {
|
||||
const subject = event.data.member.name || event.data.member.email;
|
||||
const subject = event.data.member ? (event.data.member.name || event.data.member.email) : (event.data.name || event.data.email || '');
|
||||
const icon = this.getIcon(event);
|
||||
const action = this.getAction(event, hasMultipleNewsletters);
|
||||
const info = this.getInfo(event);
|
||||
@ -110,6 +110,10 @@ export default class ParseMemberEventHelper extends Helper {
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type === 'donation_event') {
|
||||
icon = 'subscriptions';
|
||||
}
|
||||
|
||||
return 'event-' + icon;
|
||||
}
|
||||
|
||||
@ -203,6 +207,10 @@ export default class ParseMemberEventHelper extends Helper {
|
||||
}
|
||||
return 'less like this';
|
||||
}
|
||||
|
||||
if (event.type === 'donation_event') {
|
||||
return `Made a one-time payment`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -222,7 +230,7 @@ export default class ParseMemberEventHelper extends Helper {
|
||||
* 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.type === 'signup_event' || event.type === 'subscription_event' || event.type === 'donation_event') {
|
||||
if (event.data.attribution?.title) {
|
||||
return event.data.attribution.title;
|
||||
}
|
||||
@ -278,6 +286,12 @@ export default class ParseMemberEventHelper extends Helper {
|
||||
return 'Free';
|
||||
}
|
||||
|
||||
if (event.type === 'donation_event') {
|
||||
const symbol = getSymbol(event.data.currency);
|
||||
const formattedAmount = symbol + getNonDecimal(event.data.amount, event.data.currency);
|
||||
return formattedAmount;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -304,7 +318,7 @@ export default class ParseMemberEventHelper extends Helper {
|
||||
}
|
||||
}
|
||||
|
||||
if (['signup_event', 'subscription_event'].includes(event.type)) {
|
||||
if (['signup_event', 'subscription_event', 'donation_event'].includes(event.type)) {
|
||||
if (event.data.attribution && event.data.attribution.url) {
|
||||
return event.data.attribution.url;
|
||||
}
|
||||
|
@ -182,6 +182,7 @@ function createApiInstance(config) {
|
||||
}
|
||||
},
|
||||
models: {
|
||||
DonationPaymentEvent: models.DonationPaymentEvent,
|
||||
EmailRecipient: models.EmailRecipient,
|
||||
StripeCustomer: models.MemberStripeCustomer,
|
||||
StripeCustomerSubscription: models.StripeCustomerSubscription,
|
||||
|
@ -37,6 +37,7 @@ module.exports = function MembersAPI({
|
||||
getSubject
|
||||
},
|
||||
models: {
|
||||
DonationPaymentEvent,
|
||||
EmailRecipient,
|
||||
StripeCustomer,
|
||||
StripeCustomerSubscription,
|
||||
@ -107,6 +108,7 @@ module.exports = function MembersAPI({
|
||||
});
|
||||
|
||||
const eventRepository = new EventRepository({
|
||||
DonationPaymentEvent,
|
||||
EmailRecipient,
|
||||
MemberSubscribeEvent,
|
||||
MemberPaidSubscriptionEvent,
|
||||
|
@ -17,6 +17,7 @@ function replaceCustomFilterTransformer(filter) {
|
||||
|
||||
module.exports = class EventRepository {
|
||||
constructor({
|
||||
DonationPaymentEvent,
|
||||
EmailRecipient,
|
||||
MemberSubscribeEvent,
|
||||
MemberPaymentEvent,
|
||||
@ -32,6 +33,7 @@ module.exports = class EventRepository {
|
||||
labsService,
|
||||
memberAttributionService
|
||||
}) {
|
||||
this._DonationPaymentEvent = DonationPaymentEvent;
|
||||
this._MemberSubscribeEvent = MemberSubscribeEvent;
|
||||
this._MemberPaidSubscriptionEvent = MemberPaidSubscriptionEvent;
|
||||
this._MemberPaymentEvent = MemberPaymentEvent;
|
||||
@ -65,7 +67,8 @@ module.exports = class EventRepository {
|
||||
{type: 'click_event', action: 'getClickEvents'},
|
||||
{type: 'aggregated_click_event', action: 'getAggregatedClickEvents'},
|
||||
{type: 'signup_event', action: 'getSignupEvents'},
|
||||
{type: 'subscription_event', action: 'getSubscriptionEvents'}
|
||||
{type: 'subscription_event', action: 'getSubscriptionEvents'},
|
||||
{type: 'donation_event', action: 'getDonationEvents'}
|
||||
];
|
||||
|
||||
// Some events are not filterable by post_id
|
||||
@ -352,6 +355,59 @@ module.exports = class EventRepository {
|
||||
};
|
||||
}
|
||||
|
||||
async getDonationEvents(options = {}, filter) {
|
||||
options = {
|
||||
...options,
|
||||
withRelated: [
|
||||
'member',
|
||||
'postAttribution',
|
||||
'userAttribution',
|
||||
'tagAttribution'
|
||||
],
|
||||
filter: 'member_id:-null+custom:true',
|
||||
mongoTransformer: chainTransformers(
|
||||
// First set the filter manually
|
||||
replaceCustomFilterTransformer(filter),
|
||||
|
||||
// Map the used keys in that filter
|
||||
...mapKeys({
|
||||
'data.created_at': 'created_at',
|
||||
'data.member_id': 'member_id'
|
||||
}),
|
||||
|
||||
(f) => {
|
||||
// Special one: when data.post_id is used, replace it with two filters: attribution_id:x+attribution_type:post
|
||||
return expandFilters(f, [{
|
||||
key: 'data.post_id',
|
||||
replacement: 'attribution_id',
|
||||
expansion: {attribution_type: 'post'}
|
||||
}]);
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
const {data: models, meta} = await this._DonationPaymentEvent.findPage(options);
|
||||
|
||||
const data = models.map((model) => {
|
||||
const json = model.toJSON(options);
|
||||
delete json.postAttribution?.mobiledoc;
|
||||
delete json.postAttribution?.lexical;
|
||||
delete json.postAttribution?.plaintext;
|
||||
return {
|
||||
type: 'donation_event',
|
||||
data: {
|
||||
...json,
|
||||
attribution: this._memberAttributionService.getEventAttribution(model)
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
meta
|
||||
};
|
||||
}
|
||||
|
||||
async getCommentEvents(options = {}, filter) {
|
||||
options = {
|
||||
...options,
|
||||
|
Loading…
Reference in New Issue
Block a user