Skip to content

Commit 3391854

Browse files
authored
Merge branch 'master' into account-for-long-text
2 parents 85bae47 + a10137f commit 3391854

File tree

7 files changed

+92
-6
lines changed

7 files changed

+92
-6
lines changed

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-plotly.js-editor",
3-
"version": "0.2.2-alpha.1",
3+
"version": "0.3.0",
44
"license": "MIT",
55
"description": "plotly.js chart editor react component UI",
66
"author": "Plotly, Inc.",

src/PlotlyEditor.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class PlotlyEditor extends Component {
3838
data: gd.data,
3939
dataSources: this.props.dataSources,
4040
dataSourceOptions: this.props.dataSourceOptions,
41+
dataSourceValueRenderer: this.props.dataSourceValueRenderer,
42+
dataSourceOptionRenderer: this.props.dataSourceOptionRenderer,
4143
dictionaries: dictionaries,
4244
fullData: gd._fullData,
4345
fullLayout: gd._fullLayout,
@@ -104,7 +106,7 @@ class PlotlyEditor extends Component {
104106
this.props.onDeleteTrace(payload);
105107
}
106108
if (payload.traceIndexes && payload.traceIndexes.length) {
107-
graphDiv.data.splice(payload[0], 1);
109+
graphDiv.data.splice(payload.traceIndexes[0], 1);
108110
if (this.props.onUpdate) {
109111
this.props.onUpdate();
110112
}
@@ -150,6 +152,8 @@ PlotlyEditor.propTypes = {
150152
className: PropTypes.string,
151153
dataSources: PropTypes.object,
152154
dataSourceOptions: PropTypes.array,
155+
dataSourceValueRenderer: PropTypes.func,
156+
dataSourceOptionRenderer: PropTypes.func,
153157
graphDiv: PropTypes.object,
154158
locale: PropTypes.string,
155159
revision: PropTypes.any,
@@ -170,6 +174,8 @@ PlotlyEditor.childContextTypes = {
170174
data: PropTypes.array,
171175
dataSources: PropTypes.object,
172176
dataSourceOptions: PropTypes.array,
177+
dataSourceValueRenderer: PropTypes.func,
178+
dataSourceOptionRenderer: PropTypes.func,
173179
dictionaries: PropTypes.object,
174180
fullData: PropTypes.array,
175181
fullLayout: PropTypes.object,

src/components/fields/DataSelector.js

+4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class DataSelector extends Component {
6161
options={this.dataSourceOptions}
6262
value={this.fullValue}
6363
onChange={this.updatePlot}
64+
optionRenderer={this.context.dataSourceOptionRenderer}
65+
valueRenderer={this.context.dataSourceValueRenderer}
6466
clearable={this.props.clearable}
6567
/>
6668
</Field>
@@ -78,6 +80,8 @@ DataSelector.propTypes = {
7880
DataSelector.contextTypes = {
7981
dataSources: PropTypes.object,
8082
dataSourceOptions: PropTypes.array,
83+
dataSourceValueRenderer: PropTypes.func,
84+
dataSourceOptionRenderer: PropTypes.func,
8185
};
8286

8387
function modifyPlotProps(props, context, plotProps) {

src/components/fields/TraceSelector.js

+17-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ class TraceSelector extends Component {
5252
'tonext',
5353
];
5454
}
55-
55+
this.setTraceDefaults(
56+
props.container,
57+
props.fullContainer,
58+
props.updateContainer
59+
);
5660
this.setLocals(props, context);
5761
}
5862

@@ -64,17 +68,26 @@ class TraceSelector extends Component {
6468
} else {
6569
this.traceOptions = [{label: 'Scatter', value: 'scatter'}];
6670
}
71+
this.fullValue = plotlyTraceToCustomTrace(props.container);
72+
}
6773

68-
this.fullValue = plotlyTraceToCustomTrace(props.fullContainer);
74+
setTraceDefaults(container, fullContainer, updateContainer) {
75+
if (!container.mode && fullContainer.type === 'scatter') {
76+
updateContainer({
77+
type: 'scatter',
78+
mode: fullContainer.mode || 'markers',
79+
});
80+
}
6981
}
7082

7183
componentWillReceiveProps(nextProps, nextContext) {
84+
const {container, fullContainer, updateContainer} = nextProps;
85+
this.setTraceDefaults(container, fullContainer, updateContainer);
7286
this.setLocals(nextProps, nextContext);
7387
}
7488

7589
updatePlot(value) {
7690
const update = customTraceToPlotlyTrace(value);
77-
7891
if (this.props.updateContainer) {
7992
this.props.updateContainer(update);
8093
}
@@ -97,6 +110,7 @@ TraceSelector.contextTypes = {
97110

98111
TraceSelector.propTypes = {
99112
getValObject: PropTypes.func,
113+
container: PropTypes.object.isRequired,
100114
fullContainer: PropTypes.object.isRequired,
101115
fullValue: PropTypes.any.isRequired,
102116
updateContainer: PropTypes.func,

src/components/fields/__tests__/DataSelector-test.js

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ describe('DataSelector', () => {
3737
it('calls updatePlot with srcAttr and data when present', () => {
3838
const onUpdateTraces = jest.fn();
3939
const wrapper = render({onUpdateTraces}).find(DropdownWidget);
40+
onUpdateTraces.mockClear();
4041
wrapper.prop('onChange')('y1');
4142
expect(onUpdateTraces.mock.calls[0][0]).toEqual({
4243
update: {xsrc: 'y1', x: [2, 3, 4]},

src/components/fields/__tests__/TraceSelector-test.js

+61
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,67 @@ import {connectTraceToPlot} from 'lib';
99
describe('TraceSelector', () => {
1010
const TraceSection = connectTraceToPlot(Section);
1111

12+
it('sets mode to markers if trace scatter, no data or mode provided', () => {
13+
const editorProps = {
14+
...fixtures.scatter({data: [{mode: null, xsrc: null, ysrc: null}]}),
15+
onUpdate: jest.fn(),
16+
};
17+
const wrapper = mount(
18+
<TestEditor {...editorProps} plotly={plotly}>
19+
<TraceSection traceIndex={0}>
20+
<TraceSelector attr="type" />
21+
</TraceSection>
22+
</TestEditor>
23+
).find(TraceSelector);
24+
25+
const innerDropdown = wrapper.find(Dropdown);
26+
27+
expect(wrapper.props().plotProps.container.mode).toBe('markers');
28+
expect(innerDropdown.prop('value')).toEqual('scatter');
29+
});
30+
31+
it('if no data provided, but mode is provided, displays correct trace type', () => {
32+
const editorProps = {
33+
...fixtures.scatter({
34+
data: [{mode: 'lines+markers', xsrc: null, ysrc: null}],
35+
}),
36+
onUpdate: jest.fn(),
37+
};
38+
const wrapper = mount(
39+
<TestEditor {...editorProps} plotly={plotly}>
40+
<TraceSection traceIndex={0}>
41+
<TraceSelector attr="type" />
42+
</TraceSection>
43+
</TestEditor>
44+
).find(TraceSelector);
45+
46+
const innerDropdown = wrapper.find(Dropdown);
47+
48+
expect(innerDropdown.prop('value')).toEqual('line');
49+
});
50+
51+
it('if data provided, but no mode is provided, chooses mode according to fullData', () => {
52+
const editorProps = {
53+
...fixtures.scatter(),
54+
onUpdate: jest.fn(),
55+
};
56+
57+
expect(!editorProps.graphDiv.data[0].mode).toBe(true);
58+
expect(editorProps.graphDiv._fullData[0].mode).toBe('lines+markers');
59+
60+
const wrapper = mount(
61+
<TestEditor {...editorProps} plotly={plotly}>
62+
<TraceSection traceIndex={0}>
63+
<TraceSelector attr="type" />
64+
</TraceSection>
65+
</TestEditor>
66+
).find(TraceSelector);
67+
68+
const innerDropdown = wrapper.find(Dropdown);
69+
expect(wrapper.props().plotProps.container.mode).toBe('lines+markers');
70+
expect(innerDropdown.prop('value')).toEqual('line');
71+
});
72+
1273
it('interprets scatter + fill as type=area', () => {
1374
const editorProps = {
1475
...fixtures.scatter({data: [{fill: 'tonexty'}]}),

0 commit comments

Comments
 (0)