This is an automated email from the ASF dual-hosted git repository.
ccwilliams pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push:
new 2a7b64f [SIP-5] Remove references to slice from all deck.gl
components. (#6039)
2a7b64f is described below
commit 2a7b64fef5823760fd619f217b3161d2d7d00cc6
Author: Krist Wongsuphasawat <[email protected]>
AuthorDate: Thu Oct 11 20:56:36 2018 -0700
[SIP-5] Remove references to slice from all deck.gl components. (#6039)
* start removing slice.
* migrate arc
* refactor arc
* refactor path
* refactor deck polygon
* remove commented code
* refactor factory function
* refactor grid
* refactor hex
* refactor polygon
* refactor scatter
* refactor geojson
* refactor screengrid
* remove unnecessary nesting
* add proptypes
* add proptypes
* refactor deck.gl Multi
* fix lint
* Use export syntax instead of module.exports
---
.../deckgl/CategoricalDeckGLContainer.jsx | 21 ++--
.../src/visualizations/deckgl/createAdaptor.jsx | 30 ++++++
.../assets/src/visualizations/deckgl/factory.jsx | 87 ++++++++++++++++
.../src/visualizations/deckgl/layers/arc.jsx | 46 ++-------
.../src/visualizations/deckgl/layers/common.jsx | 9 +-
.../src/visualizations/deckgl/layers/geojson.jsx | 64 +++++++-----
.../src/visualizations/deckgl/layers/grid.jsx | 44 ++------
.../src/visualizations/deckgl/layers/hex.jsx | 43 ++------
.../src/visualizations/deckgl/layers/index.js | 1 +
.../src/visualizations/deckgl/layers/path.jsx | 43 ++------
.../src/visualizations/deckgl/layers/polygon.jsx | 46 ++-------
.../src/visualizations/deckgl/layers/scatter.jsx | 46 ++-------
.../visualizations/deckgl/layers/screengrid.jsx | 65 +++++-------
.../assets/src/visualizations/deckgl/multi.jsx | 114 +++++++++++++--------
14 files changed, 312 insertions(+), 347 deletions(-)
diff --git
a/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
b/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
index 0976ec0..61c9eed 100644
--- a/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
+++ b/superset/assets/src/visualizations/deckgl/CategoricalDeckGLContainer.jsx
@@ -31,12 +31,14 @@ function getCategories(fd, data) {
}
const propTypes = {
- slice: PropTypes.object.isRequired,
+ formData: PropTypes.object.isRequired,
mapboxApiKey: PropTypes.string.isRequired,
setControlValue: PropTypes.func.isRequired,
viewport: PropTypes.object.isRequired,
getLayer: PropTypes.func.isRequired,
payload: PropTypes.object.isRequired,
+ onAddFilter: PropTypes.func,
+ onTooltip: PropTypes.func,
};
export default class CategoricalDeckGLContainer extends React.PureComponent {
@@ -49,7 +51,7 @@ export default class CategoricalDeckGLContainer extends
React.PureComponent {
/* eslint-disable-next-line react/sort-comp */
static getDerivedStateFromProps(nextProps) {
- const fd = nextProps.slice.formData;
+ const fd = nextProps.formData;
const timeGrain = fd.time_grain_sqla || fd.granularity || 'PT1M';
const timestamps = nextProps.payload.data.features.map(f => f.__timestamp);
@@ -70,8 +72,13 @@ export default class CategoricalDeckGLContainer extends
React.PureComponent {
this.setState(CategoricalDeckGLContainer.getDerivedStateFromProps(nextProps,
this.state));
}
getLayers(values) {
- const { getLayer, payload, slice } = this.props;
- const fd = slice.formData;
+ const {
+ getLayer,
+ payload,
+ formData: fd,
+ onAddFilter,
+ onTooltip,
+ } = this.props;
let data = [...payload.data.features];
// Add colors from categories or fixed color
@@ -96,7 +103,7 @@ export default class CategoricalDeckGLContainer extends
React.PureComponent {
}
payload.data.features = data;
- return [getLayer(fd, payload, slice)];
+ return [getLayer(fd, payload, onAddFilter, onTooltip)];
}
addColor(data, fd) {
const c = fd.color_picker || { r: 0, g: 0, b: 0, a: 1 };
@@ -142,14 +149,14 @@ export default class CategoricalDeckGLContainer extends
React.PureComponent {
disabled={this.state.disabled}
viewport={this.props.viewport}
mapboxApiAccessToken={this.props.mapboxApiKey}
- mapStyle={this.props.slice.formData.mapbox_style}
+ mapStyle={this.props.formData.mapbox_style}
setControlValue={this.props.setControlValue}
>
<Legend
categories={this.state.categories}
toggleCategory={this.toggleCategory}
showSingleCategory={this.showSingleCategory}
- position={this.props.slice.formData.legend_position}
+ position={this.props.formData.legend_position}
/>
</AnimatableDeckGLContainer>
</div>
diff --git a/superset/assets/src/visualizations/deckgl/createAdaptor.jsx
b/superset/assets/src/visualizations/deckgl/createAdaptor.jsx
new file mode 100644
index 0000000..6dfe11b
--- /dev/null
+++ b/superset/assets/src/visualizations/deckgl/createAdaptor.jsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+const IDENTITY = x => x;
+
+class DeckGlChartInput {
+ constructor(slice, payload, setControlValue) {
+ this.formData = slice.formData;
+ this.payload = payload;
+ this.setControlValue = setControlValue;
+ this.viewport = {
+ ...this.formData.viewport,
+ width: slice.width(),
+ height: slice.height(),
+ };
+
+ this.onAddFilter = ((...args) => { slice.addFilter(...args); });
+ this.onTooltip = ((...args) => { slice.tooltip(...args); });
+ }
+}
+
+export default function createAdaptor(Component, transformProps = IDENTITY) {
+ return function adaptor(slice, payload, setControlValue) {
+ const chartInput = new DeckGlChartInput(slice, payload, setControlValue);
+ ReactDOM.render(
+ <Component {...transformProps(chartInput)} />,
+ document.querySelector(slice.selector),
+ );
+ };
+}
diff --git a/superset/assets/src/visualizations/deckgl/factory.jsx
b/superset/assets/src/visualizations/deckgl/factory.jsx
new file mode 100644
index 0000000..fc61e34
--- /dev/null
+++ b/superset/assets/src/visualizations/deckgl/factory.jsx
@@ -0,0 +1,87 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import DeckGLContainer from './DeckGLContainer';
+import CategoricalDeckGLContainer from './CategoricalDeckGLContainer';
+import { fitViewport } from './layers/common';
+
+const propTypes = {
+ formData: PropTypes.object.isRequired,
+ payload: PropTypes.object.isRequired,
+ setControlValue: PropTypes.func.isRequired,
+ viewport: PropTypes.object.isRequired,
+ onAddFilter: PropTypes.func,
+ onTooltip: PropTypes.func,
+};
+const defaultProps = {
+ onAddFilter() {},
+ onTooltip() {},
+};
+
+export function createDeckGLComponent(getLayer, getPoints) {
+ function Component(props) {
+ const {
+ formData,
+ payload,
+ setControlValue,
+ onAddFilter,
+ onTooltip,
+ viewport: originalViewport,
+ } = props;
+
+ const viewport = formData.autozoom
+ ? fitViewport(originalViewport, getPoints(payload.data.features))
+ : originalViewport;
+
+ const layer = getLayer(formData, payload, onAddFilter, onTooltip);
+
+ return (
+ <DeckGLContainer
+ mapboxApiAccessToken={payload.data.mapboxApiKey}
+ viewport={viewport}
+ layers={[layer]}
+ mapStyle={formData.mapbox_style}
+ setControlValue={setControlValue}
+ />
+ );
+ }
+
+ Component.propTypes = propTypes;
+ Component.defaultProps = defaultProps;
+
+ return Component;
+}
+
+export function createCategoricalDeckGLComponent(getLayer, getPoints) {
+ function Component(props) {
+ const {
+ formData,
+ payload,
+ setControlValue,
+ onAddFilter,
+ onTooltip,
+ viewport: originalViewport,
+ } = props;
+
+ const viewport = formData.autozoom
+ ? fitViewport(originalViewport, getPoints(payload.data.features))
+ : originalViewport;
+
+ return (
+ <CategoricalDeckGLContainer
+ formData={formData}
+ mapboxApiKey={payload.data.mapboxApiKey}
+ setControlValue={setControlValue}
+ viewport={viewport}
+ getLayer={getLayer}
+ payload={payload}
+ onAddFilter={onAddFilter}
+ onTooltip={onTooltip}
+ />
+ );
+ }
+
+ Component.propTypes = propTypes;
+ Component.defaultProps = defaultProps;
+
+ return Component;
+}
diff --git a/superset/assets/src/visualizations/deckgl/layers/arc.jsx
b/superset/assets/src/visualizations/deckgl/layers/arc.jsx
index 883ffbd..e2a3233 100644
--- a/superset/assets/src/visualizations/deckgl/layers/arc.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/arc.jsx
@@ -1,13 +1,7 @@
-/* eslint no-underscore-dangle: ["error", { "allow": ["", "__timestamp"] }] */
-
-import React from 'react';
-import ReactDOM from 'react-dom';
-
import { ArcLayer } from 'deck.gl';
-
-import CategoricalDeckGLContainer from '../CategoricalDeckGLContainer';
-
-import * as common from './common';
+import { commonLayerProps } from './common';
+import createAdaptor from '../createAdaptor';
+import { createCategoricalDeckGLComponent } from '../factory';
function getPoints(data) {
const points = [];
@@ -18,7 +12,7 @@ function getPoints(data) {
return points;
}
-function getLayer(fd, payload, slice) {
+export function getLayer(fd, payload, onAddFilter, onTooltip) {
const data = payload.data.features;
const sc = fd.color_picker;
const tc = fd.target_color_picker;
@@ -28,36 +22,8 @@ function getLayer(fd, payload, slice) {
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,
- ...common.commonLayerProps(fd, slice),
+ ...commonLayerProps(fd, onAddFilter, onTooltip),
});
}
-function deckArc(slice, payload, setControlValue) {
- const fd = slice.formData;
- let viewport = {
- ...fd.viewport,
- width: slice.width(),
- height: slice.height(),
- };
-
- if (fd.autozoom) {
- viewport = common.fitViewport(viewport, getPoints(payload.data.features));
- }
-
- ReactDOM.render(
- <CategoricalDeckGLContainer
- slice={slice}
- mapboxApiKey={payload.data.mapboxApiKey}
- setControlValue={setControlValue}
- viewport={viewport}
- getLayer={getLayer}
- payload={payload}
- />,
- document.getElementById(slice.containerId),
- );
-}
-
-module.exports = {
- default: deckArc,
- getLayer,
-};
+export default createAdaptor(createCategoricalDeckGLComponent(getLayer,
getPoints));
diff --git a/superset/assets/src/visualizations/deckgl/layers/common.jsx
b/superset/assets/src/visualizations/deckgl/layers/common.jsx
index 8a3ecc5..a0b1e13 100644
--- a/superset/assets/src/visualizations/deckgl/layers/common.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/common.jsx
@@ -1,7 +1,6 @@
import React from 'react';
import { fitBounds } from 'viewport-mercator-project';
import d3 from 'd3';
-
import sandboxedEval from '../../../modules/sandbox';
export function getBounds(points) {
@@ -32,7 +31,7 @@ export function fitViewport(viewport, points, padding = 10) {
}
}
-export function commonLayerProps(formData, slice) {
+export function commonLayerProps(formData, onAddFilter, onTooltip) {
const fd = formData;
let onHover;
let tooltipContentGenerator;
@@ -49,13 +48,13 @@ export function commonLayerProps(formData, slice) {
if (tooltipContentGenerator) {
onHover = (o) => {
if (o.picked) {
- slice.setTooltip({
+ onTooltip({
content: tooltipContentGenerator(o),
x: o.x,
y: o.y,
});
} else {
- slice.setTooltip(null);
+ onTooltip(null);
}
};
}
@@ -66,7 +65,7 @@ export function commonLayerProps(formData, slice) {
window.open(href);
};
} else if (fd.table_filter && fd.line_type === 'geohash') {
- onClick = o => slice.addFilter(fd.line_column, [o.object[fd.line_column]],
false);
+ onClick = o => onAddFilter(fd.line_column, [o.object[fd.line_column]],
false);
}
return {
onClick,
diff --git a/superset/assets/src/visualizations/deckgl/layers/geojson.jsx
b/superset/assets/src/visualizations/deckgl/layers/geojson.jsx
index 72790f1..64a39a9 100644
--- a/superset/assets/src/visualizations/deckgl/layers/geojson.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/geojson.jsx
@@ -1,12 +1,13 @@
import React from 'react';
-import ReactDOM from 'react-dom';
+import PropTypes from 'prop-types';
import { GeoJsonLayer } from 'deck.gl';
// TODO import geojsonExtent from 'geojson-extent';
import DeckGLContainer from './../DeckGLContainer';
-import * as common from './common';
import { hexToRGB } from '../../../modules/colors';
import sandboxedEval from '../../../modules/sandbox';
+import { commonLayerProps } from './common';
+import createAdaptor from '../createAdaptor';
const propertyMap = {
fillColor: 'fillColor',
@@ -57,7 +58,7 @@ const recurseGeoJson = (node, propOverrides, extraProps) => {
}
};
-function getLayer(formData, payload, slice) {
+export function getLayer(formData, payload, onAddFilter, onTooltip) {
const fd = formData;
const fc = fd.fill_color_picker;
const sc = fd.stroke_color_picker;
@@ -88,35 +89,52 @@ function getLayer(formData, payload, slice) {
stroked: fd.stroked,
extruded: fd.extruded,
pointRadiusScale: fd.point_radius_scale,
- ...common.commonLayerProps(fd, slice),
+ ...commonLayerProps(fd, onAddFilter, onTooltip),
});
}
-function deckGeoJson(slice, payload, setControlValue) {
- const layer = getLayer(slice.formData, payload, slice);
- const viewport = {
- ...slice.formData.viewport,
- width: slice.width(),
- height: slice.height(),
- };
- if (slice.formData.autozoom) {
- // TODO get this to work
- // viewport = common.fitViewport(viewport,
geojsonExtent(payload.data.features));
- }
+const propTypes = {
+ formData: PropTypes.object.isRequired,
+ payload: PropTypes.object.isRequired,
+ setControlValue: PropTypes.func.isRequired,
+ viewport: PropTypes.object.isRequired,
+ onAddFilter: PropTypes.func,
+ onTooltip: PropTypes.func,
+};
+const defaultProps = {
+ onAddFilter() {},
+ onTooltip() {},
+};
+
+function deckGeoJson(props) {
+ const {
+ formData,
+ payload,
+ setControlValue,
+ onAddFilter,
+ onTooltip,
+ viewport,
+ } = props;
- ReactDOM.render(
+ // TODO get this to work
+ // if (formData.autozoom) {
+ // viewport = common.fitViewport(viewport,
geojsonExtent(payload.data.features));
+ // }
+
+ const layer = getLayer(formData, payload, onAddFilter, onTooltip);
+
+ return (
<DeckGLContainer
mapboxApiAccessToken={payload.data.mapboxApiKey}
viewport={viewport}
layers={[layer]}
- mapStyle={slice.formData.mapbox_style}
+ mapStyle={formData.mapbox_style}
setControlValue={setControlValue}
- />,
- document.getElementById(slice.containerId),
+ />
);
}
-module.exports = {
- default: deckGeoJson,
- getLayer,
-};
+deckGeoJson.propTypes = propTypes;
+deckGeoJson.defaultProps = defaultProps;
+
+export default createAdaptor(deckGeoJson);
diff --git a/superset/assets/src/visualizations/deckgl/layers/grid.jsx
b/superset/assets/src/visualizations/deckgl/layers/grid.jsx
index 16a538c..0f5cf31 100644
--- a/superset/assets/src/visualizations/deckgl/layers/grid.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/grid.jsx
@@ -1,14 +1,10 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-
import { GridLayer } from 'deck.gl';
-
-import DeckGLContainer from './../DeckGLContainer';
-
-import * as common from './common';
+import { commonLayerProps } from './common';
import sandboxedEval from '../../../modules/sandbox';
+import createAdaptor from '../createAdaptor';
+import { createDeckGLComponent } from '../factory';
-function getLayer(formData, payload, slice) {
+export function getLayer(formData, payload, onAddFilter, onTooltip) {
const fd = formData;
const c = fd.color_picker;
let data = payload.data.features.map(d => ({
@@ -21,6 +17,7 @@ function getLayer(formData, payload, slice) {
const jsFnMutator = sandboxedEval(fd.js_data_mutator);
data = jsFnMutator(data);
}
+
return new GridLayer({
id: `grid-layer-${fd.slice_id}`,
data,
@@ -32,7 +29,7 @@ function getLayer(formData, payload, slice) {
outline: false,
getElevationValue: points => points.reduce((sum, point) => sum +
point.weight, 0),
getColorValue: points => points.reduce((sum, point) => sum + point.weight,
0),
- ...common.commonLayerProps(fd, slice),
+ ...commonLayerProps(fd, onAddFilter, onTooltip),
});
}
@@ -40,31 +37,4 @@ function getPoints(data) {
return data.map(d => d.position);
}
-function deckGrid(slice, payload, setControlValue) {
- const layer = getLayer(slice.formData, payload, slice);
- let viewport = {
- ...slice.formData.viewport,
- width: slice.width(),
- height: slice.height(),
- };
-
- if (slice.formData.autozoom) {
- viewport = common.fitViewport(viewport, getPoints(payload.data.features));
- }
-
- ReactDOM.render(
- <DeckGLContainer
- mapboxApiAccessToken={payload.data.mapboxApiKey}
- viewport={viewport}
- layers={[layer]}
- mapStyle={slice.formData.mapbox_style}
- setControlValue={setControlValue}
- />,
- document.getElementById(slice.containerId),
- );
-}
-
-module.exports = {
- default: deckGrid,
- getLayer,
-};
+export default createAdaptor(createDeckGLComponent(getLayer, getPoints));
diff --git a/superset/assets/src/visualizations/deckgl/layers/hex.jsx
b/superset/assets/src/visualizations/deckgl/layers/hex.jsx
index 14c9951..3dabb76 100644
--- a/superset/assets/src/visualizations/deckgl/layers/hex.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/hex.jsx
@@ -1,14 +1,10 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-
import { HexagonLayer } from 'deck.gl';
-
-import DeckGLContainer from './../DeckGLContainer';
-
-import * as common from './common';
+import { commonLayerProps } from './common';
import sandboxedEval from '../../../modules/sandbox';
+import createAdaptor from '../createAdaptor';
+import { createDeckGLComponent } from '../factory';
-function getLayer(formData, payload, slice) {
+export function getLayer(formData, payload, onAddFilter, onTooltip) {
const fd = formData;
const c = fd.color_picker;
let data = payload.data.features.map(d => ({
@@ -33,7 +29,7 @@ function getLayer(formData, payload, slice) {
outline: false,
getElevationValue: points => points.reduce((sum, point) => sum +
point.weight, 0),
getColorValue: points => points.reduce((sum, point) => sum + point.weight,
0),
- ...common.commonLayerProps(fd, slice),
+ ...commonLayerProps(fd, onAddFilter, onTooltip),
});
}
@@ -41,31 +37,4 @@ function getPoints(data) {
return data.map(d => d.position);
}
-function deckHex(slice, payload, setControlValue) {
- const layer = getLayer(slice.formData, payload, slice);
- let viewport = {
- ...slice.formData.viewport,
- width: slice.width(),
- height: slice.height(),
- };
-
- if (slice.formData.autozoom) {
- viewport = common.fitViewport(viewport, getPoints(payload.data.features));
- }
-
- ReactDOM.render(
- <DeckGLContainer
- mapboxApiAccessToken={payload.data.mapboxApiKey}
- viewport={viewport}
- layers={[layer]}
- mapStyle={slice.formData.mapbox_style}
- setControlValue={setControlValue}
- />,
- document.getElementById(slice.containerId),
- );
-}
-
-module.exports = {
- default: deckHex,
- getLayer,
-};
+export default createAdaptor(createDeckGLComponent(getLayer, getPoints));
diff --git a/superset/assets/src/visualizations/deckgl/layers/index.js
b/superset/assets/src/visualizations/deckgl/layers/index.js
index d8d25d5..e98f743 100644
--- a/superset/assets/src/visualizations/deckgl/layers/index.js
+++ b/superset/assets/src/visualizations/deckgl/layers/index.js
@@ -18,4 +18,5 @@ const layerGenerators = {
deck_arc,
deck_polygon,
};
+
export default layerGenerators;
diff --git a/superset/assets/src/visualizations/deckgl/layers/path.jsx
b/superset/assets/src/visualizations/deckgl/layers/path.jsx
index 0951edd..ede01b2 100644
--- a/superset/assets/src/visualizations/deckgl/layers/path.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/path.jsx
@@ -1,14 +1,10 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-
import { PathLayer } from 'deck.gl';
-
-import DeckGLContainer from './../DeckGLContainer';
-
-import * as common from './common';
+import { commonLayerProps } from './common';
import sandboxedEval from '../../../modules/sandbox';
+import createAdaptor from '../createAdaptor';
+import { createDeckGLComponent } from '../factory';
-function getLayer(formData, payload, slice) {
+export function getLayer(formData, payload, onAddFilter, onTooltip) {
const fd = formData;
const c = fd.color_picker;
const fixedColor = [c.r, c.g, c.b, 255 * c.a];
@@ -29,7 +25,7 @@ function getLayer(formData, payload, slice) {
data,
rounded: true,
widthScale: 1,
- ...common.commonLayerProps(fd, slice),
+ ...commonLayerProps(fd, onAddFilter, onTooltip),
});
}
@@ -41,31 +37,4 @@ function getPoints(data) {
return points;
}
-function deckPath(slice, payload, setControlValue) {
- const layer = getLayer(slice.formData, payload, slice);
- let viewport = {
- ...slice.formData.viewport,
- width: slice.width(),
- height: slice.height(),
- };
-
- if (slice.formData.autozoom) {
- viewport = common.fitViewport(viewport, getPoints(payload.data.features));
- }
-
- ReactDOM.render(
- <DeckGLContainer
- mapboxApiAccessToken={payload.data.mapboxApiKey}
- viewport={viewport}
- layers={[layer]}
- mapStyle={slice.formData.mapbox_style}
- setControlValue={setControlValue}
- />,
- document.getElementById(slice.containerId),
- );
-}
-
-module.exports = {
- default: deckPath,
- getLayer,
-};
+export default createAdaptor(createDeckGLComponent(getLayer, getPoints));
diff --git a/superset/assets/src/visualizations/deckgl/layers/polygon.jsx
b/superset/assets/src/visualizations/deckgl/layers/polygon.jsx
index e84b943..73537dc 100644
--- a/superset/assets/src/visualizations/deckgl/layers/polygon.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/polygon.jsx
@@ -1,21 +1,17 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-
+import d3 from 'd3';
import { PolygonLayer } from 'deck.gl';
import { flatten } from 'lodash';
-import d3 from 'd3';
-
-import DeckGLContainer from './../DeckGLContainer';
-
-import * as common from './common';
import { colorScalerFactory } from '../../../modules/colors';
+import { commonLayerProps } from './common';
import sandboxedEval from '../../../modules/sandbox';
+import createAdaptor from '../createAdaptor';
+import { createDeckGLComponent } from '../factory';
function getPoints(features) {
return flatten(features.map(d => d.polygon), true);
}
-function getLayer(formData, payload, slice) {
+export function getLayer(formData, payload, onAddFilter, onTooltip) {
const fd = formData;
const fc = fd.fill_color_picker;
const sc = fd.stroke_color_picker;
@@ -49,36 +45,8 @@ function getLayer(formData, payload, slice) {
getLineWidth: fd.line_width,
extruded: fd.extruded,
fp64: true,
- ...common.commonLayerProps(fd, slice),
+ ...commonLayerProps(fd, onAddFilter, onTooltip),
});
}
-function deckPolygon(slice, payload, setControlValue) {
- const layer = getLayer(slice.formData, payload, slice);
- const fd = slice.formData;
- let viewport = {
- ...slice.formData.viewport,
- width: slice.width(),
- height: slice.height(),
- };
-
- if (fd.autozoom) {
- viewport = common.fitViewport(viewport, getPoints(payload.data.features));
- }
-
- ReactDOM.render(
- <DeckGLContainer
- mapboxApiAccessToken={payload.data.mapboxApiKey}
- viewport={viewport}
- layers={[layer]}
- mapStyle={slice.formData.mapbox_style}
- setControlValue={setControlValue}
- />,
- document.getElementById(slice.containerId),
- );
-}
-
-module.exports = {
- default: deckPolygon,
- getLayer,
-};
+export default createAdaptor(createDeckGLComponent(getLayer, getPoints));
diff --git a/superset/assets/src/visualizations/deckgl/layers/scatter.jsx
b/superset/assets/src/visualizations/deckgl/layers/scatter.jsx
index d9474a4..b740ce1 100644
--- a/superset/assets/src/visualizations/deckgl/layers/scatter.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/scatter.jsx
@@ -1,20 +1,14 @@
-/* eslint no-underscore-dangle: ["error", { "allow": ["", "__timestamp"] }] */
-
-import React from 'react';
-import ReactDOM from 'react-dom';
-
import { ScatterplotLayer } from 'deck.gl';
-
-import CategoricalDeckGLContainer from '../CategoricalDeckGLContainer';
-import * as common from './common';
+import { commonLayerProps } from './common';
+import createAdaptor from '../createAdaptor';
+import { createCategoricalDeckGLComponent } from '../factory';
import { unitToRadius } from '../../../modules/geo';
-
function getPoints(data) {
return data.map(d => d.position);
}
-function getLayer(fd, payload, slice) {
+export function getLayer(fd, payload, slice) {
const dataWithRadius = payload.data.features.map((d) => {
let radius = unitToRadius(fd.point_unit, d.radius) || 10;
if (fd.multiplier) {
@@ -35,36 +29,8 @@ function getLayer(fd, payload, slice) {
radiusMinPixels: fd.min_radius || null,
radiusMaxPixels: fd.max_radius || null,
outline: false,
- ...common.commonLayerProps(fd, slice),
+ ...commonLayerProps(fd, slice),
});
}
-function deckScatter(slice, payload, setControlValue) {
- const fd = slice.formData;
- let viewport = {
- ...fd.viewport,
- width: slice.width(),
- height: slice.height(),
- };
-
- if (fd.autozoom) {
- viewport = common.fitViewport(viewport, getPoints(payload.data.features));
- }
-
- ReactDOM.render(
- <CategoricalDeckGLContainer
- slice={slice}
- mapboxApiKey={payload.data.mapboxApiKey}
- setControlValue={setControlValue}
- viewport={viewport}
- getLayer={getLayer}
- payload={payload}
- />,
- document.getElementById(slice.containerId),
- );
-}
-
-module.exports = {
- default: deckScatter,
- getLayer,
-};
+export default createAdaptor(createCategoricalDeckGLComponent(getLayer,
getPoints));
diff --git a/superset/assets/src/visualizations/deckgl/layers/screengrid.jsx
b/superset/assets/src/visualizations/deckgl/layers/screengrid.jsx
index b4df577..4331cec 100644
--- a/superset/assets/src/visualizations/deckgl/layers/screengrid.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/screengrid.jsx
@@ -1,22 +1,19 @@
/* eslint no-underscore-dangle: ["error", { "allow": ["", "__timestamp"] }] */
import React from 'react';
-import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
-
import { ScreenGridLayer } from 'deck.gl';
-
import AnimatableDeckGLContainer from '../AnimatableDeckGLContainer';
-
-import * as common from './common';
import { getPlaySliderParams } from '../../../modules/time';
import sandboxedEval from '../../../modules/sandbox';
+import { commonLayerProps, fitViewport } from './common';
+import createAdaptor from '../createAdaptor';
function getPoints(data) {
return data.map(d => d.position);
}
-function getLayer(formData, payload, slice, filters) {
+export function getLayer(formData, payload, onAddFilter, onTooltip, filters) {
const fd = formData;
const c = fd.color_picker;
let data = payload.data.features.map(d => ({
@@ -47,21 +44,27 @@ function getLayer(formData, payload, slice, filters) {
maxColor: [c.r, c.g, c.b, 255 * c.a],
outline: false,
getWeight: d => d.weight || 0,
- ...common.commonLayerProps(fd, slice),
+ ...commonLayerProps(fd, onAddFilter, onTooltip),
});
}
const propTypes = {
- slice: PropTypes.object.isRequired,
+ formData: PropTypes.object.isRequired,
payload: PropTypes.object.isRequired,
setControlValue: PropTypes.func.isRequired,
viewport: PropTypes.object.isRequired,
+ onAddFilter: PropTypes.func,
+ onTooltip: PropTypes.func,
+};
+const defaultProps = {
+ onAddFilter() {},
+ onTooltip() {},
};
class DeckGLScreenGrid extends React.PureComponent {
/* eslint-disable-next-line react/sort-comp */
static getDerivedStateFromProps(nextProps) {
- const fd = nextProps.slice.formData;
+ const fd = nextProps.formData;
const timeGrain = fd.time_grain_sqla || fd.granularity || 'PT1M';
const timestamps = nextProps.payload.data.features.map(f => f.__timestamp);
@@ -89,14 +92,21 @@ class DeckGLScreenGrid extends React.PureComponent {
}
const layer = getLayer(
- this.props.slice.formData,
+ this.props.formData,
this.props.payload,
- this.props.slice,
+ this.props.onAddFilter,
+ this.props.onTooltip,
filters);
return [layer];
}
+
render() {
+ const { formData, payload } = this.props;
+ const viewport = formData.autozoom
+ ? fitViewport(this.props.viewport, getPoints(payload.data.features))
+ : this.props.viewport;
+
return (
<div>
<AnimatableDeckGLContainer
@@ -106,9 +116,9 @@ class DeckGLScreenGrid extends React.PureComponent {
getStep={this.state.getStep}
values={this.state.values}
disabled={this.state.disabled}
- viewport={this.props.viewport}
+ viewport={viewport}
mapboxApiAccessToken={this.props.payload.data.mapboxApiKey}
- mapStyle={this.props.slice.formData.mapbox_style}
+ mapStyle={this.props.formData.mapbox_style}
setControlValue={this.props.setControlValue}
aggregation
/>
@@ -118,31 +128,6 @@ class DeckGLScreenGrid extends React.PureComponent {
}
DeckGLScreenGrid.propTypes = propTypes;
+DeckGLScreenGrid.defaultProps = defaultProps;
-function deckScreenGrid(slice, payload, setControlValue) {
- const fd = slice.formData;
- let viewport = {
- ...fd.viewport,
- width: slice.width(),
- height: slice.height(),
- };
-
- if (fd.autozoom) {
- viewport = common.fitViewport(viewport, getPoints(payload.data.features));
- }
-
- ReactDOM.render(
- <DeckGLScreenGrid
- slice={slice}
- payload={payload}
- setControlValue={setControlValue}
- viewport={viewport}
- />,
- document.getElementById(slice.containerId),
- );
-}
-
-module.exports = {
- default: deckScreenGrid,
- getLayer,
-};
+export default createAdaptor(DeckGLScreenGrid);
diff --git a/superset/assets/src/visualizations/deckgl/multi.jsx
b/superset/assets/src/visualizations/deckgl/multi.jsx
index 8b35c86..76a7072 100644
--- a/superset/assets/src/visualizations/deckgl/multi.jsx
+++ b/superset/assets/src/visualizations/deckgl/multi.jsx
@@ -1,57 +1,87 @@
import React from 'react';
-import ReactDOM from 'react-dom';
+import PropTypes from 'prop-types';
import $ from 'jquery';
-
import DeckGLContainer from './DeckGLContainer';
import { getExploreLongUrl } from '../../explore/exploreUtils';
import layerGenerators from './layers';
+import createAdaptor from './createAdaptor';
+
+const propTypes = {
+ formData: PropTypes.object.isRequired,
+ payload: PropTypes.object.isRequired,
+ setControlValue: PropTypes.func.isRequired,
+ viewport: PropTypes.object.isRequired,
+};
+
+class DeckMulti extends React.PureComponent {
+ constructor(props) {
+ super(props);
+ this.state = { subSlicesLayers: {} };
+ }
+
+ componentDidMount() {
+ const { formData, payload } = this.props;
+ this.loadLayers(formData, payload);
+ }
+
+ componentWillReceiveProps(nextProps) {
+ const { formData, payload } = nextProps;
+ this.loadLayers(formData, payload);
+ }
+
+ loadLayers(formData, payload) {
+ this.setState({ subSlicesLayers: {} });
+ payload.data.slices.forEach((subslice) => {
+ // Filters applied to multi_deck are passed down to underlying charts
+ // note that dashboard contextual information (filter_immune_slices and
such) aren't
+ // taken into consideration here
+ const filters = [
+ ...(subslice.form_data.filters || []),
+ ...(formData.filters || []),
+ ...(formData.extra_filters || []),
+ ];
+ const subsliceCopy = {
+ ...subslice,
+ form_data: {
+ ...subslice.form_data,
+ filters,
+ },
+ };
+ const url = getExploreLongUrl(subsliceCopy.form_data, 'json');
+ $.get(url, (data) => {
+ const layer = layerGenerators[subsliceCopy.form_data.viz_type](
+ subsliceCopy.form_data,
+ data,
+ );
+ this.setState({
+ subSlicesLayers: {
+ ...this.state.subSlicesLayers,
+ [subsliceCopy.slice_id]: layer,
+ },
+ });
+ });
+ });
+ }
+
+ render() {
+ const { payload, viewport, formData, setControlValue } = this.props;
+ const { subSlicesLayers } = this.state;
-function deckMulti(slice, payload, setControlValue) {
- const subSlicesLayers = {};
- const fd = slice.formData;
- const render = () => {
- const viewport = {
- ...fd.viewport,
- width: slice.width(),
- height: slice.height(),
- };
const layers = Object.keys(subSlicesLayers).map(k => subSlicesLayers[k]);
- ReactDOM.render(
+
+ return (
<DeckGLContainer
mapboxApiAccessToken={payload.data.mapboxApiKey}
viewport={viewport}
layers={layers}
- mapStyle={fd.mapbox_style}
+ mapStyle={formData.mapbox_style}
setControlValue={setControlValue}
- />,
- document.getElementById(slice.containerId),
+ />
);
- };
- render();
- payload.data.slices.forEach((subslice) => {
- // Filters applied to multi_deck are passed down to underlying charts
- // note that dashboard contextual information (filter_immune_slices and
such) aren't
- // taken into consideration here
- const filters = [
- ...(subslice.form_data.filters || []),
- ...(fd.filters || []),
- ...(fd.extra_filters || []),
- ];
- const subsliceCopy = {
- ...subslice,
- form_data: {
- ...subslice.form_data,
- filters,
- },
- };
-
- const url = getExploreLongUrl(subsliceCopy.form_data, 'json');
- $.get(url, (data) => {
- const layer =
layerGenerators[subsliceCopy.form_data.viz_type](subsliceCopy.form_data, data);
- subSlicesLayers[subsliceCopy.slice_id] = layer;
- render();
- });
- });
+ }
}
-module.exports = deckMulti;
+
+DeckMulti.propTypes = propTypes;
+
+export default createAdaptor(DeckMulti);