hughhhh closed pull request #4068: [geo] Add Deckgl GeoJson layer
URL: https://github.com/apache/incubator-superset/pull/4068
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/superset/assets/images/viz_thumbnails/deck_geojson.png 
b/superset/assets/images/viz_thumbnails/deck_geojson.png
new file mode 100644
index 0000000000..40d1b63f3b
Binary files /dev/null and 
b/superset/assets/images/viz_thumbnails/deck_geojson.png differ
diff --git a/superset/assets/javascripts/explore/stores/controls.jsx 
b/superset/assets/javascripts/explore/stores/controls.jsx
index 7117712d21..4519b76bb2 100644
--- a/superset/assets/javascripts/explore/stores/controls.jsx
+++ b/superset/assets/javascripts/explore/stores/controls.jsx
@@ -143,6 +143,22 @@ export const controls = {
     renderTrigger: true,
   },
 
+  fill_color_picker: {
+    label: t('Fill Color'),
+    description: t('Use to set fill color of geojson'),
+    type: 'ColorPickerControl',
+    default: colorPrimary,
+    renderTrigger: true,
+  },
+
+  stroke_color_picker: {
+    label: t('Stroke Color'),
+    description: t('Use to set stroke color of geojson'),
+    type: 'ColorPickerControl',
+    default: colorPrimary,
+    renderTrigger: true,
+  },
+
   metric: {
     type: 'SelectControl',
     label: t('Metric'),
@@ -496,6 +512,25 @@ export const controls = {
     }),
   },
 
+  geojson: {
+    type: 'SelectControl',
+    label: t('GeoJson Column'),
+    validators: [v.nonEmpty],
+    description: t('Select the geojson column'),
+    mapStateToProps: state => ({
+      choices: (state.datasource) ? state.datasource.all_cols : [],
+    }),
+  },
+
+  point_radius_scale: {
+    type: 'SelectControl',
+    freeForm: true,
+    label: t('Point Radius Scale'),
+    validators: [v.integer],
+    default: null,
+    choices: formatSelectOptions([0,100,200,300,500]),
+  },
+
   all_columns_x: {
     type: 'SelectControl',
     label: 'X',
diff --git a/superset/assets/javascripts/explore/stores/visTypes.js 
b/superset/assets/javascripts/explore/stores/visTypes.js
index 2c5f2a61e1..e3342331c2 100644
--- a/superset/assets/javascripts/explore/stores/visTypes.js
+++ b/superset/assets/javascripts/explore/stores/visTypes.js
@@ -455,6 +455,35 @@ export const visTypes = {
     },
   },
 
