diff --git a/src/PlotlyEditor.js b/src/PlotlyEditor.js index 7e553be97..5e7868711 100644 --- a/src/PlotlyEditor.js +++ b/src/PlotlyEditor.js @@ -106,7 +106,7 @@ class PlotlyEditor extends Component { this.props.onDeleteTrace(payload); } if (payload.traceIndexes && payload.traceIndexes.length) { - graphDiv.data.splice(payload[0], 1); + graphDiv.data.splice(payload.traceIndexes[0], 1); if (this.props.onUpdate) { this.props.onUpdate(); } diff --git a/src/components/fields/TraceSelector.js b/src/components/fields/TraceSelector.js index 6538c45a8..353cdd581 100644 --- a/src/components/fields/TraceSelector.js +++ b/src/components/fields/TraceSelector.js @@ -52,7 +52,11 @@ class TraceSelector extends Component { 'tonext', ]; } - + this.setTraceDefaults( + props.container, + props.fullContainer, + props.updateContainer + ); this.setLocals(props, context); } @@ -64,17 +68,26 @@ class TraceSelector extends Component { } else { this.traceOptions = [{label: 'Scatter', value: 'scatter'}]; } + this.fullValue = plotlyTraceToCustomTrace(props.container); + } - this.fullValue = plotlyTraceToCustomTrace(props.fullContainer); + setTraceDefaults(container, fullContainer, updateContainer) { + if (!container.mode && fullContainer.type === 'scatter') { + updateContainer({ + type: 'scatter', + mode: fullContainer.mode || 'markers', + }); + } } componentWillReceiveProps(nextProps, nextContext) { + const {container, fullContainer, updateContainer} = nextProps; + this.setTraceDefaults(container, fullContainer, updateContainer); this.setLocals(nextProps, nextContext); } updatePlot(value) { const update = customTraceToPlotlyTrace(value); - if (this.props.updateContainer) { this.props.updateContainer(update); } @@ -97,6 +110,7 @@ TraceSelector.contextTypes = { TraceSelector.propTypes = { getValObject: PropTypes.func, + container: PropTypes.object.isRequired, fullContainer: PropTypes.object.isRequired, fullValue: PropTypes.any.isRequired, updateContainer: PropTypes.func, diff --git a/src/components/fields/__tests__/DataSelector-test.js b/src/components/fields/__tests__/DataSelector-test.js index 7a7f6d153..1ffae96dc 100644 --- a/src/components/fields/__tests__/DataSelector-test.js +++ b/src/components/fields/__tests__/DataSelector-test.js @@ -37,6 +37,7 @@ describe('DataSelector', () => { it('calls updatePlot with srcAttr and data when present', () => { const onUpdateTraces = jest.fn(); const wrapper = render({onUpdateTraces}).find(DropdownWidget); + onUpdateTraces.mockClear(); wrapper.prop('onChange')('y1'); expect(onUpdateTraces.mock.calls[0][0]).toEqual({ update: {xsrc: 'y1', x: [2, 3, 4]}, diff --git a/src/components/fields/__tests__/TraceSelector-test.js b/src/components/fields/__tests__/TraceSelector-test.js index f7ea24edc..d9a189ee9 100644 --- a/src/components/fields/__tests__/TraceSelector-test.js +++ b/src/components/fields/__tests__/TraceSelector-test.js @@ -9,6 +9,67 @@ import {connectTraceToPlot} from 'lib'; describe('TraceSelector', () => { const TraceSection = connectTraceToPlot(Section); + it('sets mode to markers if trace scatter, no data or mode provided', () => { + const editorProps = { + ...fixtures.scatter({data: [{mode: null, xsrc: null, ysrc: null}]}), + onUpdate: jest.fn(), + }; + const wrapper = mount( + + + + + + ).find(TraceSelector); + + const innerDropdown = wrapper.find(Dropdown); + + expect(wrapper.props().plotProps.container.mode).toBe('markers'); + expect(innerDropdown.prop('value')).toEqual('scatter'); + }); + + it('if no data provided, but mode is provided, displays correct trace type', () => { + const editorProps = { + ...fixtures.scatter({ + data: [{mode: 'lines+markers', xsrc: null, ysrc: null}], + }), + onUpdate: jest.fn(), + }; + const wrapper = mount( + + + + + + ).find(TraceSelector); + + const innerDropdown = wrapper.find(Dropdown); + + expect(innerDropdown.prop('value')).toEqual('line'); + }); + + it('if data provided, but no mode is provided, chooses mode according to fullData', () => { + const editorProps = { + ...fixtures.scatter(), + onUpdate: jest.fn(), + }; + + expect(!editorProps.graphDiv.data[0].mode).toBe(true); + expect(editorProps.graphDiv._fullData[0].mode).toBe('lines+markers'); + + const wrapper = mount( + + + + + + ).find(TraceSelector); + + const innerDropdown = wrapper.find(Dropdown); + expect(wrapper.props().plotProps.container.mode).toBe('lines+markers'); + expect(innerDropdown.prop('value')).toEqual('line'); + }); + it('interprets scatter + fill as type=area', () => { const editorProps = { ...fixtures.scatter({data: [{fill: 'tonexty'}]}),