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
This commit is contained in:
parent
e714dc19fe
commit
1132c3cbde
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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)),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue