Skip to content

Group style panels #160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/simple/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'},
};

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"raf": "^3.4.0",
"react-color": "^2.13.8",
"react-select": "^1.0.0-rc.10",
"react-tabs": "^2.0.0",
"tinycolor2": "^1.4.1"
},
"browserify-global-shim": {
Expand Down
2 changes: 1 addition & 1 deletion src/DefaultEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class DefaultEditor extends Component {
</Panel>

<Panel group="Style" name="Traces">
<TraceAccordion>
<TraceAccordion canGroup>
<Section name={_('Trace')}>
<Numeric label={_('Opacity')} step={0.1} attr="opacity" />
</Section>
Expand Down
2 changes: 1 addition & 1 deletion src/PlotlyEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
62 changes: 54 additions & 8 deletions src/components/containers/TraceAccordion.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import Fold from './Fold';
import PropTypes from 'prop-types';
import React, {Component} from 'react';
import {EDITOR_ACTIONS} from '../../lib/constants';
import {connectTraceToPlot} from '../../lib';
import {connectTraceToPlot, plotlyToCustom} from '../../lib';
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';

const TraceFold = connectTraceToPlot(Fold);

export default class TraceAccordion extends Component {
constructor(props) {
super(props);

this.addTrace = this.addTrace.bind(this);
}

Expand All @@ -23,29 +23,75 @@ export default class TraceAccordion extends Component {

render() {
const data = this.context.data || [];
const fullData = this.context.fullData || [];
const {canGroup, canAdd} = this.props;
const individualPanel = data.map((d, i) => (
<TraceFold key={i} traceIndexes={[i]}>
{this.props.children}
</TraceFold>
));
let content = individualPanel;

if (canGroup && data.length > 1) {
const groupedTraces = data.reduce((allTraces, next, index) => {
const traceType = plotlyToCustom(
fullData.filter(trace => trace.index === index)[0]
);
if (allTraces[traceType]) {
allTraces[traceType].push(index);
} else {
allTraces[traceType] = [index];
}
return allTraces;
}, {});

const groupedPanel = Object.keys(groupedTraces).map(
(traceType, index) => {
return (
<TraceFold
key={index}
traceIndexes={groupedTraces[traceType]}
name={traceType}
>
{this.props.children}
</TraceFold>
);
}
);

content = (
<Tabs>
<TabList>
<Tab>Grouped</Tab>
<Tab>Individual</Tab>
</TabList>
<TabPanel key={0}>{groupedPanel}</TabPanel>
<TabPanel key={1}>{individualPanel}</TabPanel>
</Tabs>
);
}

return (
<div>
{this.props.canAdd ? (
{canAdd ? (
<button className="panel__add-button" onClick={this.addTrace}>
+ Trace
</button>
) : null}
{data.map((d, i) => (
<TraceFold key={i} traceIndex={i}>
{this.props.children}
</TraceFold>
))}
{content}
</div>
);
}
}

TraceAccordion.contextTypes = {
fullData: PropTypes.array,
data: PropTypes.array,
onUpdate: PropTypes.func,
};

TraceAccordion.propTypes = {
children: PropTypes.node,
canAdd: PropTypes.bool,
canGroup: PropTypes.bool,
};
11 changes: 0 additions & 11 deletions src/components/fields/Field.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,6 @@ import {bem, localize} from '../../lib';
import {getMultiValueText} from '../../lib/constants';

class Field extends Component {
renderPostfix() {
if (!this.props.units) {
return null;
}
return (
<div className={bem('field', 'units')}>
<div className={bem('field', 'units-text')}>{this.props.units}</div>
</div>
);
}

render() {
const {
center,
Expand Down
29 changes: 4 additions & 25 deletions src/components/fields/TraceSelector.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
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, customToPlotly, plotlyToCustom} from '../../lib';

function computeTraceOptionsFromSchema(schema) {
const capitalize = s => s.charAt(0).toUpperCase() + s.substring(1);
Expand Down Expand Up @@ -62,35 +61,15 @@ 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 = plotlyToCustom(props.fullContainer);
}

componentWillReceiveProps(nextProps, nextContext) {
this.setLocals(nextProps, nextContext);
}

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 = customToPlotly(value);

if (this.props.updateContainer) {
this.props.updateContainer(update);
Expand All @@ -114,7 +93,7 @@ TraceSelector.contextTypes = {

TraceSelector.propTypes = {
getValObject: PropTypes.func,
container: PropTypes.object.isRequired,
fullContainer: PropTypes.object.isRequired,
fullValue: PropTypes.any.isRequired,
updateContainer: PropTypes.func,
};
Expand Down
15 changes: 9 additions & 6 deletions src/lib/connectTraceToPlot.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ export default function connectTraceToPlot(WrappedComponent) {
}

setLocals(props, context) {
const {traceIndex} = props;
const {traceIndexes} = props;
const {data, fullData, plotly} = context;

const trace = data[traceIndex] || {};
const fullTraceIndex = findFullTraceIndex(fullData, traceIndex);
const trace = traceIndexes.length === 1 ? data[traceIndexes[0]] : {};
const fullTraceIndex =
traceIndexes.length === 1
? findFullTraceIndex(fullData, traceIndexes[0])
: findFullTraceIndex(fullData, 0);
const fullTrace = fullData[fullTraceIndex] || {};

let getValObject;
Expand Down Expand Up @@ -55,7 +58,7 @@ export default function connectTraceToPlot(WrappedComponent) {
type: EDITOR_ACTIONS.UPDATE_TRACES,
payload: {
update,
traceIndexes: [this.props.traceIndex],
traceIndexes: this.props.traceIndexes,
},
});
}
Expand All @@ -65,7 +68,7 @@ export default function connectTraceToPlot(WrappedComponent) {
if (this.context.onUpdate) {
this.context.onUpdate({
type: EDITOR_ACTIONS.DELETE_TRACE,
payload: {traceIndexes: [this.props.traceIndex]},
payload: {traceIndexes: this.props.traceIndexes},
});
}
}
Expand All @@ -80,7 +83,7 @@ export default function connectTraceToPlot(WrappedComponent) {
)}`;

TraceConnectedComponent.propTypes = {
traceIndex: PropTypes.number.isRequired,
traceIndexes: PropTypes.array,
};

TraceConnectedComponent.contextTypes = {
Expand Down
5 changes: 4 additions & 1 deletion src/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import localize, {localizeString} from './localize';
import tinyColor from 'tinycolor2';
import unpackPlotProps from './unpackPlotProps';
import walkObject, {isPlainObject} from './walkObject';
import {customToPlotly, plotlyToCustom} from './customTraceType';

function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
Expand All @@ -33,14 +34,16 @@ export {
connectLayoutToPlot,
connectToContainer,
connectTraceToPlot,
customToPlotly,
dereference,
findFullTraceIndex,
getDisplayName,
getLayoutContext,
findFullTraceIndex,
icon,
isPlainObject,
localize,
localizeString,
plotlyToCustom,
unpackPlotProps,
walkObject,
};