mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
Updated open rate chart
- changed to bar chart - added handling of empty dataset
This commit is contained in:
parent
c7bc501d23
commit
92dbc288ec
5 changed files with 55 additions and 17 deletions
|
@ -3,7 +3,7 @@
|
||||||
<GhLoadingSpinner />
|
<GhLoadingSpinner />
|
||||||
{{else}}
|
{{else}}
|
||||||
<EmberChart
|
<EmberChart
|
||||||
@type="LineWithLine"
|
@type={{this.type}}
|
||||||
@options={{this.chartOptions}}
|
@options={{this.chartOptions}}
|
||||||
@data={{this.chartData}}
|
@data={{this.chartData}}
|
||||||
@height={{300}} />
|
@height={{300}} />
|
||||||
|
|
|
@ -126,6 +126,18 @@ export default Component.extend({
|
||||||
// Internal ----------------------------------------------------------------
|
// Internal ----------------------------------------------------------------
|
||||||
|
|
||||||
setChartData({dateLabels, dateValues, label = 'Total Members'}) {
|
setChartData({dateLabels, dateValues, label = 'Total Members'}) {
|
||||||
|
let backgroundColors = this.lineColor;
|
||||||
|
|
||||||
|
if (this.chartType === 'open-rate') {
|
||||||
|
backgroundColors = dateValues.map((dateValue) => {
|
||||||
|
if (dateValue) {
|
||||||
|
return this.lineColor;
|
||||||
|
} else {
|
||||||
|
return (this.nightShift ? '#7C8B9A' : '#CED4D9');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.set('chartData', {
|
this.set('chartData', {
|
||||||
labels: dateLabels,
|
labels: dateLabels,
|
||||||
datasets: [{
|
datasets: [{
|
||||||
|
@ -133,11 +145,13 @@ export default Component.extend({
|
||||||
cubicInterpolationMode: 'monotone',
|
cubicInterpolationMode: 'monotone',
|
||||||
data: dateValues,
|
data: dateValues,
|
||||||
fill: false,
|
fill: false,
|
||||||
backgroundColor: this.lineColor,
|
backgroundColor: backgroundColors,
|
||||||
pointRadius: 0,
|
pointRadius: 0,
|
||||||
pointHitRadius: 10,
|
pointHitRadius: 10,
|
||||||
borderColor: this.lineColor,
|
borderColor: this.lineColor,
|
||||||
borderJoinStyle: 'miter'
|
borderJoinStyle: 'miter',
|
||||||
|
maxBarThickness: 20,
|
||||||
|
minBarLength: 2
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -145,6 +159,10 @@ export default Component.extend({
|
||||||
setChartOptions({rangeInDays}) {
|
setChartOptions({rangeInDays}) {
|
||||||
let maxTicksAllowed = this.isSmall ? 3 : this.getTicksForRange(rangeInDays);
|
let maxTicksAllowed = this.isSmall ? 3 : this.getTicksForRange(rangeInDays);
|
||||||
|
|
||||||
|
if (this.chartType === 'open-rate') {
|
||||||
|
maxTicksAllowed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
this.setChartJSDefaults();
|
this.setChartJSDefaults();
|
||||||
let options = {
|
let options = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
|
@ -176,6 +194,15 @@ export default Component.extend({
|
||||||
titleFontStyle: 'normal',
|
titleFontStyle: 'normal',
|
||||||
titleFontColor: 'rgba(255, 255, 255, 0.7)',
|
titleFontColor: 'rgba(255, 255, 255, 0.7)',
|
||||||
titleMarginBottom: 3,
|
titleMarginBottom: 3,
|
||||||
|
filter: (tooltipItems, data) => {
|
||||||
|
if (this.chartType === 'open-rate') {
|
||||||
|
let label = data.labels[tooltipItems.index];
|
||||||
|
if (label === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
callbacks: {
|
callbacks: {
|
||||||
label: (tooltipItems, data) => {
|
label: (tooltipItems, data) => {
|
||||||
const labelText = data.datasets[tooltipItems.datasetIndex].label;
|
const labelText = data.datasets[tooltipItems.datasetIndex].label;
|
||||||
|
@ -184,9 +211,19 @@ export default Component.extend({
|
||||||
const currency = getSymbol(this.stats.currency);
|
const currency = getSymbol(this.stats.currency);
|
||||||
valueText = `${currency}${valueText}`;
|
valueText = `${currency}${valueText}`;
|
||||||
}
|
}
|
||||||
|
if (this.chartType === 'open-rate') {
|
||||||
|
valueText = `${valueText}%`;
|
||||||
|
}
|
||||||
return `${labelText}: ${valueText}`;
|
return `${labelText}: ${valueText}`;
|
||||||
},
|
},
|
||||||
title: function (tooltipItems) {
|
title: (tooltipItems) => {
|
||||||
|
if (this.chartType === 'open-rate') {
|
||||||
|
if (tooltipItems.length) {
|
||||||
|
return tooltipItems[0].xLabel;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
return moment(tooltipItems[0].xLabel).format(DATE_FORMAT);
|
return moment(tooltipItems[0].xLabel).format(DATE_FORMAT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,7 +252,7 @@ export default Component.extend({
|
||||||
autoSkip: false,
|
autoSkip: false,
|
||||||
fontColor: '#626D79',
|
fontColor: '#626D79',
|
||||||
maxTicksLimit: 10,
|
maxTicksLimit: 10,
|
||||||
callback: function (value, index, values) {
|
callback: (value, index, values) => {
|
||||||
let step = (values.length - 1) / (maxTicksAllowed);
|
let step = (values.length - 1) / (maxTicksAllowed);
|
||||||
let steps = [];
|
let steps = [];
|
||||||
for (let i = 0; i < maxTicksAllowed; i++) {
|
for (let i = 0; i < maxTicksAllowed; i++) {
|
||||||
|
@ -225,7 +262,7 @@ export default Component.extend({
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (index === (values.length - 1)) {
|
if (index === (values.length - 1) && this.chartType !== 'open-rate') {
|
||||||
return 'Today';
|
return 'Today';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,11 +167,11 @@ export default class DashboardController extends Controller {
|
||||||
rangeInDays: 30
|
rangeInDays: 30
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
label: 'Open Rate',
|
label: 'Open rate',
|
||||||
dateLabels: results.map(d => d.submittedAt),
|
dateLabels: results.map(d => d.subject),
|
||||||
dateValues: results.map(d => d.openRate)
|
dateValues: results.map(d => d.openRate)
|
||||||
},
|
},
|
||||||
title: 'Open Rate',
|
title: 'Open rate',
|
||||||
stats: results
|
stats: results
|
||||||
};
|
};
|
||||||
this.newsletterOpenRatesLoading = false;
|
this.newsletterOpenRatesLoading = false;
|
||||||
|
|
|
@ -144,10 +144,11 @@ export default class MembersStatsService extends Service {
|
||||||
|
|
||||||
@task
|
@task
|
||||||
*_fetchNewsletterStatsTask() {
|
*_fetchNewsletterStatsTask() {
|
||||||
|
const limit = 5;
|
||||||
let query = {
|
let query = {
|
||||||
filter: 'email_count:-0',
|
filter: 'email_count:-0',
|
||||||
order: 'submitted_at desc',
|
order: 'submitted_at desc',
|
||||||
limit: 10
|
limit: limit
|
||||||
};
|
};
|
||||||
const results = yield this.store.query('email', query);
|
const results = yield this.store.query('email', query);
|
||||||
const data = results.toArray();
|
const data = results.toArray();
|
||||||
|
@ -160,8 +161,8 @@ export default class MembersStatsService extends Service {
|
||||||
});
|
});
|
||||||
|
|
||||||
const paddedResults = [];
|
const paddedResults = [];
|
||||||
if (data.length < 10) {
|
if (data.length < limit) {
|
||||||
const pad = 10 - data.length;
|
const pad = limit - data.length;
|
||||||
const lastSubmittedAt = data.length > 0 ? data[results.length - 1].submittedAtUTC : moment();
|
const lastSubmittedAt = data.length > 0 ? data[results.length - 1].submittedAtUTC : moment();
|
||||||
for (let i = 0; i < pad; i++) {
|
for (let i = 0; i < pad; i++) {
|
||||||
paddedResults.push({
|
paddedResults.push({
|
||||||
|
@ -171,7 +172,7 @@ export default class MembersStatsService extends Service {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stats = stats.concat(paddedResults);
|
stats = stats .concat(paddedResults);
|
||||||
stats.reverse();
|
stats.reverse();
|
||||||
this.newsletterStats = stats;
|
this.newsletterStats = stats;
|
||||||
return stats;
|
return stats;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{#if this.mrrStatsData}}
|
{{#if this.mrrStatsData}}
|
||||||
<div class="gh-dashboard-chart">
|
<div class="gh-dashboard-chart">
|
||||||
<GhMembersChart @nightShift={{feature "nightShift"}} @showSummary={{false}} @showRange={{false}} @chartType="mrr" @chartStats={{this.mrrStatsData}} />
|
<GhMembersChart @type="LineWithLine" @nightShift={{feature "nightShift"}} @showSummary={{false}} @showRange={{false}} @chartType="mrr" @chartStats={{this.mrrStatsData}} />
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="gh-dashboard-chart nodata">
|
<div class="gh-dashboard-chart nodata">
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="gh-dashboard-chart small">
|
<div class="gh-dashboard-chart small">
|
||||||
<GhMembersChart @nightShift={{feature "nightShift"}} @chartSize="small" @showSummary={{false}} @chartType="all-members" @showRange={{false}} @chartStats={{this.memberCountStatsData.all}} />
|
<GhMembersChart @type="LineWithLine" @nightShift={{feature "nightShift"}} @chartSize="small" @showSummary={{false}} @chartType="all-members" @showRange={{false}} @chartStats={{this.memberCountStatsData.all}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="gh-dashboard-chart small">
|
<div class="gh-dashboard-chart small">
|
||||||
<GhMembersChart @nightShift={{feature "nightShift"}} @chartSize="small" @showSummary={{false}} @chartType="paid-members" @showRange={{false}} @chartStats={{this.memberCountStatsData.paid}} />
|
<GhMembersChart @type="LineWithLine" @nightShift={{feature "nightShift"}} @chartSize="small" @showSummary={{false}} @chartType="paid-members" @showRange={{false}} @chartStats={{this.memberCountStatsData.paid}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="gh-dashboard-chart small">
|
<div class="gh-dashboard-chart small">
|
||||||
<GhMembersChart @nightShift={{feature "nightShift"}} @chartSize="small" @showSummary={{false}} @chartType="paid-members" @showRange={{false}} @chartStats={{this.newsletterOpenRatesData}} />
|
<GhMembersChart @type="bar" @nightShift={{feature "nightShift"}} @chartSize="small" @showSummary={{false}} @chartType="open-rate" @showRange={{false}} @chartStats={{this.newsletterOpenRatesData}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue