Skip to content

Commit 3ae82b3

Browse files
Merging Hub into Editor (#176)
1 parent 11e2b4c commit 3ae82b3

20 files changed

+319
-433
lines changed

examples/async-data/package-lock.json

Lines changed: 17 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/async-data/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"plotly.js": "^1.31.2",
88
"react": "^15.6.1",
99
"react-dom": "^15.6.1",
10+
"react-plotly.js": "^1.0.4",
11+
"react-plotly.js-editor": "^0.1.0",
1012
"react-scripts": "1.0.17"
1113
},
1214
"scripts": {

examples/async-data/src/App.js

Lines changed: 46 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import './App.css';
22
import 'react-plotly.js-editor/lib/react-plotly.js-editor.css';
33
import 'react-select/dist/react-select.css';
4-
import PlotlyEditor, {
5-
EDITOR_ACTIONS,
6-
Hub,
7-
dereference,
8-
} from 'react-plotly.js-editor';
4+
import PlotlyEditor, {dereference} from 'react-plotly.js-editor';
95
import React, {Component} from 'react';
106
import createPlotComponent from 'react-plotly.js/factory';
117
import ee from 'event-emitter';
@@ -49,6 +45,7 @@ class Backend {
4945
ee(Backend.prototype);
5046

5147
const backend = new Backend({
48+
// eslint-disable-next-line no-magic-numbers
5249
dataSources: {col1: [1, 2, 3], col2: [4, 3, 2], col3: [17, 13, 9]},
5350
delay: 10,
5451
});
@@ -57,38 +54,25 @@ class App extends Component {
5754
constructor() {
5855
super();
5956

60-
// A basic starting plotly.js figure object. Instead of assigning
61-
const figure = {
57+
// This object is passed to Plotly.js, which then causes it to be
58+
// overwritten with a full DOM node that contains data, layout, _fullData,
59+
// _fullLayout etc in handlePlotUpdate()
60+
const graphDiv = {
6261
data: [{type: 'scatter'}],
6362
layout: {title: 'Room readings'},
6463
};
6564

6665
// Store the figure, dataSource and dataSourceOptions in state.
67-
this.state = {figure, dataSources: {}};
68-
69-
// Instantiate a Hub object. The hub is a convenience module that updates
70-
// the applies Editor updates to the figure object. After an update it
71-
// will call the onUpdate function with the editor and plot revision numbers.
72-
// We set these in our state and pass them to react-plotly.js-editor and
73-
// react-plotly.js plot component respectively. This is necessary because
74-
// the plotly.js library will mutate the figure object with user interactions.
75-
// The hub listens for events from plotly.js and alerts us to the mutation here.
76-
// The Editor follows the same mutation pattern (for good or ill) and the Hub
77-
// will pick up editor results in the same way.
78-
this.hub = new Hub({
79-
debug: true,
80-
onUpdate: ({editorRevision, plotRevision}) =>
81-
this.setState(prevState => ({
82-
...prevState,
83-
editorRevision,
84-
plotRevision,
85-
})),
86-
});
66+
this.state = {
67+
graphDiv,
68+
editorRevision: 0,
69+
plotRevision: 0,
70+
dataSources: {},
71+
};
8772

8873
this.getChartingData = this.getChartingData.bind(this);
8974
this.setChartingData = this.setChartingData.bind(this);
9075
this.setChartingDataOptions = this.setChartingDataOptions.bind(this);
91-
this.onEditorUpdate = this.onEditorUpdate.bind(this);
9276
}
9377

9478
componentDidMount() {
@@ -98,18 +82,18 @@ class App extends Component {
9882
this.getChartingDataColumnsNames();
9983
}
10084

101-
componentDidUnmount() {
85+
componentWillUnmount() {
10286
backend.off('ChartingDataColumnNames', this.setChartingDataOptions);
10387
backend.off('ChartingData', this.setChartingData);
10488
}
10589

10690
setChartingDataOptions(columnNames) {
107-
const dataSourceOptions = columnNames.map(name => ({
108-
value: name,
109-
label: name,
110-
}));
111-
this.setState(prevState => ({...prevState, dataSourceOptions}));
112-
this.hub.editorSourcesUpdated();
91+
this.setState({
92+
dataSourceOptions: columnNames.map(name => ({
93+
value: name,
94+
label: name,
95+
})),
96+
});
11397
}
11498

11599
getChartingDataColumnsNames() {
@@ -127,35 +111,34 @@ class App extends Component {
127111

128112
setChartingData({columnName, data}) {
129113
if (Array.isArray(data) && data.length) {
130-
const {dataSources, ...otherState} = this.state;
131-
dataSources[columnName] = data;
132-
dereference(this.state.figure.data, dataSources);
133-
this.setState({
134-
dataSources,
135-
...otherState,
114+
this.setState(({dataSources, graphDiv}) => {
115+
const newDataSources = {...dataSources, [columnName]: data};
116+
dereference(graphDiv.data, newDataSources);
117+
return {dataSources: newDataSources, graphDiv};
136118
});
137-
this.hub.figureUpdated();
138119
}
139120
}
140121

141-
onEditorUpdate(event) {
142-
const {type, payload} = event;
143-
if (type === EDITOR_ACTIONS.UPDATE_TRACES) {
144-
const {update} = payload;
145-
if (update) {
146-
for (const key in update) {
147-
if (key.substr(key.length - 3) === 'src') {
148-
const columnId = update[key];
149-
const data = this.state.dataSources[columnId];
150-
if (!Array.isArray(data).length || !data.length) {
151-
this.getChartingData(columnId);
152-
}
122+
handleEditorUpdateTraces({update}) {
123+
if (update) {
124+
for (const key in update) {
125+
if (key.substr(key.length - 3) === 'src') {
126+
const columnId = update[key];
127+
const data = this.state.dataSources[columnId];
128+
if (!Array.isArray(data).length || !data.length) {
129+
this.getChartingData(columnId);
153130
}
154131
}
155132
}
156133
}
134+
}
157135

158-
this.hub.handleEditorUpdate(event);
136+
handlePlotUpdate(graphDiv) {
137+
this.setState(({editorRevision: x}) => ({editorRevision: x + 1, graphDiv}));
138+
}
139+
140+
handleEditorUpdate() {
141+
this.setState(({plotRevision: x}) => ({plotRevision: x + 1}));
159142
}
160143

161144
render() {
@@ -165,17 +148,18 @@ class App extends Component {
165148
locale="en"
166149
dataSources={this.state.dataSources}
167150
dataSourceOptions={this.state.dataSourceOptions}
168-
graphDiv={this.hub.graphDiv}
169-
onUpdate={this.onEditorUpdate}
170-
plotly={plotly}
151+
graphDiv={this.state.graphDiv}
152+
onUpdate={this.handleEditorUpdate.bind(this)}
153+
onUpdateTraces={this.handleEditorUpdateTraces.bind(this)}
171154
revision={this.state.editorRevision}
155+
plotly={plotly}
172156
/>
173157
<Plot
174158
debug
175-
data={this.state.figure.data}
176-
layout={this.state.figure.layout}
177-
onUpdate={this.hub.handlePlotUpdate}
178-
onInitialized={this.hub.handlePlotInitialized}
159+
data={this.state.graphDiv.data}
160+
layout={this.state.graphDiv.layout}
161+
onUpdate={this.handlePlotUpdate.bind(this)}
162+
onInitialized={this.handlePlotUpdate.bind(this)}
179163
revision={this.state.plotRevision}
180164
/>
181165
</div>

examples/simple/src/App.js

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, {Component} from 'react';
22
import plotly from 'plotly.js/dist/plotly-basic';
33
import createPlotComponent from 'react-plotly.js/factory';
4-
import PlotlyEditor, {Hub, dereference} from 'react-plotly.js-editor';
4+
import PlotlyEditor, {dereference} from 'react-plotly.js-editor';
55
import 'react-plotly.js-editor/lib/react-plotly.js-editor.css';
66
import 'react-select/dist/react-select.css';
77

@@ -12,46 +12,40 @@ class App extends Component {
1212
super();
1313

1414
// DataSources are a mapping of column or data source ids to data arrays.
15+
// eslint-disable-next-line no-magic-numbers
1516
const dataSources = {col1: [1, 2, 3], col2: [4, 3, 2], col3: [17, 13, 9]};
1617
const dataSourceOptions = [
1718
{value: 'col1', label: 'CO2'},
1819
{value: 'col2', label: 'NO2'},
1920
{value: 'col3', label: 'SiO2'},
2021
];
2122

22-
// A basic starting plotly.js figure object. Instead of assigning
23-
const figure = {
23+
// This object is passed to Plotly.js, which then causes it to be
24+
// overwritten with a full DOM node that contains data, layout, _fullData,
25+
// _fullLayout etc in handlePlotUpdate()
26+
const graphDiv = {
2427
data: [{type: 'scatter', xsrc: 'col1', ysrc: 'col2'}],
2528
layout: {title: 'Room readings'},
2629
};
2730

28-
dereference(figure.data, dataSources);
31+
dereference(graphDiv.data, dataSources);
2932

3033
// Store the figure, dataSource and dataSourceOptions in state.
3134
this.state = {
32-
figure,
35+
graphDiv,
36+
editorRevision: 0,
37+
plotRevision: 0,
3338
dataSources,
3439
dataSourceOptions,
3540
};
41+
}
42+
43+
handlePlotUpdate(graphDiv) {
44+
this.setState(({editorRevision: x}) => ({editorRevision: x + 1, graphDiv}));
45+
}
3646

37-
// Instantiate a Hub object. The hub is a convenience module that updates
38-
// the applies Editor updates to the figure object. After an update it
39-
// will call the onUpdate function with the editor and plot revision numbers.
40-
// We set these in our state and pass them to react-plotly.js-editor and
41-
// react-plotly.js plot component respectively. This is necessary because
42-
// the plotly.js library will mutate the figure object with user interactions.
43-
// The hub listens for events from plotly.js and alerts us to the mutation here.
44-
// The Editor follows the same mutation pattern (for good or ill) and the Hub
45-
// will pick up editor results in the same way.
46-
this.hub = new Hub({
47-
debug: true,
48-
onUpdate: ({editorRevision, plotRevision}) =>
49-
this.setState(prevState => ({
50-
...prevState,
51-
editorRevision,
52-
plotRevision,
53-
})),
54-
});
47+
handleEditorUpdate() {
48+
this.setState(({plotRevision: x}) => ({plotRevision: x + 1}));
5549
}
5650

5751
render() {
@@ -61,18 +55,18 @@ class App extends Component {
6155
locale="en"
6256
dataSources={this.state.dataSources}
6357
dataSourceOptions={this.state.dataSourceOptions}
64-
graphDiv={this.hub.graphDiv}
65-
onUpdate={this.hub.handleEditorUpdate}
66-
plotly={plotly}
58+
graphDiv={this.state.graphDiv}
59+
onUpdate={this.handleEditorUpdate.bind(this)}
6760
revision={this.state.editorRevision}
61+
plotly={plotly}
6862
/>
6963
<div className="plotlyPlot">
7064
<Plot
7165
debug
72-
data={this.state.figure.data}
73-
layout={this.state.figure.layout}
74-
onUpdate={this.hub.handlePlotUpdate}
75-
onInitialized={this.hub.handlePlotInitialized}
66+
data={this.state.graphDiv.data}
67+
layout={this.state.graphDiv.layout}
68+
onUpdate={this.handlePlotUpdate.bind(this)}
69+
onInitialized={this.handlePlotUpdate.bind(this)}
7670
revision={this.state.plotRevision}
7771
/>
7872
</div>

0 commit comments

Comments
 (0)