Skip to content

Commit 05f31dd

Browse files
authored
Merge pull request #821 from plotly/dtick
AxisInterval adjustments
2 parents 0e20d19 + dc9aaeb commit 05f31dd

File tree

7 files changed

+71
-16
lines changed

7 files changed

+71
-16
lines changed

src/components/fields/AxisInterval.js

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ const MILLISECONDS_IN_DAY = MILLISECONDS_IN_MINUTE * 60 * 24; // eslint-disable-
1313
const DAYS_IN_MONTH = 30;
1414
const MONTHS_IN_YEAR = 12; //eslint-disable-line
1515

16+
function twoDecimalsRound(value) {
17+
return Math.round(value * 100) / 100;
18+
}
19+
1620
function getSmallestUnit(milliseconds) {
1721
const units = {
1822
seconds: MILLISECONDS_IN_SECOND,
@@ -36,7 +40,7 @@ function getSmallestUnit(milliseconds) {
3640
return smallestUnit;
3741
}
3842

39-
class UnconnectedAxisInterval extends Component {
43+
export class UnconnectedAxisInterval extends Component {
4044
constructor(props) {
4145
super(props);
4246

@@ -54,13 +58,22 @@ class UnconnectedAxisInterval extends Component {
5458

5559
update(value) {
5660
let adjustedValue = value < 0 ? 0 : value;
61+
const isValueInteger = adjustedValue % 1 === 0;
5762

5863
if (this.state.units === 'years') {
59-
adjustedValue = 'M' + adjustedValue * MONTHS_IN_YEAR;
64+
if (isValueInteger) {
65+
adjustedValue = 'M' + adjustedValue * MONTHS_IN_YEAR;
66+
} else {
67+
adjustedValue = adjustedValue * MONTHS_IN_YEAR * DAYS_IN_MONTH * MILLISECONDS_IN_DAY;
68+
}
6069
}
6170

6271
if (this.state.units === 'months') {
63-
adjustedValue = 'M' + adjustedValue;
72+
if (isValueInteger) {
73+
adjustedValue = 'M' + adjustedValue;
74+
} else {
75+
adjustedValue = adjustedValue * DAYS_IN_MONTH * MILLISECONDS_IN_DAY;
76+
}
6477
}
6578

6679
if (this.state.units === 'days') {
@@ -89,7 +102,12 @@ class UnconnectedAxisInterval extends Component {
89102
this.setState({units: value});
90103

91104
if (['years', 'months'].includes(value)) {
92-
this.props.updatePlot('M' + Math.round(milliseconds / MILLISECONDS_IN_DAY / DAYS_IN_MONTH));
105+
const nbMonths = milliseconds / MILLISECONDS_IN_DAY / DAYS_IN_MONTH;
106+
if (nbMonths % 1 === 0) {
107+
this.props.updatePlot('M' + nbMonths);
108+
} else {
109+
this.props.updatePlot(milliseconds);
110+
}
93111
} else {
94112
this.props.updatePlot(milliseconds);
95113
}
@@ -100,19 +118,25 @@ class UnconnectedAxisInterval extends Component {
100118
typeof value === 'string' && value[0] === 'M' ? parseInt(value.substring(1), 10) : value;
101119

102120
if (this.state.units === 'years') {
103-
return numericValue / MONTHS_IN_YEAR;
121+
if (typeof value === 'string') {
122+
return twoDecimalsRound(numericValue / MONTHS_IN_YEAR);
123+
}
124+
return twoDecimalsRound(numericValue / MILLISECONDS_IN_DAY / DAYS_IN_MONTH / MONTHS_IN_YEAR);
104125
}
105126
if (this.state.units === 'months') {
106-
return numericValue;
127+
if (typeof value === 'string') {
128+
return twoDecimalsRound(numericValue);
129+
}
130+
return twoDecimalsRound(numericValue / MILLISECONDS_IN_DAY / DAYS_IN_MONTH);
107131
}
108132
if (this.state.units === 'days') {
109-
return Math.round(numericValue / MILLISECONDS_IN_DAY);
133+
return twoDecimalsRound(numericValue / MILLISECONDS_IN_DAY);
110134
}
111135
if (this.state.units === 'minutes') {
112-
return Math.round(numericValue / MILLISECONDS_IN_MINUTE);
136+
return twoDecimalsRound(numericValue / MILLISECONDS_IN_MINUTE);
113137
}
114138
if (this.state.units === 'seconds') {
115-
return Math.round(numericValue / MILLISECONDS_IN_SECOND);
139+
return twoDecimalsRound(numericValue / MILLISECONDS_IN_SECOND);
116140
}
117141
if (this.state.units === 'milliseconds') {
118142
return numericValue;
@@ -126,8 +150,12 @@ class UnconnectedAxisInterval extends Component {
126150
const binStartValue = this.props.fullContainer[attrHead].start;
127151
const BinStartIsDate =
128152
typeof binStartValue === 'string' && (isDateTime(binStartValue) || isJSDate(binStartValue));
153+
const tick0 =
154+
this.props.fullContainer.tick0 &&
155+
(this.props.fullContainer.tick0 || this.props.fullContainer.colorbar.tick0);
156+
const tick0IsDate = tick0 && (isDateTime(tick0) || isJSDate(tick0));
129157

130-
return BinStartIsDate ? (
158+
return BinStartIsDate || tick0IsDate ? (
131159
<Field {...this.props}>
132160
<Dropdown
133161
options={[
@@ -142,7 +170,7 @@ class UnconnectedAxisInterval extends Component {
142170
onChange={value => this.onUnitChange(value)}
143171
value={this.state.units}
144172
/>
145-
<div style={{height: '7px', width: '100%', display: 'block'}}> </div>
173+
<div style={{width: '100%', display: 'block'}}> </div>
146174
<NumericInput
147175
value={this.getDisplayValue(this.props.fullValue)}
148176
onUpdate={value => this.update(value)}

src/components/fields/derived.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {UnconnectedNumeric} from './Numeric';
66
import {UnconnectedNumericOrDate} from './NumericOrDate';
77
import {UnconnectedAxisRangeValue} from './AxisRangeValue';
88
import {UnconnectedRadio} from './Radio';
9+
import {UnconnectedAxisInterval} from './AxisInterval';
910
import Info from './Info';
1011
import {UnconnectedColorPicker} from './ColorPicker';
1112
import {UnconnectedTextEditor} from './TextEditor';
@@ -226,6 +227,24 @@ export const DTicks = connectToContainer(UnconnectedAxisRangeValue, {
226227
},
227228
});
228229

230+
export const DTicksInterval = connectToContainer(UnconnectedAxisInterval, {
231+
modifyPlotProps: (props, context, plotProps) => {
232+
const {fullContainer} = plotProps;
233+
if (
234+
fullContainer &&
235+
fullContainer._name &&
236+
(fullContainer._name.startsWith('lat') || fullContainer._name.startsWith('lon'))
237+
) {
238+
// don't mess with visibility on geo axes
239+
return plotProps;
240+
}
241+
if (plotProps.isVisible && fullContainer && fullContainer.tickmode !== 'linear') {
242+
plotProps.isVisible = false;
243+
}
244+
return plotProps;
245+
},
246+
});
247+
229248
class UnconnectedNumericFraction extends UnconnectedNumeric {}
230249
UnconnectedNumericFraction.propTypes = UnconnectedNumeric.propTypes;
231250
UnconnectedNumericFraction.defaultProps = {

src/components/fields/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
AxesRange,
4141
NTicks,
4242
DTicks,
43+
DTicksInterval,
4344
AxisAnchorDropdown,
4445
ContourNumeric,
4546
FillDropdown,
@@ -72,6 +73,7 @@ export {
7273
AxesRange,
7374
NTicks,
7475
DTicks,
76+
DTicksInterval,
7577
AxesSelector,
7678
ColorPicker,
7779
ColorscalePicker,

src/components/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
AxesRange,
1010
NTicks,
1111
DTicks,
12+
DTicksInterval,
1213
AxesSelector,
1314
ColorPicker,
1415
ColorscalePicker,
@@ -103,6 +104,7 @@ export {
103104
AxisSide,
104105
NTicks,
105106
DTicks,
107+
DTicksInterval,
106108
ShapeAccordion,
107109
RangeSelectorAccordion,
108110
SliderAccordion,

src/default_panels/StyleAxesPanel.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
33
import {
44
AxesRange,
55
DTicks,
6+
DTicksInterval,
67
NTicks,
78
ColorPicker,
89
Dropdown,
@@ -121,7 +122,7 @@ class StyleAxesPanel extends Component {
121122
/>
122123

123124
<DTicks label={_('Step Offset')} attr="tick0" />
124-
<DTicks label={_('Step Size')} attr="dtick" />
125+
<DTicksInterval label={_('Step Size')} attr="dtick" />
125126
<NTicks label={_('Max Number of Lines')} attr="nticks" />
126127
</VisibilitySelect>
127128
</PlotlySection>
@@ -274,7 +275,7 @@ class StyleAxesPanel extends Component {
274275
/>
275276

276277
<DTicks label={_('Step Offset')} attr="tick0" />
277-
<DTicks label={_('Step Size')} attr="dtick" />
278+
<DTicksInterval label={_('Step Size')} attr="dtick" />
278279
<NTicks label={_('Max Number of Labels')} attr="nticks" />
279280
</VisibilitySelect>
280281
</PlotlySection>
@@ -310,7 +311,7 @@ class StyleAxesPanel extends Component {
310311
/>
311312

312313
<DTicks label={_('Step Offset')} attr="tick0" />
313-
<DTicks label={_('Step Size')} attr="dtick" />
314+
<DTicksInterval label={_('Step Size')} attr="dtick" />
314315
<NTicks label={_('Max Number of Markers')} attr="nticks" />
315316
</VisibilitySelect>
316317
</PlotlySection>

src/default_panels/StyleColorbarsPanel.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
ColorPicker,
1616
VisibilitySelect,
1717
NumericOrDate,
18+
AxisInterval,
1819
} from '../components';
1920

2021
export const traceHasColorbar = (trace, fullTrace) =>
@@ -213,7 +214,7 @@ const StyleColorBarsPanel = (props, {localize: _}) => {
213214
/>
214215

215216
<NumericOrDate label={_('Step Offset')} attr={prefix + 'colorbar.tick0'} />
216-
<Numeric label={_('Step Size')} attr={prefix + 'colorbar.dtick'} />
217+
<AxisInterval label={_('Step Size')} attr={prefix + 'colorbar.dtick'} />
217218
<Numeric label={_('Max Number of Labels')} attr={prefix + 'colorbar.nticks'} />
218219
</VisibilitySelect>
219220
</PlotlyFold>
@@ -241,7 +242,7 @@ const StyleColorBarsPanel = (props, {localize: _}) => {
241242
/>
242243

243244
<NumericOrDate label={_('Step Offset')} attr={prefix + 'colorbar.tick0'} />
244-
<Numeric label={_('Step Size')} attr={prefix + 'colorbar.dtick'} />
245+
<AxisInterval label={_('Step Size')} attr={prefix + 'colorbar.dtick'} />
245246
<Numeric label={_('Max Number of Labels')} attr={prefix + 'colorbar.nticks'} />
246247
</VisibilitySelect>
247248
</PlotlyFold>

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
TransformAccordion,
3636
NTicks,
3737
DTicks,
38+
DTicksInterval,
3839
AxesSelector,
3940
PanelMessage,
4041
Button,
@@ -107,6 +108,7 @@ export {
107108
AxesRange,
108109
NTicks,
109110
DTicks,
111+
DTicksInterval,
110112
AxesSelector,
111113
Button,
112114
ColorPicker,

0 commit comments

Comments
 (0)