Skip to content

Commit

Permalink
Duration Formatting for TSVB (#13337)
Browse files Browse the repository at this point in the history
* Adding duration formatter

* Adding decimal places

* Fixing bug with decimals

* Relaxing the duration format test
  • Loading branch information
simianhacker authored Aug 18, 2017
1 parent ef67957 commit 7fb2d7f
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 6 deletions.
82 changes: 82 additions & 0 deletions src/core_plugins/metrics/public/components/data_format_picker.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import React, { Component, PropTypes } from 'react';
import _ from 'lodash';
import Select from 'react-select';
import { durationOutputOptions, durationInputOptions } from './lib/durations';
const durationFormatTest = /[pnumshdwMY]+,[pnumshdwMY]+/;

class DataFormatPicker extends Component {

constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleCustomChange = this.handleCustomChange.bind(this);
let from = 'ms';
let to = 'ms';
let decimals = 2;
if (durationFormatTest.test(props.value)) {
[from, to, decimals] = props.value.split(',');
}
this.state = {
from,
to,
decimals
};
}

handleCustomChange() {
Expand All @@ -17,25 +30,94 @@ class DataFormatPicker extends Component {
handleChange(value) {
if (value.value === 'custom') {
this.handleCustomChange();
} else if (value.value === 'duration') {
const { from, to, decimals } = this.state;
this.props.onChange({
value: `${from},${to},${decimals}`
});
} else {
this.props.onChange(value);
}
}

handleDurationChange(name) {
return (value) => {
if (name === 'decimals') {
value = this.decimals;
}
this.setState({
[name]: value.value
}, () => {
const { from, to, decimals } = this.state;
this.props.onChange({
value: `${from},${to},${decimals}`
});
});
};
}

render() {
const value = this.props.value || '';
let defaultValue = value;
if (!_.includes(['bytes', 'number', 'percent'], value)) {
defaultValue = 'custom';
}
if (durationFormatTest.test(value)) {
defaultValue = 'duration';
}
const options = [
{ label: 'Bytes', value: 'bytes' },
{ label: 'Number', value: 'number' },
{ label: 'Percent', value: 'percent' },
{ label: 'Duration', value: 'duration' },
{ label: 'Custom', value: 'custom' }
];

let custom;
if (defaultValue === 'duration') {
const [from, to, decimals] = value.split(',');
return (
<div className="vis_editor__data_format_picker-container">
<div className="vis_editor__label">
{this.props.label}
</div>
<div className="vis_editor__item">
<Select
clearable={false}
value={defaultValue}
options={options}
onChange={this.handleChange}
/>
</div>
<div className="vis_editor__label">From</div>
<div className="vis_editor__item">
<Select
clearable={false}
value={from}
options={durationInputOptions}
onChange={this.handleDurationChange('from')}
/>
</div>
<div className="vis_editor__label">To</div>
<div className="vis_editor__item">
<Select
clearable={false}
value={to}
options={durationOutputOptions}
onChange={this.handleDurationChange('to')}
/>
</div>
<div className="vis_editor__label">Decimal Places</div>
<input
className="vis_editor__input"
defaultValue={decimals}
ref={(el) => this.decimals = el}
onChange={this.handleDurationChange('decimals')}
type="text"
/>
</div>
);
}
if (defaultValue === 'custom') {
custom = (
<div className="vis_editor__data_format_picker-custom_row">
Expand Down
18 changes: 18 additions & 0 deletions src/core_plugins/metrics/public/components/lib/durations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const durationOutputOptions = [
{ label: 'milliseconds', value: 'ms' },
{ label: 'seconds', value: 's' },
{ label: 'minutes', value: 'm' },
{ label: 'hours', value: 'h' },
{ label: 'days', value: 'd' },
{ label: 'weeks', value: 'w' },
{ label: 'months', value: 'M' },
{ label: 'years', value: 'Y' }
];

export const durationInputOptions = [
{ label: 'picoseconds', value: 'ps' },
{ label: 'nanoseconds', value: 'ns' },
{ label: 'microseconds', value: 'us' },
...durationOutputOptions
];

32 changes: 26 additions & 6 deletions src/core_plugins/metrics/public/components/lib/tick_formatter.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,46 @@
import numeral from '@elastic/numeral';
import _ from 'lodash';
import handlebars from 'handlebars/dist/handlebars';
import { durationInputOptions } from './durations';
import { DurationFormat } from '../../../../kibana/common/field_formats/types/duration';
import { capitalize, isNumber } from 'lodash';

const formatLookup = {
'bytes': '0.0b',
'number': '0,0.[00]',
'percent': '0.[00]%'
};

const durationsLookup = durationInputOptions.reduce((acc, row) => {
acc[row.value] = row.label;
return acc;
}, {});

export default (format = '0,0.[00]', template) => {
if (!template) template = '{{value}}';
const render = handlebars.compile(template);
const durationFormatTest = /[pnumshdwMY]+,[pnumshdwMY]+,\d+/;
return (val) => {
const formatString = formatLookup[format] || format;
let value;
if (!_.isNumber(val)) {
if (!isNumber(val)) {
value = 0;
} else {
try {
value = numeral(val).format(formatString);
} catch (e) {
value = val;
if (durationFormatTest.test(format)) {
const [from, to, decimals] = format.split(',');
const inputFormat = durationsLookup[from];
const outputFormat = `as${capitalize(durationsLookup[to])}`;
const formatter = new DurationFormat({
inputFormat,
outputFormat,
outputPrecision: decimals
});
value = formatter.convert(val, 'text');
} else {
try {
value = numeral(val).format(formatString);
} catch (e) {
value = val;
}
}
}
try {
Expand Down

0 comments on commit 7fb2d7f

Please sign in to comment.