diff --git a/.travis.yml b/.travis.yml index 914c4b63b4..806fc023fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ env: - TOX_ENV=py27-mysql - TOX_ENV=py27-sqlite before_install: - - npm install -g npm@'>=5.0.3' + - npm install -g npm@'>=5.4.1' before_script: - mysql -e 'drop database if exists superset; create database superset DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci' -u root - mysql -u root -e "CREATE USER 'mysqluser'@'localhost' IDENTIFIED BY 'mysqluserpassword';" diff --git a/superset/assets/javascripts/explore/components/ChartContainer.jsx b/superset/assets/javascripts/explore/components/ChartContainer.jsx index e8766d939c..1dc13455d8 100644 --- a/superset/assets/javascripts/explore/components/ChartContainer.jsx +++ b/superset/assets/javascripts/explore/components/ChartContainer.jsx @@ -178,8 +178,8 @@ class ChartContainer extends React.PureComponent { this.props.actions.renderTriggered(); const mockSlice = this.getMockedSliceObject(); this.setState({ mockSlice }); + const viz = visMap[this.props.viz_type]; try { - const viz = visMap[this.props.viz_type]; viz(mockSlice, this.props.queryResponse, this.props.actions.setControlValue); } catch (e) { this.props.actions.chartRenderingFailed(e); diff --git a/superset/assets/package.json b/superset/assets/package.json index fd78bdeaa8..8733abac0f 100644 --- a/superset/assets/package.json +++ b/superset/assets/package.json @@ -70,7 +70,7 @@ "react-dom": "^15.5.1", "react-gravatar": "^2.6.1", "react-grid-layout": "^0.14.4", - "react-map-gl": "^2.0.3", + "react-map-gl": "^3.0.4", "react-redux": "^5.0.2", "react-resizable": "^1.3.3", "react-select": "1.0.0-rc.3", diff --git a/superset/assets/visualizations/mapbox.jsx b/superset/assets/visualizations/mapbox.jsx index c01ad28a40..b5050f10ff 100644 --- a/superset/assets/visualizations/mapbox.jsx +++ b/superset/assets/visualizations/mapbox.jsx @@ -1,10 +1,10 @@ /* eslint-disable no-param-reassign */ +/* eslint-disable react/no-multi-comp */ import d3 from 'd3'; import React from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import MapGL from 'react-map-gl'; -import ScatterPlotOverlay from 'react-map-gl/dist/overlays/scatterplot.react'; import Immutable from 'immutable'; import supercluster from 'supercluster'; import ViewportMercator from 'viewport-mercator-project'; @@ -22,7 +22,14 @@ import './mapbox.css'; const NOOP = () => {}; -class ScatterPlotGlowOverlay extends ScatterPlotOverlay { +class ScatterPlotGlowOverlay extends React.Component { + componentDidMount() { + this.redraw(); + } + + componentDidUpdate() { + this.redraw(); + } drawText(ctx, pixel, options = {}) { const IS_DARK_THRESHOLD = 110; const { fontHeight = 0, label = '', radius = 0, rgb = [0, 0, 0], shadow = false } = options; @@ -52,7 +59,7 @@ class ScatterPlotGlowOverlay extends ScatterPlotOverlay { } // Modified: https://github.com/uber/react-map-gl/blob/master/src/overlays/scatterplot.react.js - _redraw() { + redraw() { const props = this.props; const pixelRatio = window.devicePixelRatio || 1; const canvas = this.refs.overlay; @@ -181,12 +188,60 @@ class ScatterPlotGlowOverlay extends ScatterPlotOverlay { ctx.restore(); } + render() { + let width = 0; + let height = 0; + if (this.context.viewport) { + width = this.context.viewport.width; + height = this.context.viewport.height; + } + const { globalOpacity } = this.props; + const pixelRatio = window.devicePixelRatio || 1; + return ( + React.createElement('canvas', { + ref: 'overlay', + width: width * pixelRatio, + height: height * pixelRatio, + style: { + width: `${width}px`, + height: `${height}px`, + position: 'absolute', + pointerEvents: 'none', + opacity: globalOpacity, + left: 0, + top: 0, + }, + }) + ); + } } +ScatterPlotGlowOverlay.propTypes = { + locations: PropTypes.instanceOf(Immutable.List).isRequired, + lngLatAccessor: PropTypes.func, + renderWhileDragging: PropTypes.bool, + globalOpacity: PropTypes.number, + dotRadius: PropTypes.number, + dotFill: PropTypes.string, + compositeOperation: PropTypes.string, +}; + +ScatterPlotGlowOverlay.defaultProps = { + lngLatAccessor: location => [location.get(0), location.get(1)], + renderWhileDragging: true, + dotRadius: 4, + dotFill: '#1FBAD6', + globalOpacity: 1, + // Same as browser default. + compositeOperation: 'source-over', +}; +ScatterPlotGlowOverlay.contextTypes = { + viewport: PropTypes.object, + isDragging: PropTypes.bool, +}; class MapboxViz extends React.Component { constructor(props) { super(props); - const longitude = this.props.viewportLongitude || DEFAULT_LONGITUDE; const latitude = this.props.viewportLatitude || DEFAULT_LATITUDE; @@ -198,11 +253,10 @@ class MapboxViz extends React.Component { startDragLngLat: [longitude, latitude], }, }; - - this.onChangeViewport = this.onChangeViewport.bind(this); + this.onViewportChange = this.onViewportChange.bind(this); } - onChangeViewport(viewport) { + onViewportChange(viewport) { this.setState({ viewport }); this.props.setControlValue('viewport_longitude', viewport.longitude); this.props.setControlValue('viewport_latitude', viewport.latitude); @@ -230,7 +284,7 @@ class MapboxViz extends React.Component { width={this.props.sliceWidth} height={this.props.sliceHeight} mapboxApiAccessToken={this.props.mapboxApiKey} - onChangeViewport={this.onChangeViewport} + onViewportChange={this.onViewportChange} >