From 1132c3cbde8db11168c6852d7c7775717ac0dba2 Mon Sep 17 00:00:00 2001
From: Kim Truong <47833996+khtruong@users.noreply.github.com>
Date: Wed, 3 Apr 2019 13:35:27 -0700
Subject: [PATCH] feat: [lyftga] add tooltips to deck.gl viz types (#7206)
* Add tooltips to deck.gl viz types
* Handle text overflow
* Use .css file instead of .less
* fix: add tooltip component
* Add tooltips to deck.gl viz types
* Handle text overflow
* Use .css file instead of .less
* fix: add tooltip component
* fix: casing, types, and keys
---
.../visualizations/deckgl/DeckGLContainer.jsx | 1 +
.../src/visualizations/deckgl/TooltipRow.jsx | 36 +++++++++++++++++++
.../visualizations/deckgl/layers/Arc/Arc.jsx | 17 ++++++++-
.../deckgl/layers/Geojson/Geojson.jsx | 16 ++++++++-
.../deckgl/layers/Grid/Grid.jsx | 14 +++++++-
.../visualizations/deckgl/layers/Hex/Hex.jsx | 14 +++++++-
.../deckgl/layers/Path/Path.jsx | 17 ++++++++-
.../deckgl/layers/Polygon/Polygon.jsx | 15 +++++++-
.../deckgl/layers/Scatter/Scatter.jsx | 19 +++++++++-
.../deckgl/layers/Screengrid/Screengrid.jsx | 13 ++++++-
.../visualizations/deckgl/layers/common.jsx | 14 ++------
.../src/visualizations/stylesheets/deckgl.css | 22 ++++++++++++
12 files changed, 178 insertions(+), 20 deletions(-)
create mode 100644 superset/assets/src/visualizations/deckgl/TooltipRow.jsx
create mode 100644 superset/assets/src/visualizations/stylesheets/deckgl.css
diff --git a/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx b/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx
index c10f16ac9..ff414bfc0 100644
--- a/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx
+++ b/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx
@@ -22,6 +22,7 @@ import MapGL from 'react-map-gl';
import DeckGL from 'deck.gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import { isEqual } from 'lodash';
+import '../stylesheets/deckgl.css';
const TICK = 2000; // milliseconds
diff --git a/superset/assets/src/visualizations/deckgl/TooltipRow.jsx b/superset/assets/src/visualizations/deckgl/TooltipRow.jsx
new file mode 100644
index 000000000..cc85bfd98
--- /dev/null
+++ b/superset/assets/src/visualizations/deckgl/TooltipRow.jsx
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const propTypes = {
+ label: PropTypes.string.isRequired,
+ value: PropTypes.string.isRequired,
+};
+
+
+export default class TooltipRow extends React.PureComponent {
+ render() {
+ return (
+
{this.props.label}{this.props.value}
+ );
+ }
+}
+
+TooltipRow.propTypes = propTypes;
diff --git a/superset/assets/src/visualizations/deckgl/layers/Arc/Arc.jsx b/superset/assets/src/visualizations/deckgl/layers/Arc/Arc.jsx
index b6adbbfbf..2c0a99b09 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Arc/Arc.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Arc/Arc.jsx
@@ -17,8 +17,11 @@
* under the License.
*/
import { ArcLayer } from 'deck.gl';
+import React from 'react';
+import { t } from '@superset-ui/translation';
import { commonLayerProps } from '../common';
import { createCategoricalDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
function getPoints(data) {
const points = [];
@@ -29,6 +32,18 @@ function getPoints(data) {
return points;
}
+function setTooltipContent(formData) {
+ return o => (
+
+
+
+ {
+ formData.dimension &&
+ }
+
+ );
+}
+
export function getLayer(fd, payload, onAddFilter, setTooltip) {
const data = payload.data.features;
const sc = fd.color_picker;
@@ -39,7 +54,7 @@ export function getLayer(fd, payload, onAddFilter, setTooltip) {
getSourceColor: d => d.sourceColor || d.color || [sc.r, sc.g, sc.b, 255 * sc.a],
getTargetColor: d => d.targetColor || d.color || [tc.r, tc.g, tc.b, 255 * tc.a],
strokeWidth: (fd.stroke_width) ? fd.stroke_width : 3,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent(fd)),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Geojson/Geojson.jsx b/superset/assets/src/visualizations/deckgl/layers/Geojson/Geojson.jsx
index 1dd3cdb47..7488a3ddf 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Geojson/Geojson.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Geojson/Geojson.jsx
@@ -25,6 +25,7 @@ import DeckGLContainer from '../../DeckGLContainer';
import { hexToRGB } from '../../../../modules/colors';
import sandboxedEval from '../../../../modules/sandbox';
import { commonLayerProps } from '../common';
+import TooltipRow from '../../TooltipRow';
const propertyMap = {
fillColor: 'fillColor',
@@ -75,6 +76,19 @@ const recurseGeoJson = (node, propOverrides, extraProps) => {
}
};
+function setTooltipContent(o) {
+ return (
+ o.object.extraProps &&
+
+ {
+ Object.keys(o.object.extraProps).map((prop, index) =>
+ ,
+ )
+ }
+
+ );
+}
+
export function getLayer(formData, payload, onAddFilter, setTooltip) {
const fd = formData;
const fc = fd.fill_color_picker;
@@ -106,7 +120,7 @@ export function getLayer(formData, payload, onAddFilter, setTooltip) {
stroked: fd.stroked,
extruded: fd.extruded,
pointRadiusScale: fd.point_radius_scale,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Grid/Grid.jsx b/superset/assets/src/visualizations/deckgl/layers/Grid/Grid.jsx
index 67c4bfd83..a0cc8613f 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Grid/Grid.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Grid/Grid.jsx
@@ -17,10 +17,22 @@
* under the License.
*/
import { GridLayer } from 'deck.gl';
+import React from 'react';
+import { t } from '@superset-ui/translation';
import { commonLayerProps, getAggFunc } from '../common';
import sandboxedEval from '../../../../modules/sandbox';
import { createDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
+
+function setTooltipContent(o) {
+ return (
+
+
+
+
+ );
+}
export function getLayer(formData, payload, onAddFilter, setTooltip) {
const fd = formData;
@@ -48,7 +60,7 @@ export function getLayer(formData, payload, onAddFilter, setTooltip) {
outline: false,
getElevationValue: aggFunc,
getColorValue: aggFunc,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Hex/Hex.jsx b/superset/assets/src/visualizations/deckgl/layers/Hex/Hex.jsx
index f8562254e..9901b2262 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Hex/Hex.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Hex/Hex.jsx
@@ -17,10 +17,22 @@
* under the License.
*/
import { HexagonLayer } from 'deck.gl';
+import React from 'react';
+import { t } from '@superset-ui/translation';
import { commonLayerProps, getAggFunc } from '../common';
import sandboxedEval from '../../../../modules/sandbox';
import { createDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
+
+function setTooltipContent(o) {
+ return (
+
+
+
+
+ );
+}
export function getLayer(formData, payload, onAddFilter, setTooltip) {
const fd = formData;
@@ -47,7 +59,7 @@ export function getLayer(formData, payload, onAddFilter, setTooltip) {
outline: false,
getElevationValue: aggFunc,
getColorValue: aggFunc,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Path/Path.jsx b/superset/assets/src/visualizations/deckgl/layers/Path/Path.jsx
index 633ccec9e..7bf098241 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Path/Path.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Path/Path.jsx
@@ -17,9 +17,24 @@
* under the License.
*/
import { PathLayer } from 'deck.gl';
+import React from 'react';
import { commonLayerProps } from '../common';
import sandboxedEval from '../../../../modules/sandbox';
import { createDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
+
+function setTooltipContent(o) {
+ return (
+ o.object.extraProps &&
+
+ {
+ Object.keys(o.object.extraProps).map((prop, index) =>
+ ,
+ )
+ }
+
+ );
+}
export function getLayer(formData, payload, onAddFilter, setTooltip) {
const fd = formData;
@@ -42,7 +57,7 @@ export function getLayer(formData, payload, onAddFilter, setTooltip) {
data,
rounded: true,
widthScale: 1,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx b/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
index 8a3c2f402..ca7d4132a 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
@@ -25,6 +25,7 @@ import { PolygonLayer } from 'deck.gl';
import AnimatableDeckGLContainer from '../../AnimatableDeckGLContainer';
import Legend from '../../../Legend';
+import TooltipRow from '../../TooltipRow';
import { getBuckets, getBreakPointColorScaler } from '../../utils';
import { commonLayerProps, fitViewport } from '../common';
@@ -48,6 +49,18 @@ function getElevation(d, colorScaler) {
: d.elevation;
}
+function setTooltipContent(formData) {
+ return (o) => {
+ const metricLabel = formData.metric.label || formData.metric;
+ return (
+
+
+ {formData.metric && }
+
+ );
+ };
+}
+
export function getLayer(formData, payload, setTooltip, selected, onSelect, filters) {
const fd = formData;
const fc = fd.fill_color_picker;
@@ -95,7 +108,7 @@ export function getLayer(formData, payload, setTooltip, selected, onSelect, filt
getElevation: d => getElevation(d, colorScaler),
elevationScale: fd.multiplier,
fp64: true,
- ...commonLayerProps(fd, setTooltip, onSelect),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent(fd), onSelect),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Scatter/Scatter.jsx b/superset/assets/src/visualizations/deckgl/layers/Scatter/Scatter.jsx
index 194a7755a..8ca13aac4 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Scatter/Scatter.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Scatter/Scatter.jsx
@@ -17,14 +17,31 @@
* under the License.
*/
import { ScatterplotLayer } from 'deck.gl';
+import React from 'react';
+import { t } from '@superset-ui/translation';
import { commonLayerProps } from '../common';
import { createCategoricalDeckGLComponent } from '../../factory';
+import TooltipRow from '../../TooltipRow';
import { unitToRadius } from '../../../../modules/geo';
function getPoints(data) {
return data.map(d => d.position);
}
+function setTooltipContent(formData) {
+ return o => (
+
+
+ {
+ o.object.cat_color &&
+ }
+ {
+ o.object.metric &&
+ }
+
+ );
+}
+
export function getLayer(fd, payload, onAddFilter, setTooltip) {
const dataWithRadius = payload.data.features.map((d) => {
let radius = unitToRadius(fd.point_unit, d.radius) || 10;
@@ -46,7 +63,7 @@ export function getLayer(fd, payload, onAddFilter, setTooltip) {
radiusMinPixels: fd.min_radius || null,
radiusMaxPixels: fd.max_radius || null,
outline: false,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent(fd)),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/Screengrid/Screengrid.jsx b/superset/assets/src/visualizations/deckgl/layers/Screengrid/Screengrid.jsx
index a4bdede05..1efefae21 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Screengrid/Screengrid.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Screengrid/Screengrid.jsx
@@ -21,15 +21,26 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ScreenGridLayer } from 'deck.gl';
+import { t } from '@superset-ui/translation';
import AnimatableDeckGLContainer from '../../AnimatableDeckGLContainer';
import { getPlaySliderParams } from '../../../../modules/time';
import sandboxedEval from '../../../../modules/sandbox';
import { commonLayerProps, fitViewport } from '../common';
+import TooltipRow from '../../TooltipRow';
function getPoints(data) {
return data.map(d => d.position);
}
+function setTooltipContent(o) {
+ return (
+
+
+
+
+ );
+}
+
export function getLayer(formData, payload, onAddFilter, setTooltip, filters) {
const fd = formData;
const c = fd.color_picker;
@@ -61,7 +72,7 @@ export function getLayer(formData, payload, onAddFilter, setTooltip, filters) {
maxColor: [c.r, c.g, c.b, 255 * c.a],
outline: false,
getWeight: d => d.weight || 0,
- ...commonLayerProps(fd, setTooltip),
+ ...commonLayerProps(fd, setTooltip, setTooltipContent),
});
}
diff --git a/superset/assets/src/visualizations/deckgl/layers/common.jsx b/superset/assets/src/visualizations/deckgl/layers/common.jsx
index b9b271640..7adf3b789 100644
--- a/superset/assets/src/visualizations/deckgl/layers/common.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/common.jsx
@@ -16,8 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-import React from 'react';
-
import { fitBounds } from 'viewport-mercator-project';
import * as d3array from 'd3-array';
import sandboxedEval from '../../../modules/sandbox';
@@ -50,20 +48,12 @@ export function fitViewport(viewport, points, padding = 10) {
}
}
-export function commonLayerProps(formData, setTooltip, onSelect) {
+export function commonLayerProps(formData, setTooltip, setTooltipContent, onSelect) {
const fd = formData;
let onHover;
- let tooltipContentGenerator;
+ let tooltipContentGenerator = setTooltipContent;
if (fd.js_tooltip) {
tooltipContentGenerator = sandboxedEval(fd.js_tooltip);
- } else if (fd.line_column && fd.metric && ['geohash', 'zipcode'].indexOf(fd.line_type) >= 0) {
- const metricLabel = fd.metric.label || fd.metric;
- tooltipContentGenerator = o => (
-
-
{fd.line_column}: {o.object[fd.line_column]}
- {fd.metric &&
-
{metricLabel}: {o.object[metricLabel]}
}
-
);
}
if (tooltipContentGenerator) {
onHover = (o) => {
diff --git a/superset/assets/src/visualizations/stylesheets/deckgl.css b/superset/assets/src/visualizations/stylesheets/deckgl.css
new file mode 100644
index 000000000..b085d1c6b
--- /dev/null
+++ b/superset/assets/src/visualizations/stylesheets/deckgl.css
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ .deckgl-tooltip > div {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }