From 3aee0ec7cb63a4ebcb1fe602de73f82eb4deac3f Mon Sep 17 00:00:00 2001 From: Tom Robinson <tlrobinson@gmail.com> Date: Fri, 19 May 2017 16:22:29 -0700 Subject: [PATCH] Highlight selected dots --- .../components/LineAreaBarChart.css | 17 +++++-- .../visualizations/lib/LineAreaBarRenderer.js | 19 ++++---- .../visualizations/lib/graph/addons.js | 48 +++++++++++++++++++ 3 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 frontend/src/metabase/visualizations/lib/graph/addons.js diff --git a/frontend/src/metabase/visualizations/components/LineAreaBarChart.css b/frontend/src/metabase/visualizations/components/LineAreaBarChart.css index fd039c40c2a..8f2abd39f5d 100644 --- a/frontend/src/metabase/visualizations/components/LineAreaBarChart.css +++ b/frontend/src/metabase/visualizations/components/LineAreaBarChart.css @@ -84,7 +84,7 @@ opacity: 1 !important; } -.LineAreaBarChart .dc-chart .enable-dots .dc-tooltip circle.dot { +.LineAreaBarChart .dc-chart .enable-dots .dc-tooltip .dot { r: 3px !important; fill: white; stroke: currentColor; @@ -99,13 +99,14 @@ stroke: white; } -.LineAreaBarChart .dc-chart .enable-dots .dc-tooltip circle.dot:hover, -.LineAreaBarChart .dc-chart .enable-dots .dc-tooltip circle.dot.hover { +.LineAreaBarChart .dc-chart .enable-dots .dc-tooltip .dot:hover, +.LineAreaBarChart .dc-chart .enable-dots .dc-tooltip .dot.hover { fill: currentColor; } -.LineAreaBarChart .dc-chart .enable-dots-onhover .dc-tooltip circle.dot:hover, -.LineAreaBarChart .dc-chart .enable-dots-onhover .dc-tooltip circle.dot.hover { +.LineAreaBarChart .dc-chart .dc-tooltip .dot.selected, +.LineAreaBarChart .dc-chart .enable-dots-onhover .dc-tooltip .dot:hover, +.LineAreaBarChart .dc-chart .enable-dots-onhover .dc-tooltip .dot.hover { r: 3px !important; fill: white; stroke: currentColor; @@ -113,6 +114,12 @@ fill-opacity: 1 !important; stroke-opacity: 1 !important; } +.LineAreaBarChart .dc-chart .dc-tooltip .dot.deselected { + opacity: 0; +} +.LineAreaBarChart .dc-chart .line.deselected { + color: #ccc; +} .LineAreaBarChart .dc-chart .area, .LineAreaBarChart .dc-chart .bar, diff --git a/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js b/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js index caf7ab01f25..e2a79ed02dc 100644 --- a/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js +++ b/frontend/src/metabase/visualizations/lib/LineAreaBarRenderer.js @@ -87,13 +87,15 @@ function adjustTicksIfNeeded(axis, axisSize: number, minPixelsPerTick: number) { } } -function getDcjsChartType(cardType) { +import { lineAddons } from "./graph/addons" + +function getDcjsChart(cardType, parent) { switch (cardType) { - case "line": return "lineChart"; - case "area": return "lineChart"; - case "bar": return "barChart"; - case "scatter": return "bubbleChart"; - default: return "barChart"; + case "line": return lineAddons(dc.lineChart(parent)); + case "area": return lineAddons(dc.lineChart(parent)); + case "bar": return dc.barChart(parent); + case "scatter": return dc.bubbleChart(parent); + default: return dc.barChart(parent); } } @@ -453,7 +455,8 @@ function applyChartTooltips(chart, series, isStacked, isScalarSeries, onHoverCha } } - chart.selectAll(".dot, .area, .bubble") + // for some reason interaction with brush requires we use click for .dot and .bubble but mousedown for bar + chart.selectAll(".dot, .bubble") .style({ "cursor": "pointer" }) .on("click", onClick); chart.selectAll(".bar") @@ -1066,7 +1069,7 @@ export default function lineAreaBar(element, { } let charts = groups.map((group, index) => { - let chart = dc[getDcjsChartType(chartType)](parent); + let chart = getDcjsChart(chartType, parent); if (onChangeCardAndRun) { initBrush(parent, chart, onBrushChange, onBrushEnd); diff --git a/frontend/src/metabase/visualizations/lib/graph/addons.js b/frontend/src/metabase/visualizations/lib/graph/addons.js new file mode 100644 index 00000000000..93a149bc9a5 --- /dev/null +++ b/frontend/src/metabase/visualizations/lib/graph/addons.js @@ -0,0 +1,48 @@ +/* @flow weak */ + +import dc from "dc"; +import moment from "moment"; + +export const lineAddons = _chart => { + _chart.fadeDeselectedArea = function() { + var dots = _chart.chartBodyG().selectAll(".dot"); + var extent = _chart.brush().extent(); + + if (_chart.isOrdinal()) { + if (_chart.hasFilter()) { + dots.classed(dc.constants.SELECTED_CLASS, function(d) { + return _chart.hasFilter(d.x); + }); + dots.classed(dc.constants.DESELECTED_CLASS, function(d) { + return !_chart.hasFilter(d.x); + }); + } else { + dots.classed(dc.constants.SELECTED_CLASS, false); + dots.classed(dc.constants.DESELECTED_CLASS, false); + } + } else { + if (!_chart.brushIsEmpty(extent)) { + var start = extent[0]; + var end = extent[1]; + const isSelected = d => { + if (moment.isDate(start)) { + return !(moment(d.x).isBefore(start) || + moment(d.x).isAfter(end)); + } else { + return !(d.x < start || d.x >= end); + } + }; + dots.classed( + dc.constants.DESELECTED_CLASS, + d => !isSelected(d) + ); + dots.classed(dc.constants.SELECTED_CLASS, d => isSelected(d)); + } else { + dots.classed(dc.constants.DESELECTED_CLASS, false); + dots.classed(dc.constants.SELECTED_CLASS, false); + } + } + }; + + return _chart; +}; -- GitLab