mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
Added ability to filter members by attribution to Admin
refs https://github.com/TryGhost/Team/issues/1832
This commit is contained in:
parent
73466c1c40
commit
0fc0bf40f1
5 changed files with 151 additions and 2 deletions
14
ghost/admin/app/components/gh-resource-select.hbs
Normal file
14
ghost/admin/app/components/gh-resource-select.hbs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<GhTokenInput
|
||||||
|
@options={{this.options}}
|
||||||
|
@selected={{this.selectedOptions}}
|
||||||
|
@disabled={{or @disabled this.fetchOptionsTask.isRunning}}
|
||||||
|
@optionsComponent="power-select/options"
|
||||||
|
@allowCreation={{false}}
|
||||||
|
@renderInPlace={{this.renderInPlace}}
|
||||||
|
@onChange={{this.onChange}}
|
||||||
|
@class="select-members"
|
||||||
|
@placeholder="Select a Post/Page"
|
||||||
|
as |resource|
|
||||||
|
>
|
||||||
|
{{resource.name}}
|
||||||
|
</GhTokenInput>
|
81
ghost/admin/app/components/gh-resource-select.js
Normal file
81
ghost/admin/app/components/gh-resource-select.js
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
import Component from '@glimmer/component';
|
||||||
|
import {action} from '@ember/object';
|
||||||
|
import {inject as service} from '@ember/service';
|
||||||
|
import {task} from 'ember-concurrency';
|
||||||
|
import {tracked} from '@glimmer/tracking';
|
||||||
|
|
||||||
|
export default class GhResourceSelect extends Component {
|
||||||
|
@service store;
|
||||||
|
|
||||||
|
@tracked _options = [];
|
||||||
|
|
||||||
|
get renderInPlace() {
|
||||||
|
return this.args.renderInPlace === undefined ? false : this.args.renderInPlace;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.fetchOptionsTask.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
get options() {
|
||||||
|
return this._options;
|
||||||
|
}
|
||||||
|
|
||||||
|
get flatOptions() {
|
||||||
|
const options = [];
|
||||||
|
|
||||||
|
function getOptions(option) {
|
||||||
|
if (option.options) {
|
||||||
|
return option.options.forEach(getOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.push(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._options.forEach(getOptions);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
get selectedOptions() {
|
||||||
|
const resources = this.args.resources || [];
|
||||||
|
return this.flatOptions.filter(option => resources.find(resource => resource.id === option.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
onChange(options) {
|
||||||
|
this.args.onChange(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@task
|
||||||
|
*fetchOptionsTask() {
|
||||||
|
const options = yield [];
|
||||||
|
|
||||||
|
const posts = yield this.store.query('post', {filter: 'status:published', limit: 'all'});
|
||||||
|
const pages = yield this.store.query('page', {filter: 'status:published', limit: 'all'});
|
||||||
|
|
||||||
|
function mapResource(resource) {
|
||||||
|
return {
|
||||||
|
name: resource.title,
|
||||||
|
id: resource.id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (posts.length > 0) {
|
||||||
|
options.push({
|
||||||
|
groupName: 'Posts',
|
||||||
|
options: posts.map(mapResource)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pages.length > 0) {
|
||||||
|
options.push({
|
||||||
|
groupName: 'Pages',
|
||||||
|
options: pages.map(mapResource)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this._options = options;
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,6 +42,22 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{else if (eq @filter.type 'conversion')}}
|
||||||
|
<div class="relative">
|
||||||
|
<GhResourceSelect
|
||||||
|
@onChange={{fn this.setConversionAttributionFilterValue @filter}}
|
||||||
|
@resources={{this.conversionAttributionFilterValue}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{else if (eq @filter.type 'signup')}}
|
||||||
|
<div class="relative">
|
||||||
|
<GhResourceSelect
|
||||||
|
@onChange={{fn this.setSignupAttributionFilterValue @filter}}
|
||||||
|
@resources={{this.signupAttributionFilterValue}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{else if (eq @filter.type 'subscribed')}}
|
{{else if (eq @filter.type 'subscribed')}}
|
||||||
<span class="gh-select">
|
<span class="gh-select">
|
||||||
<OneWaySelect
|
<OneWaySelect
|
||||||
|
|
|
@ -48,6 +48,30 @@ export default class MembersFilterValue extends Component {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get signupAttributionFilterValue() {
|
||||||
|
if (this.args.filter?.type === 'signup') {
|
||||||
|
const resources = this.args.filter?.value || [];
|
||||||
|
return resources.map((resource) => {
|
||||||
|
return {
|
||||||
|
id: resource
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get conversionAttributionFilterValue() {
|
||||||
|
if (this.args.filter?.type === 'conversion') {
|
||||||
|
const resources = this.args.filter?.value || [];
|
||||||
|
return resources.map((resource) => {
|
||||||
|
return {
|
||||||
|
id: resource
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
setInputFilterValue(filter, event) {
|
setInputFilterValue(filter, event) {
|
||||||
this.filterValue = event.target.value;
|
this.filterValue = event.target.value;
|
||||||
|
@ -78,4 +102,14 @@ export default class MembersFilterValue extends Component {
|
||||||
setTiersFilterValue(filter, tiers) {
|
setTiersFilterValue(filter, tiers) {
|
||||||
this.args.setFilterValue(filter, tiers.map(tier => tier.slug));
|
this.args.setFilterValue(filter, tiers.map(tier => tier.slug));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
setConversionAttributionFilterValue(filter, resources) {
|
||||||
|
this.args.setFilterValue(filter, resources.map(resource => resource.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
setSignupAttributionFilterValue(filter, resources) {
|
||||||
|
this.args.setFilterValue(filter, resources.map(resource => resource.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,15 @@ const FILTER_PROPERTIES = [
|
||||||
// Emails
|
// Emails
|
||||||
{label: 'Emails sent (all time)', name: 'email_count', group: 'Email'},
|
{label: 'Emails sent (all time)', name: 'email_count', group: 'Email'},
|
||||||
{label: 'Emails opened (all time)', name: 'email_opened_count', group: 'Email'},
|
{label: 'Emails opened (all time)', name: 'email_opened_count', group: 'Email'},
|
||||||
{label: 'Open rate (all time)', name: 'email_open_rate', group: 'Email'}
|
{label: 'Open rate (all time)', name: 'email_open_rate', group: 'Email'},
|
||||||
// {label: 'Emails sent (30 days)', name: 'x', group: 'Email'},
|
// {label: 'Emails sent (30 days)', name: 'x', group: 'Email'},
|
||||||
// {label: 'Emails opened (30 days)', name: 'x', group: 'Email'},
|
// {label: 'Emails opened (30 days)', name: 'x', group: 'Email'},
|
||||||
// {label: 'Open rate (30 days)', name: 'x', group: 'Email'},
|
// {label: 'Open rate (30 days)', name: 'x', group: 'Email'},
|
||||||
// {label: 'Emails sent (60 days)', name: 'x', group: 'Email'},
|
// {label: 'Emails sent (60 days)', name: 'x', group: 'Email'},
|
||||||
// {label: 'Emails opened (60 days)', name: 'x', group: 'Email'},
|
// {label: 'Emails opened (60 days)', name: 'x', group: 'Email'},
|
||||||
// {label: 'Open rate (60 days)', name: 'x', group: 'Email'},
|
// {label: 'Open rate (60 days)', name: 'x', group: 'Email'},
|
||||||
|
{label: 'Subscribed from', name: 'signup', group: 'Attribution', valueType: 'array', feature: 'memberAttribution'},
|
||||||
|
{label: 'Converted from', name: 'conversion', group: 'Attribution', valueType: 'array', feature: 'memberAttribution'}
|
||||||
];
|
];
|
||||||
|
|
||||||
const MATCH_RELATION_OPTIONS = [
|
const MATCH_RELATION_OPTIONS = [
|
||||||
|
@ -82,7 +84,9 @@ const FILTER_RELATIONS_OPTIONS = {
|
||||||
'subscriptions.current_period_end': DATE_RELATION_OPTIONS,
|
'subscriptions.current_period_end': DATE_RELATION_OPTIONS,
|
||||||
email_count: NUMBER_RELATION_OPTIONS,
|
email_count: NUMBER_RELATION_OPTIONS,
|
||||||
email_opened_count: NUMBER_RELATION_OPTIONS,
|
email_opened_count: NUMBER_RELATION_OPTIONS,
|
||||||
email_open_rate: NUMBER_RELATION_OPTIONS
|
email_open_rate: NUMBER_RELATION_OPTIONS,
|
||||||
|
signup: MATCH_RELATION_OPTIONS,
|
||||||
|
conversion: MATCH_RELATION_OPTIONS
|
||||||
};
|
};
|
||||||
|
|
||||||
const FILTER_VALUE_OPTIONS = {
|
const FILTER_VALUE_OPTIONS = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue