diff --git a/dev/App.js b/dev/App.js
index 9a3cf8114..6aa816836 100644
--- a/dev/App.js
+++ b/dev/App.js
@@ -31,6 +31,18 @@ const dataSources = {
months: ['January', 'February', 'March', 'April', 'May', 'June'],
colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo'],
'blue and red': ['blue', 'red'],
+ countries: [
+ 'Angola',
+ 'Albania',
+ 'United Arab Emirates',
+ 'Argentina',
+ 'Armenia',
+ 'Australia',
+ 'Austria',
+ 'Azerbaijan',
+ ],
+ 'countries iso': ['AGO', 'ALB', 'ARE', 'ARG', 'ARM', 'AUS', 'AUT', 'AZE'],
+ states: ['AL', 'AK', 'AZ', 'AR', 'CA', 'CO', 'CT', 'DE', 'FL', 'GA'],
...tips,
};
const dataSourceOptions = Object.keys(dataSources).map(name => ({
diff --git a/src/components/fields/LocationSelector.js b/src/components/fields/LocationSelector.js
new file mode 100644
index 000000000..b932301b6
--- /dev/null
+++ b/src/components/fields/LocationSelector.js
@@ -0,0 +1,137 @@
+import React, {Fragment, Component} from 'react';
+import PropTypes from 'prop-types';
+import {connectToContainer} from 'lib';
+import Field from './Field';
+import Radio from './Radio';
+import {UnconnectedDropdown} from './Dropdown';
+import DataSelector from './DataSelector';
+
+const LocationmodeVisible = connectToContainer(UnconnectedDropdown, {
+ modifyPlotProps: (props, context, plotProps) => {
+ if (!plotProps.fullValue) {
+ plotProps.isVisible = true;
+ plotProps.fullValue = plotProps.container.locationmode;
+ return;
+ }
+ },
+});
+
+class UnconnectedLocation extends Component {
+ render() {
+ const {localize: _} = this.context;
+
+ return (
+
+
+
+
+ );
+ }
+}
+
+UnconnectedLocation.propTypes = {
+ attr: PropTypes.string,
+ ...Field.propTypes,
+};
+
+UnconnectedLocation.contextTypes = {
+ localize: PropTypes.func,
+ updateContainer: PropTypes.func,
+};
+
+const Location = connectToContainer(UnconnectedLocation);
+
+class UnconnectedLocationSelector extends Component {
+ constructor(props, context) {
+ super(props, context);
+
+ this.state = {
+ mode: props.container.locations ? 'location' : 'latlon',
+ };
+
+ this.setMode = this.setMode.bind(this);
+ }
+
+ componentWillMount() {
+ this.setState({
+ mode: this.props.container.locations ? 'location' : 'latlon',
+ });
+ }
+
+ setMode(mode) {
+ this.setState({mode: mode});
+ this.props.updateContainer(
+ mode === 'latlon'
+ ? {
+ locations: null,
+ locationmode: null,
+ locationssrc: null,
+ locationmodesrc: null,
+ }
+ : {lat: null, lon: null, latsrc: null, lonsrc: null}
+ );
+ }
+
+ render() {
+ const {mode} = this.state;
+ const {
+ localize: _,
+ container: {type: type},
+ } = this.context;
+
+ return type === 'scattergeo' ? (
+
+
+
+
+ {mode === 'latlon' ? (
+
+
+
+
+ ) : (
+
+ )}
+
+ ) : type === 'choropleth' ? (
+
+ ) : (
+ ''
+ );
+ }
+}
+
+UnconnectedLocationSelector.propTypes = {
+ fullValue: PropTypes.any,
+ updatePlot: PropTypes.func,
+ attr: PropTypes.string,
+ ...Field.propTypes,
+};
+
+UnconnectedLocationSelector.contextTypes = {
+ container: PropTypes.object,
+ localize: PropTypes.func,
+ updateContainer: PropTypes.func,
+};
+
+export default connectToContainer(UnconnectedLocationSelector);
diff --git a/src/components/fields/derived.js b/src/components/fields/derived.js
index 78dd465d8..9fda4242c 100644
--- a/src/components/fields/derived.js
+++ b/src/components/fields/derived.js
@@ -528,11 +528,14 @@ export const HoverInfo = connectToContainer(UnconnectedFlaglist, {
}
if (container.type === 'scattergeo') {
- options = [
- {label: _('Longitude'), value: 'loc'},
- {label: _('Latitude'), value: 'lat'},
- {label: _('Location'), value: 'location'},
- ];
+ if (container.locations) {
+ options = [{label: _('Location'), value: 'location'}];
+ } else if (container.lat || container.lon) {
+ options = [
+ {label: _('Longitude'), value: 'lon'},
+ {label: _('Latitude'), value: 'lat'},
+ ];
+ }
}
if (container.type === 'scattermapbox') {
diff --git a/src/components/fields/index.js b/src/components/fields/index.js
index b85d34abb..7d38e3ce4 100644
--- a/src/components/fields/index.js
+++ b/src/components/fields/index.js
@@ -26,6 +26,7 @@ import MarkerColor from './MarkerColor';
import VisibilitySelect from './VisibilitySelect';
import MultiColorPicker from './MultiColorPicker';
import RectanglePositioner from './RectanglePositioner';
+import LocationSelector from './LocationSelector';
import {
AnnotationArrowRef,
AnnotationRef,
@@ -102,4 +103,5 @@ export {
MultiColorPicker,
VisibilitySelect,
RectanglePositioner,
+ LocationSelector,
};
diff --git a/src/components/index.js b/src/components/index.js
index be590da84..dc5f23660 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -49,6 +49,7 @@ import {
MultiColorPicker,
VisibilitySelect,
RectanglePositioner,
+ LocationSelector,
} from './fields';
import {
@@ -155,4 +156,5 @@ export {
MultiColorPicker,
VisibilitySelect,
RectanglePositioner,
+ LocationSelector,
};
diff --git a/src/default_panels/GraphCreatePanel.js b/src/default_panels/GraphCreatePanel.js
index c0fcb5e0b..77cfcb546 100644
--- a/src/default_panels/GraphCreatePanel.js
+++ b/src/default_panels/GraphCreatePanel.js
@@ -11,6 +11,7 @@ import {
TraceSelector,
Numeric,
TraceTypeSection,
+ LocationSelector,
} from '../components';
import {
HistogramInfoVertical,
@@ -22,11 +23,10 @@ const GraphCreatePanel = (props, {localize: _}) => {
-
-
+
+
-
{
-