diff --git a/examples/simple/src/App.js b/examples/simple/src/App.js index 11d344ad2..3b1f05325 100644 --- a/examples/simple/src/App.js +++ b/examples/simple/src/App.js @@ -24,7 +24,7 @@ class App extends Component { // overwritten with a full DOM node that contains data, layout, _fullData, // _fullLayout etc in handlePlotUpdate() const graphDiv = { - data: [{type: 'scatter', xsrc: 'col1', ysrc: 'col2'}], + data: [{type: 'scatter', xsrc: 'col1', ysrc: 'col2', mode: 'markers'}], layout: {title: 'Room readings'}, }; diff --git a/src/PlotlyEditor.js b/src/PlotlyEditor.js index 080072870..88f676170 100644 --- a/src/PlotlyEditor.js +++ b/src/PlotlyEditor.js @@ -93,7 +93,7 @@ class PlotlyEditor extends Component { if (this.props.onAddTrace) { this.props.onAddTrace(payload); } - graphDiv.data.push({x: [], y: []}); + graphDiv.data.push({x: [], y: [], type: 'scatter', mode: 'markers'}); if (this.props.onUpdate) { this.props.onUpdate(); } diff --git a/src/components/fields/Field.js b/src/components/fields/Field.js index 8283139a0..ddf9690b0 100644 --- a/src/components/fields/Field.js +++ b/src/components/fields/Field.js @@ -6,18 +6,6 @@ import {bem, localize} from 'lib'; import {getMultiValueText} from 'lib/constants'; class Field extends Component { - renderPostfix() { - const {units} = this.props; - if (!units) { - return null; - } - return ( -
-
{units}
-
- ); - } - render() { const { center, diff --git a/src/components/fields/TraceSelector.js b/src/components/fields/TraceSelector.js index 02336222e..d5d3fda59 100644 --- a/src/components/fields/TraceSelector.js +++ b/src/components/fields/TraceSelector.js @@ -1,8 +1,11 @@ import {UnconnectedDropdown} from './Dropdown'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; -import nestedProperty from 'plotly.js/src/lib/nested_property'; -import {connectToContainer} from '../../lib'; +import { + connectToContainer, + customTraceToPlotlyTrace, + plotlyTraceToCustomTrace, +} from '../../lib'; function computeTraceOptionsFromSchema(schema) { const capitalize = s => s.charAt(0).toUpperCase() + s.substring(1); @@ -62,18 +65,7 @@ class TraceSelector extends Component { this.traceOptions = [{label: 'Scatter', value: 'scatter'}]; } - // If we used fullData mode or fill it may be undefined if the fullTrace - // is not visible and therefore does not have these values computed. - const mode = nestedProperty(props.container, 'mode').get(); - const fill = nestedProperty(props.container, 'fill').get(); - const fullValue = props.fullValue; - if (fullValue === 'scatter' && this.fillTypes.includes(fill)) { - this.fullValue = 'area'; - } else if (fullValue === 'scatter' && mode === 'lines') { - this.fullValue = 'line'; - } else { - this.fullValue = fullValue; - } + this.fullValue = plotlyTraceToCustomTrace(props.fullContainer); } componentWillReceiveProps(nextProps, nextContext) { @@ -81,16 +73,7 @@ class TraceSelector extends Component { } updatePlot(value) { - let update; - if (value === 'line') { - update = {type: 'scatter', mode: 'lines', fill: 'none'}; - } else if (value === 'scatter') { - update = {type: 'scatter', mode: 'markers', fill: 'none'}; - } else if (value === 'area') { - update = {type: 'scatter', fill: 'tozeroy'}; - } else { - update = {type: value}; - } + const update = customTraceToPlotlyTrace(value); if (this.props.updateContainer) { this.props.updateContainer(update); @@ -114,7 +97,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__/TraceSelector-test.js b/src/components/fields/__tests__/TraceSelector-test.js index f9db1ca1a..f6fdc50eb 100644 --- a/src/components/fields/__tests__/TraceSelector-test.js +++ b/src/components/fields/__tests__/TraceSelector-test.js @@ -45,6 +45,24 @@ describe('TraceSelector', () => { expect(innerDropdown.prop('value')).toEqual('line'); }); + it('interprets scatter + mode=lines+markers as type=line', () => { + const editorProps = { + ...fixtures.scatter({data: [{mode: 'lines+markers'}]}), + onUpdate: jest.fn(), + }; + const wrapper = mount( + + + + + + ).find(TraceSelector); + + const innerDropdown = wrapper.find(Dropdown); + + expect(innerDropdown.prop('value')).toEqual('line'); + }); + it('updates type=scatter mode=lines when type=line', () => { const onUpdateTraces = jest.fn(); const editorProps = { diff --git a/src/lib/customTraceType.js b/src/lib/customTraceType.js new file mode 100644 index 000000000..58b5115cf --- /dev/null +++ b/src/lib/customTraceType.js @@ -0,0 +1,32 @@ +export function plotlyTraceToCustomTrace(trace) { + if ( + trace.type === 'scatter' && + ['tozeroy', 'tozerox', 'tonexty', 'tonextx', 'toself', 'tonext'].includes( + trace.fill + ) + ) { + return 'area'; + } else if ( + trace.type === 'scatter' && + (trace.mode === 'lines' || trace.mode === 'lines+markers') + ) { + return 'line'; + } + return trace.type; +} + +export function customTraceToPlotlyTrace(customTraceType) { + if (customTraceType === 'line') { + return {type: 'scatter', mode: 'lines', fill: 'none'}; + } + + if (customTraceType === 'scatter') { + return {type: 'scatter', mode: 'markers', fill: 'none'}; + } + + if (customTraceType === 'area') { + return {type: 'scatter', fill: 'tozeroy'}; + } + + return {type: customTraceType}; +} diff --git a/src/lib/index.js b/src/lib/index.js index 438c93e1d..5fcc5513a 100644 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -10,6 +10,10 @@ import localize, {localizeString} from './localize'; import tinyColor from 'tinycolor2'; import unpackPlotProps from './unpackPlotProps'; import walkObject, {isPlainObject} from './walkObject'; +import { + customTraceToPlotlyTrace, + plotlyTraceToCustomTrace, +} from './customTraceType'; function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); @@ -33,14 +37,16 @@ export { connectLayoutToPlot, connectToContainer, connectTraceToPlot, + customTraceToPlotlyTrace, dereference, + findFullTraceIndex, getDisplayName, getLayoutContext, - findFullTraceIndex, icon, isPlainObject, localize, localizeString, + plotlyTraceToCustomTrace, unpackPlotProps, walkObject, };