diff --git a/README.md b/README.md
index aed29b950..1d07f74af 100644
--- a/README.md
+++ b/README.md
@@ -148,6 +148,7 @@ Simple component that takes in props and renders.
* ``: `` whose children are replicated into `` connected to traces via `connectTraceToPlot()`.
* ``: `` whose children are connected to the `layout` figure key
* ``: `` renders `` if no trace data is set
+* ``: `` renders `` if no axis in `_fullLayout._subplots`
* ``: `` whose children are replicated into `` connected to annotations via `connectAnnotationToLayout()`. For use in a ``.
* ``: `` whose children are replicated into `` connected to shapes via `connectShapeToLayout()`. For use in a ``.
* ``: `` whose children are replicated into `` connected to images via `connectImageToLayout()`. For use in a ``.
diff --git a/src/components/containers/AxisRequiredPanel.js b/src/components/containers/AxisRequiredPanel.js
new file mode 100644
index 000000000..e5a8a8ac3
--- /dev/null
+++ b/src/components/containers/AxisRequiredPanel.js
@@ -0,0 +1,51 @@
+import React, {Component} from 'react';
+import PropTypes from 'prop-types';
+import PanelEmpty from './PanelEmpty';
+import Panel from './Panel';
+
+class AxisRequiredPanel extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ hasAxis: true,
+ };
+ }
+
+ checkAxisExistence() {
+ const hasSubplot =
+ Object.keys(this.context.fullContainer._subplots).filter(
+ type =>
+ !['cartesian', 'mapbox'].includes(type) &&
+ this.context.fullContainer._subplots[type].length > 0
+ ).length > 0;
+ if (!hasSubplot) {
+ this.setState({hasAxis: false});
+ }
+ }
+
+ componentWillReceiveProps() {
+ this.checkAxisExistence();
+ }
+
+ componentDidMount() {
+ this.checkAxisExistence();
+ }
+
+ render() {
+ if (this.state.hasAxis) {
+ return {this.props.children};
+ }
+ return ;
+ }
+}
+
+AxisRequiredPanel.propTypes = {
+ children: PropTypes.node,
+ emptyPanelHeader: PropTypes.string,
+};
+
+AxisRequiredPanel.contextTypes = {
+ fullContainer: PropTypes.object,
+};
+
+export default AxisRequiredPanel;
diff --git a/src/components/containers/PanelEmpty.js b/src/components/containers/PanelEmpty.js
index 403fadad6..30e78f5c8 100644
--- a/src/components/containers/PanelEmpty.js
+++ b/src/components/containers/PanelEmpty.js
@@ -1,17 +1,13 @@
import PropTypes from 'prop-types';
import React, {Component} from 'react';
import {ChartLineIcon} from 'plotly-icons';
-import {bem, localize} from 'lib';
+import {bem} from 'lib';
class PanelEmpty extends Component {
render() {
- const {
- children,
- localize: _,
- heading = _("Looks like there aren't any traces defined yet."),
- message = _("Go to the 'Create' tab to define traces."),
- icon: Icon,
- } = this.props;
+ const {children, icon: Icon} = this.props;
+ const heading = this.props.heading || '';
+ const message = this.props.message || '';
return (
@@ -38,4 +34,4 @@ PanelEmpty.propTypes = {
icon: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
};
-export default localize(PanelEmpty);
+export default PanelEmpty;
diff --git a/src/components/containers/TraceRequiredPanel.js b/src/components/containers/TraceRequiredPanel.js
index 31bfc0893..140b8fd69 100644
--- a/src/components/containers/TraceRequiredPanel.js
+++ b/src/components/containers/TraceRequiredPanel.js
@@ -1,7 +1,8 @@
-import React, {Component} from 'react';
-import PropTypes from 'prop-types';
import PanelEmpty from './PanelEmpty';
+import PropTypes from 'prop-types';
+import React, {Component} from 'react';
import {LayoutPanel} from './derived';
+import {localize} from 'lib';
class TraceRequiredPanel extends Component {
constructor(props) {
@@ -36,14 +37,17 @@ class TraceRequiredPanel extends Component {
}
render() {
- const {children, ...rest} = this.props;
+ const {localize: _, children, ...rest} = this.props;
const {hasTraces} = this.state;
if (this.props.visible) {
return hasTraces ? (
{children}
) : (
-
+
);
}
return null;
@@ -52,6 +56,7 @@ class TraceRequiredPanel extends Component {
TraceRequiredPanel.propTypes = {
children: PropTypes.node,
+ localize: PropTypes.func,
visible: PropTypes.bool,
};
@@ -63,4 +68,4 @@ TraceRequiredPanel.contextTypes = {
fullData: PropTypes.array,
};
-export default TraceRequiredPanel;
+export default localize(TraceRequiredPanel);
diff --git a/src/components/containers/index.js b/src/components/containers/index.js
index 5c8937f1e..8a7c373ed 100644
--- a/src/components/containers/index.js
+++ b/src/components/containers/index.js
@@ -2,6 +2,7 @@ import AnnotationAccordion from './AnnotationAccordion';
import ShapeAccordion from './ShapeAccordion';
import ImageAccordion from './ImageAccordion';
import AxesFold from './AxesFold';
+import AxisRequiredPanel from './AxisRequiredPanel';
import Fold from './Fold';
import MenuPanel from './MenuPanel';
import Panel from './Panel';
@@ -14,6 +15,7 @@ import SingleSidebarItem from './SingleSidebarItem';
export {
AnnotationAccordion,
+ AxisRequiredPanel,
ShapeAccordion,
ImageAccordion,
MenuPanel,
diff --git a/src/components/index.js b/src/components/index.js
index f118eac30..1d004da59 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -36,6 +36,7 @@ import {
ShapeAccordion,
ImageAccordion,
AxesFold,
+ AxisRequiredPanel,
Fold,
LayoutPanel,
MenuPanel,
@@ -63,6 +64,7 @@ export {
AxesFold,
AxesRange,
AxesSelector,
+ AxisRequiredPanel,
Button,
CanvasSize,
ColorPicker,
diff --git a/src/default_panels/StyleAxesPanel.js b/src/default_panels/StyleAxesPanel.js
index f8fdaac71..785d28478 100644
--- a/src/default_panels/StyleAxesPanel.js
+++ b/src/default_panels/StyleAxesPanel.js
@@ -11,321 +11,335 @@ import {
MenuPanel,
Section,
TraceRequiredPanel,
+ AxisRequiredPanel,
AxesFold,
Fold,
+ TraceTypeSection,
} from '../components';
import {localize} from '../lib';
const StyleAxesPanel = ({localize: _}) => (
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
);
diff --git a/src/lib/__tests__/multiValued-test.js b/src/lib/__tests__/multiValued-test.js
index d0ed601eb..55ac08230 100644
--- a/src/lib/__tests__/multiValued-test.js
+++ b/src/lib/__tests__/multiValued-test.js
@@ -7,7 +7,7 @@ import {connectLayoutToPlot, connectAxesToLayout} from '..';
import {mount} from 'enzyme';
describe('multiValued Numeric', () => {
- it('uses placeholder and empty string value', () => {
+ it.only('uses placeholder and empty string value', () => {
const fixtureProps = fixtures.scatter({
layout: {xaxis: {range: [0, 1]}, yaxis: {range: [-1, 1]}},
});
diff --git a/src/lib/connectAxesToLayout.js b/src/lib/connectAxesToLayout.js
index a002535d8..3b17d4b25 100644
--- a/src/lib/connectAxesToLayout.js
+++ b/src/lib/connectAxesToLayout.js
@@ -2,16 +2,14 @@ import React, {Component} from 'react';
import PropTypes from 'prop-types';
import nestedProperty from 'plotly.js/src/lib/nested_property';
import {deepCopyPublic, setMultiValuedContainer} from './multiValues';
-import {getDisplayName, localize} from '../lib';
+import {getDisplayName, localize, capitalize} from '../lib';
function computeAxesOptions(axes, _) {
const options = [{label: _('All'), value: 'allaxes'}];
for (let i = 0; i < axes.length; i++) {
const ax = axes[i];
- const axesPrefix = ax._id.length > 1 ? ' ' + ax._id.substr(1) : '';
- const label = `${ax._id.charAt(0).toUpperCase()}${axesPrefix}`;
- const value =
- (axesPrefix.length > 0 ? axesPrefix + '.' : '').trim() + ax._name;
+ const label = capitalize(ax._name.split('axis')[0]);
+ const value = (ax.prefix ? ax.prefix + '.' : '').trim() + ax._name;
options[i + 1] = {label, value};
}
@@ -35,18 +33,41 @@ export default function connectAxesToLayout(WrappedComponent) {
this.setLocals(nextProps, nextState, nextContext);
}
- // This function should be optimized. We can compare a list of
- // axesNames to nextAxesNames and check gd.layout[axesN] for shallow
- // equality. Unfortunately we are currently mutating gd.layout so the
- // shallow check is not possible.
setLocals(nextProps, nextState, nextContext) {
- const {plotly, graphDiv, container, fullContainer} = nextContext;
+ const {container, fullContainer} = nextContext;
const {axesTarget} = nextState;
- if (plotly) {
- this.axes = plotly.Axes.list(graphDiv);
- } else {
- this.axes = [];
- }
+
+ this.axes = [];
+
+ // Plotly.js should really have a helper function for this, but until it does..
+ Object.keys(fullContainer._subplots)
+ .filter(
+ // cartesian types will have xaxis or yaxis directly in _fullLayout
+ type =>
+ type !== 'cartesian' && fullContainer._subplots[type].length !== 0
+ )
+ .forEach(type => {
+ if (['xaxis', 'yaxis'].includes(type)) {
+ this.axes.push(fullContainer[type]);
+ }
+ if (!['xaxis', 'yaxis', 'cartesian'].includes(type)) {
+ this.axes = Object.keys(
+ fullContainer[fullContainer._subplots[type]]
+ )
+ .filter(key => key.includes('axis'))
+ .map(axis => {
+ // will take care of subplots after
+ const prefix = fullContainer._subplots[type][0];
+ fullContainer[prefix][axis].prefix = prefix;
+ if (!fullContainer[prefix][axis]._name) {
+ // it should be in plotly.js, but it's not there for geo axes..
+ fullContainer[prefix][axis]._name = axis;
+ }
+ return fullContainer[prefix][axis];
+ });
+ }
+ });
+
this.axesOptions = computeAxesOptions(this.axes, nextProps.localize);
if (axesTarget === 'allaxes') {
@@ -60,11 +81,11 @@ export default function connectAxesToLayout(WrappedComponent) {
);
this.fullContainer = multiValuedContainer;
this.defaultContainer = this.axes[0];
- // what should this be set to? Probably doesn't matter.
this.container = {};
} else {
this.fullContainer = nestedProperty(fullContainer, axesTarget).get();
- this.container = nestedProperty(container, axesTarget).get();
+ this.container = this.container =
+ nestedProperty(container, axesTarget).get() || {};
}
}
@@ -97,12 +118,11 @@ export default function connectAxesToLayout(WrappedComponent) {
const keys = Object.keys(update);
for (let i = 0; i < keys.length; i++) {
for (let j = 0; j < axes.length; j++) {
- const scene = axes[j]._id.substr(1);
+ const prefix = axes[j].prefix;
let axesKey = axes[j]._name;
- // scenes are nested
- if (scene.indexOf('scene') !== -1) {
- axesKey = `${scene}.${axesKey}`;
+ if (prefix) {
+ axesKey = `${prefix}.${axesKey}`;
}
const newkey = `${axesKey}.${keys[i]}`;
@@ -134,8 +154,6 @@ export default function connectAxesToLayout(WrappedComponent) {
AxesConnectedComponent.contextTypes = {
container: PropTypes.object.isRequired,
fullContainer: PropTypes.object.isRequired,
- graphDiv: PropTypes.object.isRequired,
- plotly: PropTypes.object,
updateContainer: PropTypes.func,
};