+  deck_geojson: {
+    label: t('Deck.gl - geoJson'),
+    requiresTime: true,
+    controlPanelSections: [
+      {
+        label: t('Query'),
+        expanded: true,
+        controlSetRows: [
+          ['geojson'],
+          ['row_limit'],
+        ],
+      },
+      {
+        label: t('Map'),
+        controlSetRows: [
+          ['mapbox_style', 'viewport'],
+        ],
+      },
+      {
+        label: t('GeoJson Settings'),
+        controlSetRows: [
+          ['fill_color_picker', null],
+          ['stroke_color_picker', null],
+          ['point_radius_scale', null],
+        ],
+      },
+    ],
+  },
+
   deck_scatter: {
     label: t('Deck.gl - Scatter plot'),
     requiresTime: true,
diff --git a/superset/assets/visualizations/deckgl/geojson.jsx 
b/superset/assets/visualizations/deckgl/geojson.jsx
new file mode 100644
index 0000000000..855d25a2ae
--- /dev/null
+++ b/superset/assets/visualizations/deckgl/geojson.jsx
@@ -0,0 +1,58 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { GeoJsonLayer } from 'deck.gl';
+
+import DeckGLContainer from './DeckGLContainer';
+
+const propertyMap = {
+  color: 'fillColor',
+  fill: 'fillColor',
+  'fill-color': 'fillColor',
+  'stroke-color': 'strokeColor',
+  'stroke-width': 'strokeWidth',
+}
+
+const convertGeoJsonProps = (p) => {
+  const obj = {}
+  Object.entries(p).forEach(
+    ([key, value]) => { obj[(propertyMap[key]) ? propertyMap[key] : key] = 
value }
+  );
+  return obj
+}
+
+function DeckGeoJsonLayer(slice, payload, setControlValue) {
+  const fd = slice.formData;
+  const fillColor = fd.fill_color_picker;
+  const strokeColor = fd.stroke_color_picker;
+  const pointRadiusScale = fd.point_radius_scale;
+  const data = payload.data.geojson.features.map(d => ({
+    ...d,
+    properties: convertGeoJsonProps(d.properties),
+  }));
+
+  const layer = new GeoJsonLayer({
+    id: 'geojson-layer',
+    data,
+    filled: true,
+    stroked: false,
+    extruded: true,
+    pointRadiusScale: pointRadiusScale,
+  });
+
+  const viewport = {
+    ...fd.viewport,
+    width: slice.width(),
+    height: slice.height(),
+  };
+  ReactDOM.render(
+    <DeckGLContainer
+      mapboxApiAccessToken={payload.data.mapboxApiKey}
+      viewport={viewport}
+      layers={[layer]}
+      mapStyle={fd.mapbox_style}
+      setControlValue={setControlValue}
+    />,
+    document.getElementById(slice.containerId),
+  );
+}
+module.exports = DeckGeoJsonLayer;
diff --git a/superset/assets/visualizations/main.js 
b/superset/assets/visualizations/main.js
index 06d30a1bb1..be65024c0a 100644
--- a/superset/assets/visualizations/main.js
+++ b/superset/assets/visualizations/main.js
@@ -42,51 +42,7 @@ export const VIZ_TYPES = {
   deck_screengrid: 'deck_screengrid',
   deck_grid: 'deck_grid',
   deck_hex: 'deck_hex',
+  deck_geojson: 'deck_geojson',
   deck_path: 'deck_path',
 };
 
-const vizMap = {
-  [VIZ_TYPES.area]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.bar]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.big_number]: require('./big_number.js'),
-  [VIZ_TYPES.big_number_total]: require('./big_number.js'),
-  [VIZ_TYPES.box_plot]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.bubble]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.bullet]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.cal_heatmap]: require('./cal_heatmap.js'),
-  [VIZ_TYPES.compare]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.directed_force]: require('./directed_force.js'),
-  [VIZ_TYPES.chord]: require('./chord.jsx'),
-  [VIZ_TYPES.dist_bar]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.filter_box]: require('./filter_box.jsx'),
-  [VIZ_TYPES.heatmap]: require('./heatmap.js'),
-  [VIZ_TYPES.histogram]: require('./histogram.js'),
-  [VIZ_TYPES.horizon]: require('./horizon.js'),
-  [VIZ_TYPES.iframe]: require('./iframe.js'),
-  [VIZ_TYPES.line]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.time_pivot]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.mapbox]: require('./mapbox.jsx'),
-  [VIZ_TYPES.markup]: require('./markup.js'),
-  [VIZ_TYPES.para]: require('./parallel_coordinates.js'),
-  [VIZ_TYPES.pie]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.pivot_table]: require('./pivot_table.js'),
-  [VIZ_TYPES.sankey]: require('./sankey.js'),
-  [VIZ_TYPES.separator]: require('./markup.js'),
-  [VIZ_TYPES.sunburst]: require('./sunburst.js'),
-  [VIZ_TYPES.table]: require('./table.js'),
-  [VIZ_TYPES.time_table]: require('./time_table.jsx'),
-  [VIZ_TYPES.treemap]: require('./treemap.js'),
-  [VIZ_TYPES.country_map]: require('./country_map.js'),
-  [VIZ_TYPES.word_cloud]: require('./word_cloud.js'),
-  [VIZ_TYPES.world_map]: require('./world_map.js'),
-  [VIZ_TYPES.dual_line]: require('./nvd3_vis.js'),
-  [VIZ_TYPES.event_flow]: require('./EventFlow.jsx'),
-  [VIZ_TYPES.paired_ttest]: require('./paired_ttest.jsx'),
-  [VIZ_TYPES.partition]: require('./partition.js'),
-  [VIZ_TYPES.deck_scatter]: require('./deckgl/scatter.jsx'),
-  [VIZ_TYPES.deck_screengrid]: require('./deckgl/screengrid.jsx'),
-  [VIZ_TYPES.deck_grid]: require('./deckgl/grid.jsx'),
-  [VIZ_TYPES.deck_hex]: require('./deckgl/hex.jsx'),
-  [VIZ_TYPES.deck_path]: require('./deckgl/path.jsx'),
-};
-export default vizMap;
diff --git a/superset/cli.py b/superset/cli.py
index 56ead72b41..14a592bed1 100755
--- a/superset/cli.py
+++ b/superset/cli.py
@@ -139,6 +139,9 @@ def load_examples(load_test_data):
     print('Loading DECK.gl demo')
     data.load_deck_dash()
 
