mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
FieldConfig: set min/max automatically for gauge (#21073)
This commit is contained in:
parent
e27ab89aed
commit
6de4933a4a
@ -79,6 +79,7 @@ export interface GetFieldDisplayValuesOptions {
|
||||
replaceVariables: InterpolateFunction;
|
||||
sparkline?: boolean; // Calculate the sparkline
|
||||
theme: GrafanaTheme;
|
||||
autoMinMax?: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_FIELD_DISPLAY_VALUES_LIMIT = 25;
|
||||
@ -90,7 +91,7 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi
|
||||
const values: FieldDisplay[] = [];
|
||||
|
||||
if (options.data) {
|
||||
const data = applyFieldOverrides(options.data, fieldOptions, replaceVariables, options.theme);
|
||||
const data = applyFieldOverrides(options);
|
||||
|
||||
let hitLimit = false;
|
||||
const limit = fieldOptions.limit ? fieldOptions.limit : DEFAULT_FIELD_DISPLAY_VALUES_LIMIT;
|
||||
|
@ -2,8 +2,35 @@ import { setFieldConfigDefaults, findNumericFieldMinMax, applyFieldOverrides } f
|
||||
import { MutableDataFrame } from '../dataframe';
|
||||
import { FieldConfig, FieldConfigSource, InterpolateFunction, GrafanaTheme } from '../types';
|
||||
import { FieldMatcherID } from '../transformations';
|
||||
import { FieldDisplayOptions } from './fieldDisplay';
|
||||
|
||||
describe('FieldOverrides', () => {
|
||||
const f0 = new MutableDataFrame();
|
||||
f0.add({ title: 'AAA', value: 100, value2: 1234 }, true);
|
||||
f0.add({ title: 'BBB', value: -20 }, true);
|
||||
f0.add({ title: 'CCC', value: 200, value2: 1000 }, true);
|
||||
expect(f0.length).toEqual(3);
|
||||
|
||||
// Hardcode the max value
|
||||
f0.fields[1].config.max = 0;
|
||||
f0.fields[1].config.decimals = 6;
|
||||
|
||||
const src: FieldConfigSource = {
|
||||
defaults: {
|
||||
unit: 'xyz',
|
||||
decimals: 2,
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
matcher: { id: FieldMatcherID.numeric },
|
||||
properties: [
|
||||
{ path: 'decimals', value: 1 }, // Numeric
|
||||
{ path: 'title', value: 'Kittens' }, // Text
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
it('will merge FieldConfig with default values', () => {
|
||||
const field: FieldConfig = {
|
||||
min: 0,
|
||||
@ -22,46 +49,20 @@ describe('FieldOverrides', () => {
|
||||
});
|
||||
|
||||
it('will apply field overrides', () => {
|
||||
const f0 = new MutableDataFrame();
|
||||
f0.add({ title: 'AAA', value: 100, value2: 1234 }, true);
|
||||
f0.add({ title: 'BBB', value: -20 }, true);
|
||||
f0.add({ title: 'CCC', value: 200, value2: 1000 }, true);
|
||||
expect(f0.length).toEqual(3);
|
||||
|
||||
// Hardcode the max value
|
||||
f0.fields[1].config.max = 0;
|
||||
f0.fields[1].config.decimals = 6;
|
||||
|
||||
const src: FieldConfigSource = {
|
||||
defaults: {
|
||||
unit: 'xyz',
|
||||
decimals: 2,
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
matcher: { id: FieldMatcherID.numeric },
|
||||
properties: [
|
||||
{ path: 'decimals', value: 1 }, // Numeric
|
||||
{ path: 'title', value: 'Kittens' }, // Text
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const data = applyFieldOverrides(
|
||||
[f0], // the frame
|
||||
src, // defaults + overrides
|
||||
(undefined as any) as InterpolateFunction,
|
||||
(undefined as any) as GrafanaTheme
|
||||
)[0];
|
||||
const data = applyFieldOverrides({
|
||||
data: [f0], // the frame
|
||||
fieldOptions: src as FieldDisplayOptions, // defaults + overrides
|
||||
replaceVariables: (undefined as any) as InterpolateFunction,
|
||||
theme: (undefined as any) as GrafanaTheme,
|
||||
})[0];
|
||||
const valueColumn = data.fields[1];
|
||||
const config = valueColumn.config;
|
||||
|
||||
// Keep max from the original setting
|
||||
expect(config.max).toEqual(0);
|
||||
|
||||
// Automatically pick the min value
|
||||
expect(config.min).toEqual(-20);
|
||||
// Don't Automatically pick the min value
|
||||
expect(config.min).toEqual(undefined);
|
||||
|
||||
// The default value applied
|
||||
expect(config.unit).toEqual('xyz');
|
||||
@ -72,6 +73,24 @@ describe('FieldOverrides', () => {
|
||||
// The override applied
|
||||
expect(config.decimals).toEqual(1);
|
||||
});
|
||||
|
||||
it('will apply set min/max when asked', () => {
|
||||
const data = applyFieldOverrides({
|
||||
data: [f0], // the frame
|
||||
fieldOptions: src as FieldDisplayOptions, // defaults + overrides
|
||||
replaceVariables: (undefined as any) as InterpolateFunction,
|
||||
theme: (undefined as any) as GrafanaTheme,
|
||||
autoMinMax: true,
|
||||
})[0];
|
||||
const valueColumn = data.fields[1];
|
||||
const config = valueColumn.config;
|
||||
|
||||
// Keep max from the original setting
|
||||
expect(config.max).toEqual(0);
|
||||
|
||||
// Don't Automatically pick the min value
|
||||
expect(config.min).toEqual(-20);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Global MinMax', () => {
|
||||
|
@ -1,19 +1,11 @@
|
||||
import set from 'lodash/set';
|
||||
import {
|
||||
DynamicConfigValue,
|
||||
FieldConfigSource,
|
||||
FieldConfig,
|
||||
InterpolateFunction,
|
||||
GrafanaTheme,
|
||||
DataFrame,
|
||||
Field,
|
||||
FieldType,
|
||||
} from '../types';
|
||||
import { DynamicConfigValue, FieldConfig, InterpolateFunction, DataFrame, Field, FieldType } from '../types';
|
||||
import { fieldMatchers, ReducerID, reduceField } from '../transformations';
|
||||
import { FieldMatcher } from '../types/transformations';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
import toNumber from 'lodash/toNumber';
|
||||
import { getDisplayProcessor } from './displayProcessor';
|
||||
import { GetFieldDisplayValuesOptions } from './fieldDisplay';
|
||||
|
||||
interface OverrideProps {
|
||||
match: FieldMatcher;
|
||||
@ -50,15 +42,13 @@ export function findNumericFieldMinMax(data: DataFrame[]): GlobalMinMax {
|
||||
/**
|
||||
* Return a copy of the DataFrame with all rules applied
|
||||
*/
|
||||
export function applyFieldOverrides(
|
||||
data: DataFrame[],
|
||||
source: FieldConfigSource,
|
||||
replaceVariables: InterpolateFunction,
|
||||
theme: GrafanaTheme,
|
||||
isUtc?: boolean
|
||||
): DataFrame[] {
|
||||
export function applyFieldOverrides(options: GetFieldDisplayValuesOptions): DataFrame[] {
|
||||
if (!options.data) {
|
||||
return [];
|
||||
}
|
||||
const source = options.fieldOptions;
|
||||
if (!source) {
|
||||
return data;
|
||||
return options.data;
|
||||
}
|
||||
let range: GlobalMinMax | undefined = undefined;
|
||||
|
||||
@ -76,7 +66,7 @@ export function applyFieldOverrides(
|
||||
}
|
||||
}
|
||||
|
||||
return data.map((frame, index) => {
|
||||
return options.data.map((frame, index) => {
|
||||
let name = frame.name;
|
||||
if (!name) {
|
||||
name = `Series[${index}]`;
|
||||
@ -98,17 +88,17 @@ export function applyFieldOverrides(
|
||||
config,
|
||||
field,
|
||||
data: frame,
|
||||
replaceVariables,
|
||||
replaceVariables: options.replaceVariables,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the Min/Max value automatically
|
||||
if (field.type === FieldType.number) {
|
||||
if (options.autoMinMax && field.type === FieldType.number) {
|
||||
if (!isNumber(config.min) || !isNumber(config.max)) {
|
||||
if (!range) {
|
||||
range = findNumericFieldMinMax(data);
|
||||
range = findNumericFieldMinMax(options.data!); // Global value
|
||||
}
|
||||
if (!isNumber(config.min)) {
|
||||
config.min = range.min;
|
||||
@ -129,8 +119,7 @@ export function applyFieldOverrides(
|
||||
processor: getDisplayProcessor({
|
||||
type: field.type,
|
||||
config: config,
|
||||
theme,
|
||||
isUtc,
|
||||
theme: options.theme,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
@ -111,6 +111,7 @@ export const FieldPropertiesEditor: React.FC<Props> = ({ value, onChange, showMi
|
||||
onChange={onMinChange}
|
||||
onBlur={commitChanges}
|
||||
value={min}
|
||||
placeholder="Auto"
|
||||
type="number"
|
||||
/>
|
||||
<FormField
|
||||
@ -120,6 +121,7 @@ export const FieldPropertiesEditor: React.FC<Props> = ({ value, onChange, showMi
|
||||
onBlur={commitChanges}
|
||||
value={max}
|
||||
type="number"
|
||||
placeholder="Auto"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
@ -57,6 +57,7 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
data: data.series,
|
||||
autoMinMax: true,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,7 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
data: data.series,
|
||||
autoMinMax: true,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -27,8 +27,6 @@ export const standardFieldDisplayOptions: FieldDisplayOptions = {
|
||||
values: false,
|
||||
calcs: [ReducerID.mean],
|
||||
defaults: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
thresholds: [
|
||||
{ value: -Infinity, color: 'green' },
|
||||
{ value: 80, color: 'red' }, // 80%
|
||||
|
Loading…
Reference in New Issue
Block a user