mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-20 17:32:15 +03:00
7c4674507e
no issue In the new publish flow we use `{{members-count-fetcher}}` to show member counts as needed in the template without needing to worry about manually fetching counts in the backing classes. However, when switching between states in the flow the count would be re-requested resulting in some glitchy looking async count rendering. By changing `{{members-count-fetcher}}` to use our `members-count-cache` service internally we reduce the likelihood of an async count being triggered when switching between publish flow states. - updated `members-count-cache` service methods to work with filter strings or full query objects - switched `members-count-fetcher` resource to use `members-count-cache` in place of directly querying the store
92 lines
2.7 KiB
JavaScript
92 lines
2.7 KiB
JavaScript
import Service, {inject as service} from '@ember/service';
|
|
import moment from 'moment';
|
|
import {action} from '@ember/object';
|
|
import {ghPluralize} from 'ghost-admin/helpers/gh-pluralize';
|
|
import {task} from 'ember-concurrency';
|
|
|
|
export default class MembersCountCacheService extends Service {
|
|
@service session;
|
|
@service store;
|
|
|
|
cache = {};
|
|
|
|
@action
|
|
async count(query) {
|
|
if (typeof query === 'string') {
|
|
query = {filter: query};
|
|
}
|
|
|
|
const cacheKey = JSON.stringify(query);
|
|
const cachedValue = this.cache[cacheKey];
|
|
|
|
if (cachedValue && moment().diff(cachedValue.time, 'seconds') <= 60) {
|
|
return cachedValue.count;
|
|
}
|
|
|
|
const count = this._countMembersTask.perform(query);
|
|
|
|
this.cache[cacheKey] = {count, time: moment()};
|
|
|
|
return count;
|
|
}
|
|
|
|
@action
|
|
async countString(filter = '', {knownCount} = {}) {
|
|
const user = this.session.user;
|
|
|
|
const basicFilter = filter.replace(/^newsletters\.status:active\+\((.*)\)$/, '$1');
|
|
const filterParts = basicFilter.split(',');
|
|
const isFree = filterParts.length === 1 && filterParts[0] === 'status:free';
|
|
const isPaid = filterParts.length === 1 && filterParts[0] === 'status:-free';
|
|
const isAll = !filter || (filterParts.includes('status:free') && filterParts.includes('status:-free'));
|
|
|
|
// editors don't have permission to browse members so can't retrieve a count
|
|
// TODO: remove when editors have relevant permissions or we have a different way of fetching counts
|
|
if (user.isEditor && knownCount === undefined) {
|
|
if (isFree) {
|
|
return 'all free members';
|
|
}
|
|
if (isPaid) {
|
|
return 'all paid members';
|
|
}
|
|
if (isAll) {
|
|
return 'all members';
|
|
}
|
|
|
|
return 'a custom members segment';
|
|
}
|
|
|
|
const recipientCount = knownCount !== undefined ? knownCount : await this.count(filter);
|
|
|
|
if (isFree) {
|
|
return ghPluralize(recipientCount, 'free member');
|
|
}
|
|
|
|
if (isPaid) {
|
|
return ghPluralize(recipientCount, 'paid member');
|
|
}
|
|
|
|
return ghPluralize(recipientCount, 'member');
|
|
}
|
|
|
|
@action
|
|
clear() {
|
|
this.cache = {};
|
|
}
|
|
|
|
@task
|
|
*_countMembersTask(query) {
|
|
if (!query) {
|
|
return 0;
|
|
}
|
|
|
|
try {
|
|
const result = yield this.store.query('member', {...query, limit: 1, page: 1});
|
|
return result.meta.pagination.total;
|
|
} catch (e) {
|
|
console.error(e); // eslint-disable-line
|
|
return 0;
|
|
}
|
|
}
|
|
}
|