superset-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From maximebeauche...@apache.org
Subject [incubator-superset] branch master updated: Fix adhoc metrics in Polygon (#6399)
Date Sat, 17 Nov 2018 01:06:26 GMT
This is an automated email from the ASF dual-hosted git repository.

maximebeauchemin 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 4c94447  Fix adhoc metrics in Polygon (#6399)
4c94447 is described below

commit 4c94447635114e3270f6198232216edca7f1fa70
Author: Maxime Beauchemin <maximebeauchemin@gmail.com>
AuthorDate: Fri Nov 16 17:06:21 2018 -0800

    Fix adhoc metrics in Polygon (#6399)
    
    * Fix adhoc metrics in Polygon
    
    * Addressing comments
---
 .../visualizations/deckgl/utils_spec.js            | 18 +++----
 superset/assets/src/chart/Chart.jsx                | 56 +++++++++++-----------
 .../deckgl/layers/Polygon/Polygon.jsx              | 12 +++--
 .../src/visualizations/deckgl/layers/common.jsx    |  5 +-
 superset/assets/src/visualizations/deckgl/utils.js | 32 ++++++-------
 5 files changed, 64 insertions(+), 59 deletions(-)

diff --git a/superset/assets/spec/javascripts/visualizations/deckgl/utils_spec.js b/superset/assets/spec/javascripts/visualizations/deckgl/utils_spec.js
index 16ed41e..be4a44b 100644
--- a/superset/assets/spec/javascripts/visualizations/deckgl/utils_spec.js
+++ b/superset/assets/spec/javascripts/visualizations/deckgl/utils_spec.js
@@ -4,6 +4,8 @@ import {
   getBuckets,
 } from '../../../../src/visualizations/deckgl/utils';
 
+const metricAccessor = d => d.count;
+
 describe('getBreakPoints', () => {
   it('is a function', () => {
     expect(typeof getBreakPoints).toBe('function');
@@ -11,7 +13,7 @@ describe('getBreakPoints', () => {
 
   it('returns sorted break points', () => {
     const fd = { break_points: ['0', '10', '100', '50', '1000'] };
-    const result = getBreakPoints(fd, []);
+    const result = getBreakPoints(fd, [], metricAccessor);
     const expected = ['0', '10', '50', '100', '1000'];
     expect(result).toEqual(expected);
   });
@@ -19,7 +21,7 @@ describe('getBreakPoints', () => {
   it('returns evenly distributed break points when no break points are specified', () =>
{
     const fd = { metric: 'count' };
     const features = [0, 1, 2, 10].map(count => ({ count }));
-    const result = getBreakPoints(fd, features);
+    const result = getBreakPoints(fd, features, metricAccessor);
     const expected = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
     expect(result).toEqual(expected);
   });
@@ -27,7 +29,7 @@ describe('getBreakPoints', () => {
   it('formats number with proper precision', () => {
     const fd = { metric: 'count', num_buckets: 2 };
     const features = [0, 1 / 3, 2 / 3, 1].map(count => ({ count }));
-    const result = getBreakPoints(fd, features);
+    const result = getBreakPoints(fd, features, metricAccessor);
     const expected = ['0.0', '0.5', '1.0'];
     expect(result).toEqual(expected);
   });
@@ -35,7 +37,7 @@ describe('getBreakPoints', () => {
   it('works with a zero range', () => {
     const fd = { metric: 'count', num_buckets: 1 };
     const features = [1, 1, 1].map(count => ({ count }));
-    const result = getBreakPoints(fd, features);
+    const result = getBreakPoints(fd, features, metricAccessor);
     const expected = ['1', '1'];
     expect(result).toEqual(expected);
   });
@@ -53,7 +55,7 @@ describe('getBreakPointColorScaler', () => {
       opacity: 100,
     };
     const features = [10, 20, 30].map(count => ({ count }));
-    const scaler = getBreakPointColorScaler(fd, features);
+    const scaler = getBreakPointColorScaler(fd, features, metricAccessor);
     expect(scaler({ count: 10 })).toEqual([0, 0, 0, 255]);
     expect(scaler({ count: 15 })).toEqual([64, 64, 64, 255]);
     expect(scaler({ count: 30 })).toEqual([255, 255, 255, 255]);
@@ -67,7 +69,7 @@ describe('getBreakPointColorScaler', () => {
       opacity: 100,
     };
     const features = [];
-    const scaler = getBreakPointColorScaler(fd, features);
+    const scaler = getBreakPointColorScaler(fd, features, metricAccessor);
     expect(scaler({ count: 0 })).toEqual([0, 0, 0, 255]);
     expect(scaler({ count: 0.5 })).toEqual([0, 0, 0, 255]);
     expect(scaler({ count: 1 })).toEqual([255, 255, 255, 255]);
@@ -82,7 +84,7 @@ describe('getBreakPointColorScaler', () => {
       opacity: 100,
     };
     const features = [];
-    const scaler = getBreakPointColorScaler(fd, features);
+    const scaler = getBreakPointColorScaler(fd, features, metricAccessor);
     expect(scaler({ count: -1 })).toEqual([0, 0, 0, 0]);
     expect(scaler({ count: 11 })).toEqual([255, 255, 255, 0]);
   });
@@ -101,7 +103,7 @@ describe('getBuckets', () => {
       opacity: 100,
     };
     const features = [];
-    const result = getBuckets(fd, features);
+    const result = getBuckets(fd, features, metricAccessor);
     const expected = {
       '0 - 1': { color: [0, 0, 0, 255], enabled: true },
       '1 - 10': { color: [255, 255, 255, 255], enabled: true },
diff --git a/superset/assets/src/chart/Chart.jsx b/superset/assets/src/chart/Chart.jsx
index 67ae006..2a35fbe 100644
--- a/superset/assets/src/chart/Chart.jsx
+++ b/superset/assets/src/chart/Chart.jsx
@@ -126,8 +126,7 @@ class Chart extends React.PureComponent {
 
   renderTooltip() {
     const { tooltip } = this.state;
-
-    if (tooltip) {
+    if (tooltip && tooltip.content) {
       return (
         <Tooltip
           className="chart-tooltip"
@@ -173,32 +172,31 @@ class Chart extends React.PureComponent {
     this.renderStartTime = Logger.getTimestamp();
 
     return (
-      <div
-        className={`chart-container ${isLoading ? 'is-loading' : ''}`}
-        style={containerStyles}
-      >
-        {this.renderTooltip()}
-
-        {['loading', 'success'].indexOf(chartStatus) >= 0 && <Loading size={50}
/>}
-
-        {chartAlert && (
-          <StackTraceMessage
-            message={chartAlert}
-            link={queryResponse ? queryResponse.link : null}
-            stackTrace={chartStackTrace}
-          />
-        )}
-
-        {!isLoading && !chartAlert && isFaded && (
-          <RefreshChartOverlay
-            width={width}
-            height={height}
-            onQuery={onQuery}
-            onDismiss={onDismissRefreshOverlay}
-          />
-        )}
+      <ErrorBoundary onError={this.handleRenderFailure} showMessage={false}>
+        <div
+          className={`chart-container ${isLoading ? 'is-loading' : ''}`}
+          style={containerStyles}
+        >
+          {this.renderTooltip()}
 
-        <ErrorBoundary onError={this.handleRenderFailure} showMessage={false}>
+          {['loading', 'success'].indexOf(chartStatus) >= 0 && <Loading size={50}
/>}
+
+          {chartAlert && (
+            <StackTraceMessage
+              message={chartAlert}
+              link={queryResponse ? queryResponse.link : null}
+              stackTrace={chartStackTrace}
+            />
+          )}
+
+          {!isLoading && !chartAlert && isFaded && (
+            <RefreshChartOverlay
+              width={width}
+              height={height}
+              onQuery={onQuery}
+              onDismiss={onDismissRefreshOverlay}
+            />
+          )}
           <SuperChart
             className={`slice_container ${snakeCase(vizType)} ${isFaded ? ' faded' : ''}`}
             chartType={vizType}
@@ -207,8 +205,8 @@ class Chart extends React.PureComponent {
             onRenderFailure={this.handleRenderFailure}
             skipRendering={skipChartRendering}
           />
-        </ErrorBoundary>
-      </div>
+        </div>
+      </ErrorBoundary>
     );
   }
 }
diff --git a/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx b/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
index a245023..21de46e 100644
--- a/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/Polygon/Polygon.jsx
@@ -48,10 +48,12 @@ export function getLayer(formData, payload, setTooltip, selected, onSelect,
filt
     data = jsFnMutator(data);
   }
 
+  const metricLabel = fd.metric ? fd.metric.label || fd.metric : null;
+  const accessor = d => d[metricLabel];
   // base color for the polygons
   const baseColorScaler = fd.metric === null
     ? () => [fc.r, fc.g, fc.b, 255 * fc.a]
-    : getBreakPointColorScaler(fd, data);
+    : getBreakPointColorScaler(fd, data, accessor);
 
   // when polygons are selected, reduce the opacity of non-selected polygons
   const colorScaler = (d) => {
@@ -61,7 +63,6 @@ export function getLayer(formData, payload, setTooltip, selected, onSelect,
filt
     }
     return baseColor;
   };
-
   return new PolygonLayer({
     id: `path-layer-${fd.slice_id}`,
     data,
@@ -211,7 +212,12 @@ class DeckGLPolygon extends React.Component {
   render() {
     const { payload, formData, setControlValue } = this.props;
     const { start, end, getStep, values, disabled, viewport } = this.state;
-    const buckets = getBuckets(formData, payload.data.features);
+
+    const fd = formData;
+    const metricLabel = fd.metric ? fd.metric.label || fd.metric : null;
+    const accessor = d => d[metricLabel];
+
+    const buckets = getBuckets(formData, payload.data.features, accessor);
     return (
       <div style={{ position: 'relative' }}>
         <AnimatableDeckGLContainer
diff --git a/superset/assets/src/visualizations/deckgl/layers/common.jsx b/superset/assets/src/visualizations/deckgl/layers/common.jsx
index 36b05ce..02ec70f 100644
--- a/superset/assets/src/visualizations/deckgl/layers/common.jsx
+++ b/superset/assets/src/visualizations/deckgl/layers/common.jsx
@@ -38,12 +38,13 @@ export function commonLayerProps(formData, setTooltip, onSelect) {
   let tooltipContentGenerator;
   if (fd.js_tooltip) {
     tooltipContentGenerator = sandboxedEval(fd.js_tooltip);
-  } else if (fd.line_column && fd.line_type === 'geohash') {
+  } else if (fd.line_column && fd.metric && ['geohash', 'zipcode'].indexOf(fd.line_type)
>= 0) {
+    const metricLabel = fd.metric.label || fd.metric;
     tooltipContentGenerator = o => (
       <div>
         <div>{fd.line_column}: <strong>{o.object[fd.line_column]}</strong></div>
         {fd.metric &&
-          <div>{fd.metric}: <strong>{o.object[fd.metric]}</strong></div>}
+          <div>{metricLabel}: <strong>{o.object[metricLabel]}</strong></div>}
       </div>);
   }
   if (tooltipContentGenerator) {
diff --git a/superset/assets/src/visualizations/deckgl/utils.js b/superset/assets/src/visualizations/deckgl/utils.js
index 533ec58..b692f6f 100644
--- a/superset/assets/src/visualizations/deckgl/utils.js
+++ b/superset/assets/src/visualizations/deckgl/utils.js
@@ -3,20 +3,19 @@ import { scaleThreshold } from 'd3-scale';
 import { getSequentialSchemeRegistry, SequentialScheme } from '@superset-ui/color';
 import { hexToRGB } from '../../modules/colors';
 
+const DEFAULT_NUM_BUCKETS = 10;
+
 export function getBreakPoints({
     break_points: formDataBreakPoints,
     num_buckets: formDataNumBuckets,
-    metric,
-  }, features) {
+  }, features, accessor) {
   if (!features) {
     return [];
   }
   if (formDataBreakPoints === undefined || formDataBreakPoints.length === 0) {
     // compute evenly distributed break points based on number of buckets
-    const numBuckets = formDataNumBuckets
-      ? parseInt(formDataNumBuckets, 10)
-      : 10;
-    const [minValue, maxValue] = extent(features, d => d[metric]);
+    const numBuckets = formDataNumBuckets ? parseInt(formDataNumBuckets, 10) : DEFAULT_NUM_BUCKETS;
+    const [minValue, maxValue] = extent(features, accessor);
     const delta = (maxValue - minValue) / numBuckets;
     const precision = delta === 0
       ? 0
@@ -32,15 +31,13 @@ export function getBreakPointColorScaler({
     break_points: formDataBreakPoints,
     num_buckets: formDataNumBuckets,
     linear_color_scheme: linearColorScheme,
-    metric,
     opacity,
-  }, features) {
+  }, features, accessor) {
   const breakPoints = formDataBreakPoints || formDataNumBuckets
     ? getBreakPoints({
       break_points: formDataBreakPoints,
       num_buckets: formDataNumBuckets,
-      metric,
-    }, features)
+    }, features, accessor)
     : null;
   const colorScheme = Array.isArray(linearColorScheme)
     ? new SequentialScheme({
@@ -69,13 +66,14 @@ export function getBreakPointColorScaler({
     maskPoint = value => value > breakPoints[n] || value < breakPoints[0];
   } else {
     // interpolate colors linearly
-    scaler = colorScheme.createLinearScale(extent(features, d => d[metric]));
+    scaler = colorScheme.createLinearScale(extent(features, accessor));
     maskPoint = () => false;
   }
 
   return (d) => {
-    const c = hexToRGB(scaler(d[metric]));
-    if (maskPoint(d[metric])) {
+    const v = accessor(d);
+    const c = hexToRGB(scaler(v));
+    if (maskPoint(v)) {
       c[3] = 0;
     } else {
       c[3] = (opacity / 100.0) * 255;
@@ -84,15 +82,15 @@ export function getBreakPointColorScaler({
   };
 }
 
-export function getBuckets(fd, features) {
-  const breakPoints = getBreakPoints(fd, features, true);
-  const colorScaler = getBreakPointColorScaler(fd, features);
+export function getBuckets(fd, features, accessor) {
+  const breakPoints = getBreakPoints(fd, features, accessor);
+  const colorScaler = getBreakPointColorScaler(fd, features, accessor);
   const buckets = {};
   breakPoints.slice(1).forEach((value, i) => {
     const range = breakPoints[i] + ' - ' + breakPoints[i + 1];
     const mid = 0.5 * (parseInt(breakPoints[i], 10) + parseInt(breakPoints[i + 1], 10));
     buckets[range] = {
-      color: colorScaler({ [fd.metric]: mid }),
+      color: colorScaler({ [fd.metric.label || fd.metric]: mid }),
       enabled: true,
     };
   });


Mime
View raw message