mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-25 09:03:12 +03:00
Switched members table to show info from most-recently-updated subscription instead of first in array
no issue - members having multiple subscriptions is not really expected but if it does happen then the most recently updated subscription is most likely to be the one that we're interested in showing the details of in the members table - added `{{most-recently-updated arr}}` helper+function that will return the item in the array argument with the most recent "updated at" value - uses `updatedAtUTC` or `updatedAt` or `updated_at` values so it will work against any of our models or un-transformed API response objects - updated `<GhMembersListItemColumn>` to use a `mostRecentSubscription` getter when showing subscription data rather than assuming the first object in the subscriptions array should be displayed
This commit is contained in:
parent
f52fcbd3be
commit
17710c3e8e
@ -56,8 +56,8 @@
|
|||||||
|
|
||||||
{{else if (eq @filterColumn 'subscriptions.status')}}
|
{{else if (eq @filterColumn 'subscriptions.status')}}
|
||||||
<LinkTo @route="member" @model={{@member}} class="gh-list-data middarkgrey f8" data-test-table-data={{@filterColumn}}>
|
<LinkTo @route="member" @model={{@member}} class="gh-list-data middarkgrey f8" data-test-table-data={{@filterColumn}}>
|
||||||
{{#if (not (is-empty this.subscriptionStatus))}}
|
{{#if (not (is-empty this.mostRecentSubscription.status))}}
|
||||||
<span>{{capitalize this.subscriptionStatus}}</span>
|
<span>{{capitalize this.mostRecentSubscription.status}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="midlightgrey">-</span>
|
<span class="midlightgrey">-</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -65,8 +65,8 @@
|
|||||||
|
|
||||||
{{else if (eq @filterColumn 'subscriptions.plan_interval')}}
|
{{else if (eq @filterColumn 'subscriptions.plan_interval')}}
|
||||||
<LinkTo @route="member" @model={{@member}} class="gh-list-data middarkgrey f8" data-test-table-data={{@filterColumn}}>
|
<LinkTo @route="member" @model={{@member}} class="gh-list-data middarkgrey f8" data-test-table-data={{@filterColumn}}>
|
||||||
{{#if (not (is-empty this.billingPeriod))}}
|
{{#if (not (is-empty this.mostRecentSubscription.price.interval))}}
|
||||||
<span>{{capitalize this.billingPeriod}}</span>
|
<span>{{capitalize this.mostRecentSubscription.price.interval}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="midlightgrey">-</span>
|
<span class="midlightgrey">-</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -74,9 +74,9 @@
|
|||||||
|
|
||||||
{{else if (eq @filterColumn 'subscriptions.start_date')}}
|
{{else if (eq @filterColumn 'subscriptions.start_date')}}
|
||||||
<LinkTo @route="member" @model={{@member}} class="gh-list-data middarkgrey f8" data-test-table-data={{@filterColumn}}>
|
<LinkTo @route="member" @model={{@member}} class="gh-list-data middarkgrey f8" data-test-table-data={{@filterColumn}}>
|
||||||
{{#if (not (is-empty @member.subscriptions.firstObject.start_date))}}
|
{{#if (not (is-empty this.mostRecentSubscription.start_date))}}
|
||||||
{{moment-format (moment-site-tz @member.subscriptions.firstObject.start_date) "D MMM YYYY"}}
|
{{moment-format (moment-site-tz this.mostRecentSubscription.start_date) "D MMM YYYY"}}
|
||||||
<div class="midlightgrey gh-members-list-subscribed-moment">{{moment-from-now @member.subscriptions.firstObject.start_date}}</div>
|
<div class="midlightgrey gh-members-list-subscribed-moment">{{moment-from-now this.mostRecentSubscription.start_date}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="midlightgrey">-</span>
|
<span class="midlightgrey">-</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -84,9 +84,9 @@
|
|||||||
|
|
||||||
{{else if (eq @filterColumn 'subscriptions.current_period_end')}}
|
{{else if (eq @filterColumn 'subscriptions.current_period_end')}}
|
||||||
<LinkTo @route="member" @model={{@member}} class="gh-list-data middarkgrey f8" data-test-table-data={{@filterColumn}}>
|
<LinkTo @route="member" @model={{@member}} class="gh-list-data middarkgrey f8" data-test-table-data={{@filterColumn}}>
|
||||||
{{#if (not (is-empty @member.subscriptions.firstObject.current_period_end))}}
|
{{#if (not (is-empty this.mostRecentSubscription.current_period_end))}}
|
||||||
{{moment-format (moment-site-tz @member.subscriptions.firstObject.current_period_end) "D MMM YYYY"}}
|
{{moment-format (moment-site-tz this.mostRecentSubscription.current_period_end) "D MMM YYYY"}}
|
||||||
<div class="midlightgrey gh-members-list-subscribed-moment">{{moment-from-now @member.subscriptions.firstObject.current_period_end}}</div>
|
<div class="midlightgrey gh-members-list-subscribed-moment">{{moment-from-now this.mostRecentSubscription.current_period_end}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="midlightgrey">-</span>
|
<span class="midlightgrey">-</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import Component from '@glimmer/component';
|
import Component from '@glimmer/component';
|
||||||
|
import {get} from '@ember/object';
|
||||||
|
import {mostRecentlyUpdated} from 'ghost-admin/helpers/most-recently-updated';
|
||||||
|
|
||||||
export default class GhMembersListItemColumn extends Component {
|
export default class GhMembersListItemColumn extends Component {
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
@ -6,23 +8,16 @@ export default class GhMembersListItemColumn extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get labels() {
|
get labels() {
|
||||||
const labelData = this.args.member.get('labels') || [];
|
const labelData = get(this.args.member, 'labels') || [];
|
||||||
return labelData.map(label => label.name).join(', ');
|
return labelData.map(label => label.name).join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
get products() {
|
get products() {
|
||||||
const productData = this.args.member.get('products') || [];
|
const productData = get(this.args.member, 'products') || [];
|
||||||
return productData.map(product => product.name).join(', ');
|
return productData.map(product => product.name).join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
get subscriptionStatus() {
|
get mostRecentSubscription() {
|
||||||
const subscriptions = this.args.member.get('subscriptions') || [];
|
return mostRecentlyUpdated(get(this.args.member, 'subscriptions'));
|
||||||
return subscriptions[0]?.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
get billingPeriod() {
|
|
||||||
const subscriptions = this.args.member.get('subscriptions') || [];
|
|
||||||
const billingPeriod = subscriptions[0]?.price?.interval;
|
|
||||||
return billingPeriod;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
ghost/admin/app/helpers/most-recently-updated.js
Normal file
19
ghost/admin/app/helpers/most-recently-updated.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
import {helper} from '@ember/component/helper';
|
||||||
|
|
||||||
|
export function mostRecentlyUpdated(objs) {
|
||||||
|
const items = [...(objs || [])];
|
||||||
|
|
||||||
|
(items || []).sort((a, b) => {
|
||||||
|
const momentA = moment(a.updatedAtUTC || a.updatedAt || a.updated_at);
|
||||||
|
const momentB = moment(b.updatedAtUTC || b.updatedAt || b.updated_at);
|
||||||
|
|
||||||
|
return momentB.valueOf() - momentA.valueOf();
|
||||||
|
});
|
||||||
|
|
||||||
|
return items[0] || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default helper(function ([items = []]) {
|
||||||
|
return mostRecentlyUpdated(items);
|
||||||
|
});
|
64
ghost/admin/tests/unit/helpers/most-recently-updated-test.js
Normal file
64
ghost/admin/tests/unit/helpers/most-recently-updated-test.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
import {describe, it} from 'mocha';
|
||||||
|
import {expect} from 'chai';
|
||||||
|
import {mostRecentlyUpdated} from 'ghost-admin/helpers/most-recently-updated';
|
||||||
|
|
||||||
|
describe('Unit: Helper: most-recently-updated', function () {
|
||||||
|
it('returns most recent - updatedAtUTC', function () {
|
||||||
|
const a = {updatedAtUTC: moment.utc('2022-03-04 16:10')};
|
||||||
|
const b = {updatedAtUTC: moment.utc('2022-03-03 16:10')};
|
||||||
|
const c = {updatedAtUTC: moment.utc('2022-03-04 16:20')};
|
||||||
|
|
||||||
|
const subs = [a, b, c];
|
||||||
|
|
||||||
|
expect(mostRecentlyUpdated(subs)).to.equal(c);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns most recent - updatedAt', function () {
|
||||||
|
const a = {updatedAt: moment('2022-03-04 16:10')};
|
||||||
|
const b = {updatedAt: moment('2022-03-05 16:10')};
|
||||||
|
const c = {updatedAt: moment('2022-03-04 16:20')};
|
||||||
|
|
||||||
|
const subs = [a, b, c];
|
||||||
|
|
||||||
|
expect(mostRecentlyUpdated(subs)).to.equal(b);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns most recent - updated_at', function () {
|
||||||
|
const a = {updated_at: '2022-03-04 16:10'};
|
||||||
|
const b = {updated_at: '2022-03-03 16:10'};
|
||||||
|
const c = {updated_at: '2022-03-04 16:20'};
|
||||||
|
|
||||||
|
const subs = [a, b, c];
|
||||||
|
|
||||||
|
expect(mostRecentlyUpdated(subs)).to.equal(c);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles a single-element array', function () {
|
||||||
|
const a = {updated_at: '2022-02-22'};
|
||||||
|
|
||||||
|
expect(mostRecentlyUpdated([a])).to.equal(a);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles null', function () {
|
||||||
|
expect(mostRecentlyUpdated(null)).to.equal(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles empty array', function () {
|
||||||
|
expect(mostRecentlyUpdated([])).to.equal(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not modify original array', function () {
|
||||||
|
const a = {updated_at: '2022-03-04 16:10'};
|
||||||
|
const b = {updated_at: '2022-03-03 16:10'};
|
||||||
|
const c = {updated_at: '2022-03-04 16:20'};
|
||||||
|
|
||||||
|
const subs = [a, b, c];
|
||||||
|
|
||||||
|
mostRecentlyUpdated(subs);
|
||||||
|
|
||||||
|
expect(subs[0]).to.equal(a);
|
||||||
|
expect(subs[1]).to.equal(b);
|
||||||
|
expect(subs[2]).to.equal(c);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user