Skip to content

Commit

Permalink
feat: support polygon tooltip independently from superset app (#12)
Browse files Browse the repository at this point in the history
* feat: support polygon tooltip independently from superset app

* fix: remove unintended changes

* fix: minor styling

* fix: tooltip

* fix: lowercase name

* fix: storybook
  • Loading branch information
kristw authored and zhaoyongjie committed Nov 30, 2021
1 parent 4f0d4e0 commit abc4a04
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"react-bootstrap-slider": "2.1.5",
"react-map-gl": "^4.0.10",
"underscore": "^1.8.3",
"urijs": "^1.18.10"
"urijs": "^1.18.10",
"xss": "^1.0.6"
},
"peerDependencies": {
"@superset-ui/chart": "^0.12.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ const defaultProps = {
};

export default class AnimatableDeckGLContainer extends React.PureComponent {
containerRef = React.createRef();

setTooltip = tooltip => {
if (this.containerRef.current) {
this.containerRef.current.setTooltip(tooltip);
}
};

render() {
const {
start,
Expand All @@ -78,6 +86,7 @@ export default class AnimatableDeckGLContainer extends React.PureComponent {
return (
<div>
<DeckGLContainer
ref={this.containerRef}
viewport={viewport}
layers={layers}
setControlValue={setControlValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ const propTypes = {
};

export default class CategoricalDeckGLContainer extends React.PureComponent {
containerRef = React.createRef();

/*
* A Deck.gl container that handles categories.
*
Expand Down Expand Up @@ -225,10 +227,17 @@ export default class CategoricalDeckGLContainer extends React.PureComponent {
this.setState({ categories });
}

setTooltip = tooltip => {
if (this.containerRef.current) {
this.containerRef.current.setTooltip(tooltip);
}
};

render() {
return (
<div style={{ position: 'relative' }}>
<AnimatableDeckGLContainer
ref={this.containerRef}
getLayers={this.getLayers}
start={this.state.start}
end={this.state.end}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import { StaticMap } from 'react-map-gl';
import DeckGL from 'deck.gl';
// eslint-disable-next-line import/extensions
import Tooltip from './components/Tooltip';
import 'mapbox-gl/dist/mapbox-gl.css';
import './css/deckgl.css';

Expand Down Expand Up @@ -55,6 +57,7 @@ export default class DeckGLContainer extends React.Component {
// This has to be placed after this.tick is bound to this
this.state = {
timer: setInterval(this.tick, TICK),
tooltip: null,
viewState: props.viewport,
};
}
Expand Down Expand Up @@ -88,31 +91,38 @@ export default class DeckGLContainer extends React.Component {
return this.props.layers;
}

setTooltip = tooltip => {
this.setState({ tooltip });
};

render() {
const { children, bottomMargin, height, width } = this.props;
const { viewState } = this.state;
const { viewState, tooltip } = this.state;
const adjustedHeight = height - bottomMargin;

const layers = this.layers();

return (
<div style={{ position: 'relative', width, height: adjustedHeight }}>
<DeckGL
initWebGLParameters
controller
width={width}
height={adjustedHeight}
layers={layers}
viewState={viewState}
onViewStateChange={this.onViewStateChange}
>
<StaticMap
mapStyle={this.props.mapStyle}
mapboxApiAccessToken={this.props.mapboxApiAccessToken}
/>
</DeckGL>
{children}
</div>
<>
<div style={{ position: 'relative', width, height: adjustedHeight }}>
<DeckGL
initWebGLParameters
controller
width={width}
height={adjustedHeight}
layers={layers}
viewState={viewState}
onViewStateChange={this.onViewStateChange}
>
<StaticMap
mapStyle={this.props.mapStyle}
mapboxApiAccessToken={this.props.mapboxApiAccessToken}
/>
</DeckGL>
{children}
</div>
<Tooltip tooltip={tooltip} />
</>
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { useMemo, CSSProperties } from 'react';
import { filterXSS } from 'xss';

export type TooltipProps = {
tooltip:
| {
x: number;
y: number;
content: string;
}
| null
| undefined;
};

export default function Tooltip(props: TooltipProps) {
const { tooltip } = props;
if (typeof tooltip === 'undefined' || tooltip === null) {
return null;
}

const { x, y, content } = tooltip;

// eslint-disable-next-line react-hooks/rules-of-hooks
const style: CSSProperties = useMemo(
() => ({
position: 'absolute',
top: `${y}px`,
left: `${x}px`,
padding: '8px',
margin: '8px',
background: 'rgba(0, 0, 0, 0.8)',
color: '#fff',
maxWidth: '300px',
fontSize: '12px',
zIndex: 9,
pointerEvents: 'none',
}),
[x, y],
);

if (typeof content === 'string') {
// eslint-disable-next-line react-hooks/rules-of-hooks
const contentHtml = useMemo(
() => ({
__html: filterXSS(content, { stripIgnoreTag: true }),
}),
[content],
);
return (
<div style={style}>
<div
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={contentHtml}
/>
</div>
);
}

return <div style={style}>{content}</div>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,13 @@ function setTooltipContent(formData) {

return (
<div className="deckgl-tooltip">
<TooltipRow
label={`${formData.line_column}: `}
value={`${o.object[formData.line_column]}`}
/>
{o.object.name && <TooltipRow label="name: " value={`${o.object.name}`} />}
{o.object[formData.line_column] && (
<TooltipRow
label={`${formData.line_column}: `}
value={`${o.object[formData.line_column]}`}
/>
)}
{formData.metric && (
<TooltipRow label={`${metricLabel}: `} value={`${o.object[metricLabel]}`} />
)}
Expand Down Expand Up @@ -103,8 +106,9 @@ export function getLayer(formData, payload, onAddFilter, setTooltip, selected, o

return baseColor;
};

const tooltipContentGenerator =
fd.line_column && fd.metric && ['geohash', 'zipcode'].includes(fd.line_type)
fd.line_column && fd.metric && ['json', 'geohash', 'zipcode'].includes(fd.line_type)
? setTooltipContent(fd)
: undefined;

Expand Down Expand Up @@ -132,17 +136,17 @@ const propTypes = {
setControlValue: PropTypes.func.isRequired,
viewport: PropTypes.object.isRequired,
onAddFilter: PropTypes.func,
setTooltip: PropTypes.func,
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
};

const defaultProps = {
onAddFilter() {},
setTooltip() {},
};

class DeckGLPolygon extends React.Component {
containerRef = React.createRef();

constructor(props) {
super(props);

Expand Down Expand Up @@ -245,7 +249,7 @@ class DeckGLPolygon extends React.Component {
this.props.formData,
this.props.payload,
this.props.onAddFilter,
this.props.setTooltip,
this.setTooltip,
this.state.selected,
this.onSelect,
filters,
Expand All @@ -254,6 +258,12 @@ class DeckGLPolygon extends React.Component {
return [layer];
}

setTooltip = tooltip => {
if (this.containerRef.current) {
this.containerRef.current.setTooltip(tooltip);
}
};

render() {
const { payload, formData, setControlValue } = this.props;
const { start, end, getStep, values, disabled, viewport } = this.state;
Expand All @@ -267,6 +277,7 @@ class DeckGLPolygon extends React.Component {
return (
<div style={{ position: 'relative' }}>
<AnimatableDeckGLContainer
ref={this.containerRef}
aggregation
getLayers={this.getLayers}
start={start}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,6 @@ export default [
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-deckgl|ArcChartPlugin',
storyPath: 'legacy-preset-chart-deckgl|ArcChartPlugin',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ export default [
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-deckgl|GridChartPlugin',
storyPath: 'legacy-preset-chart-deckgl|GridChartPlugin',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ export default [
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-deckgl|HexChartPlugin',
storyPath: 'legacy-preset-chart-deckgl|HexChartPlugin',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ export default [
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-deckgl|PathChartPlugin',
storyPath: 'legacy-preset-chart-deckgl|PathChartPlugin',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default [
line_column: 'contour',
line_type: 'json',
adhoc_filters: [],
metric: 'count',
metric: 'population',
point_radius_fixed: { type: 'fix', value: 1000 },
row_limit: 10000,
reverse_long_lat: false,
Expand Down Expand Up @@ -71,7 +71,7 @@ export default [
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-deckgl|PolygonChartPlugin',
storyPath: 'legacy-preset-chart-deckgl|PolygonChartPlugin',
},
{
renderStory: () => (
Expand Down Expand Up @@ -119,6 +119,6 @@ export default [
/>
),
storyName: 'Single Polygon in geojson format',
storyPath: 'legacy-|preset-chart-deckgl|PolygonChartPlugin',
storyPath: 'legacy-preset-chart-deckgl|PolygonChartPlugin',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ export default {
data: {
features: [
{
count: 1,
count: 10,
name: 'Test',
polygon: {
type: 'Feature',
properties: {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,6 @@ export default [
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-deckgl|ScatterChartPlugin',
storyPath: 'legacy-preset-chart-deckgl|ScatterChartPlugin',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ export default [
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-deckgl|ScreengridChartPlugin',
storyPath: 'legacy-preset-chart-deckgl|ScreengridChartPlugin',
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -6831,6 +6831,11 @@ cssesc@^3.0.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==

cssfilter@0.0.10:
version "0.0.10"
resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae"
integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=

csso@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d"
Expand Down Expand Up @@ -17859,6 +17864,14 @@ xmlhttprequest@1:
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=

xss@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.6.tgz#eaf11e9fc476e3ae289944a1009efddd8a124b51"
integrity sha512-6Q9TPBeNyoTRxgZFk5Ggaepk/4vUOYdOsIUYvLehcsIZTFjaavbVnsuAkLA5lIFuug5hw8zxcB9tm01gsjph2A==
dependencies:
commander "^2.9.0"
cssfilter "0.0.10"

xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
Expand Down

0 comments on commit abc4a04

Please sign in to comment.