From a219c785b242394e181ef56c4c3db698b20144e9 Mon Sep 17 00:00:00 2001 From: Paul Rosenzweig <paulrosenzweig@users.noreply.github.com> Date: Mon, 23 Mar 2020 13:40:19 -0400 Subject: [PATCH] Chart label updates (#12169) --- frontend/src/metabase/css/dashboard.css | 10 +++++++ frontend/src/metabase/css/query_builder.css | 20 -------------- .../components/LineAreaBarChart.css | 16 +++++++++++ .../lib/LineAreaBarPostRender.js | 20 +++++++------- .../metabase/visualizations/lib/apply_axis.js | 27 +++++++++++++++++++ 5 files changed, 64 insertions(+), 29 deletions(-) diff --git a/frontend/src/metabase/css/dashboard.css b/frontend/src/metabase/css/dashboard.css index bfaaa027943..54685ac3faf 100644 --- a/frontend/src/metabase/css/dashboard.css +++ b/frontend/src/metabase/css/dashboard.css @@ -366,6 +366,16 @@ background-color: color(var(--color-bg-white) alpha(-86%)); } +.Dashboard--night text.value-label-outline { + stroke: var(--night-mode-card); +} + +.Dashboard text.value-label, +.Dashboard text.value-label-outline, +.Dashboard .LineAreaBarChart .dc-chart .axis text { + font-size: 12px; +} + .ScalarValue { font-weight: 900; font-size: 1.8rem; diff --git a/frontend/src/metabase/css/query_builder.css b/frontend/src/metabase/css/query_builder.css index 8e7c769f524..ff08afdcd93 100644 --- a/frontend/src/metabase/css/query_builder.css +++ b/frontend/src/metabase/css/query_builder.css @@ -692,23 +692,3 @@ .ParameterValuePickerNoPopover input::-webkit-input-placeholder { color: var(--color-text-medium); } - -text.value-label-outline { - font-weight: 900; - stroke-width: 4px; - stroke: var(--color-text-white); -} - -text.value-label { - fill: var(--color-text-dark); - font-weight: 900; -} - -text.value-label-outline, -text.value-label { - pointer-events: none; -} - -.Dashboard--night text.value-label-outline { - stroke: var(--night-mode-card); -} diff --git a/frontend/src/metabase/visualizations/components/LineAreaBarChart.css b/frontend/src/metabase/visualizations/components/LineAreaBarChart.css index 2b4cacc6b84..340c87758df 100644 --- a/frontend/src/metabase/visualizations/components/LineAreaBarChart.css +++ b/frontend/src/metabase/visualizations/components/LineAreaBarChart.css @@ -206,3 +206,19 @@ .LineAreaBarChart .dc-chart .trend .line { stroke-dasharray: 5, 5; } + +text.value-label-outline, +text.value-label { + pointer-events: none; +} + +text.value-label-outline { + font-weight: 800; + stroke-width: 4px; + stroke: var(--color-text-white); +} + +text.value-label { + fill: var(--color-text-dark); + font-weight: 800; +} diff --git a/frontend/src/metabase/visualizations/lib/LineAreaBarPostRender.js b/frontend/src/metabase/visualizations/lib/LineAreaBarPostRender.js index 910a357ae12..3edd8f8c189 100644 --- a/frontend/src/metabase/visualizations/lib/LineAreaBarPostRender.js +++ b/frontend/src/metabase/visualizations/lib/LineAreaBarPostRender.js @@ -262,15 +262,17 @@ function onRenderValueLabels(chart, formatYValue, [data]) { // Update `data` to use named x/y and include `showLabelBelow`. // We need to do that before data is filtered to show every nth value. - data = data.map(([x, y], i) => { - const isLocalMin = - // first point or prior is greater than y - (i === 0 || data[i - 1][1] > y) && - // last point point or next is greater than y - (i === data.length - 1 || data[i + 1][1] > y); - const showLabelBelow = isLocalMin && display === "line"; - return { x, y, showLabelBelow }; - }); + data = data + .map(([x, y], i) => { + const isLocalMin = + // first point or prior is greater than y + (i === 0 || data[i - 1][1] > y) && + // last point point or next is greater than y + (i === data.length - 1 || data[i + 1][1] > y); + const showLabelBelow = isLocalMin && display === "line"; + return { x, y, showLabelBelow }; + }) + .filter(d => display !== "bar" || d.y !== 0); const formattingSetting = chart.settings["graph.label_value_formatting"]; let compact; diff --git a/frontend/src/metabase/visualizations/lib/apply_axis.js b/frontend/src/metabase/visualizations/lib/apply_axis.js index 006b4c58c4f..ab07a1688d1 100644 --- a/frontend/src/metabase/visualizations/lib/apply_axis.js +++ b/frontend/src/metabase/visualizations/lib/apply_axis.js @@ -369,6 +369,33 @@ export function applyChartYAxis(chart, series, yExtent, axisName) { scale = d3.scale.linear(); } + // This makes non-zero bar values take up at least one pixel. + // Ideally, we would just pass a custom interpolate factory to `interpolate`. + // However, dc.js passes its own after we give it the scael, so instead we + // overwrite the scale's interpolate method. That let's us use theirs but + // special case values withing one pixel of the edge. + if (series.every(s => s.card.display === "bar")) { + const _interpolate = scale.interpolate.bind(scale); + scale.interpolate = customInterpolatorFactory => + _interpolate((a, b) => { + // dc.js uses a rounding interpolator. We want to use the factory they + // pass in, but we also need to create d3's default interpolator. We use + // that to see when a value is between 0 and 1. If we just looked at the + // rounded value, 0.49 would round to 0 and we wouldn't bump it up to 1. + const custom = customInterpolatorFactory(a, b); + const unrounded = d3.interpolate(a, b); + return t => { + const value = unrounded(t); + const onePixelUp = custom(0) - 1; + // y goes from top to bottom, so "onePixelUp" is actually the largest value + if (onePixelUp < value && value < unrounded(0)) { + return onePixelUp; + } + return custom(t); + }; + }); + } + scale.clamp(true); if (axis.setting("auto_range")) { -- GitLab