Tons of tweaks based on feedback for new Dashboard

refs: https://github.com/TryGhost/Team/issues/1531
This commit is contained in:
James Morris 2022-04-28 16:40:19 +01:00
parent f81801549b
commit 059ad77939
6 changed files with 120 additions and 47 deletions

View File

@ -35,7 +35,7 @@
</div> </div>
{{else}} {{else}}
<EmberChart <EmberChart
@type="line" @type={{this.chartType}}
@data={{this.chartData}} @data={{this.chartData}}
@options={{this.chartOptions}} @options={{this.chartOptions}}
@height={{200}} /> @height={{200}} />

View File

@ -1,3 +1,5 @@
/* global Chart */
import Component from '@glimmer/component'; import Component from '@glimmer/component';
import moment from 'moment'; import moment from 'moment';
import {action} from '@ember/object'; import {action} from '@ember/object';
@ -32,6 +34,33 @@ const DISPLAY_OPTIONS = [{
value: 'free' value: 'free'
}]; }];
// custom ChartJS draw function
Chart.defaults.hoverLine = Chart.defaults.line;
Chart.controllers.hoverLine = Chart.controllers.line.extend({
draw: function (ease) {
Chart.controllers.line.prototype.draw.call(this, ease);
if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
let activePoint = this.chart.tooltip._active[0],
ctx = this.chart.ctx,
x = activePoint.tooltipPosition().x,
topY = this.chart.legend.bottom,
bottomY = this.chart.chartArea.bottom;
// draw line
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.setLineDash([3, 4]);
ctx.lineWidth = 1;
ctx.strokeStyle = '#7C8B9A';
ctx.stroke();
ctx.restore();
}
}
});
export default class Anchor extends Component { export default class Anchor extends Component {
@service dashboardStats; @service dashboardStats;
@service feature; @service feature;
@ -113,7 +142,7 @@ export default class Anchor extends Component {
} }
get chartType() { get chartType() {
return 'line'; return 'hoverLine'; // uses custom ChartJS draw function
} }
get chartTitle() { get chartTitle() {
@ -212,8 +241,8 @@ export default class Anchor extends Component {
padding: { padding: {
top: 2, top: 2,
bottom: 2, bottom: 2,
left: 0, left: 1,
right: 0 right: 1
} }
}, },
hover: { hover: {
@ -276,13 +305,13 @@ export default class Anchor extends Component {
}, },
gridLines: { gridLines: {
color: barColor, color: barColor,
borderDash: [4,4], borderDash: [3,4],
display: true, display: true,
drawBorder: true, drawBorder: true,
drawTicks: false, drawTicks: false,
zeroLineWidth: 1, zeroLineWidth: 1,
zeroLineColor: barColor, zeroLineColor: barColor,
zeroLineBorderDash: [4,4] zeroLineBorderDash: [3,4]
}, },
ticks: { ticks: {
display: false, display: false,

View File

@ -1,3 +1,5 @@
/* global Chart */
import Component from '@glimmer/component'; import Component from '@glimmer/component';
import moment from 'moment'; import moment from 'moment';
import {getSymbol} from 'ghost-admin/utils/currency'; import {getSymbol} from 'ghost-admin/utils/currency';
@ -6,6 +8,33 @@ import {inject as service} from '@ember/service';
const DATE_FORMAT = 'D MMM'; const DATE_FORMAT = 'D MMM';
// custom ChartJS draw function
Chart.defaults.hoverLine = Chart.defaults.line;
Chart.controllers.hoverLine = Chart.controllers.line.extend({
draw: function (ease) {
Chart.controllers.line.prototype.draw.call(this, ease);
if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
let activePoint = this.chart.tooltip._active[0],
ctx = this.chart.ctx,
x = activePoint.tooltipPosition().x,
topY = this.chart.legend.bottom,
bottomY = this.chart.chartArea.bottom;
// draw line
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.setLineDash([3, 4]);
ctx.lineWidth = 1;
ctx.strokeStyle = '#7C8B9A';
ctx.stroke();
ctx.restore();
}
}
});
export default class Mrr extends Component { export default class Mrr extends Component {
@service dashboardStats; @service dashboardStats;
@service feature; @service feature;
@ -32,7 +61,7 @@ export default class Mrr extends Component {
} }
get chartType() { get chartType() {
return 'line'; return 'hoverLine'; // uses custom ChartJS draw function
} }
get mrrCurrencySymbol() { get mrrCurrencySymbol() {

View File

@ -1,3 +1,5 @@
/* globals Chart */
import Component from '@glimmer/component'; import Component from '@glimmer/component';
import moment from 'moment'; import moment from 'moment';
import {action} from '@ember/object'; import {action} from '@ember/object';
@ -5,6 +7,33 @@ import {inject as service} from '@ember/service';
const DATE_FORMAT = 'D MMM'; const DATE_FORMAT = 'D MMM';
// custom ChartJS draw function
Chart.defaults.hoverBar = Chart.defaults.bar;
Chart.controllers.hoverBar = Chart.controllers.bar.extend({
draw: function (ease) {
Chart.controllers.line.prototype.draw.call(this, ease);
if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
let activePoint = this.chart.tooltip._active[0],
ctx = this.chart.ctx,
x = activePoint.tooltipPosition().x,
topY = this.chart.legend.bottom,
bottomY = this.chart.chartArea.bottom;
// draw line
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.setLineDash([3, 4]);
ctx.lineWidth = 1;
ctx.strokeStyle = '#7C8B9A';
ctx.stroke();
ctx.restore();
}
}
});
export default class PaidBreakdown extends Component { export default class PaidBreakdown extends Component {
@service dashboardStats; @service dashboardStats;
@service feature; @service feature;
@ -23,7 +52,7 @@ export default class PaidBreakdown extends Component {
} }
get chartType() { get chartType() {
return 'bar'; return 'hoverBar';
} }
get chartData() { get chartData() {
@ -31,38 +60,19 @@ export default class PaidBreakdown extends Component {
const labels = stats.map(stat => stat.date); const labels = stats.map(stat => stat.date);
const newData = stats.map(stat => stat.positiveDelta); const newData = stats.map(stat => stat.positiveDelta);
const canceledData = stats.map(stat => -stat.negativeDelta); const canceledData = stats.map(stat => -stat.negativeDelta);
const netData = stats.map(stat => stat.positiveDelta - stat.negativeDelta);
const barThickness = 5; const barThickness = 5;
return { return {
labels: labels, labels: labels,
datasets: [ datasets: [
{ {
type: 'line',
data: netData,
tension: 0,
cubicInterpolationMode: 'monotone',
fill: false,
pointRadius: 0,
pointHitRadius: 10,
pointBorderColor: '#14B8FF',
pointBackgroundColor: '#14B8FF',
pointHoverBackgroundColor: '#14B8FF',
pointHoverBorderColor: '#14B8FF',
pointHoverRadius: 0,
borderColor: 'rgba(189, 197, 204, 0.5)',
borderJoinStyle: 'miter',
borderWidth: 3
}, {
data: newData, data: newData,
fill: false,
backgroundColor: '#8E42FF', backgroundColor: '#8E42FF',
cubicInterpolationMode: 'monotone', cubicInterpolationMode: 'monotone',
barThickness: barThickness, barThickness: barThickness,
minBarLength: 3 minBarLength: 3
}, { }, {
data: canceledData, data: canceledData,
fill: false,
backgroundColor: '#FB76B4', backgroundColor: '#FB76B4',
cubicInterpolationMode: 'monotone', cubicInterpolationMode: 'monotone',
barThickness: barThickness, barThickness: barThickness,
@ -120,15 +130,17 @@ export default class PaidBreakdown extends Component {
tooltipEl.style.opacity = 1; tooltipEl.style.opacity = 1;
tooltipEl.style.position = 'absolute'; tooltipEl.style.position = 'absolute';
tooltipEl.style.left = tooltip.x + 'px'; tooltipEl.style.left = tooltip.x + 'px';
tooltipEl.style.top = tooltip.y + 'px'; tooltipEl.style.top = '70px';
}, },
callbacks: { callbacks: {
label: (tooltipItems, data) => { label: (tooltipItems, data) => {
let newValue = data.datasets[1].data[tooltipItems.index].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); // new data
document.querySelector('#gh-dashboard5-breakdown-tooltip .gh-dashboard5-tooltip-value-2').innerHTML = `New ${newValue}`; let newValue = parseInt(data.datasets[0].data[tooltipItems.index].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','));
document.querySelector('#gh-dashboard5-breakdown-tooltip .gh-dashboard5-tooltip-value-1').innerHTML = `New ${newValue}`;
let canceldValue = data.datasets[2].data[tooltipItems.index].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); // canceld data
document.querySelector('#gh-dashboard5-breakdown-tooltip .gh-dashboard5-tooltip-value-3').innerHTML = `Canceled ${canceldValue}`; let canceledValue = Math.abs(parseInt(data.datasets[1].data[tooltipItems.index].toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')));
document.querySelector('#gh-dashboard5-breakdown-tooltip .gh-dashboard5-tooltip-value-2').innerHTML = `Canceled ${canceledValue}`;
}, },
title: (tooltipItems) => { title: (tooltipItems) => {
const value = moment(tooltipItems[0].xLabel).format(DATE_FORMAT); const value = moment(tooltipItems[0].xLabel).format(DATE_FORMAT);

View File

@ -117,10 +117,10 @@ export default class PaidMix extends Component {
}, },
layout: { layout: {
padding: { padding: {
top: 30, top: 45,
bottom: 0, bottom: 0,
left: 0, left: 0,
right: 0 right: 4
} }
}, },
animation: { animation: {

View File

@ -219,7 +219,6 @@ Dashboard v5 Layout */
border-left: 1px solid var(--whitegrey); border-left: 1px solid var(--whitegrey);
padding: 4px 24px; padding: 4px 24px;
position: relative; position: relative;
height: 110px;
} }
.gh-dashboard5-minichart .gh-dashboard5-data { .gh-dashboard5-minichart .gh-dashboard5-data {
@ -256,6 +255,10 @@ Dashboard v5 Layout */
padding: 0; padding: 0;
} }
.gh-dashboard5-minichart .gh-dashboard5-chart-box {
height: 110px;
}
.gh-dashboard5-legend { .gh-dashboard5-legend {
flex: 1; flex: 1;
display: flex; display: flex;
@ -324,16 +327,20 @@ Dashboard v5 Layout */
.gh-dashboard5-select { .gh-dashboard5-select {
position: absolute; position: absolute;
top: 16px; top: 14px;
right: 4px; right: 4px;
} }
.gh-dashboard5-select .gh-dashboard5-select {
height: 36px;
}
.gh-dashboard5-select .ember-power-select-selected-item { .gh-dashboard5-select .ember-power-select-selected-item {
font-size: 1.25rem; font-size: 1.25rem;
font-weight: 600; font-weight: 600;
letter-spacing: -.1px; letter-spacing: -.1px;
line-height: 1em; line-height: 1em;
padding: 0; padding: 0 0 10px;
color: var(--middarkgrey); color: var(--middarkgrey);
white-space: nowrap; white-space: nowrap;
} }
@ -465,10 +472,6 @@ Dashboard v5 Chart */
padding: 0 0 0 30%; padding: 0 0 0 30%;
} }
.gh-dashboard5-minicharts .gh-dashboard5-chart-box {
height: 110px;
}
/* --------------------------------- /* ---------------------------------
Dashboard v5 Percentage */ Dashboard v5 Percentage */
@ -816,11 +819,11 @@ Dashboard v5 Anchor */
} }
.gh-dashboard5-anchor .gh-dashboard5-minicharts { .gh-dashboard5-anchor .gh-dashboard5-minicharts {
margin-top: 48px; margin-top: 32px;
} }
.gh-dashboard5-mix .gh-dashboard5-select { .gh-dashboard5-mix .gh-dashboard5-select {
top: -8px; top: -11px;
right: -18px; right: -18px;
} }
@ -833,10 +836,11 @@ Dashboard v5 Engagement */
} }
.gh-dashboard5-engagement .gh-dashboard5-columns { .gh-dashboard5-engagement .gh-dashboard5-columns {
padding-top: 24px; padding-top: 16px;
} }
.gh-dashboard5-engagement .gh-dashboard5-select { .gh-dashboard5-engagement .gh-dashboard5-select {
top: 16px;
right: 6px; right: 6px;
} }
@ -1015,7 +1019,7 @@ Dashboard v5 Recents */
} }
.gh-dashboard5-recents .gh-dashboard5-list-header { .gh-dashboard5-recents .gh-dashboard5-list-header {
margin-top: 32px; margin-top: 24px;
} }
.gh-dashboard5-recents .gh-dashboard5-list-loading { .gh-dashboard5-recents .gh-dashboard5-list-loading {
@ -1602,10 +1606,9 @@ Dashboard v5 Tooltips */
border: 1px solid var(--whitegrey); border: 1px solid var(--whitegrey);
border-radius: 8px; border-radius: 8px;
padding: 12px; padding: 12px;
box-shadow: 0 2px 12px rgba(0,0,0,0.05); box-shadow: 0 3px 12px rgba(0,0,0,0.12);
z-index: 9999; z-index: 9999;
pointer-events: none; pointer-events: none;
transition: top 50ms ease-out, left 50ms ease-out;
} }
.gh-dashboard5-tooltip .gh-dashboard5-metric-value { .gh-dashboard5-tooltip .gh-dashboard5-metric-value {