0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Added custom filter operators for filtering UI

refs https://github.com/TryGhost/Team/issues/943

- adds custom operators for each filter based on type
- adds `name or email` filter for `contains` search  on name or email
This commit is contained in:
Rishabh 2021-08-13 13:42:16 +05:30
parent 615dc8d24c
commit a34fac50b0
3 changed files with 102 additions and 22 deletions

View file

@ -36,7 +36,7 @@
<span class="gh-select"> <span class="gh-select">
<OneWaySelect <OneWaySelect
@value={{filter.relation}} @value={{filter.relation}}
@options={{this.availableFilterRelations}} @options={{filter.relationOptions}}
@optionValuePath="name" @optionValuePath="name"
@optionLabelPath="label" @optionLabelPath="label"
@optionTargetPath="name" @optionTargetPath="name"

View file

@ -8,6 +8,7 @@ const FILTER_PROPERTIES = [
// Basic // Basic
{label: 'Name', name: 'name', group: 'Basic'}, {label: 'Name', name: 'name', group: 'Basic'},
{label: 'Email', name: 'email', group: 'Basic'}, {label: 'Email', name: 'email', group: 'Basic'},
{label: 'Name or Email', name: 'name_email', group: 'Basic'},
// {label: 'Location', name: 'location', group: 'Basic'}, // {label: 'Location', name: 'location', group: 'Basic'},
{label: 'Newsletter subscription', name: 'subscribed', group: 'Basic'}, {label: 'Newsletter subscription', name: 'subscribed', group: 'Basic'},
{label: 'Label', name: 'label', group: 'Basic'}, {label: 'Label', name: 'label', group: 'Basic'},
@ -30,15 +31,79 @@ const FILTER_PROPERTIES = [
{label: 'Stripe subscription status', name: 'subscriptions.status', group: 'Email'} {label: 'Stripe subscription status', name: 'subscriptions.status', group: 'Email'}
]; ];
const FILTER_RELATIONS = [ const FILTER_RELATIONS_OPTIONS = {
{label: 'is', name: 'is'}, name_email: [
{label: 'is not', name: 'is-not'}, {label: 'contains', name: 'contains'}
{label: 'in', name: 'in'} ],
// {label: 'contains', name: 'contains'}, subscribed: [
// {label: 'exists', name: 'exists'}, {label: 'is', name: 'is'},
// {label: 'does not exist', name: 'does-not-exist'} {label: 'is not', name: 'is-not'}
]; ],
name: [
{label: 'is', name: 'is'},
{label: 'is not', name: 'is-not'}
],
email: [
{label: 'is', name: 'is'},
{label: 'is not', name: 'is-not'}
],
status: [
{label: 'is', name: 'is'},
{label: 'is not', name: 'is-not'}
],
'subscriptions.plan_interval': [
{label: 'is', name: 'is'},
{label: 'is not', name: 'is-not'}
],
'subscriptions.status': [
{label: 'is', name: 'is'},
{label: 'is not', name: 'is-not'}
],
label: [
{label: 'is in', name: 'is'},
{label: 'is not in', name: 'is-not'}
],
email_count: [
{label: 'is', name: 'is'},
{label: 'is greater than', name: 'is-greater'},
{label: 'is less than', name: 'is-less'}
],
email_opened_count: [
{label: 'is', name: 'is'},
{label: 'is greater than', name: 'is-greater'},
{label: 'is less than', name: 'is-less'}
],
email_open_rate: [
{label: 'is', name: 'is'},
{label: 'is greater than', name: 'is-greater'},
{label: 'is less than', name: 'is-less'}
]
};
const FILTER_VALUE_OPTIONS = {
'subscriptions.plan_interval': [
{label: 'Monthly', name: 'month'},
{label: 'Yearly', name: 'year'}
],
status: [
{label: 'Paid', name: 'paid'},
{label: 'Free', name: 'free'},
{label: 'Complimentary', name: 'comped'}
],
subscribed: [
{label: 'Subscribed', name: 'true'},
{label: 'Unsubscribed', name: 'false'}
],
'subscriptions.status': [
{label: 'Active', name: 'active'},
{label: 'Trialing', name: 'trialing'},
{label: 'Canceled', name: 'canceled'},
{label: 'Unpaid', name: 'unpaid'},
{label: 'Past Due', name: 'past_due'},
{label: 'Incomplete', name: 'incomplete'},
{label: 'Incomplete - Expired', name: 'incomplete_expired'}
]
};
export default class GhMembersFilterLabsComponent extends Component { export default class GhMembersFilterLabsComponent extends Component {
@service session @service session
@tracked filters = A([ @tracked filters = A([
@ -46,14 +111,16 @@ export default class GhMembersFilterLabsComponent extends Component {
id: `filter-0`, id: `filter-0`,
type: 'name', type: 'name',
relation: 'is', relation: 'is',
value: '' value: '',
relationOptions: FILTER_RELATIONS_OPTIONS.name
}) })
]); ]);
constructor(...args) { constructor(...args) {
super(...args); super(...args);
this.availableFilterProperties = FILTER_PROPERTIES; this.availableFilterProperties = FILTER_PROPERTIES;
this.availableFilterRelations = FILTER_RELATIONS; this.availableFilterRelationsOptions = FILTER_RELATIONS_OPTIONS;
this.availableFilterValueOptions = FILTER_VALUE_OPTIONS;
this.nextFilterId = 1; this.nextFilterId = 1;
} }
@ -63,7 +130,8 @@ export default class GhMembersFilterLabsComponent extends Component {
id: `filter-${this.nextFilterId}`, id: `filter-${this.nextFilterId}`,
type: 'name', type: 'name',
relation: 'is', relation: 'is',
value: '' value: '',
relationOptions: this.availableFilterRelationsOptions.name
})); }));
this.nextFilterId = this.nextFilterId + 1; this.nextFilterId = this.nextFilterId + 1;
} }
@ -71,14 +139,16 @@ export default class GhMembersFilterLabsComponent extends Component {
generateNqlFilter(filters) { generateNqlFilter(filters) {
let query = ''; let query = '';
filters.forEach((filter) => { filters.forEach((filter) => {
if (filter.type === 'label') { if (filter.value && !['name_email'].includes(filter.type)) {
const relationStr = filter.relation === 'is-not' ? '-' : ''; if (filter.type === 'label') {
const filterValue = '[' + filter.value.join(',') + ']'; const relationStr = filter.relation === 'is-not' ? '-' : '';
query += `${filter.type}:${relationStr}${filterValue}+`; const filterValue = '[' + filter.value.join(',') + ']';
} else { query += `${filter.type}:${relationStr}${filterValue}+`;
const relationStr = filter.relation === 'is-not' ? '-' : ''; } else {
const filterValue = filter.value.includes(' ') ? `'${filter.value}'` : filter.value; const relationStr = filter.relation === 'is-not' ? '-' : '';
query += `${filter.type}:${relationStr}${filterValue}+`; const filterValue = filter.value.includes(' ') ? `'${filter.value}'` : filter.value;
query += `${filter.type}:${relationStr}${filterValue}+`;
}
} }
}); });
return query.slice(0, -1); return query.slice(0, -1);
@ -94,7 +164,9 @@ export default class GhMembersFilterLabsComponent extends Component {
setFilterType(filterId, newType) { setFilterType(filterId, newType) {
const filterToEdit = this.filters.findBy('id', filterId); const filterToEdit = this.filters.findBy('id', filterId);
filterToEdit.set('type', newType); filterToEdit.set('type', newType);
filterToEdit.set('value', ''); filterToEdit.set('relationOptions', this.availableFilterRelationsOptions[newType]);
const defaultValue = this.availableFilterValueOptions[newType] ? this.availableFilterValueOptions[newType][0].name : '';
filterToEdit.set('value', defaultValue);
} }
@action @action

View file

@ -213,8 +213,16 @@ export default class MembersController extends Controller {
@action @action
applyFilter(filterStr, filters) { applyFilter(filterStr, filters) {
this.filters = filters; this.filters = filters.filter((filter) => {
return filter.type !== 'name_email';
});
this.filterParam = filterStr || null; this.filterParam = filterStr || null;
this.searchParam = null;
filters.forEach((filter) => {
if (filter.type === 'name_email' && filter.value) {
this.searchParam = filter.value;
}
});
} }
@action @action