Skip to content

Commit fa1651e

Browse files
authored
Merge pull request #427 from plotly/axes-selector-fixes
Smarter Axes Selector
2 parents 388faf2 + 7611baf commit fa1651e

11 files changed

+100
-95
lines changed

Diff for: src/components/containers/AxesFold.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@ import React, {Component} from 'react';
55
import {connectAxesToLayout} from 'lib';
66

77
class AxesFold extends Component {
8+
renderAxesSelector() {
9+
if (this.props.options.length > 1) {
10+
return <AxesSelector axesOptions={this.props.options} />;
11+
}
12+
return null;
13+
}
14+
815
render() {
916
return this.props.children ? (
1017
<Fold {...this.props}>
11-
<AxesSelector />
18+
{this.renderAxesSelector()}
1219
{this.props.children}
1320
</Fold>
1421
) : null;
@@ -17,6 +24,7 @@ class AxesFold extends Component {
1724

1825
AxesFold.propTypes = {
1926
children: PropTypes.any,
27+
options: PropTypes.array,
2028
};
2129

2230
AxesFold.plotly_editor_traits = {foldable: true};

Diff for: src/components/containers/RangeSelectorAccordion.js

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const RangeSelectorFold = connectRangeSelectorToAxis(Fold);
99
class RangeSelectorAccordion extends Component {
1010
render() {
1111
if (
12+
!this.context.fullContainer ||
1213
!this.context.fullContainer.rangeselector ||
1314
!this.context.fullContainer.rangeselector.visible ||
1415
// next line checks for "all" case
@@ -61,4 +62,8 @@ RangeSelectorAccordion.propTypes = {
6162
localize: PropTypes.func,
6263
};
6364

65+
RangeSelectorAccordion.plotly_editor_traits = {
66+
no_visibility_forcing: true,
67+
};
68+
6469
export default localize(RangeSelectorAccordion);

Diff for: src/components/fields/AxesSelector.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ class AxesSelector extends Component {
1717
}
1818

1919
render() {
20-
const {axesTargetHandler, axesOptions, axesTarget} = this.context;
21-
const {localize: _} = this.props;
20+
const {axesTargetHandler, axesTarget} = this.context;
21+
const {localize: _, axesOptions} = this.props;
2222
const maxOptions = axesOptions.length > 4; // eslint-disable-line
2323

2424
if (maxOptions) {
@@ -57,13 +57,13 @@ class AxesSelector extends Component {
5757

5858
AxesSelector.contextTypes = {
5959
axesTargetHandler: PropTypes.func,
60-
axesOptions: PropTypes.array,
6160
axesTarget: PropTypes.string,
6261
fullLayout: PropTypes.object,
6362
};
6463

6564
AxesSelector.propTypes = {
6665
localize: PropTypes.func,
66+
axesOptions: PropTypes.array,
6767
};
6868

6969
export default localize(AxesSelector);

Diff for: src/components/fields/derived.js

+11-20
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const AxisAnchorDropdown = connectToContainer(UnconnectedDropdown, {
1919
let options = [];
2020

2121
if (
22+
plotProps.fullContainer &&
2223
plotProps.fullContainer._subplot &&
2324
plotProps.fullContainer._subplot.includes('xaxis')
2425
) {
@@ -29,6 +30,7 @@ export const AxisAnchorDropdown = connectToContainer(UnconnectedDropdown, {
2930
};
3031
});
3132
} else if (
33+
plotProps.fullContainer &&
3234
plotProps.fullContainer._subplot &&
3335
plotProps.fullContainer._subplot.includes('yaxis')
3436
) {
@@ -48,6 +50,7 @@ export const AxisOverlayDropdown = connectToContainer(UnconnectedDropdown, {
4850
modifyPlotProps: (props, context, plotProps) => {
4951
let options = [];
5052
if (
53+
plotProps.fullContainer &&
5154
plotProps.fullContainer._subplot &&
5255
plotProps.fullContainer._subplot.includes('xaxis')
5356
) {
@@ -58,6 +61,7 @@ export const AxisOverlayDropdown = connectToContainer(UnconnectedDropdown, {
5861
};
5962
});
6063
} else if (
64+
plotProps.fullContainer &&
6165
plotProps.fullContainer._subplot &&
6266
plotProps.fullContainer._subplot.includes('yaxis')
6367
) {
@@ -71,7 +75,8 @@ export const AxisOverlayDropdown = connectToContainer(UnconnectedDropdown, {
7175

7276
// filter out the current axisID, can't overlay over itself
7377
plotProps.options = options.filter(
74-
option => context.fullContainer._id !== option.value
78+
option =>
79+
context.fullContainer && context.fullContainer._id !== option.value
7580
);
7681

7782
plotProps.clearable = true;
@@ -80,25 +85,9 @@ export const AxisOverlayDropdown = connectToContainer(UnconnectedDropdown, {
8085

8186
export const RangesliderVisible = connectToContainer(UnconnectedRadio, {
8287
modifyPlotProps: (props, context, plotProps) => {
83-
if (
84-
!plotProps.isVisible &&
85-
context.fullContainer._id &&
86-
context.fullContainer._id.startsWith('x')
87-
) {
88-
plotProps.isVisible = true;
89-
return;
90-
}
91-
},
92-
});
93-
94-
export const RangeselectorVisible = connectToContainer(UnconnectedRadio, {
95-
modifyPlotProps: (props, context, plotProps) => {
96-
if (
97-
!plotProps.isVisible &&
98-
context.fullContainer._id &&
99-
context.fullContainer._id.startsWith('x') &&
100-
context.fullContainer.type === 'date'
101-
) {
88+
if (!plotProps.fullValue) {
89+
plotProps.fullValue = false;
90+
plotProps.visible = false;
10291
plotProps.isVisible = true;
10392
return;
10493
}
@@ -109,6 +98,7 @@ export const AxisSide = connectToContainer(UnconnectedRadio, {
10998
modifyPlotProps: (props, context, plotProps) => {
11099
const _ = props.localize;
111100
if (
101+
context.fullContainer &&
112102
context.fullContainer._id &&
113103
context.fullContainer._id.startsWith('y')
114104
) {
@@ -120,6 +110,7 @@ export const AxisSide = connectToContainer(UnconnectedRadio, {
120110
}
121111

122112
if (
113+
context.fullContainer &&
123114
context.fullContainer._id &&
124115
context.fullContainer._id.startsWith('x')
125116
) {

Diff for: src/components/fields/index.js

-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import {
4040
LayoutNumeric,
4141
LayoutNumericFractionInverse,
4242
RangesliderVisible,
43-
RangeselectorVisible,
4443
TraceOrientation,
4544
AxisOverlayDropdown,
4645
AxisSide,
@@ -86,7 +85,6 @@ export {
8685
Radio,
8786
SymbolSelector,
8887
RangesliderVisible,
89-
RangeselectorVisible,
9088
TextEditor,
9189
TraceOrientation,
9290
TraceSelector,

Diff for: src/components/index.js

-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import {
3838
Text,
3939
Radio,
4040
RangesliderVisible,
41-
RangeselectorVisible,
4241
AxisCreator,
4342
SymbolSelector,
4443
TextEditor,
@@ -86,7 +85,6 @@ export {
8685
UpdateMenuAccordion,
8786
AnnotationArrowRef,
8887
RangesliderVisible,
89-
RangeselectorVisible,
9088
AnnotationRef,
9189
PositioningRef,
9290
ArrowSelector,

Diff for: src/default_panels/StyleAxesPanel.js

+31-8
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import {
2020
AxesFold,
2121
TraceTypeSection,
2222
RangesliderVisible,
23-
RangeselectorVisible,
2423
RangeSelectorAccordion,
2524
} from '../components';
2625

@@ -55,14 +54,20 @@ class StyleAxesPanel extends Component {
5554
},
5655
]}
5756
>
58-
<AxesFold name={_('Titles')}>
57+
<AxesFold
58+
name={_('Titles')}
59+
axisFilter={axis => !axis._name.includes('angular')}
60+
>
5961
<TextEditor attr="title" />
6062
<FontSelector label={_('Typeface')} attr="titlefont.family" />
6163
<Numeric label={_('Font Size')} attr="titlefont.size" units="px" />
6264
<ColorPicker label={_('Font Color')} attr="titlefont.color" />
6365
</AxesFold>
6466

65-
<AxesFold name={_('Layout')}>
67+
<AxesFold
68+
name={_('Layout')}
69+
axisFilter={axis => !axis._name.includes('radial')}
70+
>
6671
<Dropdown
6772
label={_('Direction')}
6873
attr="direction"
@@ -347,7 +352,10 @@ class StyleAxesPanel extends Component {
347352
</Section>
348353
</AxesFold>
349354

350-
<AxesFold name={_('Range Slider')}>
355+
<AxesFold
356+
name={_('Range Slider')}
357+
axisFilter={axis => axis._subplot.includes('xaxis')}
358+
>
351359
<RangesliderVisible
352360
attr="rangeslider.visible"
353361
options={[
@@ -371,8 +379,13 @@ class StyleAxesPanel extends Component {
371379
/>
372380
</AxesFold>
373381

374-
<AxesFold name={_('Timescale Buttons')}>
375-
<RangeselectorVisible
382+
<AxesFold
383+
name={_('Timescale Buttons')}
384+
axisFilter={axis =>
385+
axis._subplot.includes('xaxis') && axis.type === 'date'
386+
}
387+
>
388+
<Radio
376389
attr="rangeselector.visible"
377390
options={[
378391
{label: _('Show'), value: true},
@@ -471,7 +484,12 @@ class StyleAxesPanel extends Component {
471484
</Section>
472485
</AxesFold>
473486

474-
<AxesFold name={_('Zoom Interactivity')}>
487+
<AxesFold
488+
name={_('Zoom Interactivity')}
489+
axisFilter={axis =>
490+
!axis._name.includes('angular') && !axis._name.includes('radial')
491+
}
492+
>
475493
<Radio
476494
attr="fixedrange"
477495
options={[
@@ -481,7 +499,12 @@ class StyleAxesPanel extends Component {
481499
/>
482500
</AxesFold>
483501

484-
<AxesFold name={_('Hover Projections')}>
502+
<AxesFold
503+
name={_('Hover Projections')}
504+
axisFilter={axis =>
505+
!axis._name.includes('angular') && !axis._name.includes('radial')
506+
}
507+
>
485508
<Radio
486509
attr="showspikes"
487510
options={[

Diff for: src/index.js

-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ import {
6464
SymbolSelector,
6565
TextEditor,
6666
RangesliderVisible,
67-
RangeselectorVisible,
6867
TraceAccordion,
6968
TraceMarkerSection,
7069
TraceRequiredPanel,
@@ -110,7 +109,6 @@ export {
110109
Dropzone,
111110
EDITOR_ACTIONS,
112111
RangesliderVisible,
113-
RangeselectorVisible,
114112
Flaglist,
115113
Fold,
116114
FontSelector,

Diff for: src/lib/__tests__/multiValued-test.js

+2-34
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,10 @@
1-
import NumericInput from '../../components/widgets/NumericInput';
21
import React from 'react';
3-
import {MULTI_VALUED_PLACEHOLDER} from '../constants';
42
import {Numeric} from '../../components';
53
import {TestEditor, fixtures, plotly} from '../test-utils';
64
import {connectLayoutToPlot, connectAxesToLayout} from '..';
75
import {mount} from 'enzyme';
86

97
describe('multiValued Numeric', () => {
10-
it('uses placeholder and empty string value', () => {
11-
const fixtureProps = fixtures.scatter({
12-
layout: {xaxis: {range: [0, 1]}, yaxis: {range: [-1, 1]}},
13-
});
14-
const AxesNumeric = connectLayoutToPlot(connectAxesToLayout(Numeric));
15-
16-
const rangeInputs = mount(
17-
<TestEditor {...{...fixtureProps, onUpdate: jest.fn(), plotly}}>
18-
<AxesNumeric attr="range[0]" defaultAxesTarget="xaxis" />
19-
<AxesNumeric attr="range[0]" defaultAxesTarget="yaxis" />
20-
<AxesNumeric attr="range[0]" defaultAxesTarget="allaxes" />
21-
</TestEditor>
22-
).find(NumericInput);
23-
24-
expect(rangeInputs.length).toBe(3);
25-
26-
const xaxisRangeInput = rangeInputs.at(0);
27-
const yaxisRangeInput = rangeInputs.at(1);
28-
const allaxisRangeInput = rangeInputs.at(2);
29-
30-
expect(xaxisRangeInput.prop('value')).toBe(0);
31-
expect(yaxisRangeInput.prop('value')).toBe(-1);
32-
expect(allaxisRangeInput.prop('value')).toBe('');
33-
expect(allaxisRangeInput.prop('placeholder')).toBe(
34-
MULTI_VALUED_PLACEHOLDER
35-
);
36-
});
37-
388
it('uses multiValued defaultContainer as default increment value', () => {
399
const beforeUpdateLayout = jest.fn();
4010
const xaxisLowerRange = -30;
@@ -45,7 +15,7 @@ describe('multiValued Numeric', () => {
4515

4616
mount(
4717
<TestEditor {...{...fixtureProps, beforeUpdateLayout, plotly}}>
48-
<AxesNumeric attr="range[0]" defaultAxesTarget="allaxes" />
18+
<AxesNumeric attr="range[0]" />
4919
</TestEditor>
5020
)
5121
.find('.js-numeric-increase')
@@ -54,9 +24,7 @@ describe('multiValued Numeric', () => {
5424
expect(beforeUpdateLayout).toBeCalled();
5525
const payload = beforeUpdateLayout.mock.calls[0][0];
5626
expect(payload.update).toEqual({
57-
'xaxis.range[0]': xaxisLowerRange,
58-
'yaxis.range[0]': xaxisLowerRange,
59-
'yaxis2.range[0]': xaxisLowerRange,
27+
'xaxis.range[0]': xaxisLowerRange + 1,
6028
});
6129
});
6230
});

Diff for: src/lib/__tests__/nestedContainerConnections-test.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,7 @@ describe('Plot Connection', () => {
2020
);
2121
mount(
2222
<TestEditor {...{...fixtureProps, beforeUpdateLayout}}>
23-
<LayoutAxesNumeric
24-
label="Min"
25-
attr="range[0]"
26-
defaultAxesTarget="xaxis"
27-
/>
23+
<LayoutAxesNumeric label="Min" attr="range[0]" />
2824
</TestEditor>
2925
)
3026
.find('[attr="range[0]"]')
@@ -34,7 +30,9 @@ describe('Plot Connection', () => {
3430

3531
expect(beforeUpdateLayout).toBeCalled();
3632
const payload = beforeUpdateLayout.mock.calls[0][0];
37-
expect(payload).toEqual({update: {'xaxis.range[0]': 1}});
33+
expect(payload).toEqual({
34+
update: {'xaxis.range[0]': 1},
35+
});
3836
});
3937

4038
it('can connect to layout when connected within trace context', () => {

0 commit comments

Comments
 (0)