mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-22 18:31:57 +03:00
097b232524
Added a button for editing links in newsletters after sending to the Post analytics page Co-authored-by: Rishabh <zrishabhgarg@gmail.com>
197 lines
5.1 KiB
JavaScript
197 lines
5.1 KiB
JavaScript
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';
|
|
|
|
/**
|
|
* @typedef {import('../../services/dashboard-stats').SourceAttributionCount} SourceAttributionCount
|
|
*/
|
|
|
|
const DISPLAY_OPTIONS = [{
|
|
name: 'Free signups',
|
|
value: 'signups'
|
|
}, {
|
|
name: 'Paid conversions',
|
|
value: 'paid'
|
|
}];
|
|
|
|
export default class Analytics extends Component {
|
|
@service ajax;
|
|
@service ghostPaths;
|
|
@service settings;
|
|
@service membersUtils;
|
|
@service utils;
|
|
@service feature;
|
|
|
|
@tracked sources = null;
|
|
@tracked links = null;
|
|
@tracked sortColumn = 'signups';
|
|
displayOptions = DISPLAY_OPTIONS;
|
|
|
|
get post() {
|
|
return this.args.post;
|
|
}
|
|
|
|
get allowedDisplayOptions() {
|
|
if (!this.hasPaidConversionData) {
|
|
return this.displayOptions.filter(d => d.value === 'signups');
|
|
}
|
|
|
|
if (!this.hasFreeSignups) {
|
|
return this.displayOptions.filter(d => d.value === 'paid');
|
|
}
|
|
|
|
return this.displayOptions;
|
|
}
|
|
|
|
get isDropdownDisabled() {
|
|
if (!this.hasPaidConversionData || !this.hasFreeSignups) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
get selectedDisplayOption() {
|
|
if (!this.hasPaidConversionData) {
|
|
return this.displayOptions.find(d => d.value === 'signups');
|
|
}
|
|
|
|
if (!this.hasFreeSignups) {
|
|
return this.displayOptions.find(d => d.value === 'paid');
|
|
}
|
|
|
|
return this.displayOptions.find(d => d.value === this.sortColumn) ?? this.displayOptions[0];
|
|
}
|
|
|
|
get selectedSortColumn() {
|
|
if (!this.hasPaidConversionData) {
|
|
return 'signups';
|
|
}
|
|
|
|
if (!this.hasFreeSignups) {
|
|
return 'paid';
|
|
}
|
|
return this.sortColumn;
|
|
}
|
|
|
|
get hasPaidConversionData() {
|
|
return this.sources.some(sourceData => sourceData.paidConversions > 0);
|
|
}
|
|
|
|
get hasFreeSignups() {
|
|
return this.sources.some(sourceData => sourceData.signups > 0);
|
|
}
|
|
|
|
@action
|
|
onDisplayChange(selected) {
|
|
this.sortColumn = selected.value;
|
|
}
|
|
|
|
@action
|
|
setSortColumn(column) {
|
|
this.sortColumn = column;
|
|
}
|
|
|
|
@action
|
|
updateLink(linkId, linkTo) {
|
|
this.links = this.links?.map((link) => {
|
|
if (link.link.link_id === linkId) {
|
|
return {
|
|
...link,
|
|
link: {
|
|
...link.link,
|
|
to: this.utils.cleanTrackedUrl(linkTo, false),
|
|
title: this.utils.cleanTrackedUrl(linkTo, true)
|
|
}
|
|
};
|
|
}
|
|
return link;
|
|
});
|
|
}
|
|
|
|
@action
|
|
loadData() {
|
|
if (this.showSources) {
|
|
this.fetchReferrersStats();
|
|
} else {
|
|
this.sources = [];
|
|
}
|
|
|
|
if (this.showLinks) {
|
|
this.fetchLinks();
|
|
} else {
|
|
this.links = [];
|
|
}
|
|
}
|
|
|
|
async fetchReferrersStats() {
|
|
if (this._fetchReferrersStats.isRunning) {
|
|
return this._fetchReferrersStats.last;
|
|
}
|
|
return this._fetchReferrersStats.perform();
|
|
}
|
|
|
|
async fetchLinks() {
|
|
if (this._fetchLinks.isRunning) {
|
|
return this._fetchLinks.last;
|
|
}
|
|
return this._fetchLinks.perform();
|
|
}
|
|
|
|
@task
|
|
*_fetchReferrersStats() {
|
|
let statsUrl = this.ghostPaths.url.api(`stats/referrers/posts/${this.post.id}`);
|
|
let result = yield this.ajax.request(statsUrl);
|
|
this.sources = result.stats.map((stat) => {
|
|
return {
|
|
source: stat.source ?? 'Direct',
|
|
signups: stat.signups,
|
|
paidConversions: stat.paid_conversions
|
|
};
|
|
});
|
|
}
|
|
|
|
@task
|
|
*_fetchLinks() {
|
|
const filter = `post_id:${this.post.id}`;
|
|
let statsUrl = this.ghostPaths.url.api(`links/`) + `?filter=${encodeURIComponent(filter)}`;
|
|
let result = yield this.ajax.request(statsUrl);
|
|
const links = result.links.map((link) => {
|
|
return {
|
|
...link,
|
|
link: {
|
|
...link.link,
|
|
to: this.utils.cleanTrackedUrl(link.link.to, false),
|
|
title: this.utils.cleanTrackedUrl(link.link.to, true)
|
|
}
|
|
};
|
|
});
|
|
|
|
// Remove duplicates by title ad merge
|
|
const linksByTitle = links.reduce((acc, link) => {
|
|
if (!acc[link.link.title]) {
|
|
acc[link.link.title] = link;
|
|
} else {
|
|
acc[link.link.title].clicks += link.clicks;
|
|
}
|
|
return acc;
|
|
}, {});
|
|
|
|
this.links = Object.values(linksByTitle);
|
|
}
|
|
|
|
get showLinks() {
|
|
return this.post.showEmailClickAnalytics;
|
|
}
|
|
|
|
get showSources() {
|
|
return this.feature.get('sourceAttribution') && this.post.showAttributionAnalytics;
|
|
}
|
|
|
|
get isLoaded() {
|
|
return this.links !== null && this.souces !== null;
|
|
}
|
|
}
|