PlotlyChartControl

Source

Histogram.js
import React from 'react';
import PropTypes from 'prop-types';

import style from 'PVWStyle/ReactWidgets/PlotlySelectionWidgets.mcss';

export default function render(props) {
function handleChange(event) {
const newXArray = event.target.value;
const forceNewPlot =
props.arrays[props.chartState.x] !== props.arrays[newXArray];
props.onChange({
chartType: 'Histogram',
x: newXArray,
forceNewPlot,
});
}

return (
<div>
<table className={style.fullWidth}>
<tbody>
<tr>
<td className={style.label}>x</td>
<td className={style.fullWidth}>
<select
className={style.fullWidth}
onChange={handleChange}
value={props.chartState.x}
>
{Object.keys(props.arrays).map((arrayName) => (
<option value={arrayName} key={arrayName}>
{arrayName}
</option>
))}
</select>
</td>
</tr>
</tbody>
</table>
</div>
);
}

render.propTypes = {
chartState: PropTypes.object,
arrays: PropTypes.object,
onChange: PropTypes.func,
};

render.defaultProps = {
chartState: {},
arrays: {},
onChange: () => {},
};
Histogram2D.js
import React from 'react';
import PropTypes from 'prop-types';

import style from 'PVWStyle/ReactWidgets/PlotlySelectionWidgets.mcss';

export default function render(props) {
function handleChange(event) {
const rootContainer = event.target.parentNode.parentNode.parentNode;
const newXArray = rootContainer.querySelector('.jsX').value;
const newYArray = rootContainer.querySelector('.jsY').value;
// const forceNewPlot = props.arrays[props.chartState.x] !== props.arrays[newXArray] ||
// props.arrays[props.chartState.y] !== props.arrays[newYArray];
props.onChange({
chartType: 'Histogram2D',
x: newXArray,
y: newYArray,
forceNewPlot: true,
});
}

return (
<div>
<table className={style.fullWidth}>
<tbody>
<tr>
<td className={style.label}>x</td>
<td className={style.fullWidth}>
<select
className={['jsX', style.fullWidth].join(' ')}
onChange={handleChange}
value={props.chartState.x}
>
{Object.keys(props.arrays).map((arrayName) => (
<option value={arrayName} key={arrayName}>
{arrayName}
</option>
))}
</select>
</td>
</tr>
<tr>
<td className={style.label}>y</td>
<td>
<select
className={['jsY', style.fullWidth].join(' ')}
onChange={handleChange}
value={props.chartState.y}
>
{Object.keys(props.arrays).map((arrayName) => (
<option value={arrayName} key={arrayName}>
{arrayName}
</option>
))}
</select>
</td>
</tr>
</tbody>
</table>
</div>
);
}

render.propTypes = {
chartState: PropTypes.object,
arrays: PropTypes.object,
onChange: PropTypes.func,
};

render.defaultProps = {
chartState: {},
arrays: [],
onChange: () => {},
};
PieChart.js
import React from 'react';
import PropTypes from 'prop-types';

import style from 'PVWStyle/ReactWidgets/PlotlySelectionWidgets.mcss';

export default function render(props) {
function handleChange(event) {
const rootContainer = event.target.parentNode.parentNode.parentNode;
const newLabelArray = rootContainer.querySelector('.jsLabels').value;
const newValueArray = rootContainer.querySelector('.jsValues').value;
const forceNewPlot =
props.arrays[props.chartState.labels] !== props.arrays[newLabelArray] ||
props.arrays[props.chartState.values] !== props.arrays[newValueArray];
props.onChange({
chartType: 'PieChart',
labels: newLabelArray,
values: newValueArray,
operation: rootContainer.querySelector('.jsOps').value,
forceNewPlot,
});
}

return (
<div>
<table className={style.fullWidth}>
<tbody>
<tr>
<td className={style.label}>labels</td>
<td className={style.fullWidth}>
<select
className={['jsLabels', style.fullWidth].join(' ')}
onChange={handleChange}
value={props.chartState.labels}
>
{Object.keys(props.arrays)
.filter(
(elt, idx, array) => props.arrays[elt] === 'categorical'
)
.map((name) => (
<option value={name} key={name}>
{name}
</option>
))}
</select>
</td>
</tr>
<tr>
<td className={style.label}>values</td>
<td>
<select
className={['jsValues', style.fullWidth].join(' ')}
onChange={handleChange}
value={props.chartState.values}
>
{Object.keys(props.arrays).map((name) => (
<option value={name} key={name}>
{name}
</option>
))}
</select>
</td>
</tr>
<tr>
<td className={style.label}>Operation</td>
<td>
<select
className={['jsOps', style.fullWidth].join(' ')}
onChange={handleChange}
value={props.chartState.operation}
>
<option value="Count" key="Count">
Count
</option>
<option value="Average" key="Average">
Average
</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
);
}

