mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Show bucket size for Time Series Visual Builder on X-Axis (#11639)
* Adding seconds to the timeseries tooltip * Adding x-axis label to show the bucket size
This commit is contained in:
parent
ee6fa6bcc9
commit
98de700e51
8 changed files with 72 additions and 4 deletions
|
@ -0,0 +1,16 @@
|
|||
import { expect } from 'chai';
|
||||
import { getAxisLabelString } from '../get_axis_label_string';
|
||||
|
||||
describe('getAxisLabelString(interval)', () => {
|
||||
it('should return a valid label for 10 seconds', () => {
|
||||
expect(getAxisLabelString(10000)).to.equal('per 10 seconds');
|
||||
});
|
||||
it('should return a valid label for 2 minutes', () => {
|
||||
expect(getAxisLabelString(120000)).to.equal('per 2 minutes');
|
||||
});
|
||||
it('should return a valid label for 2 hour', () => {
|
||||
expect(getAxisLabelString(7200000)).to.equal('per 2 hours');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { relativeOptions } from '../../../../../ui/public/timepicker/relative_options';
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
const unitLookup = {
|
||||
s: 'seconds',
|
||||
m: 'minutes',
|
||||
h: 'hours',
|
||||
d: 'days',
|
||||
w: 'weeks',
|
||||
M: 'months',
|
||||
y: 'years'
|
||||
};
|
||||
export function getAxisLabelString(interval) {
|
||||
const units = _.pluck(_.clone(relativeOptions).reverse(), 'value')
|
||||
.filter(s => /^[smhdwMy]$/.test(s));
|
||||
const duration = moment.duration(interval, 'ms');
|
||||
for (let i = 0; i < units.length; i++) {
|
||||
const as = duration.as(units[i]);
|
||||
if (Math.abs(as) > 1) {
|
||||
const unitValue = Math.round(Math.abs(as));
|
||||
const unitString = unitLookup[units[i]];
|
||||
return `per ${unitValue} ${unitString}`;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import _ from 'lodash';
|
|||
import { Timeseries } from 'plugins/metrics/visualizations';
|
||||
import color from 'color';
|
||||
import replaceVars from '../../lib/replace_vars';
|
||||
import { getAxisLabelString } from '../../lib/get_axis_label_string';
|
||||
|
||||
function hasSeperateAxis(row) {
|
||||
return row.seperate_axis;
|
||||
|
@ -76,6 +77,10 @@ function TimeseriesVisualization(props) {
|
|||
}
|
||||
});
|
||||
|
||||
const interval = series.reduce((currentInterval, item) => {
|
||||
const seriesInterval = item.data[1][0] - item.data[0][0];
|
||||
if (!currentInterval || seriesInterval < currentInterval) return seriesInterval;
|
||||
}, 0);
|
||||
|
||||
let axisCount = 1;
|
||||
if (seriesModel.some(hasSeperateAxis)) {
|
||||
|
@ -120,6 +125,9 @@ function TimeseriesVisualization(props) {
|
|||
if (props.onBrush) props.onBrush(ranges);
|
||||
}
|
||||
};
|
||||
if (interval) {
|
||||
params.xaxisLabel = getAxisLabelString(interval);
|
||||
}
|
||||
const style = { };
|
||||
const panelBackgroundColor = model.background_color || backgroundColor;
|
||||
if (panelBackgroundColor) {
|
||||
|
|
|
@ -102,3 +102,4 @@
|
|||
color: rgba(255,255,255,0.8);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import parseInterval from 'ui/utils/parse_interval';
|
||||
import { parseInterval } from 'ui/utils/parse_interval';
|
||||
export function validateInterval(timefilter, panel, maxBuckets) {
|
||||
const { interval } = panel;
|
||||
const { min, max } = timefilter.getBounds();
|
||||
|
|
|
@ -130,6 +130,7 @@ class Timeseries extends Component {
|
|||
show={ this.state.show }
|
||||
tickFormatter={this.props.tickFormatter}
|
||||
options={this.props.options}
|
||||
xaxisLabel={this.props.xaxisLabel}
|
||||
yaxes={this.props.yaxes} />
|
||||
</div>
|
||||
<Legend
|
||||
|
@ -162,7 +163,8 @@ Timeseries.propTypes = {
|
|||
annotations: PropTypes.array,
|
||||
reversed: PropTypes.bool,
|
||||
options: PropTypes.object,
|
||||
tickFormatter: PropTypes.func
|
||||
tickFormatter: PropTypes.func,
|
||||
xaxisLabel: PropTypes.string
|
||||
};
|
||||
|
||||
export default Timeseries;
|
||||
|
|
|
@ -172,7 +172,7 @@ class TimeseriesChart extends Component {
|
|||
<div style={styles.text}>{ item.series.label }</div>
|
||||
<div style={styles.value}>{ formatter(value) }</div>
|
||||
</div>
|
||||
<div style={styles.date}>{ moment(item.datapoint[0]).format('lll') }</div>
|
||||
<div style={styles.date}>{ moment(item.datapoint[0]).format('ll LTS') }</div>
|
||||
</div>
|
||||
<i className="fa fa-caret-right" style={styles.rightCaret}></i>
|
||||
</div>
|
||||
|
@ -197,12 +197,17 @@ class TimeseriesChart extends Component {
|
|||
};
|
||||
|
||||
const annotations = this.state.annotations.map(this.renderAnnotations);
|
||||
let axisLabelClass = 'rhythm_chart__axis-label';
|
||||
if (this.props.reversed) {
|
||||
axisLabelClass += ' reversed';
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={(el) => this.container = el} className="rhythm_chart__timeseries-container">
|
||||
{ tooltip }
|
||||
{ annotations }
|
||||
<FlotChart {...params}/>
|
||||
<div className={axisLabelClass}>{this.props.xaxisLabel}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -221,6 +226,7 @@ TimeseriesChart.propTypes = {
|
|||
show: PropTypes.array,
|
||||
tickFormatter: PropTypes.func,
|
||||
yaxes: PropTypes.array,
|
||||
xaxisLabel: PropTypes.string
|
||||
};
|
||||
|
||||
export default TimeseriesChart;
|
||||
|
|
|
@ -118,10 +118,20 @@
|
|||
.rhythm_chart__timeseries-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
row-direction: column;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.rhythm_chart__axis-label {
|
||||
font-size: 0.8em;
|
||||
color: rgba(0,0,0,0.4);
|
||||
text-align: center;
|
||||
min-height: 1.2em;
|
||||
&.reversed {
|
||||
color: rgba(255,255,255,0.6);
|
||||
}
|
||||
}
|
||||
|
||||
.annotation {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue