You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by cc...@apache.org on 2018/11/09 19:43:00 UTC
[incubator-superset] branch master updated: [reviewable] Organize
d3 utilities usage (#6287)
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 3ffb48c [reviewable] Organize d3 utilities usage (#6287)
3ffb48c is described below
commit 3ffb48c4921b989eb8075089da9996d060278b91
Author: Krist Wongsuphasawat <kr...@gmail.com>
AuthorDate: Fri Nov 9 11:42:54 2018 -0800
[reviewable] Organize d3 utilities usage (#6287)
* update package.json
* extract changes from another PR
* add d3 prefix
* two more places
* update lockfile
---
superset/assets/package.json | 4 ++
superset/assets/src/modules/geo.js | 14 +++++++
superset/assets/src/modules/utils.js | 44 ++++++++++++----------
superset/assets/src/utils/common.js | 11 ------
.../src/visualizations/BigNumber/transformProps.js | 4 +-
.../src/visualizations/Horizon/HorizonChart.jsx | 4 +-
.../src/visualizations/Horizon/HorizonRow.jsx | 7 ++--
.../MapBox/ScatterPlotGlowOverlay.jsx | 25 ++++++------
superset/assets/src/visualizations/Table/Table.js | 7 ++--
.../src/visualizations/TimeTable/TimeTable.jsx | 6 +--
superset/assets/yarn.lock | 8 ++--
11 files changed, 72 insertions(+), 62 deletions(-)
diff --git a/superset/assets/package.json b/superset/assets/package.json
index 8c15bfa..b5ce7d8 100644
--- a/superset/assets/package.json
+++ b/superset/assets/package.json
@@ -66,9 +66,13 @@
"d3-array": "^1.2.4",
"d3-cloud": "^1.2.1",
"d3-color": "^1.2.0",
+ "d3-format": "^1.3.2",
"d3-hierarchy": "^1.1.5",
"d3-sankey": "^0.4.2",
+ "d3-scale": "^2.1.2",
+ "d3-selection": "^1.3.2",
"d3-svg-legend": "^1.x",
+ "d3-time-format": "^2.1.3",
"d3-tip": "^0.9.1",
"datamaps": "^0.5.8",
"datatables.net-bs": "^1.10.15",
diff --git a/superset/assets/src/modules/geo.js b/superset/assets/src/modules/geo.js
index e689a41..2fc2744 100644
--- a/superset/assets/src/modules/geo.js
+++ b/superset/assets/src/modules/geo.js
@@ -1,3 +1,5 @@
+import { round as d3Round } from 'd3-format';
+
export const defaultViewport = {
longitude: 6.85236157047845,
latitude: 31.222656842808707,
@@ -7,6 +9,7 @@ export const defaultViewport = {
};
const METER_TO_MILE = 1609.34;
+
export function unitToRadius(unit, num) {
if (unit === 'square_m') {
return Math.sqrt(num / Math.PI);
@@ -23,3 +26,14 @@ export function unitToRadius(unit, num) {
}
return null;
}
+
+export const EARTH_CIRCUMFERENCE_KM = 40075.16;
+export const MILES_PER_KM = 1.60934;
+
+export function kmToPixels(kilometers, latitude, zoomLevel) {
+ // Algorithm from: http://wiki.openstreetmap.org/wiki/Zoom_levels
+ const latitudeRad = latitude * (Math.PI / 180);
+ // Seems like the zoomLevel is off by one
+ const kmPerPixel = (EARTH_CIRCUMFERENCE_KM * Math.cos(latitudeRad)) / Math.pow(2, zoomLevel + 9);
+ return d3Round(kilometers / kmPerPixel, 2);
+}
diff --git a/superset/assets/src/modules/utils.js b/superset/assets/src/modules/utils.js
index bc22c5a..1bd82e2 100644
--- a/superset/assets/src/modules/utils.js
+++ b/superset/assets/src/modules/utils.js
@@ -1,9 +1,11 @@
/* eslint camelcase: 0 */
import $ from 'jquery';
-import d3 from 'd3';
+import { format as d3Format } from 'd3-format';
+import { d3Select } from 'd3-selection';
+import { timeFormat as d3TimeFormat } from 'd3-time-format';
import { formatDate, UTC } from './dates';
-const siFormatter = d3.format('.3s');
+const siFormatter = d3Format('.3s');
export function defaultNumberFormatter(n) {
let si = siFormatter(n);
@@ -15,27 +17,43 @@ export function defaultNumberFormatter(n) {
}
export function d3FormatPreset(format) {
- // like d3.format, but with support for presets like 'smart_date'
+ // like d3Format, but with support for presets like 'smart_date'
if (format === 'smart_date') {
return formatDate;
}
if (format) {
- return d3.format(format);
+ return d3Format(format);
}
return defaultNumberFormatter;
}
+
export const d3TimeFormatPreset = function (format) {
const effFormat = format || 'smart_date';
if (effFormat === 'smart_date') {
return formatDate;
}
- const f = d3.time.format(effFormat);
+ const f = d3TimeFormat(effFormat);
return function (dttm) {
const d = UTC(new Date(dttm));
return f(d);
};
};
+const formatters = {};
+
+export function d3format(format, number) {
+ format = format || '.3s';
+ // Formats a number and memoizes formatters to be reused
+ if (!(format in formatters)) {
+ formatters[format] = d3Format(format);
+ }
+ try {
+ return formatters[format](number);
+ } catch (e) {
+ return 'ERR';
+ }
+}
+
/*
Utility function that takes a d3 svg:text selection and a max width, and splits the
text's text across multiple tspan lines such that any given line does not exceed max width
@@ -47,7 +65,7 @@ export function wrapSvgText(text, width, adjustedY) {
const lineHeight = 1;
// ems
text.each(function () {
- const d3Text = d3.select(this);
+ const d3Text = d3Select(this);
const words = d3Text.text().split(/\s+/);
let word;
let line = [];
@@ -118,20 +136,6 @@ export const fixDataTableBodyHeight = function ($tableDom, height) {
$tableDom.find('.dataTables_scrollBody').css('max-height', height - headHeight - controlsHeight - paginationHeight);
};
-export function d3format(format, number) {
- const formatters = {};
- // Formats a number and memoizes formatters to be reused
- format = format || '.3s';
- if (!(format in formatters)) {
- formatters[format] = d3.format(format);
- }
- try {
- return formatters[format](number);
- } catch (e) {
- return 'ERR';
- }
-}
-
export function formatSelectOptionsForRange(start, end) {
// outputs array of arrays
// formatSelectOptionsForRange(1, 5)
diff --git a/superset/assets/src/utils/common.js b/superset/assets/src/utils/common.js
index 282518f..e044df1 100644
--- a/superset/assets/src/utils/common.js
+++ b/superset/assets/src/utils/common.js
@@ -1,24 +1,13 @@
-import d3 from 'd3';
import { SupersetClient } from '@superset-ui/connection';
import getClientErrorObject from './getClientErrorObject';
-export const EARTH_CIRCUMFERENCE_KM = 40075.16;
export const LUMINANCE_RED_WEIGHT = 0.2126;
export const LUMINANCE_GREEN_WEIGHT = 0.7152;
export const LUMINANCE_BLUE_WEIGHT = 0.0722;
-export const MILES_PER_KM = 1.60934;
// Regexp for the label added to time shifted series (1 hour offset, 2 days offset, etc.)
export const TIME_SHIFT_PATTERN = /\d+ \w+ offset/;
-export function kmToPixels(kilometers, latitude, zoomLevel) {
- // Algorithm from: http://wiki.openstreetmap.org/wiki/Zoom_levels
- const latitudeRad = latitude * (Math.PI / 180);
- // Seems like the zoomLevel is off by one
- const kmPerPixel = (EARTH_CIRCUMFERENCE_KM * Math.cos(latitudeRad)) / Math.pow(2, zoomLevel + 9);
- return d3.round(kilometers / kmPerPixel, 2);
-}
-
export function rgbLuminance(r, g, b) {
// Formula: https://en.wikipedia.org/wiki/Relative_luminance
return LUMINANCE_RED_WEIGHT * r + LUMINANCE_GREEN_WEIGHT * g + LUMINANCE_BLUE_WEIGHT * b;
diff --git a/superset/assets/src/visualizations/BigNumber/transformProps.js b/superset/assets/src/visualizations/BigNumber/transformProps.js
index 41a9df5..a046da3 100644
--- a/superset/assets/src/visualizations/BigNumber/transformProps.js
+++ b/superset/assets/src/visualizations/BigNumber/transformProps.js
@@ -1,5 +1,5 @@
import * as color from 'd3-color';
-import d3 from 'd3';
+import { format as d3Format } from 'd3-format';
import { d3FormatPreset } from '../../modules/utils';
import { renderTooltipFactory } from './BigNumber';
@@ -43,7 +43,7 @@ export default function transformProps(chartProps) {
const compareValue = sortedData[compareIndex][metricName];
percentChange = compareValue === 0
? 0 : (bigNumber - compareValue) / Math.abs(compareValue);
- const formatPercentChange = d3.format('+.1%');
+ const formatPercentChange = d3Format('+.1%');
formattedSubheader = `${formatPercentChange(percentChange)} ${compareSuffix}`;
}
}
diff --git a/superset/assets/src/visualizations/Horizon/HorizonChart.jsx b/superset/assets/src/visualizations/Horizon/HorizonChart.jsx
index f9bb05a..655e89c 100644
--- a/superset/assets/src/visualizations/Horizon/HorizonChart.jsx
+++ b/superset/assets/src/visualizations/Horizon/HorizonChart.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import d3 from 'd3';
+import { extent as d3Extent } from 'd3-array';
import HorizonRow, { DEFAULT_COLORS } from './HorizonRow';
import './HorizonChart.css';
@@ -52,7 +52,7 @@ class HorizonChart extends React.PureComponent {
(acc, current) => acc.concat(current.values),
[],
);
- yDomain = d3.extent(allValues, d => d.y);
+ yDomain = d3Extent(allValues, d => d.y);
}
return (
diff --git a/superset/assets/src/visualizations/Horizon/HorizonRow.jsx b/superset/assets/src/visualizations/Horizon/HorizonRow.jsx
index fd96ad5..df69657 100644
--- a/superset/assets/src/visualizations/Horizon/HorizonRow.jsx
+++ b/superset/assets/src/visualizations/Horizon/HorizonRow.jsx
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
-import d3 from 'd3';
+import { extent as d3Extent } from 'd3-array';
+import { scaleLinear } from 'd3-scale';
export const DEFAULT_COLORS = [
'#313695',
@@ -91,8 +92,8 @@ class HorizonRow extends React.PureComponent {
}
// Create y-scale
- const [min, max] = yDomain || d3.extent(data, d => d.y);
- const y = d3.scale.linear()
+ const [min, max] = yDomain || d3Extent(data, d => d.y);
+ const y = scaleLinear()
.domain([0, Math.max(-min, max)])
.range([0, height]);
diff --git a/superset/assets/src/visualizations/MapBox/ScatterPlotGlowOverlay.jsx b/superset/assets/src/visualizations/MapBox/ScatterPlotGlowOverlay.jsx
index e67302a..5a6ba27 100644
--- a/superset/assets/src/visualizations/MapBox/ScatterPlotGlowOverlay.jsx
+++ b/superset/assets/src/visualizations/MapBox/ScatterPlotGlowOverlay.jsx
@@ -1,13 +1,10 @@
-import d3 from 'd3';
import Immutable from 'immutable';
import React from 'react';
import PropTypes from 'prop-types';
import ViewportMercator from 'viewport-mercator-project';
-import {
- kmToPixels,
- rgbLuminance,
- MILES_PER_KM,
-} from '../../utils/common';
+import { round as d3Round } from 'd3-format';
+import { kmToPixels, MILES_PER_KM } from '../../modules/geo';
+import { rgbLuminance } from '../../utils/common';
const propTypes = {
aggregation: PropTypes.string,
@@ -131,7 +128,7 @@ class ScatterPlotGlowOverlay extends React.Component {
if ((props.renderWhileDragging || !props.isDragging) && props.locations) {
props.locations.forEach(function _forEach(location, i) {
const pixel = mercator.project(props.lngLatAccessor(location));
- const pixelRounded = [d3.round(pixel[0], 1), d3.round(pixel[1], 1)];
+ const pixelRounded = [d3Round(pixel[0], 1), d3Round(pixel[1], 1)];
if (pixelRounded[0] + radius >= 0
&& pixelRounded[0] - radius < props.width
@@ -140,8 +137,8 @@ class ScatterPlotGlowOverlay extends React.Component {
ctx.beginPath();
if (location.get('properties').get('cluster')) {
let clusterLabel = clusterLabelMap[i];
- const scaledRadius = d3.round(Math.pow(clusterLabel / maxLabel, 0.5) * radius, 1);
- const fontHeight = d3.round(scaledRadius * 0.5, 1);
+ const scaledRadius = d3Round(Math.pow(clusterLabel / maxLabel, 0.5) * radius, 1);
+ const fontHeight = d3Round(scaledRadius * 0.5, 1);
const gradient = ctx.createRadialGradient(
pixelRounded[0], pixelRounded[1], scaledRadius,
pixelRounded[0], pixelRounded[1], 0,
@@ -177,17 +174,17 @@ class ScatterPlotGlowOverlay extends React.Component {
if (radiusProperty !== null) {
const pointLatitude = props.lngLatAccessor(location)[1];
if (props.pointRadiusUnit === 'Kilometers') {
- pointLabel = d3.round(pointRadius, 2) + 'km';
+ pointLabel = d3Round(pointRadius, 2) + 'km';
pointRadius = kmToPixels(pointRadius, pointLatitude, props.zoom);
} else if (props.pointRadiusUnit === 'Miles') {
- pointLabel = d3.round(pointRadius, 2) + 'mi';
+ pointLabel = d3Round(pointRadius, 2) + 'mi';
pointRadius = kmToPixels(pointRadius * MILES_PER_KM, pointLatitude, props.zoom);
}
}
if (pointMetric !== null) {
pointLabel = Number.isFinite(parseFloat(pointMetric))
- ? d3.round(pointMetric, 2)
+ ? d3Round(pointMetric, 2)
: pointMetric;
}
@@ -196,13 +193,13 @@ class ScatterPlotGlowOverlay extends React.Component {
pointRadius = defaultRadius;
}
- ctx.arc(pixelRounded[0], pixelRounded[1], d3.round(pointRadius, 1), 0, Math.PI * 2);
+ ctx.arc(pixelRounded[0], pixelRounded[1], d3Round(pointRadius, 1), 0, Math.PI * 2);
ctx.fillStyle = 'rgb(' + rgb[1] + ', ' + rgb[2] + ', ' + rgb[3] + ')';
ctx.fill();
if (pointLabel !== undefined) {
this.drawText(ctx, pixelRounded, {
- fontHeight: d3.round(pointRadius, 1),
+ fontHeight: d3Round(pointRadius, 1),
label: pointLabel,
radius: pointRadius,
rgb,
diff --git a/superset/assets/src/visualizations/Table/Table.js b/superset/assets/src/visualizations/Table/Table.js
index 070a96c..7056235 100644
--- a/superset/assets/src/visualizations/Table/Table.js
+++ b/superset/assets/src/visualizations/Table/Table.js
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import dt from 'datatables.net-bs';
import 'datatables.net-bs/css/dataTables.bootstrap.css';
import dompurify from 'dompurify';
+import { format as d3Format } from 'd3-format';
import { fixDataTableBodyHeight, d3TimeFormatPreset } from '../../modules/utils';
import './Table.css';
@@ -45,8 +46,8 @@ const propTypes = {
]),
};
-const formatValue = d3.format('0,000');
-const formatPercent = d3.format('.3p');
+const formatValue = d3Format(',.0d');
+const formatPercent = d3Format('.3p');
function NOOP() {}
function TableVis(element, props) {
@@ -129,7 +130,7 @@ function TableVis(element, props) {
html = `<span class="like-pre">${dompurify.sanitize(val)}</span>`;
}
if (isMetric) {
- html = d3.format(format || '0.3s')(val);
+ html = d3Format(format || '0.3s')(val);
}
if (key[0] === '%') {
html = formatPercent(val);
diff --git a/superset/assets/src/visualizations/TimeTable/TimeTable.jsx b/superset/assets/src/visualizations/TimeTable/TimeTable.jsx
index 0eaafc7..38bf058 100644
--- a/superset/assets/src/visualizations/TimeTable/TimeTable.jsx
+++ b/superset/assets/src/visualizations/TimeTable/TimeTable.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
-import d3 from 'd3';
import Mustache from 'mustache';
+import { scaleLinear } from 'd3-scale';
import { Table, Thead, Th, Tr, Td } from 'reactable';
import MetricOption from '../../components/MetricOption';
@@ -19,7 +19,7 @@ function colorFromBounds(value, bounds, colorBounds = ACCESSIBLE_COLOR_BOUNDS) {
const [min, max] = bounds;
const [minColor, maxColor] = colorBounds;
if (min !== null && max !== null) {
- const colorScale = d3.scale.linear()
+ const colorScale = scaleLinear()
.domain([min, (max + min) / 2, max])
.range([minColor, 'grey', maxColor]);
return colorScale(value);
@@ -131,7 +131,7 @@ class TimeTable extends React.PureComponent {
showYAxis={column.showYAxis}
renderTooltip={({ index }) => (
<div>
- <strong>{d3format(column.d3Format, sparkData[index])}</strong>
+ <strong>{d3format(column.d3format, sparkData[index])}</strong>
<div>{formatDate(entries[index].time)}</div>
</div>
)}
diff --git a/superset/assets/yarn.lock b/superset/assets/yarn.lock
index b1ab09e..cffbb36 100644
--- a/superset/assets/yarn.lock
+++ b/superset/assets/yarn.lock
@@ -3943,7 +3943,7 @@ d3-ease@1:
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.5.tgz#8ce59276d81241b1b72042d6af2d40e76d936ffb"
integrity sha512-Ct1O//ly5y5lFM9YTdu+ygq7LleSgSE4oj7vUt9tPLHUi8VCV7QoizGpdWRWAwCO9LdYzIrQDg97+hGVdsSGPQ==
-d3-format@1, d3-format@^1.2.0:
+d3-format@1, d3-format@^1.2.0, d3-format@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.3.2.tgz#6a96b5e31bcb98122a30863f7d92365c00603562"
integrity sha512-Z18Dprj96ExragQ0DeGi+SYPQ7pPfRMtUXtsg/ChVIKNBCzjO8XYJvRTC1usblx52lqge56V5ect+frYTQc8WQ==
@@ -4009,7 +4009,7 @@ d3-scale@^1.0.5, d3-scale@^1.0.6:
d3-time "1"
d3-time-format "2"
-d3-scale@^2.0.0:
+d3-scale@^2.0.0, d3-scale@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-2.1.2.tgz#4e932b7b60182aee9073ede8764c98423e5f9a94"
integrity sha512-bESpd64ylaKzCDzvULcmHKZTlzA/6DGSVwx7QSDj/EnX9cpSevsdiwdHFYI9ouo9tNBbV3v5xztHS2uFeOzh8Q==
@@ -4021,7 +4021,7 @@ d3-scale@^2.0.0:
d3-time "1"
d3-time-format "2"
-d3-selection@1, d3-selection@^1.1.0, d3-selection@^1.3.0:
+d3-selection@1, d3-selection@^1.1.0, d3-selection@^1.3.0, d3-selection@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.3.2.tgz#6e70a9df60801c8af28ac24d10072d82cbfdf652"
integrity sha512-OoXdv1nZ7h2aKMVg3kaUFbLLK5jXUFAMLD/Tu5JA96mjf8f2a9ZUESGY+C36t8R1WFeWk/e55hy54Ml2I62CRQ==
@@ -4038,7 +4038,7 @@ d3-svg-legend@^1.x:
resolved "https://registry.yarnpkg.com/d3-svg-legend/-/d3-svg-legend-1.13.0.tgz#6217478c9add9d62cb333617e1961311a41a4db3"
integrity sha1-YhdHjJrdnWLLMzYX4ZYTEaQaTbM=
-d3-time-format@2:
+d3-time-format@2, d3-time-format@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.1.3.tgz#ae06f8e0126a9d60d6364eac5b1533ae1bac826b"
integrity sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA==