mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-29 13:52:10 +03:00
Added sorting for attribution data on dashboard (#15474)
refs https://github.com/TryGhost/Team/issues/1941 - sorts attribution table and chart on signups or paid conversions
This commit is contained in:
parent
83e608c25b
commit
b1b3c72642
@ -4,11 +4,20 @@
|
||||
<div style="display: grid;grid-template-columns: 2fr 1fr;grid-gap: 24px; position: relative;">
|
||||
<div>
|
||||
<h3 class="gh-dashboard-metric-label">Top sources</h3>
|
||||
<MemberAttribution::SourceAttributionTable @sources={{this.sources}} class="gh-dashboard-attribution-list gh-dashboard-list" style="justify-content:flex-start;" />
|
||||
<MemberAttribution::SourceAttributionTable
|
||||
@sources={{this.sources}}
|
||||
@sortColumn={{this.sortColumn}}
|
||||
@setSortColumn={{this.setSortColumn}}
|
||||
class="gh-dashboard-attribution-list gh-dashboard-list" style="justify-content:flex-start;"
|
||||
/>
|
||||
</div>
|
||||
<div style="display:flex;justify-content:center;align-items: center;height:100%;position: relative;">
|
||||
<div style="max-width: 200px; position: relative;">
|
||||
<MemberAttribution::SourceAttributionChart @sources={{this.chartSources}} />
|
||||
<MemberAttribution::SourceAttributionChart
|
||||
@sources={{this.chartSources}}
|
||||
@sortColumn={{this.sortColumn}}
|
||||
@setSortColumn={{this.setSortColumn}}
|
||||
/>
|
||||
</div>
|
||||
<div id="gh-dashboard-attribution-tooltip" class="gh-dashboard-tooltip">
|
||||
<div class="gh-dashboard-tooltip-value">
|
||||
|
@ -1,9 +1,16 @@
|
||||
import Component from '@glimmer/component';
|
||||
import {action} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {tracked} from '@glimmer/tracking';
|
||||
|
||||
export default class Recents extends Component {
|
||||
@service dashboardStats;
|
||||
@tracked sortColumn = 'signups';
|
||||
|
||||
@action
|
||||
setSortColumn(column) {
|
||||
this.sortColumn = column;
|
||||
}
|
||||
|
||||
@action
|
||||
loadData() {
|
||||
|
@ -15,7 +15,7 @@
|
||||
</div>
|
||||
<div class="gh-dashboard-list-body" style="max-height: 230px; overflow-y: clip; justify-content: flex-start;">
|
||||
<div class="gh-dashboard-attribution-list-scrollable">
|
||||
{{#each this.sources as |sourceData|}}
|
||||
{{#each @data.sources as |sourceData|}}
|
||||
<div class="gh-dashboard-list-item">
|
||||
<div class="gh-dashboard-list-item-sub gh-dashboard-list-item-sub-source">
|
||||
<span class="gh-dashboard-list-text">{{sourceData.source}}</span>
|
||||
|
@ -3,18 +3,4 @@ import {inject as service} from '@ember/service';
|
||||
|
||||
export default class FullAttributionTable extends Component {
|
||||
@service membersUtils;
|
||||
|
||||
get sources() {
|
||||
const availableSources = this.args.data.sources.filter(source => source.source);
|
||||
const unavailableSources = this.args.data.sources.filter(sourceData => !sourceData.source).map((sourceData) => {
|
||||
return {
|
||||
...sourceData,
|
||||
source: 'Unavailable'
|
||||
};
|
||||
});
|
||||
return [
|
||||
...availableSources,
|
||||
...unavailableSources
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import Component from '@glimmer/component';
|
||||
import {tracked} from '@glimmer/tracking';
|
||||
|
||||
const CHART_COLORS = [
|
||||
'#8e42ff',
|
||||
@ -11,8 +10,6 @@ const CHART_COLORS = [
|
||||
];
|
||||
|
||||
export default class SourceAttributionChart extends Component {
|
||||
@tracked chartType = 'free';
|
||||
|
||||
get sources() {
|
||||
return this.args.sources;
|
||||
}
|
||||
@ -84,7 +81,7 @@ export default class SourceAttributionChart extends Component {
|
||||
}
|
||||
|
||||
get chartData() {
|
||||
if (this.chartType === 'free') {
|
||||
if (this.args.sortColumn === 'signups') {
|
||||
const sortedByFree = [...this.sources];
|
||||
sortedByFree.sort((a, b) => {
|
||||
return b.signups - a.signups;
|
||||
|
@ -1,9 +1,21 @@
|
||||
<div ...attributes>
|
||||
<div class="gh-dashboard-list-header">
|
||||
<div class="gh-dashboard-list-title gh-dashboard-list-title-sources">Sources</div>
|
||||
<div class="gh-dashboard-list-title">Signups {{svg-jar "arrow-down-small"}}</div>
|
||||
<div
|
||||
class="gh-dashboard-list-title {{if (eq @sortColumn "signups") "sorted-by"}}"
|
||||
role="button" aria-label="Sort by free signups"
|
||||
{{on "click" (fn @setSortColumn "signups")}}
|
||||
>
|
||||
Signups {{svg-jar "arrow-down-small"}}
|
||||
</div>
|
||||
{{#if this.membersUtils.paidMembersEnabled}}
|
||||
<div class="gh-dashboard-list-title"><span class="hide-when-small">Paid </span>Conversions {{svg-jar "arrow-down-small"}}</div>
|
||||
<div
|
||||
role="button" aria-label="Sort by paid signups"
|
||||
class="gh-dashboard-list-title {{if (eq @sortColumn "paid") "sorted-by"}}"
|
||||
{{on "click" (fn @setSortColumn "paid")}}
|
||||
>
|
||||
<span class="hide-when-small">Paid </span>Conversions {{svg-jar "arrow-down-small"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="gh-dashboard-list-body">
|
||||
|
@ -10,12 +10,24 @@ export default class SourceAttributionTable extends Component {
|
||||
@action
|
||||
openAllSources() {
|
||||
this.modals.open(AllSourcesModal, {
|
||||
sources: this.args.sources
|
||||
sources: [
|
||||
...this.sortedSources,
|
||||
...this.unavailableSource
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
get unavailableSource() {
|
||||
return this.args.sources.filter(sourceData => !sourceData.source).map((sourceData) => {
|
||||
return {
|
||||
...sourceData,
|
||||
source: 'Unavailable'
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
get others() {
|
||||
const availableSources = this.args.sources.filter(source => source.source);
|
||||
const availableSources = this.sortedSources;
|
||||
const unavailableSource = this.args.sources.find(sourceData => !sourceData.source);
|
||||
if (!availableSources.length && !unavailableSource) {
|
||||
return null;
|
||||
@ -32,20 +44,17 @@ export default class SourceAttributionTable extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
get sources() {
|
||||
return this.args.sources.filter(source => source.source).slice(0, 5);
|
||||
// const availableSources = this.args.sources.filter(source => source.source);
|
||||
// return availableSources.slice(0, 5);
|
||||
get sortedSources() {
|
||||
return this.args.sources?.filter(source => source.source).sort((a, b) => {
|
||||
if (this.args.sortColumn === 'signups') {
|
||||
return b.signups - a.signups;
|
||||
} else {
|
||||
return b.paidConversions - a.paidConversions;
|
||||
}
|
||||
}) || [];
|
||||
}
|
||||
|
||||
// const unavailableSources = this.args.sources.filter(sourceData => !sourceData.source).map((sourceData) => {
|
||||
// return {
|
||||
// ...sourceData,
|
||||
// source: 'Unavailable'
|
||||
// };
|
||||
// });
|
||||
// return [
|
||||
// ...availableSources,
|
||||
// ...unavailableSources
|
||||
// ];
|
||||
get sources() {
|
||||
return this.sortedSources.slice(0, 5);
|
||||
}
|
||||
}
|
||||
|
@ -1075,7 +1075,7 @@ Dashboard Attribution */
|
||||
}
|
||||
|
||||
.gh-dashboard-list-title.sorted-by svg {
|
||||
display: block;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.gh-dashboard-list-title svg path {
|
||||
|
Loading…
Reference in New Issue
Block a user