render.propTypes = {
chartState: PropTypes.object,
arrays: PropTypes.object,
onChange: PropTypes.func,
};

render.defaultProps = {
chartState: {},
arrays: [],
onChange: () => {},
};
Scatter3D.js
import React from 'react';
import PropTypes from 'prop-types';

import style from 'PVWStyle/ReactWidgets/PlotlySelectionWidgets.mcss';

/* eslint-disable react/no-unused-prop-types */

export default function render(props) {
function handleChange(event) {
const rootContainer = event.target.parentNode.parentNode.parentNode;
const newXArray = rootContainer.querySelector('.jsX').value;
const newYArray = rootContainer.querySelector('.jsY').value;
const newZArray = rootContainer.querySelector('.jsZ').value;
const forceNewPlot =
props.arrays[props.chartState.x] !== props.arrays[newXArray] ||
props.arrays[props.chartState.y] !== props.arrays[newYArray] ||
props.arrays[props.chartState.z] !== props.arrays[newZArray];
props.onChange({
chartType: 'Scatter3D',
x: newXArray,
y: newYArray,
z: newZArray,
forceNewPlot,
});
}

return (
<div>
<table className={style.fullWidth}>
<tbody>
<tr>
<td className={style.label}>x</td>
<td className={style.fullWidth}>
<select
className={['jsX', style.fullWidth].join(' ')}
onChange={handleChange}
value={props.chartState.x}
>
{Object.keys(props.arrays).map((arrayName) => (
<option value={arrayName} key={arrayName}>
{arrayName}
</option>
))}
</select>
</td>
</tr>
<tr>
<td className={style.label}>y</td>
<td>
<select
className={['jsY', style.fullWidth].join(' ')}
onChange={handleChange}
value={props.chartState.y}
>
{Object.keys(props.arrays).map((arrayName) => (
<option value={arrayName} key={arrayName}>
{arrayName}
</option>
))}
</select>
</td>
</tr>
<tr>
<td className={style.label}>z</td>
<td>
<select
className={['jsZ', style.fullWidth].join(' ')}
onChange={handleChange}
value={props.chartState.z}
>
{Object.keys(props.arrays).map((arrayName) => (
<option value={arrayName} key={arrayName}>
{arrayName}
</option>
))}
</select>
</td>
</tr>
</tbody>
</table>
</div>
);
}

render.propTypes = {
chartState: PropTypes.object,
arrays: PropTypes.object,
onChange: PropTypes.func,
};

render.defaultProps = {
chartState: {},
arrays: [],
onChange: () => {},
};
index.js
import React from 'react';
import PropTypes from 'prop-types';

import CollapsibleWidget from '../../Widgets/CollapsibleWidget';
import DropDownWidget from '../../Widgets/DropDownWidget';

import Histogram from './Histogram';
import Histogram2D from './Histogram2D';
import Scatter3D from './Scatter3D';
import PieChart from './PieChart';

const types = {
Histogram,
Histogram2D,
Scatter3D,
PieChart,
};

export default class PlotlyChartControl extends React.Component {
constructor(props) {
super(props);

// Bind callback
this.updateChartData = this.updateChartData.bind(this);
this.updateChartType = this.updateChartType.bind(this);
}

updateChartType(chartType) {
this.props.model.updateState({
chartType,
});
this.forceUpdate();
}

updateChartData(data) {
this.props.model.updateState(data);
this.forceUpdate();
}

render() {
const arrays = this.props.model.getArrays();
const chartState = this.props.model.getState();

return (
<CollapsibleWidget
title="Chart"
activeSubTitle
subtitle={
<DropDownWidget
field={chartState.chartType}
fields={Object.keys(types)}
onChange={this.updateChartType}
/>
}
>
{React.createElement(types[chartState.chartType], {
chartState,
arrays,
onChange: this.updateChartData,
})}
</CollapsibleWidget>
);
}
}

PlotlyChartControl.propTypes = {
model: PropTypes.object.isRequired,
};