Added DeckGL.Polygon Layer w/ JS controls (#4227)

* Working polygon layer for deckGL

* add js controls

* add thumbnail

* better description

* refactor to leverage line_column controls

* templates: open code and documentation on a new tab (#4217)

As they are external resources.

* Fix tutorial doesn't match the current interface #4138 (#4215)

* [bugfix] markup and iframe viz raise 'Empty query' (#4225)

closes https://github.com/apache/incubator-superset/issues/4222

Related to: https://github.com/apache/incubator-superset/pull/4016

* [bugfix] time_pivot entry got missing in merge conflict (#4221)

PR here https://github.com/apache/incubator-superset/pull/3518 missed a
line of code while merging conflicts with time_pivot viz

* Improve deck.gl GeoJSON visualization (#4220)

* Improve geoJSON

* Addressing comments

* lint

* refactor to leverage line_column controls

* refactor to use DeckPathViz

* oops
This commit is contained in:
Hugh A. Miles II 2018-01-18 13:28:46 -08:00 committed by Maxime Beauchemin
parent cab8e7d22d
commit 5079b2aa95
9 changed files with 124 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 KiB

View File

@ -571,6 +571,16 @@ export const controls = {
}),
},
polygon: {
type: 'SelectControl',
label: t('Polygon Column'),
validators: [v.nonEmpty],
description: t('Select the polygon column. Each row should contain JSON.array(N) of [longitude, latitude] points'),
mapStateToProps: state => ({
choices: (state.datasource) ? state.datasource.all_cols : [],
}),
},
point_radius_scale: {
type: 'SelectControl',
freeForm: true,

View File

@ -517,6 +517,46 @@ export const visTypes = {
],
},
deck_polygon: {
label: t('Deck.gl - Polygon'),
requiresTime: true,
controlPanelSections: [
{
label: t('Query'),
expanded: true,
controlSetRows: [
['line_column', 'line_type'],
['row_limit', null],
],
},
{
label: t('Map'),
controlSetRows: [
['mapbox_style', 'viewport'],
['reverse_long_lat', null],
],
},
{
label: t('Polygon Settings'),
controlSetRows: [
['fill_color_picker', 'stroke_color_picker'],
['filled', 'stroked'],
['extruded', null],
['point_radius_scale', null],
],
},
{
label: t('Advanced'),
controlSetRows: [
['js_columns'],
['js_datapoint_mutator'],
['js_tooltip'],
['js_onclick_href'],
],
},
],
},
deck_arc: {
label: t('Deck.gl - Arc'),
requiresTime: true,

View File

@ -6,6 +6,7 @@ import deck_hex from './hex';
import deck_scatter from './scatter';
import deck_geojson from './geojson';
import deck_arc from './arc';
import deck_polygon from './polygon';
const layerGenerators = {
deck_grid,
@ -15,5 +16,6 @@ const layerGenerators = {
deck_scatter,
deck_geojson,
deck_arc,
deck_polygon,
};
export default layerGenerators;

View File

@ -0,0 +1,28 @@
import { PolygonLayer } from 'deck.gl';
import * as common from './common';
import sandboxedEval from '../../../javascripts/modules/sandbox';
export default function polygonLayer(formData, payload, slice) {
const fd = formData;
const fc = fd.fill_color_picker;
let data = payload.data.features.map(d => ({
...d,
fillColor: [fc.r, fc.g, fc.b, 255 * fc.a],
}));
if (fd.js_datapoint_mutator) {
// Applying user defined data mutator if defined
const jsFnMutator = sandboxedEval(fd.js_datapoint_mutator);
data = data.map(jsFnMutator);
}
return new PolygonLayer({
id: `path-layer-${fd.slice_id}`,
data,
filled: fd.filled,
stroked: fd.stoked,
extruded: fd.extruded,
...common.commonLayerProps(fd, slice),
});
}

View File

@ -48,6 +48,7 @@ export const VIZ_TYPES = {
deck_geojson: 'deck_geojson',
deck_multi: 'deck_multi',
deck_arc: 'deck_arc',
deck_polygon: 'deck_polygon',
};
const vizMap = {
@ -95,6 +96,7 @@ const vizMap = {
[VIZ_TYPES.deck_path]: deckglFactory,
[VIZ_TYPES.deck_geojson]: deckglFactory,
[VIZ_TYPES.deck_arc]: deckglFactory,
[VIZ_TYPES.deck_polygon]: deckglFactory,
[VIZ_TYPES.deck_multi]: require('./deckgl/multi.jsx'),
};
export default vizMap;

View File

@ -1552,6 +1552,36 @@ def load_paris_iris_geojson():
tbl.fetch_metadata()
def load_sf_population_polygons():
tbl_name = 'sf_population_polygons'
with gzip.open(os.path.join(DATA_FOLDER, 'sf_population.json.gz')) as f:
df = pd.read_json(f)
df['contour'] = df.contour.map(json.dumps)
df.to_sql(
tbl_name,
db.engine,
if_exists='replace',
chunksize=500,
dtype={
'zipcode': BigInteger,
'population': BigInteger,
'contour': Text,
'area': BigInteger,
},
index=False)
print("Creating table {} reference".format(tbl_name))
tbl = db.session.query(TBL).filter_by(table_name=tbl_name).first()
if not tbl:
tbl = TBL(table_name=tbl_name)
tbl.description = "Population density of San Francisco"
tbl.database = get_or_create_main_db()
db.session.merge(tbl)
db.session.commit()
tbl.fetch_metadata()
def load_bart_lines():
tbl_name = 'bart_lines'
with gzip.open(os.path.join(DATA_FOLDER, 'bart-lines.json.gz')) as f:

Binary file not shown.

View File

@ -1899,6 +1899,7 @@ class BaseDeckGLViz(BaseViz):
if extra_props:
feature['extraProps'] = extra_props
features.append(feature)
return {
'features': features,
'mapboxApiKey': config.get('MAPBOX_API_KEY'),
@ -1982,6 +1983,7 @@ class DeckPathViz(BaseDeckGLViz):
viz_type = 'deck_path'
verbose_name = _('Deck.gl - Paths')
deck_viz_key = 'path'
deser_map = {
'json': json.loads,
'polyline': polyline.decode,
@ -2003,10 +2005,19 @@ class DeckPathViz(BaseDeckGLViz):
if fd.get('reverse_long_lat'):
path = (path[1], path[0])
return {
'path': path,
self.deck_viz_key: path,
}
class DeckPolygon(DeckPathViz):
"""deck.gl's Polygon Layer"""
viz_type = 'deck_polygon'
deck_viz_key = 'polygon'
verbose_name = _('Deck.gl - Polygon')
class DeckHex(BaseDeckGLViz):
"""deck.gl's DeckLayer"""