mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
Moved around the delta sub graph to MRR to hopefully make sense contextually
refs: https://github.com/TryGhost/Team/issues/1462 - moved the delta graph into the revenue graph of the main combined graph - made the secondary dropdown work again - updated some chart titles - tidied up the code and styles to make it work well
This commit is contained in:
parent
4c5144cb61
commit
d3d0a6509d
@ -7,17 +7,17 @@
|
||||
|
||||
{{!-- Could these if else statements be cleaned up more? --}}
|
||||
{{#if this.areNewslettersEnabled}}
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
<Dashboard::V5::Charts::Email />
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
<Dashboard::V5::Charts::EmailOpenRate />
|
||||
{{else}}
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
{{/if}}
|
||||
|
||||
{{else}}
|
||||
{{#if this.areNewslettersEnabled}}
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
{{#if this.areNewslettersEnabled}}
|
||||
<Dashboard::V5::Charts::Email />
|
||||
<Dashboard::V5::Charts::Engagement />
|
||||
<Dashboard::V5::Charts::EmailOpenRate />
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
@ -52,15 +52,6 @@
|
||||
@center={{true}}
|
||||
@large={{true}} />
|
||||
</button>
|
||||
<button class="gh-dashboard5-stats-button {{if this.chartShowingPaid 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "paid-total")}}>
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label={{gh-pluralize this.paidMembers "Total paid member" without-count=true}}
|
||||
@value={{format-number this.paidMembers}}
|
||||
{{!-- @trends={{this.hasTrends}} --}}
|
||||
{{!-- @percentage={{this.paidMembersTrend}} --}}
|
||||
@center={{true}}
|
||||
@large={{true}} />
|
||||
</button>
|
||||
<button class="gh-dashboard5-stats-button {{if this.chartShowingMrr 'is-selected'}}" type="button" {{on "click" (fn this.changeChartDisplay "mrr")}}>
|
||||
<Dashboard::v5::Parts::Metric
|
||||
@label="Monthly Revenue (MRR)"
|
||||
@ -75,7 +66,7 @@
|
||||
</div>
|
||||
|
||||
<div class="gh-dashboard5-selects">
|
||||
{{#if this.chartShowingPaid}}
|
||||
{{#if this.chartShowingMrr}}
|
||||
<div class="gh-dashboard5-select">
|
||||
<PowerSelect
|
||||
@selected={{this.selectedPaidOption}}
|
||||
|
@ -21,10 +21,10 @@ const DAYS_OPTIONS = [{
|
||||
}];
|
||||
|
||||
const PAID_OPTIONS = [{
|
||||
name: 'Total Paid Members',
|
||||
value: 'paid-total'
|
||||
name: 'MRR Total',
|
||||
value: 'mrr'
|
||||
}, {
|
||||
name: 'Paid Members By Day',
|
||||
name: 'MRR Deltas',
|
||||
value: 'paid-breakdown'
|
||||
}];
|
||||
|
||||
@ -87,11 +87,11 @@ export default class Anchor extends Component {
|
||||
}
|
||||
|
||||
get chartShowingPaid() {
|
||||
return (this.chartDisplay === 'paid-total' || this.chartDisplay === 'paid-breakdown');
|
||||
return (this.chartDisplay === 'paid-total');
|
||||
}
|
||||
|
||||
get chartShowingMrr() {
|
||||
return (this.chartDisplay === 'mrr');
|
||||
return (this.chartDisplay === 'mrr' || this.chartDisplay === 'paid-breakdown');
|
||||
}
|
||||
|
||||
get loading() {
|
||||
@ -152,9 +152,9 @@ export default class Anchor extends Component {
|
||||
|
||||
get chartTitle() {
|
||||
if (this.chartDisplay === 'paid-total' || this.chartDisplay === 'paid-breakdown') {
|
||||
return 'Total paid members';
|
||||
return 'Monthly revenue (MRR) Deltas';
|
||||
} else if (this.chartDisplay === 'mrr') {
|
||||
return 'Monthly revenue (MRR)';
|
||||
return 'Monthly revenue (MRR) Total';
|
||||
}
|
||||
return 'Total members';
|
||||
}
|
||||
@ -168,19 +168,15 @@ export default class Anchor extends Component {
|
||||
}
|
||||
|
||||
get chartData() {
|
||||
let stats = [];
|
||||
let labels = [];
|
||||
let data = [];
|
||||
let newData;
|
||||
let canceledData;
|
||||
let returnable = {};
|
||||
|
||||
if (this.chartDisplay === 'paid-breakdown') {
|
||||
stats = this.dashboardStats.filledMemberCountStats;
|
||||
labels = stats.map(stat => stat.date);
|
||||
newData = stats.map(stat => stat.paidSubscribed);
|
||||
canceledData = stats.map(stat => -stat.paidCanceled);
|
||||
|
||||
return {
|
||||
let stats = this.dashboardStats.filledMemberCountStats;
|
||||
let labels = stats.map(stat => stat.date);
|
||||
let newData = stats.map(stat => stat.paidSubscribed);
|
||||
let canceledData = stats.map(stat => -stat.paidCanceled);
|
||||
|
||||
returnable = {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
@ -188,58 +184,96 @@ export default class Anchor extends Component {
|
||||
fill: false,
|
||||
backgroundColor: '#BD96F6',
|
||||
cubicInterpolationMode: 'monotone',
|
||||
barThickness: 18
|
||||
barThickness: 18,
|
||||
minBarLength: 3
|
||||
},{
|
||||
data: canceledData,
|
||||
fill: false,
|
||||
backgroundColor: '#FB76B4',
|
||||
cubicInterpolationMode: 'monotone',
|
||||
barThickness: 18
|
||||
barThickness: 18,
|
||||
minBarLength: 3
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
if (this.chartDisplay === 'total') {
|
||||
stats = this.dashboardStats.filledMemberCountStats;
|
||||
labels = stats.map(stat => stat.date);
|
||||
data = stats.map(stat => stat.paid + stat.free + stat.comped);
|
||||
}
|
||||
let stats = this.dashboardStats.filledMemberCountStats;
|
||||
let labels = stats.map(stat => stat.date);
|
||||
let data = stats.map(stat => stat.paid + stat.free + stat.comped);
|
||||
let dataPaid = stats.map(stat => stat.paid);
|
||||
|
||||
if (this.chartDisplay === 'paid-total') {
|
||||
stats = this.dashboardStats.filledMemberCountStats;
|
||||
labels = stats.map(stat => stat.date);
|
||||
data = stats.map(stat => stat.paid);
|
||||
returnable = {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
data: data,
|
||||
tension: 0,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
fillColor: 'rgba(20, 184, 255, 0.07)',
|
||||
backgroundColor: 'rgba(20, 184, 255, 0.07)',
|
||||
pointRadius: 0,
|
||||
pointHitRadius: 10,
|
||||
pointBorderColor: '#14B8FF',
|
||||
pointBackgroundColor: '#14B8FF',
|
||||
pointHoverBackgroundColor: '#14B8FF',
|
||||
pointHoverBorderColor: '#14B8FF',
|
||||
pointHoverRadius: 0,
|
||||
borderColor: '#14B8FF',
|
||||
borderJoinStyle: 'miter'
|
||||
}, {
|
||||
data: dataPaid,
|
||||
tension: 0,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
fillColor: 'rgba(189, 150, 246, 0.3)',
|
||||
backgroundColor: 'rgba(189, 150, 246, 0.3)',
|
||||
pointRadius: 0,
|
||||
pointHitRadius: 10,
|
||||
pointBorderColor: 'rgba(189, 150, 246, 1)',
|
||||
pointBackgroundColor: 'rgba(189, 150, 246, 1)',
|
||||
pointHoverBackgroundColor: 'rgba(189, 150, 246, 1)',
|
||||
pointHoverBorderColor: 'rgba(189, 150, 246, 1)',
|
||||
pointHoverRadius: 0,
|
||||
borderColor: 'rgba(189, 150, 246, 1)',
|
||||
borderJoinStyle: 'miter'
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
if (this.chartDisplay === 'mrr') {
|
||||
stats = this.dashboardStats.filledMrrStats;
|
||||
labels = stats.map(stat => stat.date);
|
||||
data = stats.map(stat => stat.mrr);
|
||||
let stats = this.dashboardStats.filledMrrStats;
|
||||
let labels = stats.map(stat => stat.date);
|
||||
let data = stats.map(stat => stat.mrr);
|
||||
|
||||
returnable = {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
data: data,
|
||||
tension: 0,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
fillColor: 'rgba(20, 184, 255, 0.07)',
|
||||
backgroundColor: 'rgba(20, 184, 255, 0.07)',
|
||||
pointRadius: 0,
|
||||
pointHitRadius: 10,
|
||||
pointBorderColor: '#14B8FF',
|
||||
pointBackgroundColor: '#14B8FF',
|
||||
pointHoverBackgroundColor: '#14B8FF',
|
||||
pointHoverBorderColor: '#14B8FF',
|
||||
pointHoverRadius: 0,
|
||||
borderColor: '#14B8FF',
|
||||
borderJoinStyle: 'miter'
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
labels: labels,
|
||||
datasets: [{
|
||||
data: data,
|
||||
tension: 0,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
fillColor: 'rgba(20, 184, 255, 0.07)',
|
||||
backgroundColor: 'rgba(20, 184, 255, 0.07)',
|
||||
pointRadius: 0,
|
||||
pointHitRadius: 10,
|
||||
pointBorderColor: '#14B8FF',
|
||||
pointBackgroundColor: '#14B8FF',
|
||||
pointHoverBackgroundColor: '#14B8FF',
|
||||
pointHoverBorderColor: '#14B8FF',
|
||||
pointHoverRadius: 0,
|
||||
borderColor: '#14B8FF',
|
||||
borderJoinStyle: 'miter'
|
||||
}]
|
||||
};
|
||||
return returnable;
|
||||
}
|
||||
|
||||
get chartOptions() {
|
||||
let barColor = this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)';
|
||||
|
||||
if (this.chartDisplay === 'paid-breakdown') {
|
||||
return {
|
||||
responsive: true,
|
||||
@ -271,6 +305,17 @@ export default class Anchor extends Component {
|
||||
titleFontColor: 'rgba(255, 255, 255, 0.7)',
|
||||
titleMarginBottom: 3,
|
||||
callbacks: {
|
||||
label: (tooltipItems, data) => {
|
||||
let valueText = data.datasets[tooltipItems.datasetIndex].data[tooltipItems.index].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
|
||||
if (tooltipItems.datasetIndex === 0) {
|
||||
return `New paid: ${valueText}`;
|
||||
}
|
||||
|
||||
if (tooltipItems.datasetIndex === 1) {
|
||||
return `Canceled paid: ${Math.abs(valueText)}`;
|
||||
}
|
||||
},
|
||||
title: (tooltipItems) => {
|
||||
return moment(tooltipItems[0].xLabel).format(DATE_FORMAT);
|
||||
}
|
||||
@ -300,13 +345,13 @@ export default class Anchor extends Component {
|
||||
offset: true,
|
||||
stacked: true,
|
||||
gridLines: {
|
||||
color: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
|
||||
color: barColor,
|
||||
borderDash: [4,4],
|
||||
display: true,
|
||||
drawBorder: false,
|
||||
drawTicks: false,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
|
||||
zeroLineColor: barColor,
|
||||
zeroLineBorderDash: [4,4]
|
||||
},
|
||||
ticks: {
|
||||
@ -363,16 +408,21 @@ export default class Anchor extends Component {
|
||||
callbacks: {
|
||||
label: (tooltipItems, data) => {
|
||||
let valueText = data.datasets[tooltipItems.datasetIndex].data[tooltipItems.index].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
let returnable = valueText;
|
||||
|
||||
if (this.chartDisplay === 'total') {
|
||||
return `Total members: ${valueText}`;
|
||||
}
|
||||
if (this.chartDisplay === 'paid-total') {
|
||||
return `Paid members: ${valueText}`;
|
||||
if (tooltipItems.datasetIndex === 0) {
|
||||
returnable = `Total members: ${valueText}`;
|
||||
} else {
|
||||
returnable = `Paid members: ${valueText}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.chartDisplay === 'mrr') {
|
||||
return `Monthly revenue (MRR): ${valueText}`;
|
||||
returnable = `Monthly revenue (MRR): $${valueText}`;
|
||||
}
|
||||
|
||||
return returnable;
|
||||
},
|
||||
title: (tooltipItems) => {
|
||||
return moment(tooltipItems[0].xLabel).format(DATE_FORMAT);
|
||||
@ -387,16 +437,11 @@ export default class Anchor extends Component {
|
||||
display: true,
|
||||
drawBorder: false,
|
||||
color: 'transparent',
|
||||
zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
|
||||
zeroLineColor: barColor,
|
||||
zeroLineWidth: 1
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
maxTicksLimit: 5,
|
||||
fontColor: '#7C8B9A',
|
||||
padding: 8,
|
||||
precision: 0,
|
||||
stepSize: 1
|
||||
display: false
|
||||
}
|
||||
}],
|
||||
xAxes: [{
|
||||
@ -405,17 +450,18 @@ export default class Anchor extends Component {
|
||||
align: 'start'
|
||||
},
|
||||
gridLines: {
|
||||
color: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
|
||||
color: barColor,
|
||||
borderDash: [4,4],
|
||||
display: true,
|
||||
drawBorder: true,
|
||||
drawTicks: false,
|
||||
zeroLineWidth: 1,
|
||||
zeroLineColor: this.feature.nightShift ? 'rgba(200, 204, 217, 0.25)' : 'rgba(200, 204, 217, 0.65)',
|
||||
zeroLineColor: barColor,
|
||||
zeroLineBorderDash: [4,4]
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
beginAtZero: true,
|
||||
callback: function (value, index, values) {
|
||||
if (index === 0) {
|
||||
document.getElementById('gh-dashboard5-anchor-date-start').innerHTML = moment(value).format(DATE_FORMAT);
|
||||
@ -432,7 +478,7 @@ export default class Anchor extends Component {
|
||||
}
|
||||
|
||||
get chartHeight() {
|
||||
return 275;
|
||||
return 250;
|
||||
}
|
||||
|
||||
get chartHeightSmall() {
|
||||
|
@ -43,7 +43,8 @@ export default class EmailOpenRate extends Component {
|
||||
fill: false,
|
||||
backgroundColor: '#14B8FF',
|
||||
cubicInterpolationMode: 'monotone',
|
||||
barThickness: 18
|
||||
barThickness: 18,
|
||||
minBarLength: 4
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ Dashboard v5 Layout */
|
||||
grid-template-rows: auto auto auto auto;
|
||||
grid-template-areas:
|
||||
"anchor anchor anchor anchor"
|
||||
"engagement email email-open-rate email-open-rate"
|
||||
"email engagement email-open-rate email-open-rate"
|
||||
"recent-posts recent-posts recent-activity recent-activity"
|
||||
"help help help help";
|
||||
}
|
||||
@ -463,7 +463,7 @@ Dashboard v5 Section Anchor */
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
padding: 16px 24px 20px;
|
||||
padding: 14px 24px 18px;
|
||||
margin: 2px 8px 2px 2px;
|
||||
text-align: left;
|
||||
background: transparent;
|
||||
|
Loading…
Reference in New Issue
Block a user