ValueFormats: dynamically create units (#20763)

* update fixed

* update fixed

* update fixed

* don't change any tests

* add mising space

* Custom unit formats

* return a string for kbn

* return a string for kbn

* return a string for kbn

* Simplify unit tests

* More units

* fix more tests

* fix more tests

* fix more tests

* format values

* format values

* TimeSeries to string

* more kbn tests

* use the formatted value

* BarGauge: Fixed font size calculations

* support prefix

* add si support

* avoid npe

* BarGauge/BigValue: value formatting

* fix some tests

* fix tests

* remove displayDateFormat

* another unicode char

* Graph: Use react unit picker

* Updated unit picker

* Fixed build errors

* more formatting

* graph2 tooltip formatting

* optional chaining
This commit is contained in:
Ryan McKinley
2019-12-04 00:08:07 -08:00
committed by Torkel Ödegaard
parent 3289ee8b77
commit d7c76dacad
40 changed files with 612 additions and 431 deletions

View File

@@ -11,6 +11,7 @@ import {
ColorPicker,
SeriesColorPickerPopoverWithTheme,
SecretFormField,
UnitPicker,
DataLinksEditor,
DataSourceHttpSettings,
} from '@grafana/ui';
@@ -61,6 +62,11 @@ export function registerAngularDirectives() {
'onColorChange',
'onToggleAxis',
]);
react2AngularDirective('unitPicker', UnitPicker, [
'value',
'width',
['onChange', { watchDepth: 'reference', wrapApply: true }],
]);
react2AngularDirective('metricSelect', MetricSelect, [
'options',
'onChange',

View File

@@ -1,6 +1,6 @@
import { getFlotTickDecimals } from 'app/core/utils/ticks';
import _ from 'lodash';
import { getValueFormat, ValueFormatter, stringToJsRegex, DecimalCount } from '@grafana/data';
import { getValueFormat, ValueFormatter, stringToJsRegex, DecimalCount, formattedValueToString } from '@grafana/data';
function matchSeriesOverride(aliasOrRegex: string, seriesAlias: string) {
if (!aliasOrRegex) {
@@ -339,7 +339,7 @@ export default class TimeSeries {
if (!_.isFinite(value)) {
value = null; // Prevent NaN formatting
}
return this.valueFormater(value, this.decimals, this.scaledDecimals);
return formattedValueToString(this.valueFormater(value, this.decimals, this.scaledDecimals));
}
isMsResolutionNeeded() {

View File

@@ -0,0 +1,52 @@
import kbn from './kbn';
import { DecimalCount, TimeZone } from '@grafana/data';
interface ValueFormatTest {
id: string;
decimals?: DecimalCount;
scaledDecimals?: DecimalCount;
timeZone?: TimeZone;
value: number;
result: string;
}
const formatTests: ValueFormatTest[] = [
// Currancy
{ id: 'currencyUSD', decimals: 2, value: 1532.82, result: '$1.53K' },
{ id: 'currencyKRW', decimals: 2, value: 1532.82, result: '₩1.53K' },
// Typical
{ id: 'ms', decimals: 4, value: 0.0024, result: '0.0024 ms' },
{ id: 'ms', decimals: 0, value: 100, result: '100 ms' },
{ id: 'ms', decimals: 2, value: 1250, result: '1.25 s' },
{ id: 'ms', decimals: 1, value: 10000086.123, result: '2.8 hour' },
{ id: 'ms', decimals: 0, value: 1200, result: '1 s' },
{ id: 'short', decimals: 0, scaledDecimals: -1, value: 98765, result: '98.77 K' },
{ id: 'short', decimals: 0, scaledDecimals: 0, value: 9876543, result: '9.876543 Mil' },
{ id: 'kbytes', decimals: 3, value: 10000000, result: '9.537 GiB' },
{ id: 'deckbytes', decimals: 3, value: 10000000, result: '10.000 GB' },
{ id: 'megwatt', decimals: 3, value: 1000, result: '1.000 GW' },
{ id: 'kohm', decimals: 3, value: 1000, result: '1.000 MΩ' },
{ id: 'Mohm', decimals: 3, value: 1000, result: '1.000 GΩ' },
{ id: 'farad', decimals: 3, value: 1000, result: '1.000 kF' },
{ id: 'µfarad', decimals: 3, value: 1000, result: '1.000 mF' },
{ id: 'nfarad', decimals: 3, value: 1000, result: '1.000 µF' },
{ id: 'pfarad', decimals: 3, value: 1000, result: '1.000 nF' },
{ id: 'ffarad', decimals: 3, value: 1000, result: '1.000 pF' },
{ id: 'henry', decimals: 3, value: 1000, result: '1.000 kH' },
{ id: 'mhenry', decimals: 3, value: 1000, result: '1.000 H' },
{ id: 'µhenry', decimals: 3, value: 1000, result: '1.000 mH' },
];
describe('Chcek KBN value formats', () => {
for (const test of formatTests) {
describe(`value format: ${test.id}`, () => {
it(`should translate ${test.value} as ${test.result}`, () => {
const result = kbn.valueFormats[test.id](test.value, test.decimals, test.scaledDecimals);
expect(result).toBe(test.result);
});
});
}
});

View File

@@ -6,6 +6,8 @@ import {
stringToJsRegex,
TimeRange,
deprecationWarning,
DecimalCount,
formattedValueToString,
} from '@grafana/data';
const kbn: any = {};
@@ -308,7 +310,10 @@ if (typeof Proxy !== 'undefined') {
const formatter = getValueFormat(name);
if (formatter) {
return formatter;
// Return the results as a simple string
return (value: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount, isUtc?: boolean) => {
return formattedValueToString(formatter(value, decimals, scaledDecimals, isUtc));
};
}
// default to look here

View File

@@ -9,7 +9,7 @@
<div ng-if="yaxis.show">
<div class="gf-form">
<label class="gf-form-label width-6">Unit</label>
<div class="gf-form-dropdown-typeahead max-width-20" ng-model="yaxis.format" dropdown-typeahead2="ctrl.unitFormats" dropdown-typeahead-on-select="ctrl.setUnitFormat(yaxis, $subItem)"></div>
<unit-picker onChange="ctrl.setUnitFormat(yaxis)" value="yaxis.format" width="20" />
</div>
</div>

View File

@@ -49,9 +49,11 @@ export class AxesEditorCtrl {
}
}
setUnitFormat(axis: { format: any }, subItem: { value: any }) {
axis.format = subItem.value;
this.panelCtrl.render();
setUnitFormat(axis: { format: any }) {
return (unit: string) => {
axis.format = unit;
this.panelCtrl.render();
};
}
render() {

View File

@@ -35,6 +35,7 @@ import {
getDisplayProcessor,
getFlotPairsConstant,
PanelEvents,
formattedValueToString,
} from '@grafana/data';
import { GraphContextMenuCtrl } from './GraphContextMenuCtrl';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
@@ -862,7 +863,7 @@ class GraphElement {
if (!formatter) {
throw new Error(`Unit '${format}' is not supported`);
}
return formatter(val, axis.tickDecimals, axis.scaledDecimals);
return formattedValueToString(formatter(val, axis.tickDecimals, axis.scaledDecimals));
};
}

View File

@@ -33,6 +33,7 @@ export const getGraphSeriesModel = (
const displayProcessor = getDisplayProcessor({
config: {
unit: fieldOptions?.defaults?.unit,
decimals: legendOptions.decimals,
},
});
@@ -68,7 +69,6 @@ export const getGraphSeriesModel = (
return {
...statDisplayValue,
text: statDisplayValue.text,
title: stat,
};
});
@@ -104,7 +104,7 @@ export const getGraphSeriesModel = (
type: timeField.type,
isUtc: timeZone === 'utc',
config: {
dateDisplayFormat: useMsDateFormat ? MS_DATE_TIME_FORMAT : DEFAULT_DATE_TIME_FORMAT,
unit: `time:${useMsDateFormat ? MS_DATE_TIME_FORMAT : DEFAULT_DATE_TIME_FORMAT}`,
},
});

View File

@@ -6,6 +6,7 @@ import {
GrafanaThemeType,
stringToJsRegex,
ScopedVars,
formattedValueToString,
} from '@grafana/data';
import { ColumnStyle } from '@grafana/ui/src/components/Table/TableCellBuilder';
import { TemplateSrv } from 'app/features/templating/template_srv';
@@ -188,7 +189,7 @@ export class TableRenderer {
}
this.setColorState(v, column.style);
return valueFormatter(v, column.style.decimals, null);
return formattedValueToString(valueFormatter(v, column.style.decimals, null));
};
}
@@ -226,7 +227,11 @@ export class TableRenderer {
}
formatColumnValue(colIndex: number, value: any) {
return this.formatters[colIndex] ? this.formatters[colIndex](value) : value;
const fmt = this.formatters[colIndex];
if (fmt) {
return fmt(value);
}
return value;
}
renderCell(columnIndex: number, rowIndex: number, value: any, addWidthHack = false) {