Skip to content

Robust plot schema lookups #48

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

Merged
merged 54 commits into from
Nov 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
ee5a3ce
compute plotSchema once
bpostlethwaite Nov 6, 2017
dacd88f
use official plotSchema accessor functions
bpostlethwaite Nov 6, 2017
818852d
filter out Polar area chart
bpostlethwaite Nov 6, 2017
de28c9c
make a "concrete" container layer in component API
bpostlethwaite Nov 6, 2017
fee7a6c
include developer architecture overview in README
bpostlethwaite Nov 6, 2017
9ed2b6a
replace trace value update array with scalar update
bpostlethwaite Nov 6, 2017
1efa2fb
add Layout component and Layout update pathway
bpostlethwaite Nov 6, 2017
4a7e250
lint ModeMenuSection
bpostlethwaite Nov 6, 2017
447524f
allow deep merge inside fixtures via config
bpostlethwaite Nov 6, 2017
cb0e36f
test <Layout>
bpostlethwaite Nov 6, 2017
ad33364
generalize trace accordion css for consumption elsewhere
bpostlethwaite Nov 7, 2017
c9ad7b9
use connectTraceToPlot over <Fold> to replace <Trace>
bpostlethwaite Nov 7, 2017
7c01592
connectToPlot -> connectToContainer
bpostlethwaite Nov 7, 2017
ec55a3e
lint and remove unnecessary imports
bpostlethwaite Nov 7, 2017
d3608d3
use connectToLayout over <Layout> component
bpostlethwaite Nov 7, 2017
b014671
update README
bpostlethwaite Nov 7, 2017
c5f72aa
Section.header -> Section.name for consistency with Panel etc
bpostlethwaite Nov 8, 2017
467bc35
Fold now has noheader variant
bpostlethwaite Nov 8, 2017
87e787d
<Field> component handles Field configuration DRY
bpostlethwaite Nov 8, 2017
058170a
Numeric FixedWidth field utilizes postfix
bpostlethwaite Nov 8, 2017
2bb2746
create field and containers folder. Move tonnes of files around
bpostlethwaite Nov 8, 2017
d2b5e92
move tests into new containers and fields folders
bpostlethwaite Nov 8, 2017
212b4de
edit test import paths
bpostlethwaite Nov 8, 2017
d9ea40c
move ModeBar into sidebar folder
bpostlethwaite Nov 8, 2017
f8d64a0
rename Modemenu -> Sidebar
bpostlethwaite Nov 8, 2017
e563f8b
Sidebar.section -> Sidebar.group to avoid confusion with <Section>
bpostlethwaite Nov 8, 2017
4feec01
lint PlotlyEditor
bpostlethwaite Nov 8, 2017
daeea6c
remove unused PlotlyEditor.scss
bpostlethwaite Nov 8, 2017
5bb3f64
add Default fonts and a few more widgets to DefaultEditor
bpostlethwaite Nov 8, 2017
83d98e9
fix plotschema accessor call + add handling for min and max
bpostlethwaite Nov 8, 2017
4ce092f
remove hardcoded min and max values from DefaultEditor
bpostlethwaite Nov 8, 2017
4adbdf2
Pass all props to <Field>. <Radio> defaults center=true
bpostlethwaite Nov 8, 2017
4c67019
Field handles centering and test <Radio> center override
bpostlethwaite Nov 8, 2017
46a2eba
small cleanup. Label, Value ordering in DefaultEditor
bpostlethwaite Nov 8, 2017
26506f4
port css over to scss. Swap `bem` to use hierarchical namespacing
bpostlethwaite Nov 8, 2017
8058d55
Colorpicker uses BEM and a some folder structure changes
bpostlethwaite Nov 9, 2017
12ace8c
delete files that are not in use
bpostlethwaite Nov 10, 2017
3b02455
split out styles/containers into separate files
bpostlethwaite Nov 10, 2017
e319b00
add initial icon support
bpostlethwaite Nov 10, 2017
000b5f1
Add plotly.js default font to default font list
bpostlethwaite Nov 10, 2017
68a41af
rename css class accordion -> fold
bpostlethwaite Nov 10, 2017
6896707
introduce CogMenu and Info
bpostlethwaite Nov 10, 2017
6335fbb
Section looks for CogMenu for special placement
bpostlethwaite Nov 10, 2017
d6f2375
Use CogMenu in Legend in DefaultEditor
bpostlethwaite Nov 10, 2017
9628ccd
css cogmenu becomes a more generic subpanel
bpostlethwaite Nov 10, 2017
2225452
rename CogMenu to SubPanel
bpostlethwaite Nov 10, 2017
440f88b
Section handles non Attr children as default Visible
bpostlethwaite Nov 10, 2017
51f7b46
add subMenu to DefaultEditor
bpostlethwaite Nov 10, 2017
7becfbe
test Section visibility and SubPanel handling
bpostlethwaite Nov 10, 2017
9367381
Merge pull request #54 from plotly/SubMenus
bpostlethwaite Nov 13, 2017
254106c
Merge pull request #53 from plotly/CenteringOfFieldsWithNoLabels
bpostlethwaite Nov 13, 2017
601fb70
Merge pull request #52 from plotly/DefaultFontsAndCorrectPlotSchemaAc…
bpostlethwaite Nov 13, 2017
7b852a5
Merge pull request #50 from plotly/reorganizeFolderStructure
bpostlethwaite Nov 13, 2017
62a29d7
Merge pull request #49 from plotly/IntroduceLayout
bpostlethwaite Nov 13, 2017
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
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ To build the dist version:
$ npm run prepublish
```

## Developer notes
A PlotlyEditor widgets is composed of 3 layers:

### Layer 1: Base Component
```
<PlotlyEditor>
```

### Layer 2: Container Components:
One or more nested Container Components with one and only one connected by a connect<Container>ToPlot function (connectLayoutToPlot, connectTraceToPlot).
```
<Panel>, <Section>, <Fold>
```

### Layer 3: Attribute Widgets
Each connected by a `connectContainerToPlot` function
<Numeric>, <ColorPicker>, <Radio> and remaining UI Controls
```

