You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@superset.apache.org by GitBox <gi...@apache.org> on 2018/02/20 22:41:39 UTC

[GitHub] mistercrunch closed pull request #4444: A collection of geospatial bug fixes

mistercrunch closed pull request #4444: A collection of geospatial bug fixes
URL: https://github.com/apache/incubator-superset/pull/4444
 
 
   

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/setup.py b/setup.py
index 393af3b5b8..2c14b90a45 100644
--- a/setup.py
+++ b/setup.py
@@ -58,6 +58,7 @@ def get_git_sha():
         'flask-wtf==0.14.2',
         'flower==0.9.2',
         'future>=0.16.0, <0.17',
+        'geopy==1.11.0',
         'python-geohash==0.8.5',
         'humanize==0.5.1',
         'gunicorn==19.7.1',
diff --git a/superset/assets/javascripts/explore/components/controls/SpatialControl.jsx b/superset/assets/javascripts/explore/components/controls/SpatialControl.jsx
index f72306f552..d9db801c4b 100644
--- a/superset/assets/javascripts/explore/components/controls/SpatialControl.jsx
+++ b/superset/assets/javascripts/explore/components/controls/SpatialControl.jsx
@@ -1,7 +1,7 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import {
-  Row, Col, Button, FormControl, Label, OverlayTrigger, Popover,
+  Row, Col, Button, Label, OverlayTrigger, Popover,
 } from 'react-bootstrap';
 import 'react-datetime/css/react-datetime.css';
 
@@ -49,7 +49,6 @@ export default class SpatialControl extends React.Component {
       value: null,
       errors: [],
     };
-    this.onDelimiterChange = this.onDelimiterChange.bind(this);
     this.toggleCheckbox = this.toggleCheckbox.bind(this);
     this.onChange = this.onChange.bind(this);
   }
@@ -83,9 +82,6 @@ export default class SpatialControl extends React.Component {
     this.setState({ value, errors });
     this.props.onChange(value, errors);
   }
-  onDelimiterChange(event) {
-    this.setState({ delimiter: event.target.value }, this.onChange);
-  }
   setType(type) {
     this.setState({ type }, this.onChange);
   }
