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:
parent
615dc8d24c
commit
a34fac50b0
3 changed files with 102 additions and 22 deletions
|
@ -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"
|
||||||
|
|
|
@ -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 = {
|
||||||
|
name_email: [
|
||||||
|
{label: 'contains', name: 'contains'}
|
||||||
|
],
|
||||||
|
subscribed: [
|
||||||
{label: 'is', name: 'is'},
|
{label: 'is', name: 'is'},
|
||||||
{label: 'is not', name: 'is-not'},
|
{label: 'is not', name: 'is-not'}
|
||||||
{label: 'in', name: 'in'}
|
],
|
||||||
// {label: 'contains', name: 'contains'},
|
name: [
|
||||||
// {label: 'exists', name: 'exists'},
|
{label: 'is', name: 'is'},
|
||||||
// {label: 'does not exist', name: 'does-not-exist'}
|
{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,6 +139,7 @@ export default class GhMembersFilterLabsComponent extends Component {
|
||||||
generateNqlFilter(filters) {
|
generateNqlFilter(filters) {
|
||||||
let query = '';
|
let query = '';
|
||||||
filters.forEach((filter) => {
|
filters.forEach((filter) => {
|
||||||
|
if (filter.value && !['name_email'].includes(filter.type)) {
|
||||||
if (filter.type === 'label') {
|
if (filter.type === 'label') {
|
||||||
const relationStr = filter.relation === 'is-not' ? '-' : '';
|
const relationStr = filter.relation === 'is-not' ? '-' : '';
|
||||||
const filterValue = '[' + filter.value.join(',') + ']';
|
const filterValue = '[' + filter.value.join(',') + ']';
|
||||||
|
@ -80,6 +149,7 @@ export default class GhMembersFilterLabsComponent extends Component {
|
||||||
const filterValue = filter.value.includes(' ') ? `'${filter.value}'` : filter.value;
|
const filterValue = filter.value.includes(' ') ? `'${filter.value}'` : filter.value;
|
||||||
query += `${filter.type}:${relationStr}${filterValue}+`;
|
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue