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:
Rishabh Garg 2022-09-26 23:29:30 +05:30 committed by GitHub
parent 83e608c25b
commit b1b3c72642
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 60 additions and 40 deletions

View File

@ -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">

View File

@ -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() {

View File

@ -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>

View File

@ -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
];
}
}

View File

@ -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;

View File

@ -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">

View File

@ -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);
}
}

View File

@ -1075,7 +1075,7 @@ Dashboard Attribution */
}
.gh-dashboard-list-title.sorted-by svg {
display: block;
display: inline;
}
.gh-dashboard-list-title svg path {