@@ -129,7 +125,7 @@ export default class SpatialControl extends React.Component {
       <Popover id="filter-popover">
         <div style={{ width: '300px' }}>
           <PopoverSection
-            title="Longitude & Latitude columns"
+            title={t('Longitude & Latitude columns')}
             isSelected={this.state.type === spatialTypes.latlong}
             onSelect={this.setType.bind(this, spatialTypes.latlong)}
           >
@@ -145,7 +141,10 @@ export default class SpatialControl extends React.Component {
             </Row>
           </PopoverSection>
           <PopoverSection
-            title="Delimited long & lat single column"
+            title={t('Delimited long & lat single column')}
+            info={t(
+              'Multiple formats accepted, look the geopy.points ' +
+              'Python library for more details')}
             isSelected={this.state.type === spatialTypes.delimited}
             onSelect={this.setType.bind(this, spatialTypes.delimited)}
           >
@@ -155,23 +154,13 @@ export default class SpatialControl extends React.Component {
                 {this.renderSelect('lonlatCol', spatialTypes.delimited)}
               </Col>
               <Col md={6}>
-                Delimiter
-                <FormControl
-                  onFocus={this.setType.bind(this, spatialTypes.delimited)}
-                  value={this.state.delimiter}
-                  onChange={this.onDelimiterChange}
-                  placeholder="delimiter"
-                  bsSize="small"
-                />
+                {t('Reverse lat/long ')}
+                <Checkbox checked={this.state.reverseCheckbox} onChange={this.toggleCheckbox} />
               </Col>
             </Row>
-            <div>
-              {t('Reverse lat/long ')}
-              <Checkbox checked={this.state.reverseCheckbox} onChange={this.toggleCheckbox} />
-            </div>
           </PopoverSection>
           <PopoverSection
-            title="Geohash"
+            title={t('Geohash')}
             isSelected={this.state.type === spatialTypes.geohash}
             onSelect={this.setType.bind(this, spatialTypes.geohash)}
           >
diff --git a/superset/assets/javascripts/explore/stores/controls.jsx b/superset/assets/javascripts/explore/stores/controls.jsx
index ea0feaa378..529e51c5a2 100644
--- a/superset/assets/javascripts/explore/stores/controls.jsx
+++ b/superset/assets/javascripts/explore/stores/controls.jsx
@@ -908,6 +908,7 @@ export const controls = {
     type: 'TextControl',
     label: t('Multiplier'),
     isFloat: true,
+    renderTrigger: true,
     default: 1,
     description: t('Factor to multiply the metric by'),
   },
diff --git a/superset/assets/visualizations/deckgl/AnimatableDeckGLContainer.jsx b/superset/assets/visualizations/deckgl/AnimatableDeckGLContainer.jsx
index 8d9e03e3fa..0343421bde 100644
--- a/superset/assets/visualizations/deckgl/AnimatableDeckGLContainer.jsx
+++ b/superset/assets/visualizations/deckgl/AnimatableDeckGLContainer.jsx
@@ -16,6 +16,7 @@ const propTypes = {
 
 const defaultProps = {
   disabled: false,
+  step: 1,
 };
 
 export default class AnimatableDeckGLContainer extends React.Component {
diff --git a/superset/assets/visualizations/deckgl/layers/common.js b/superset/assets/visualizations/deckgl/layers/common.js
index 4692401cf8..7a2cb9785d 100644
--- a/superset/assets/visualizations/deckgl/layers/common.js
+++ b/superset/assets/visualizations/deckgl/layers/common.js
@@ -13,16 +13,22 @@ export function getBounds(points) {
 }
 
 export function fitViewport(viewport, points, padding = 10) {
-  const bounds = getBounds(points);
-  return {
-    ...viewport,
-    ...fitBounds({
-      height: viewport.height,
-      width: viewport.width,
-      padding,
-      bounds,
-    }),
-  };
+  try {
+    const bounds = getBounds(points);
+    return {
+      ...viewport,
+      ...fitBounds({
+        height: viewport.height,
+        width: viewport.width,
+        padding,
+        bounds,
+      }),
+    };
+  } catch (e) {
+    /* eslint no-console: 0 */
+    console.error('Could not auto zoom', e);
+    return viewport;
+  }
 }
 
 export function commonLayerProps(formData, slice) {
diff --git a/superset/viz.py b/superset/viz.py
index 94daaa85af..c1a8d9aa0d 100644
--- a/superset/viz.py
+++ b/superset/viz.py
@@ -23,6 +23,7 @@
 from flask import escape, request
 from flask_babel import lazy_gettext as _
 import geohash
+from geopy.point import Point
 from markdown import markdown
 import numpy as np
 import pandas as pd
@@ -290,8 +291,10 @@ def get_payload(self, query_obj=None):
         df = payload.get('df')
         if df is not None and len(df.index) == 0:
             raise Exception('No data')
-        payload['data'] = self.get_data(df)
-        del payload['df']
+        if self.status != utils.QueryStatus.FAILED:
+            payload['data'] = self.get_data(df)
+        if 'df' in payload:
+            del payload['df']
         return payload
 
     def get_df_payload(self, query_obj=None):
@@ -1819,6 +1822,8 @@ def query_obj(self):
         return d
 
     def get_data(self, df):
+        if df is None:
+            return None
         fd = self.form_data
         label_col = fd.get('mapbox_label')
         custom_metric = label_col and len(label_col) >= 1
@@ -1932,9 +1937,18 @@ def process_spatial_data_obj(self, key, df):
         if spatial is None:
             raise ValueError(_('Bad spatial key'))
         if spatial.get('type') == 'latlong':
-            df[key] = list(zip(df[spatial.get('lonCol')], df[spatial.get('latCol')]))
+            df[key] = list(zip(
+                pd.to_numeric(df[spatial.get('lonCol')], errors='coerce'),
+                pd.to_numeric(df[spatial.get('latCol')], errors='coerce'),
+            ))
         elif spatial.get('type') == 'delimited':
-            df[key] = (df[spatial.get('lonlatCol')].str.split(spatial.get('delimiter')))
+
+            def tupleify(s):
+                p = Point(s)
+                return (p.latitude, p.longitude)
+
+            df[key] = df[spatial.get('lonlatCol')].apply(tupleify)
+
             if spatial.get('reverseCheckbox'):
                 df[key] = [
                     tuple(reversed(o)) if isinstance(o, (list, tuple)) else (0, 0)
@@ -1946,7 +1960,6 @@ def process_spatial_data_obj(self, key, df):
             df[key] = list(zip(latlong.apply(lambda x: x[0]),
                                latlong.apply(lambda x: x[1])))
             del df[spatial.get('geohashCol')]
-
         return df
 
     def query_obj(self):
@@ -1976,6 +1989,8 @@ def get_js_columns(self, d):
         return {col: d.get(col) for col in cols}
 
     def get_data(self, df):
+        if df is None:
+            return None
         for key in self.spatial_control_keys:
             df = self.process_spatial_data_obj(key, df)
 


 

----------------------------------------------------------------
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:
users@infra.apache.org


With regards,
Apache Git Services