+    print('Loading Paris geojson data')
+    data.load_paris_iris_geojson()
+
     if load_test_data:
         print('Loading [Unicode test data]')
         data.load_unicode_test_data()
diff --git a/superset/data/__init__.py b/superset/data/__init__.py
index b3cb4a8ea9..b41eae2fe5 100644
--- a/superset/data/__init__.py
+++ b/superset/data/__init__.py
@@ -1522,6 +1522,37 @@ def load_flights():
     obj.fetch_metadata()
 
 
+def load_paris_iris_geojson():
+    tbl_name = 'paris_iris_mapping'
+
+    with gzip.open(os.path.join(DATA_FOLDER, 'paris_iris.json.gz')) as f:
+        df = pd.read_json(f)
+        df['features'] = df.features.map(json.dumps)
+
+
+    df.to_sql(
+        tbl_name,
+        db.engine,
+        if_exists='replace',
+        chunksize=500,
+        dtype={
+            'color': String(255),
+            'name': String(255),
+            'features': Text,
+            'type': Text,
+        },
+        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 = "Map of Paris"
+    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:
@@ -1550,3 +1581,6 @@ def load_bart_lines():
     db.session.merge(tbl)
     db.session.commit()
     tbl.fetch_metadata()
+
+
+
diff --git a/superset/data/paris_iris.json.gz b/superset/data/paris_iris.json.gz
new file mode 100644
index 0000000000..4a964c94f7
Binary files /dev/null and b/superset/data/paris_iris.json.gz differ
diff --git a/superset/viz.py b/superset/viz.py
index 55f26034db..2a6b4940c9 100644
--- a/superset/viz.py
+++ b/superset/viz.py
@@ -1942,6 +1942,33 @@ class DeckHex(BaseDeckGLViz):
     verbose_name = _('Deck.gl - 3D HEX')
 
 
+class DeckGeoJson(BaseDeckGLViz):
+
+    """deck.gl's GeoJSONLayer"""
+
+    viz_type = 'deck_geojson'
+    verbose_name = _('Deck.gl - GeoJSON')
+
+    def query_obj(self):
+        d = super(DeckGeoJson, self).query_obj()
+        d['columns'] = [self.form_data.get('geojson')]
+        d['metrics'] = []
+        d['groupby'] = []
+        return d
+
+    def get_data(self, df):
+        fd = self.form_data
+        geojson = {
+            'type': 'FeatureCollection',
+            'features': [json.loads(item) for item in df[fd.get('geojson')]],
+        }
+
+        return {
+            'geojson': geojson,
+            'mapboxApiKey': config.get('MAPBOX_API_KEY'),
+        }
+
+
 class EventFlowViz(BaseViz):
 
     """A visualization to explore patterns in event sequences"""


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to