From 059ad779395a7c29402380bf76636443d3f5e3d1 Mon Sep 17 00:00:00 2001 From: James Morris Date: Thu, 28 Apr 2022 16:40:19 +0100 Subject: [PATCH] Tons of tweaks based on feedback for new Dashboard refs: https://github.com/TryGhost/Team/issues/1531 --- .../components/dashboard/v5/charts/anchor.hbs | 2 +- .../components/dashboard/v5/charts/anchor.js | 39 ++++++++++-- .../app/components/dashboard/v5/charts/mrr.js | 31 +++++++++- .../dashboard/v5/charts/paid-breakdown.js | 62 +++++++++++-------- .../dashboard/v5/charts/paid-mix.js | 4 +- .../admin/app/styles/layouts/dashboard-v5.css | 29 +++++---- 6 files changed, 120 insertions(+), 47 deletions(-) diff --git a/ghost/admin/app/components/dashboard/v5/charts/anchor.hbs b/ghost/admin/app/components/dashboard/v5/charts/anchor.hbs index 85ef5ac1d1..8a699a5a14 100644 --- a/ghost/admin/app/components/dashboard/v5/charts/anchor.hbs +++ b/ghost/admin/app/components/dashboard/v5/charts/anchor.hbs @@ -35,7 +35,7 @@ {{else}} diff --git a/ghost/admin/app/components/dashboard/v5/charts/anchor.js b/ghost/admin/app/components/dashboard/v5/charts/anchor.js index 3205b5de1e..13ccea2f8f 100644 --- a/ghost/admin/app/components/dashboard/v5/charts/anchor.js +++ b/ghost/admin/app/components/dashboard/v5/charts/anchor.js @@ -1,3 +1,5 @@ +/* global Chart */ + import Component from '@glimmer/component'; import moment from 'moment'; import {action} from '@ember/object'; @@ -32,6 +34,33 @@ const DISPLAY_OPTIONS = [{ 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 { @service dashboardStats; @service feature; @@ -113,7 +142,7 @@ export default class Anchor extends Component { } get chartType() { - return 'line'; + return 'hoverLine'; // uses custom ChartJS draw function } get chartTitle() { @@ -212,8 +241,8 @@ export default class Anchor extends Component { padding: { top: 2, bottom: 2, - left: 0, - right: 0 + left: 1, + right: 1 } }, hover: { @@ -276,13 +305,13 @@ export default class Anchor extends Component { }, gridLines: { color: barColor, - borderDash: [4,4], + borderDash: [3,4], display: true, drawBorder: true, drawTicks: false, zeroLineWidth: 1, zeroLineColor: barColor, - zeroLineBorderDash: [4,4] + zeroLineBorderDash: [3,4] }, ticks: { display: false, diff --git a/ghost/admin/app/components/dashboard/v5/charts/mrr.js b/ghost/admin/app/components/dashboard/v5/charts/mrr.js index a896030571..5be1e42d16 100644 --- a/ghost/admin/app/components/dashboard/v5/charts/mrr.js +++ b/ghost/admin/app/components/dashboard/v5/charts/mrr.js @@ -1,3 +1,5 @@ +/* global Chart */ + import Component from '@glimmer/component'; import moment from 'moment'; import {getSymbol} from 'ghost-admin/utils/currency'; @@ -6,6 +8,33 @@ import {inject as service} from '@ember/service'; 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 { @service dashboardStats; @service feature; @@ -32,7 +61,7 @@ export default class Mrr extends Component { } get chartType() { - return 'line'; + return 'hoverLine'; // uses custom ChartJS draw function } get mrrCurrencySymbol() { diff --git a/ghost/admin/app/components/dashboard/v5/charts/paid-breakdown.js b/ghost/admin/app/components/dashboard/v5/charts/paid-breakdown.js index 837cd9fe44..a4d35b4e0e 100644 --- a/ghost/admin/app/components/dashboard/v5/charts/paid-breakdown.js +++ b/ghost/admin/app/components/dashboard/v5/charts/paid-breakdown.js @@ -1,3 +1,5 @@ +/* globals Chart */ + import Component from '@glimmer/component'; import moment from 'moment'; import {action} from '@ember/object'; @@ -5,6 +7,33 @@ import {inject as service} from '@ember/service'; 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 { @service dashboardStats; @service feature; @@ -23,7 +52,7 @@ export default class PaidBreakdown extends Component { } get chartType() { - return 'bar'; + return 'hoverBar'; } get chartData() { @@ -31,38 +60,19 @@ export default class PaidBreakdown extends Component { const labels = stats.map(stat => stat.date); const newData = stats.map(stat => stat.positiveDelta); const canceledData = stats.map(stat => -stat.negativeDelta); - const netData = stats.map(stat => stat.positiveDelta - stat.negativeDelta); const barThickness = 5; return { labels: labels, 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, - fill: false, backgroundColor: '#8E42FF', cubicInterpolationMode: 'monotone', barThickness: barThickness, minBarLength: 3 }, { data: canceledData, - fill: false, backgroundColor: '#FB76B4', cubicInterpolationMode: 'monotone', barThickness: barThickness, @@ -120,15 +130,17 @@ export default class PaidBreakdown extends Component { tooltipEl.style.opacity = 1; tooltipEl.style.position = 'absolute'; tooltipEl.style.left = tooltip.x + 'px'; - tooltipEl.style.top = tooltip.y + 'px'; + tooltipEl.style.top = '70px'; }, callbacks: { label: (tooltipItems, data) => { - let newValue = 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 = `New ${newValue}`; + // new data + 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, ','); - document.querySelector('#gh-dashboard5-breakdown-tooltip .gh-dashboard5-tooltip-value-3').innerHTML = `Canceled ${canceldValue}`; + // canceld data + 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) => { const value = moment(tooltipItems[0].xLabel).format(DATE_FORMAT); diff --git a/ghost/admin/app/components/dashboard/v5/charts/paid-mix.js b/ghost/admin/app/components/dashboard/v5/charts/paid-mix.js index 1c68e13a05..78b2d95d77 100644 --- a/ghost/admin/app/components/dashboard/v5/charts/paid-mix.js +++ b/ghost/admin/app/components/dashboard/v5/charts/paid-mix.js @@ -117,10 +117,10 @@ export default class PaidMix extends Component { }, layout: { padding: { - top: 30, + top: 45, bottom: 0, left: 0, - right: 0 + right: 4 } }, animation: { diff --git a/ghost/admin/app/styles/layouts/dashboard-v5.css b/ghost/admin/app/styles/layouts/dashboard-v5.css index fe7fc89f1e..2b49dc5c4c 100644 --- a/ghost/admin/app/styles/layouts/dashboard-v5.css +++ b/ghost/admin/app/styles/layouts/dashboard-v5.css @@ -219,7 +219,6 @@ Dashboard v5 Layout */ border-left: 1px solid var(--whitegrey); padding: 4px 24px; position: relative; - height: 110px; } .gh-dashboard5-minichart .gh-dashboard5-data { @@ -256,6 +255,10 @@ Dashboard v5 Layout */ padding: 0; } +.gh-dashboard5-minichart .gh-dashboard5-chart-box { + height: 110px; +} + .gh-dashboard5-legend { flex: 1; display: flex; @@ -324,16 +327,20 @@ Dashboard v5 Layout */ .gh-dashboard5-select { position: absolute; - top: 16px; + top: 14px; right: 4px; } +.gh-dashboard5-select .gh-dashboard5-select { + height: 36px; +} + .gh-dashboard5-select .ember-power-select-selected-item { font-size: 1.25rem; font-weight: 600; letter-spacing: -.1px; line-height: 1em; - padding: 0; + padding: 0 0 10px; color: var(--middarkgrey); white-space: nowrap; } @@ -465,10 +472,6 @@ Dashboard v5 Chart */ padding: 0 0 0 30%; } -.gh-dashboard5-minicharts .gh-dashboard5-chart-box { - height: 110px; -} - /* --------------------------------- Dashboard v5 Percentage */ @@ -816,11 +819,11 @@ Dashboard v5 Anchor */ } .gh-dashboard5-anchor .gh-dashboard5-minicharts { - margin-top: 48px; + margin-top: 32px; } .gh-dashboard5-mix .gh-dashboard5-select { - top: -8px; + top: -11px; right: -18px; } @@ -833,10 +836,11 @@ Dashboard v5 Engagement */ } .gh-dashboard5-engagement .gh-dashboard5-columns { - padding-top: 24px; + padding-top: 16px; } .gh-dashboard5-engagement .gh-dashboard5-select { + top: 16px; right: 6px; } @@ -1015,7 +1019,7 @@ Dashboard v5 Recents */ } .gh-dashboard5-recents .gh-dashboard5-list-header { - margin-top: 32px; + margin-top: 24px; } .gh-dashboard5-recents .gh-dashboard5-list-loading { @@ -1602,10 +1606,9 @@ Dashboard v5 Tooltips */ border: 1px solid var(--whitegrey); border-radius: 8px; 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; pointer-events: none; - transition: top 50ms ease-out, left 50ms ease-out; } .gh-dashboard5-tooltip .gh-dashboard5-metric-value {