Skip to content

Default fonts and correct plot schema access #52

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
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
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
126 changes: 100 additions & 26 deletions src/DefaultEditor.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
SubPanel,
ColorPicker,
DataSelector,
Dropdown,
Flaglist,
Fold,
Info,
Numeric,
Panel,
PanelMenuWrapper,
Expand All @@ -14,6 +16,7 @@ import {
TraceAccordion,
TraceSelector,
} from './components';
import {DEFAULT_FONTS} from './constants';
import {localize, connectLayoutToPlot} from './lib';

const LayoutPanel = connectLayoutToPlot(Panel);
Expand Down Expand Up @@ -105,13 +108,7 @@ class DefaultEditor extends Component {
<Panel group="Style" name="Traces">
<TraceAccordion>
<Section name={_('Trace')}>
<Numeric
label={_('Opacity')}
min={0}
max={1}
step={0.1}
attr="opacity"
/>
<Numeric label={_('Opacity')} step={0.1} attr="opacity" />
</Section>

<Section name={_('Display')}>
Expand Down Expand Up @@ -144,39 +141,28 @@ class DefaultEditor extends Component {
<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 name={_('Lines')}>
<Numeric
label={_('Width')}
min={0}
step={1.0}
attr="line.width"
/>
<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>
Expand All @@ -187,7 +173,6 @@ class DefaultEditor extends Component {
<Fold name={_('Canvas')}>
<Numeric
label={_('Fixed Width')}
min={100}
step={1}
attr="width"
postfix="px"
Expand All @@ -201,8 +186,97 @@ class DefaultEditor extends Component {
<Radio
attr="showlegend"
options={[
{value: true, label: _('Show')},
{value: false, label: _('Hide')},
{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>
Expand Down
6 changes: 5 additions & 1 deletion src/PlotlyEditor.css
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@
padding: 0 12px;
}

.plotly-editor__field__no-title--center {
text-align: center;
}

.plotly-editor__field__title {
padding-left: 0.5em;
color: #69738a;
Expand All @@ -136,7 +140,7 @@
padding-right: 12px;
}

.plotly-editor__field__widget--prefix {
.plotly-editor__field__widget--postfix {
width: 50%;
padding-right: 0px;
}
Expand Down
71 changes: 71 additions & 0 deletions src/__tests__/connectLayoutToPlot-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import {Numeric} from '../components/fields';
import {Fold, Panel, Section} from '../components/containers';
import NumericInput from '../components/widgets/NumericInputStatefulWrapper';
import React from 'react';
import {EDITOR_ACTIONS} from '../constants';
import {TestEditor, fixtures, plotly} from '../lib/test-utils';
import {connectLayoutToPlot} from '../lib';
import {mount} from 'enzyme';

const Layouts = [Panel, Fold, Section].map(connectLayoutToPlot);
const Editor = props => (
<TestEditor {...{plotly, onUpdate: jest.fn(), ...props}} />
);

Layouts.forEach(Layout => {
describe(`<${Layout.displayName}>`, () => {
it(`wraps container with fullValue pointing to gd._fullLayout`, () => {
const wrapper = mount(
<Editor {...fixtures.scatter({layout: {width: 100}})}>
<Layout>
<Numeric label="Width" step={10} attr="width" />
</Layout>
</Editor>
)
.find('[attr="width"]')
.find(NumericInput);

expect(wrapper.prop('value')).toBe(100);
});

it(`sends updates to gd._layout`, () => {
const onUpdate = jest.fn();
const wrapper = mount(
<Editor
onUpdate={onUpdate}
{...fixtures.scatter({layout: {width: 100}})}
>
<Layout>
<Numeric label="Width" step={10} attr="width" />
</Layout>
</Editor>
)
.find('[attr="width"]')
.find(NumericInput);

wrapper.prop('onChange')(200);
const event = onUpdate.mock.calls[0][0];
expect(event.type).toBe(EDITOR_ACTIONS.UPDATE_LAYOUT);
expect(event.payload).toEqual({update: {width: 200}});
});

it(`automatically computes min and max defaults`, () => {
const onUpdate = jest.fn();
const wrapper = mount(
<Editor
onUpdate={onUpdate}
{...fixtures.scatter({layout: {showlegend: true}})}
>
<Layout>
<Numeric label="Position x" step={0.01} attr="legend.x" />
</Layout>
</Editor>
)
.find('[attr="legend.x"]')
.find(NumericInput);

expect(wrapper.prop('min')).toBe(-2);
expect(wrapper.prop('max')).toBe(3);
});
});
});
70 changes: 70 additions & 0 deletions src/__tests__/connectTraceToPlot-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {Numeric} from '../components/fields';
import {Fold, Panel, Section} from '../components/containers';
import NumericInput from '../components/widgets/NumericInputStatefulWrapper';
import React from 'react';
import {EDITOR_ACTIONS} from '../constants';
import {TestEditor, fixtures, plotly} from '../lib/test-utils';
import {connectTraceToPlot} from '../lib';
import {mount} from 'enzyme';

const Traces = [Panel, Fold, Section].map(connectTraceToPlot);
const Editor = props => (
<TestEditor {...{plotly, onUpdate: jest.fn(), ...props}} />
);

const defaultMarkerSize = 6;

Traces.forEach(Trace => {
describe(`<${Trace.displayName}>`, () => {
it('wraps container with fullValue pointing to gd._fullData[i]', () => {
const wrapper = mount(
<Editor {...fixtures.scatter({deref: true})}>
<Trace traceIndex={0}>
<Numeric label="Marker Size" attr="marker.size" />
</Trace>
</Editor>
)
.find('[attr="marker.size"]')
.find(NumericInput);

expect(wrapper.prop('value')).toBe(defaultMarkerSize);
});

it('sends updates to gd.data', () => {
const onUpdate = jest.fn();
const wrapper = mount(
<Editor onUpdate={onUpdate} {...fixtures.scatter({deref: true})}>
<Trace traceIndex={0}>
<Numeric label="Marker Size" attr="marker.size" />
</Trace>
</Editor>
)
.find('[attr="marker.size"]')
.find(NumericInput);

wrapper.prop('onChange')(200);
const event = onUpdate.mock.calls[0][0];
expect(event.type).toBe(EDITOR_ACTIONS.UPDATE_TRACES);
expect(event.payload).toEqual({
update: {'marker.size': 200},
traceIndexes: [0],
});
});

it('automatically computes min and max defaults', () => {
const onUpdate = jest.fn();
const wrapper = mount(
<Editor onUpdate={onUpdate} {...fixtures.scatter({deref: true})}>
<Trace traceIndex={0}>
<Numeric label="marker size" attr="marker.size" />
</Trace>
</Editor>
)
.find('[attr="marker.size"]')
.find(NumericInput);

expect(wrapper.prop('min')).toBe(0);
expect(wrapper.prop('max')).toBe(undefined);
});
});
});
8 changes: 3 additions & 5 deletions src/components/containers/Fold.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ export default class Fold extends Component {
const {canDelete, name} = this.props;
const doDelete = canDelete && typeof deleteContainer === 'function';
return (
<div className={bem('accordion-panel', 'top', ['active'])}>
<div className={bem('fold', 'top', ['active'])}>
{this.props.name}
{doDelete ? (
<a
className={bem('accordion-panel', 'delete')}
className={bem('fold', 'delete')}
href="#"
onClick={deleteContainer}
>
Expand All @@ -28,9 +28,7 @@ export default class Fold extends Component {
return (
<div>
{this.props.hideHeader ? null : this.renderHeader()}
<div className={bem('accordion-panel', 'panel', modifiers)}>
{this.props.children}
</div>
<div className={bem('fold', modifiers)}>{this.props.children}</div>
</div>
);
}
Expand Down
Loading