Skip to content
Merged
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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
"babel-traverse": "^6.26.0",
"css-loader": "^0.28.11",
"cssnano": "^3.10.0",
"enzyme": "^3.1.0",
"enzyme-adapter-react-16": "^1.0.4",
"enzyme": "3.8.0",
"enzyme-adapter-react-16": "1.7.1",
"eslint": "^5.4.0",
"eslint-config-prettier": "^3.0.1",
"eslint-plugin-import": "^2.8.0",
Expand Down
3 changes: 0 additions & 3 deletions src/EditorControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
shamefullyAdjustSplitStyleTargetContainers,
shamefullyDeleteRelatedAnalysisTransforms,
shamefullyAdjustSizeref,
shamefullyAdjustBinSize,
} from './shame';
import {EDITOR_ACTIONS} from './lib/constants';
import isNumeric from 'fast-isnumeric';
Expand Down Expand Up @@ -83,8 +82,6 @@ class EditorControls extends Component {
for (const attr in payload.update) {
const traceIndex = payload.traceIndexes[i];

shamefullyAdjustBinSize(graphDiv, payload, traceIndex);

const splitTraceGroup = payload.splitTraceGroup
? payload.splitTraceGroup.toString()
: null;
Expand Down
175 changes: 175 additions & 0 deletions src/components/fields/AxisInterval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import React, {Component} from 'react';
import Field from './Field';
import Dropdown from '../widgets/Dropdown';
import NumericInput from '../widgets/NumericInput';
import PropTypes from 'prop-types';
import {connectToContainer} from 'lib';
import {isDateTime} from 'plotly.js/src/lib';
import {isJSDate} from 'plotly.js/src/lib/dates';

const MILLISECONDS_IN_SECOND = 1000;
const MILLISECONDS_IN_MINUTE = MILLISECONDS_IN_SECOND * 60; // eslint-disable-line
const MILLISECONDS_IN_DAY = MILLISECONDS_IN_MINUTE * 60 * 24; // eslint-disable-line
const DAYS_IN_MONTH = 30;
const MONTHS_IN_YEAR = 12; //eslint-disable-line

function getSmallestUnit(milliseconds) {
const units = {
seconds: MILLISECONDS_IN_SECOND,
minutes: MILLISECONDS_IN_MINUTE,
days: MILLISECONDS_IN_DAY,
};

let smallestUnit = 'milliseconds';

['seconds', 'minutes', 'days'].forEach(unit => {
if (
milliseconds % units[unit] === 0 &&
(smallestUnit === 'milliseconds' ||
(smallestUnit !== 'milliseconds' &&
milliseconds / units[smallestUnit] > milliseconds / units[unit]))
) {
smallestUnit = unit;
}
});

return smallestUnit;
}

class UnconnectedAxisInterval extends Component {
constructor(props) {
super(props);

const initialUnit =
props.fullValue && typeof props.fullValue === 'string' && props.fullValue[0] === 'M'
? parseInt(props.fullValue.substring(1), 10) % MONTHS_IN_YEAR === 0
? 'years'
: 'months'
: getSmallestUnit(props.fullValue);

this.state = {
units: initialUnit,
};
}

update(value) {
let adjustedValue = value < 0 ? 0 : value;

if (this.state.units === 'years') {
adjustedValue = 'M' + adjustedValue * MONTHS_IN_YEAR;
}

if (this.state.units === 'months') {
adjustedValue = 'M' + adjustedValue;
}

if (this.state.units === 'days') {
adjustedValue = adjustedValue * MILLISECONDS_IN_DAY;
}

if (this.state.units === 'minutes') {
adjustedValue = adjustedValue * MILLISECONDS_IN_MINUTE;
}

if (this.state.units === 'seconds') {
adjustedValue = adjustedValue * MILLISECONDS_IN_SECOND;
}

this.props.updatePlot(adjustedValue);
}

onUnitChange(value) {
const isFullValueMonthFormat =
typeof this.props.fullValue === 'string' && this.props.fullValue[0] === 'M';

const milliseconds = isFullValueMonthFormat
? parseInt(this.props.fullValue.substring(1), 10) * DAYS_IN_MONTH * MILLISECONDS_IN_DAY
: this.props.fullValue;

this.setState({units: value});

if (['years', 'months'].includes(value)) {
this.props.updatePlot('M' + Math.round(milliseconds / MILLISECONDS_IN_DAY / DAYS_IN_MONTH));
} else {
this.props.updatePlot(milliseconds);
}
}

getDisplayValue(value) {
const numericValue =
typeof value === 'string' && value[0] === 'M' ? parseInt(value.substring(1), 10) : value;

if (this.state.units === 'years') {
return numericValue / MONTHS_IN_YEAR;
}
if (this.state.units === 'months') {
return numericValue;
}
if (this.state.units === 'days') {
return Math.round(numericValue / MILLISECONDS_IN_DAY);
}
if (this.state.units === 'minutes') {
return Math.round(numericValue / MILLISECONDS_IN_MINUTE);
}
if (this.state.units === 'seconds') {
return Math.round(numericValue / MILLISECONDS_IN_SECOND);
}
if (this.state.units === 'milliseconds') {
return numericValue;
}
return null;
}

render() {
const _ = this.context.localize;
const attrHead = this.props.attr.split('.')[0];
const binStartValue = this.props.fullContainer[attrHead].start;
const BinStartIsDate =
typeof binStartValue === 'string' && (isDateTime(binStartValue) || isJSDate(binStartValue));

return BinStartIsDate ? (
<Field {...this.props}>
<Dropdown
options={[
{value: 'years', label: _('Years')},
{value: 'months', label: _('Months')},
{value: 'days', label: _('Days')},
{value: 'minutes', label: _('Minutes')},
{value: 'seconds', label: _('Seconds')},
{value: 'milliseconds', label: _('Milliseconds')},
]}
clearable={false}
onChange={value => this.onUnitChange(value)}
value={this.state.units}
/>
<div style={{height: '7px', width: '100%', display: 'block'}}> </div>
<NumericInput
value={this.getDisplayValue(this.props.fullValue)}
onUpdate={value => this.update(value)}
editableClassName="AxisInterval-milliseconds"
/>
</Field>
) : (
<Field {...this.props}>
<NumericInput
value={this.props.fullValue}
onUpdate={value => this.props.updatePlot(value)}
/>
</Field>
);
}
}

UnconnectedAxisInterval.contextTypes = {
localize: PropTypes.func,
};

UnconnectedAxisInterval.propTypes = {
fullValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
updatePlot: PropTypes.func,
attr: PropTypes.string,
fullContainer: PropTypes.object,
...Field.propTypes,
};

export default connectToContainer(UnconnectedAxisInterval);
12 changes: 0 additions & 12 deletions src/components/fields/derived.js
Original file line number Diff line number Diff line change
Expand Up @@ -699,15 +699,3 @@ export const HoverColor = connectToContainer(UnconnectedColorPicker, {
return plotProps;
},
});

export const BinSize = connectToContainer(UnconnectedNumeric, {
modifyPlotProps: (props, context, plotProps) => {
const {localize: _} = context;
if (typeof plotProps.fullValue === 'string' && plotProps.fullValue[0] === 'M') {
plotProps.fullValue = plotProps.fullValue.substring(1);
plotProps.min = 1;
plotProps.max = 12;
plotProps.units = parseInt(plotProps.fullValue, 10) === 1 ? _('Month') : _('Months');
}
},
});
4 changes: 2 additions & 2 deletions src/components/fields/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import DropdownCustom from './DropdownCustom';
import MultiColorPicker from './MultiColorPicker';
import RectanglePositioner from './RectanglePositioner';
import LocationSelector from './LocationSelector';
import AxisInterval from './AxisInterval';
import {
AnnotationArrowRef,
AnnotationRef,
Expand All @@ -58,7 +59,6 @@ import {
HoveronDropdown,
HovermodeDropdown,
TickFormat,
BinSize,
} from './derived';
import {LineDashSelector, LineShapeSelector} from './LineSelectors';

Expand Down Expand Up @@ -124,6 +124,6 @@ export {
LocationSelector,
HoveronDropdown,
HovermodeDropdown,
BinSize,
AxisInterval,
NumericOrDate,
};
2 changes: 2 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import {
HovermodeDropdown,
TickFormat,
NumericOrDate,
AxisInterval,
} from './fields';

import {
Expand Down Expand Up @@ -181,4 +182,5 @@ export {
HoveronDropdown,
HovermodeDropdown,
NumericOrDate,
AxisInterval,
};
6 changes: 3 additions & 3 deletions src/default_panels/StyleTracesPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ import {
VisibilitySelect,
GroupCreator,
NumericOrDate,
AxisInterval,
} from '../components';
import {
BinningDropdown,
NumericReciprocal,
ShowInLegend,
TextInfo,
HoveronDropdown,
BinSize,
} from '../components/fields/derived';

const StyleTracesPanel = (props, {localize: _}) => (
Expand Down Expand Up @@ -229,13 +229,13 @@ const StyleTracesPanel = (props, {localize: _}) => (
<PlotlySection name={_('Binning')}>
<NumericOrDate label={_('X Bin Start')} attr="xbins.start" axis="x" />
<NumericOrDate label={_('X Bin End')} attr="xbins.end" axis="x" />
<BinSize label={_('X Bin Size')} attr="xbins.size" axis="x" />
<Numeric label={_('Max X Bins')} attr="nbinsx" />
<AxisInterval label={_('X Bin Size')} attr="xbins.size" axis="x" />

<NumericOrDate label={_('Y Bin Start')} attr="ybins.start" axis="y" />
<NumericOrDate label={_('Y Bin End')} attr="ybins.end" axis="y" />
<BinSize label={_('Y Bin Size')} attr="ybins.size" axis="y" />
<Numeric label={_('Max Y Bins')} attr="nbinsy" />
<AxisInterval label={_('Y Bin Size')} attr="ybins.size" axis="y" />
</PlotlySection>
<PlotlySection label={_('Bar Position')}>
<NumericOrDate label={_('Base')} attr="base" />
Expand Down
20 changes: 0 additions & 20 deletions src/shame.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/
import {getFromId} from 'plotly.js/src/plots/cartesian/axis_ids';
import nestedProperty from 'plotly.js/src/lib/nested_property';
import {isDateTime} from 'plotly.js/src/lib';

// Temporary fix for:
// https://github.com/plotly/react-chart-editor/issues/103
Expand Down Expand Up @@ -213,22 +212,3 @@ export const shamefullyAdjustSizeref = (gd, {update}) => {
update['marker.sizemode'] = 'area';
}
};

export const shamefullyAdjustBinSize = (gd, {update}, traceIndexInDataArray) => {
const traceIndexInFullDataArray = gd._fullData.filter(t => t.index === traceIndexInDataArray)[0]
._expandedIndex;
const binSizeAttrs = Object.keys(update).filter(attr => attr.includes('bins.size'));

binSizeAttrs.forEach(attr => {
const attrHead = attr.split('.')[0];
if (
gd._fullData[traceIndexInFullDataArray] &&
gd._fullData[traceIndexInFullDataArray][attrHead] &&
gd._fullData[traceIndexInFullDataArray][attrHead].start &&
isDateTime(gd._fullData[traceIndexInFullDataArray][attrHead].start)
) {
const monthNum = update[attr];
update[attr] = 'M' + monthNum;
}
});
};
4 changes: 4 additions & 0 deletions src/styles/components/widgets/_numeric-input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,7 @@
height: 13px !important;
fill: var(--color-text-base) !important;
}

.AxisInterval-milliseconds {
width: 50%;
}