Data flows via `context` downward and is augmented with additional information at each layer boundary.
The Base Components aggregate references to the graphDiv objects (data, fullData, layout...), grid Data sources, locale, update functions etc. One of the Container Components uses its knowledge about which container to target (traces, layout, ...) to generate fewer but more specific containers and updaters which are passed down the hierarchy. The Attribute widgets are higher-order wrappers around dumb UI controls. The higher-order wrapper uses the container contexts and specific attributes information to provide specific plot update functions and other behaviours for the inner UI control.

## See also

- [plotlyjs-react](https://github.com/plotly/plotlyjs-react)
Expand Down
199 changes: 155 additions & 44 deletions src/DefaultEditor.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
import ColorPicker from './components/Color';
import Dropdown from './components/Dropdown';
import DataSelector from './components/DataSelector';
import TraceSelector from './components/TraceSelector';
import Flaglist from './components/Flaglist';
import Numeric from './components/Numeric';
import Panel from './components/Panel';
import PanelMenuWrapper from './components/PanelMenuWrapper';
import PropTypes from 'prop-types';
import Radio from './components/Radio';
import React, {Component} from 'react';
import Section from './components/Section';
import TraceAccordion from './components/TraceAccordion';
import {localize} from './lib';
import PropTypes from 'prop-types';
import {
SubPanel,
ColorPicker,
DataSelector,
Dropdown,
Flaglist,
Fold,
Info,
Numeric,
Panel,
PanelMenuWrapper,
Radio,
Section,
TraceAccordion,
TraceSelector,
} from './components';
import {DEFAULT_FONTS} from './constants';
import {localize, connectLayoutToPlot} from './lib';

const LayoutPanel = connectLayoutToPlot(Panel);

class DefaultEditor extends Component {
constructor(props, context) {
super(props, context);

const capitalize = s => s.charAt(0).toUpperCase() + s.substring(1);
const traceTypes = Object.keys(context.plotSchema.traces);

// Filter out Polar "area" type (it is fairly broken and we want to present
// scatter with fill as an "area" chart type for convenience.
const traceTypes = Object.keys(context.plotSchema.traces).filter(
t => t !== 'area'
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hopefully not for long 🙏


const labels = traceTypes.map(capitalize);
this.traceOptions = traceTypes.map((t, i) => ({
label: labels[i],
Expand All @@ -39,7 +53,7 @@ class DefaultEditor extends Component {

return (
<PanelMenuWrapper>
<Panel section="Graph" name="Create">
<Panel group="Graph" name="Create">
<TraceAccordion canAdd>
<TraceSelector
label="Plot Type"
Expand Down Expand Up @@ -91,19 +105,13 @@ class DefaultEditor extends Component {
</TraceAccordion>
</Panel>

<Panel section="Style" name="Traces">
<Panel group="Style" name="Traces">
<TraceAccordion>
<Section heading={_('Trace')}>
<Numeric
label={_('Opacity')}
min={0}
max={1}
step={0.1}
attr="opacity"
/>
<Section name={_('Trace')}>
<Numeric label={_('Opacity')} step={0.1} attr="opacity" />
</Section>

<Section heading={_('Display')}>
<Section name={_('Display')}>
<Flaglist
attr="mode"
options={[
Expand All @@ -113,7 +121,7 @@ class DefaultEditor extends Component {
/>
</Section>

<Section heading={_('Filled Area')}>
<Section name={_('Filled Area')}>
<Dropdown
label="Fill to"
attr="fill"
Expand All @@ -130,47 +138,150 @@ class DefaultEditor extends Component {
<ColorPicker label={_('Color')} attr="fillcolor" />
</Section>

<Section heading={_('Points')}>
<Section name={_('Points')}>
<Numeric
label={_('Marker Opacity')}
min={0}
max={1}
step={0.1}
attr="marker.opacity"
/>

<ColorPicker label={_('Marker Color')} attr="marker.color" />

<Numeric label={_('Size')} min={0} attr="marker.size" />
<Numeric label={_('Size')} attr="marker.size" />

<Numeric
label={_('Line width')}
min={0}
attr="marker.line.width"
/>
<Numeric label={_('Line width')} attr="marker.line.width" />
</Section>

<Section heading={_('Lines')}>
<Numeric
label={_('Width')}
min={0}
step={1.0}
attr="line.width"
/>
<Section name={_('Lines')}>
<Numeric label={_('Width')} step={1.0} attr="line.width" />

<ColorPicker label={_('Line color')} attr="line.color" />

<Radio
label={_('Connect Gaps')}
attr="connectgaps"
options={[
{value: true, label: 'Connect'},
{value: false, label: 'Blank'},
{label: _('Connect'), value: true},
{label: _('Blank'), value: false},
]}
/>
</Section>
</TraceAccordion>
</Panel>

<LayoutPanel group="Style" name={_('Layout')}>
<Fold name={_('Canvas')}>
<Numeric
label={_('Fixed Width')}
step={1}
attr="width"
postfix="px"
/>
</Fold>
</LayoutPanel>

<LayoutPanel group="Style" name={_('Legend')}>
<Fold hideHeader>
<Section name={_('Legend')}>
<Radio
attr="showlegend"
options={[
{label: _('Show'), value: true},
{label: _('Hide'), value: false},
]}
/>
</Section>
<Section name={_('Text')}>
<Dropdown
label={_('Typeface')}
attr="legend.font.family"
clearable={false}
options={[...DEFAULT_FONTS]}
/>
<Numeric
label={_('Size')}
step={1}
attr="legend.font.size"
postfix="px"
/>
<ColorPicker label={_('Color')} attr="legend.font.color" />
</Section>
<Section name={_('Legend Box')}>
<Numeric
label={_('Border Width')}
step={1}
attr="legend.borderwidth"
postfix="px"
/>
<ColorPicker
label={_('Border Color')}
attr="legend.bordercolor"
/>
<ColorPicker
label={_('Background Color')}
attr="legend.bgcolor"
/>
</Section>
<Section name={_('Positioning')}>
<SubPanel>
<Section name={_('Anchor Point')}>
<Info>
{_(
'The positioning inputs are relative to the ' +
'anchor points on the text box'
)}
</Info>
<Radio
attr="legend.xanchor"
options={[
{label: _('Left'), value: 'left'},
{label: _('Center'), value: 'center'},
{label: _('Right'), value: 'right'},
]}
/>
<Radio
attr="legend.yanchor"
options={[
{label: _('Top'), value: 'top'},
{label: _('Middle'), value: 'middle'},
{label: _('Bottom'), value: 'bottom'},
]}
/>
</Section>
</SubPanel>
<Numeric
label={_('X Position')}
step={0.01}
attr="legend.x"
postfix="px"
/>
<Numeric
label={_('Y Position')}
step={0.01}
attr="legend.y"
postfix="px"
/>
</Section>
<Section name={_('Orientation')}>
<Radio
attr="legend.orientation"
options={[
{label: _('Vertical'), value: 'v'},
{label: _('Horizontal'), value: 'h'},
]}
/>
</Section>
<Section name={_('Trace Order')}>
<Radio
attr="legend.traceorder"
options={[
{label: _('Normal'), value: 'normal'},
{label: _('Reversed'), value: 'reversed'},
]}
/>
</Section>
</Fold>
</LayoutPanel>
</PanelMenuWrapper>
);
}
Expand Down
Loading