Skip to content
This repository has been archived by the owner on Dec 10, 2021. It is now read-only.

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 Mar 19, 2020
1 parent 8071e1d commit 3938c12
Show file tree
Hide file tree
Showing 15 changed files with 151 additions and 37 deletions.
3 changes: 2 additions & 1 deletion packages/superset-ui-legacy-preset-chart-deckgl/package.json
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',
},
];
13 changes: 13 additions & 0 deletions yarn.lock
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 3938c12

Please sign in to comment.