This is an automated email from the ASF dual-hosted git repository.
christine pushed a commit to branch lyftga
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/lyftga by this push:
new 1132c3c feat: [lyftga] add tooltips to deck.gl viz types (#7206)
1132c3c is described below
commit 1132c3cbde8db11168c6852d7c7775717ac0dba2
Author: Kim Truong <[email protected]>
AuthorDate: Wed Apr 3 13:35:27 2019 -0700
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
---
.../src/visualizations/deckgl/DeckGLContainer.jsx | 1 +
.../src/visualizations/deckgl/TooltipRow.jsx | 36 ++++++++++++++++++++++
.../src/visualizations/deckgl/layers/Arc/Arc.jsx | 17 +++++++++-
.../deckgl/layers/Geojson/Geojson.jsx | 16 +++++++++-
.../src/visualizations/deckgl/layers/Grid/Grid.jsx | 14 ++++++++-
.../src/visualizations/deckgl/layers/Hex/Hex.jsx | 14 ++++++++-
.../src/visualizations/deckgl/layers/Path/Path.jsx | 17 +++++++++-
.../deckgl/layers/Polygon/Polygon.jsx | 15 ++++++++-
.../deckgl/layers/Scatter/Scatter.jsx | 19 +++++++++++-
.../deckgl/layers/Screengrid/Screengrid.jsx | 13 +++++++-
.../src/visualizations/deckgl/layers/common.jsx | 14 ++-------
.../src/visualizations/stylesheets/deckgl.css | 22 +++++++++++++
12 files changed, 178 insertions(+), 20 deletions(-)
diff --git a/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx
b/superset/assets/src/visualizations/deckgl/DeckGLContainer.jsx
index c10f16a..ff414bf 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 0000000..cc85bfd
--- /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 (
+ <div>{this.props.label}<strong>{this.props.value}</strong></div>
+ );
+ }
+}
+
+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 b6adbbf..2c0a99b 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 => (
+ <div className="deckgl-tooltip">
+ <TooltipRow label={`${t('Start (Longitude, Latitude)')}: `}
value={`${o.object.sourcePosition[0]}, ${o.object.sourcePosition[1]}`} />
+ <TooltipRow label={`${t('End (Longitude, Latitude)')}: `}
value={`${o.object.targetPosition[0]}, ${o.object.targetPosition[1]}`} />
+ {
+ formData.dimension && <TooltipRow label={`${formData.dimension}: `}
value={`${o.object.cat_color}`} />
+ }
+ </div>
+ );
+}
+
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 1dd3cdb..7488a3d 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 &&
+ <div className="deckgl-tooltip">
+ {
+ Object.keys(o.object.extraProps).map((prop, index) =>
+ <TooltipRow key={`prop-${index}`} label={`${prop}: `}
value={`${o.object.extraProps[prop]}`} />,
+ )
+ }
+ </div>
+ );
+}
+
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 67c4bfd..a0cc861 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 (
+ <div className="deckgl-tooltip">
+ <TooltipRow label={`${t('Longitude and Latitude')}: `}
value={`${o.object.position[0]}, ${o.object.position[1]}`} />
+ <TooltipRow label={`${t('Height')}: `}
value={`${o.object.elevationValue}`} />
+ </div>
+ );
+}
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 f856225..9901b22 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 (
+ <div className="deckgl-tooltip">
+ <TooltipRow label={`${t('Centroid (Longitude and Latitude)')}: `}
value={`(${o.object.centroid[0]}, ${o.object.centroid[1]})`} />
+ <TooltipRow label={`${t('Height')}: `}
value={`${o.object.elevationValue}`} />
+ </div>
+ );
+}
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 633ccec..7bf0982 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 &&
+ <div className="deckgl-tooltip">
+ {
+ Object.keys(o.object.extraProps).map((prop, index) =>
+ <TooltipRow key={`prop-${index}`} label={`${prop}: `}
value={`${o.object.extraProps[prop]}`} />,
+ )
+ }
+ </div>
+ );
+}
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 8a3c2f4..ca7d413 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 (
+ <div className="deckgl-tooltip">
+ <TooltipRow label={`${formData.line_column}: `}
value={`${o.object[formData.line_column]}`} />
+ {formData.metric && <TooltipRow label={`${metricLabel}: `}
value={`${o.object[metricLabel]}`} />}
+ </div>
+ );
+ };
+}
+
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 194a775..8ca13aa 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 => (
+ <div className="deckgl-tooltip">
+ <TooltipRow label={`${t('Longitude and Latitude')}: `}
value={`${o.object.position[0]}, ${o.object.position[1]}`} />
+ {
+ o.object.cat_color && <TooltipRow label={`${t('Category')}: `}
value={`${o.object.cat_color}`} />
+ }
+ {
+ o.object.metric && <TooltipRow
label={`${formData.point_radius_fixed.value}: `} value={`${o.object.metric}`} />
+ }
+ </div>
+ );
+}
+
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 a4bdede..1efefae 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 (
+ <div className="deckgl-tooltip">
+ <TooltipRow label={`${t('Longitude and Latitude')}: `}
value={`${o.object.position[0]}, ${o.object.position[1]}`} />
+ <TooltipRow label={`${t('Weight')}: `} value={`${o.object.weight}`} />
+ </div>
+ );
+}
+
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 b9b2716..7adf3b7 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 => (
- <div>
- <div>{fd.line_column}:
<strong>{o.object[fd.line_column]}</strong></div>
- {fd.metric &&
- <div>{metricLabel}: <strong>{o.object[metricLabel]}</strong></div>}
- </div>);
}
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 0000000..b085d1c
--- /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;
+ }