diff --git a/src/core_plugins/metrics/public/components/data_format_picker.js b/src/core_plugins/metrics/public/components/data_format_picker.js
index 346ec7e2a482..fafc9e8d78d8 100644
--- a/src/core_plugins/metrics/public/components/data_format_picker.js
+++ b/src/core_plugins/metrics/public/components/data_format_picker.js
@@ -1,6 +1,8 @@
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 {
@@ -8,6 +10,17 @@ class DataFormatPicker extends Component {
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() {
@@ -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 (
+
+
+ {this.props.label}
+
+
+
+
+
From
+
+
+
+
To
+
+
+
+
Decimal Places
+
this.decimals = el}
+ onChange={this.handleDurationChange('decimals')}
+ type="text"
+ />
+
+ );
+ }
if (defaultValue === 'custom') {
custom = (
diff --git a/src/core_plugins/metrics/public/components/lib/durations.js b/src/core_plugins/metrics/public/components/lib/durations.js
new file mode 100644
index 000000000000..4e15125ea56a
--- /dev/null
+++ b/src/core_plugins/metrics/public/components/lib/durations.js
@@ -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
+];
+
diff --git a/src/core_plugins/metrics/public/components/lib/tick_formatter.js b/src/core_plugins/metrics/public/components/lib/tick_formatter.js
index dff3a7b6b20f..05a9d25342a4 100644
--- a/src/core_plugins/metrics/public/components/lib/tick_formatter.js
+++ b/src/core_plugins/metrics/public/components/lib/tick_formatter.js
@@ -1,6 +1,8 @@
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',
@@ -8,19 +10,37 @@ const formatLookup = {
'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 {