mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
Added support for exportign posts with email recipients to specific tiers
no issue Support for tiers was missing when traslating the email recipients NQL filter to a string. This is fixed now. It also improved some copy.
This commit is contained in:
parent
2dd94d4300
commit
1f39040649
3 changed files with 74 additions and 26 deletions
|
@ -19,7 +19,8 @@ const getPostServiceInstance = () => {
|
||||||
models: {
|
models: {
|
||||||
Post: models.Post,
|
Post: models.Post,
|
||||||
Newsletter: models.Newsletter,
|
Newsletter: models.Newsletter,
|
||||||
Label: models.Label
|
Label: models.Label,
|
||||||
|
Product: models.Product
|
||||||
},
|
},
|
||||||
getPostUrl(post) {
|
getPostUrl(post) {
|
||||||
const jsonModel = post.toJSON();
|
const jsonModel = post.toJSON();
|
||||||
|
|
|
@ -13,6 +13,7 @@ class PostsExporter {
|
||||||
* @param {Object} dependencies.models.Post
|
* @param {Object} dependencies.models.Post
|
||||||
* @param {Object} dependencies.models.Newsletter
|
* @param {Object} dependencies.models.Newsletter
|
||||||
* @param {Object} dependencies.models.Label
|
* @param {Object} dependencies.models.Label
|
||||||
|
* @param {Object} dependencies.models.Product
|
||||||
* @param {Object} dependencies.getPostUrl
|
* @param {Object} dependencies.getPostUrl
|
||||||
* @param {Object} dependencies.settingsCache
|
* @param {Object} dependencies.settingsCache
|
||||||
* @param {Object} dependencies.settingsHelpers
|
* @param {Object} dependencies.settingsHelpers
|
||||||
|
@ -51,6 +52,7 @@ class PostsExporter {
|
||||||
|
|
||||||
const newsletters = (await this.#models.Newsletter.findAll()).models;
|
const newsletters = (await this.#models.Newsletter.findAll()).models;
|
||||||
const labels = (await this.#models.Label.findAll()).models;
|
const labels = (await this.#models.Label.findAll()).models;
|
||||||
|
const tiers = (await this.#models.Product.findAll()).models;
|
||||||
|
|
||||||
const membersEnabled = this.#settingsHelpers.isMembersEnabled();
|
const membersEnabled = this.#settingsHelpers.isMembersEnabled();
|
||||||
const membersTrackSources = membersEnabled && this.#settingsCache.get('members_track_sources');
|
const membersTrackSources = membersEnabled && this.#settingsCache.get('members_track_sources');
|
||||||
|
@ -82,7 +84,7 @@ class PostsExporter {
|
||||||
featured: post.get('featured'),
|
featured: post.get('featured'),
|
||||||
tags: post.related('tags').map(tag => tag.get('name')).join(', '),
|
tags: post.related('tags').map(tag => tag.get('name')).join(', '),
|
||||||
post_access: this.postAccessToString(post),
|
post_access: this.postAccessToString(post),
|
||||||
email_recipients: email ? this.humanReadableEmailRecipientFilter(email?.get('recipient_filter'), labels) : null,
|
email_recipients: email ? this.humanReadableEmailRecipientFilter(email?.get('recipient_filter'), labels, tiers) : null,
|
||||||
newsletter_name: newsletters.length > 1 && post.get('newsletter_id') && email ? newsletters.find(newsletter => newsletter.get('id') === post.get('newsletter_id'))?.get('name') : null,
|
newsletter_name: newsletters.length > 1 && post.get('newsletter_id') && email ? newsletters.find(newsletter => newsletter.get('id') === post.get('newsletter_id'))?.get('name') : null,
|
||||||
sends: email?.get('email_count') ?? null,
|
sends: email?.get('email_count') ?? null,
|
||||||
opens: trackOpens ? (email?.get('opened_count') ?? null) : null,
|
opens: trackOpens ? (email?.get('opened_count') ?? null) : null,
|
||||||
|
@ -184,17 +186,18 @@ class PostsExporter {
|
||||||
* @private Convert an email filter to a human readable string
|
* @private Convert an email filter to a human readable string
|
||||||
* @param {string} recipientFilter
|
* @param {string} recipientFilter
|
||||||
* @param {*} allLabels
|
* @param {*} allLabels
|
||||||
|
* @param {*} allTiers
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
humanReadableEmailRecipientFilter(recipientFilter, allLabels) {
|
humanReadableEmailRecipientFilter(recipientFilter, allLabels, allTiers) {
|
||||||
// Examples: "label:test"; "label:test,label:batch1"; "status:-free,label:test", "all"
|
// Examples: "label:test"; "label:test,label:batch1"; "status:-free,label:test", "all"
|
||||||
if (recipientFilter === 'all') {
|
if (recipientFilter === 'all') {
|
||||||
return 'all';
|
return 'All subscribers';
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const parsed = nql(recipientFilter).parse();
|
const parsed = nql(recipientFilter).parse();
|
||||||
const strings = this.filterToString(parsed, allLabels);
|
const strings = this.filterToString(parsed, allLabels, allTiers);
|
||||||
return strings.join(', ');
|
return strings.join(', ');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logging.error(e);
|
logging.error(e);
|
||||||
|
@ -208,17 +211,17 @@ class PostsExporter {
|
||||||
* @param {*} allLabels All available member labels
|
* @param {*} allLabels All available member labels
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
filterToString(filter, allLabels) {
|
filterToString(filter, allLabels, allTiers) {
|
||||||
const strings = [];
|
const strings = [];
|
||||||
if (filter.$and) {
|
if (filter.$and) {
|
||||||
// Not supported
|
// Not supported
|
||||||
} else if (filter.$or) {
|
} else if (filter.$or) {
|
||||||
for (const subfilter of filter.$or) {
|
for (const subfilter of filter.$or) {
|
||||||
strings.push(...this.filterToString(subfilter, allLabels));
|
strings.push(...this.filterToString(subfilter, allLabels, allTiers));
|
||||||
}
|
}
|
||||||
} else if (filter.yg) {
|
} else if (filter.yg) {
|
||||||
// Single filter grouped in brackets
|
// Single filter grouped in brackets
|
||||||
strings.push(...this.filterToString(filter.yg, allLabels));
|
strings.push(...this.filterToString(filter.yg, allLabels, allTiers));
|
||||||
} else {
|
} else {
|
||||||
for (const key of Object.keys(filter)) {
|
for (const key of Object.keys(filter)) {
|
||||||
if (key === 'label') {
|
if (key === 'label') {
|
||||||
|
@ -232,22 +235,33 @@ class PostsExporter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (key === 'tier') {
|
||||||
|
if (typeof filter.tier === 'string') {
|
||||||
|
const tierSlug = filter.tier;
|
||||||
|
const tier = allTiers.find(l => l.get('slug') === tierSlug);
|
||||||
|
if (tier) {
|
||||||
|
strings.push(tier.get('name'));
|
||||||
|
} else {
|
||||||
|
strings.push(tierSlug);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (key === 'status') {
|
if (key === 'status') {
|
||||||
if (typeof filter.status === 'string') {
|
if (typeof filter.status === 'string') {
|
||||||
if (filter.status === 'free') {
|
if (filter.status === 'free') {
|
||||||
strings.push('free members');
|
strings.push('Free subscribers');
|
||||||
} else if (filter.status === 'paid') {
|
} else if (filter.status === 'paid') {
|
||||||
strings.push('paid members');
|
strings.push('Paid subscribers');
|
||||||
} else if (filter.status === 'comped') {
|
} else if (filter.status === 'comped') {
|
||||||
strings.push('complimentary members');
|
strings.push('Complimentary subscribers');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (filter.status.$ne === 'free') {
|
if (filter.status.$ne === 'free') {
|
||||||
strings.push('paid members');
|
strings.push('Paid subscribers');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.status.$ne === 'paid') {
|
if (filter.status.$ne === 'paid') {
|
||||||
strings.push('free members');
|
strings.push('Free subscribers');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,9 @@ describe('PostsExporter', function () {
|
||||||
}),
|
}),
|
||||||
Label: createModelClass({
|
Label: createModelClass({
|
||||||
findAll: []
|
findAll: []
|
||||||
|
}),
|
||||||
|
Product: createModelClass({
|
||||||
|
findAll: []
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -394,6 +397,7 @@ describe('PostsExporter', function () {
|
||||||
describe('humanReadableEmailRecipientFilter', function () {
|
describe('humanReadableEmailRecipientFilter', function () {
|
||||||
const exporter = new PostsExporter({});
|
const exporter = new PostsExporter({});
|
||||||
let labels;
|
let labels;
|
||||||
|
let tiers;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
labels = [
|
labels = [
|
||||||
|
@ -406,12 +410,22 @@ describe('PostsExporter', function () {
|
||||||
name: 'VIP'
|
name: 'VIP'
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
tiers = [
|
||||||
|
createModel({
|
||||||
|
slug: 'silver',
|
||||||
|
name: 'Silver'
|
||||||
|
}),
|
||||||
|
createModel({
|
||||||
|
slug: 'gold',
|
||||||
|
name: 'Gold'
|
||||||
|
})
|
||||||
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Returns all', function () {
|
it('Returns all', function () {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('all'),
|
exporter.humanReadableEmailRecipientFilter('all'),
|
||||||
'all'
|
'All subscribers'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -424,19 +438,38 @@ describe('PostsExporter', function () {
|
||||||
|
|
||||||
it('Returns labels', function () {
|
it('Returns labels', function () {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('label:imported', labels),
|
exporter.humanReadableEmailRecipientFilter('label:imported', labels, tiers),
|
||||||
'Imported'
|
'Imported'
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('label:imported,label:vip', labels),
|
exporter.humanReadableEmailRecipientFilter('label:imported,label:vip', labels, tiers),
|
||||||
'Imported, VIP'
|
'Imported, VIP'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Returns invalid labels', function () {
|
it('Returns invalid labels', function () {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('label:invalidone', labels),
|
exporter.humanReadableEmailRecipientFilter('label:invalidone', labels, tiers),
|
||||||
|
'invalidone'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns tiers', function () {
|
||||||
|
assert.equal(
|
||||||
|
exporter.humanReadableEmailRecipientFilter('tier:silver', labels, tiers),
|
||||||
|
'Silver'
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
exporter.humanReadableEmailRecipientFilter('tier:silver,tier:gold', labels, tiers),
|
||||||
|
'Silver, Gold'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns invalid tiers', function () {
|
||||||
|
assert.equal(
|
||||||
|
exporter.humanReadableEmailRecipientFilter('tier:invalidone', labels, tiers),
|
||||||
'invalidone'
|
'invalidone'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -444,47 +477,47 @@ describe('PostsExporter', function () {
|
||||||
it('Returns status', function () {
|
it('Returns status', function () {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('status:free'),
|
exporter.humanReadableEmailRecipientFilter('status:free'),
|
||||||
'free members'
|
'Free subscribers'
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('status:-free'),
|
exporter.humanReadableEmailRecipientFilter('status:-free'),
|
||||||
'paid members'
|
'Paid subscribers'
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('status:paid'),
|
exporter.humanReadableEmailRecipientFilter('status:paid'),
|
||||||
'paid members'
|
'Paid subscribers'
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('status:comped'),
|
exporter.humanReadableEmailRecipientFilter('status:comped'),
|
||||||
'complimentary members'
|
'Complimentary subscribers'
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('status:-paid'),
|
exporter.humanReadableEmailRecipientFilter('status:-paid'),
|
||||||
'free members'
|
'Free subscribers'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Ignores AND', function () {
|
it('Ignores AND', function () {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('status:free+status:paid', labels),
|
exporter.humanReadableEmailRecipientFilter('status:free+status:paid', labels, tiers),
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Single brackets filter', function () {
|
it('Single brackets filter', function () {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('(status:free)', labels),
|
exporter.humanReadableEmailRecipientFilter('(status:free)', labels, tiers),
|
||||||
'free members'
|
'Free subscribers'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Ignores invalid filters', function () {
|
it('Ignores invalid filters', function () {
|
||||||
assert.equal(
|
assert.equal(
|
||||||
exporter.humanReadableEmailRecipientFilter('sdgsdgsdg sdg sdg sdgs dgs', labels),
|
exporter.humanReadableEmailRecipientFilter('sdgsdgsdg sdg sdg sdgs dgs', labels, tiers),
|
||||||
'sdgsdgsdg sdg sdg sdgs dgs'
|
'sdgsdgsdg sdg sdg sdgs dgs'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue