mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-04-15 03:01:37 -05:00
Improved display of recipient filter posts list sends column tooltip
refs https://github.com/TryGhost/Team/issues/1025 - added `{{humanize-recipient-filter}}` helper that converts an NQL recipient filter into a more readable format - updated posts list to use the new helper in the sends column tooltip shown when hovering with the mouse
This commit is contained in:
parent
be70064716
commit
4ad040b4aa
3 changed files with 127 additions and 1 deletions
|
@ -5,6 +5,7 @@
|
|||
...attributes
|
||||
>
|
||||
|
||||
{{!-- Title column --}}
|
||||
{{#if (and this.session.user.isContributor @post.isPublished)}}
|
||||
<a href={{@post.url}} class="permalink gh-list-data gh-post-list-title" target="_blank" rel="noopener noreferrer">
|
||||
<h3 class="gh-content-entry-title">
|
||||
|
@ -129,12 +130,14 @@
|
|||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{!-- Sends/Opens columns --}}
|
||||
{{#if (and (not-eq this.settings.membersSignupAccess "none") (not-eq this.settings.editorDefaultEmailRecipients "disabled") (not this.session.user.isContributor))}}
|
||||
{{#if (and this.feature.emailAnalytics (eq @post.displayName "post"))}}
|
||||
{{!-- Sends column --}}
|
||||
<LinkTo @route="editor.edit" @models={{array @post.displayName @post.id}} class="permalink gh-list-data gh-post-list-recipients">
|
||||
<div class="flex fw4">
|
||||
{{#if (eq @post.email.status "submitted")}}
|
||||
<span class="flex" data-tooltip="{{capitalize @post.email.recipientFilter}} members">
|
||||
<span class="flex" data-tooltip={{humanize-recipient-filter @post.email.recipientFilter}}>
|
||||
<span class="darkgrey fw5 gh-content-email-stats">{{format-number @post.email.emailCount}}</span>
|
||||
<span class="midgrey-l2 fw4 gh-content-email-stats-mobile">{{gh-pluralize @post.email.emailCount "send"}}</span>
|
||||
</span>
|
||||
|
@ -144,6 +147,7 @@
|
|||
</div>
|
||||
</LinkTo>
|
||||
|
||||
{{!-- Opens column --}}
|
||||
<LinkTo @route="editor.edit" @models={{array @post.displayName @post.id}} class="permalink gh-list-data gh-post-list-opens">
|
||||
{{#if (and @post.email.trackOpens (eq @post.email.status "submitted"))}}
|
||||
<div class="flex">
|
||||
|
|
53
ghost/admin/app/helpers/humanize-recipient-filter.js
Normal file
53
ghost/admin/app/helpers/humanize-recipient-filter.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
import {capitalize} from '@ember/string';
|
||||
import {helper} from '@ember/component/helper';
|
||||
import {pluralize} from 'ember-inflector';
|
||||
|
||||
// NOTE: this only works for the limited set of filters that can be generated
|
||||
// via the publishing UI. Falls back to outputting the raw filter
|
||||
export default helper(function humanizeRecipientFilter([filter = '']/*, hash*/) {
|
||||
const parts = filter.split(',');
|
||||
|
||||
if (parts.includes('status:free') && parts.includes('status:-free')) {
|
||||
return 'All members';
|
||||
}
|
||||
|
||||
let outputParts = [];
|
||||
|
||||
if (parts.includes('status:free')) {
|
||||
outputParts.push('Free members');
|
||||
} else if (parts.includes('status:-free')) {
|
||||
outputParts.push('Paid members');
|
||||
}
|
||||
|
||||
const labelsArrayRegex = /labels:\[(.*?)\]/;
|
||||
const labelRegex = /label:(.*?)(?:,|$)/g;
|
||||
|
||||
if (labelsArrayRegex.test(filter)) {
|
||||
const [, labelsList] = filter.match(labelsArrayRegex);
|
||||
const labels = labelsList.split(',');
|
||||
outputParts.push(`${pluralize(labels.length, 'Label', {withoutCount: true})}: ${labels.map(capitalize).join(', ')}`);
|
||||
} else if (labelRegex.test(filter)) {
|
||||
filter.match(labelRegex); // weird JS thing, `matchAll` doesn't pick up all matches without this
|
||||
const labels = [...filter.matchAll(labelRegex)].map(([, label]) => label);
|
||||
outputParts.push(`${pluralize(labels.length, 'Label', {withoutCount: true})}: ${labels.map(capitalize).join(', ')}`);
|
||||
}
|
||||
|
||||
const productsArrayRegex = /products:\[(.*?)\]/;
|
||||
const productRegex = /product:(.*?)(?:,|$)/g;
|
||||
|
||||
if (productsArrayRegex.test(filter)) {
|
||||
const [, productsList] = filter.match(productsArrayRegex);
|
||||
const products = productsList.split(',');
|
||||
outputParts.push(`${pluralize(products.length, 'Product', {withoutCount: true})}: ${products.map(capitalize).join(', ')}`);
|
||||
} else if (productRegex.test(filter)) {
|
||||
filter.match(productRegex); // weird JS thing, `matchAll` doesn't pick up all matches without this
|
||||
const products = [...filter.matchAll(productRegex)].map(([, product]) => product);
|
||||
outputParts.push(`${pluralize(products.length, 'Product', {withoutCount: true})}: ${products.map(capitalize).join(', ')}`);
|
||||
}
|
||||
|
||||
if (!outputParts.length) {
|
||||
return filter;
|
||||
}
|
||||
|
||||
return outputParts.join(' & ');
|
||||
});
|
|
@ -0,0 +1,69 @@
|
|||
import {describe, it} from 'mocha';
|
||||
import {expect} from 'chai';
|
||||
import {hbs} from 'ember-cli-htmlbars';
|
||||
import {render} from '@ember/test-helpers';
|
||||
import {setupRenderingTest} from 'ember-mocha';
|
||||
|
||||
describe('Integration: Helper: humanize-recipient-filter', function () {
|
||||
setupRenderingTest();
|
||||
|
||||
it('handles all members', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:free,status:-free"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('All members');
|
||||
});
|
||||
|
||||
it('handles free members', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:free"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Free members');
|
||||
});
|
||||
|
||||
it('handles paid members', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:-free"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Paid members');
|
||||
});
|
||||
|
||||
it('handles free members and labels array', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:free,labels:[one,two]"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Free members & Labels: One, Two');
|
||||
});
|
||||
|
||||
it('handles free members and individual labels', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:free,label:one,label:two"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Free members & Labels: One, Two');
|
||||
});
|
||||
|
||||
it('handles paid members and labels array', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:-free,labels:[one,two]"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Paid members & Labels: One, Two');
|
||||
});
|
||||
|
||||
it('handles paid members and individual labels', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:-free,label:one,label:two"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Paid members & Labels: One, Two');
|
||||
});
|
||||
|
||||
it('handles just labels', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "label:one,label:two"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Labels: One, Two');
|
||||
});
|
||||
|
||||
it('handles paid members and products array', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:-free,products:[one,two]"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Paid members & Products: One, Two');
|
||||
});
|
||||
|
||||
it('handles paid members and individual products', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "status:-free,product:one,product:two"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Paid members & Products: One, Two');
|
||||
});
|
||||
|
||||
it('handles just products', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "product:one,product:two"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Products: One, Two');
|
||||
});
|
||||
|
||||
it('handles labels and products', async function () {
|
||||
await render(hbs`{{humanize-recipient-filter "label:one,product:two"}}`);
|
||||
expect(this.element.textContent.trim()).to.equal('Label: One & Product: Two');
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue