mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
FieldOverrides: Add value mappings editor to standard config properties registry (#22648)
This commit is contained in:
parent
9716289196
commit
9d858220ce
@ -6,8 +6,25 @@ import { ThresholdsMode } from '../types/thresholds';
|
||||
import { GrafanaTheme } from '../types/theme';
|
||||
import { MappingType, FieldConfig } from '../types';
|
||||
import { validateFieldConfig } from './fieldOverrides';
|
||||
import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRegistry';
|
||||
|
||||
describe('FieldDisplay', () => {
|
||||
beforeAll(() => {
|
||||
// Since FieldConfigEditors belong to grafana-ui we need to mock those here
|
||||
// as grafana-ui code cannot be imported in grafana-data.
|
||||
// TODO: figure out a way to share standard editors between data/ui tests
|
||||
const mappings = {
|
||||
id: 'mappings', // Match field properties
|
||||
process: (value: any) => value,
|
||||
shouldApply: () => true,
|
||||
} as any;
|
||||
|
||||
console.log('Init tegistry');
|
||||
standardFieldConfigEditorRegistry.setInit(() => {
|
||||
return [mappings];
|
||||
});
|
||||
});
|
||||
|
||||
it('show first numeric values', () => {
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
@ -148,6 +165,58 @@ describe('FieldDisplay', () => {
|
||||
const display = getFieldDisplayValues(options);
|
||||
expect(display[0].display.numeric).toEqual(0);
|
||||
});
|
||||
|
||||
describe('Value mapping', () => {
|
||||
it('should apply value mapping', () => {
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
calcs: [ReducerID.first],
|
||||
override: {},
|
||||
defaults: {
|
||||
mappings: [
|
||||
{
|
||||
id: 1,
|
||||
operator: '',
|
||||
text: 'Value mapped to text',
|
||||
type: MappingType.ValueToText,
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const result = getFieldDisplayValues(options);
|
||||
expect(result[0].display.text).toEqual('Value mapped to text');
|
||||
});
|
||||
it('should apply range value mapping', () => {
|
||||
const mappedValue = 'Range mapped to text';
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
values: true,
|
||||
override: {},
|
||||
defaults: {
|
||||
mappings: [
|
||||
{
|
||||
id: 1,
|
||||
operator: '',
|
||||
text: mappedValue,
|
||||
type: MappingType.RangeToText,
|
||||
value: 1,
|
||||
from: 1,
|
||||
to: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
const result = getFieldDisplayValues(options);
|
||||
|
||||
expect(result[0].display.text).toEqual(mappedValue);
|
||||
expect(result[2].display.text).toEqual('5');
|
||||
expect(result[3].display.text).toEqual(mappedValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createEmptyDisplayOptions(extend = {}): GetFieldDisplayValuesOptions {
|
||||
|
@ -136,8 +136,6 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra
|
||||
}
|
||||
}
|
||||
|
||||
// console.log(config)
|
||||
|
||||
// Try harder to set a real value that is not 'other'
|
||||
let type = field.type;
|
||||
if (!type || type === FieldType.other) {
|
||||
@ -242,7 +240,6 @@ function setDynamicConfigValue(config: FieldConfig, value: DynamicConfigValue, c
|
||||
export function setFieldConfigDefaults(config: FieldConfig, defaults: FieldConfig, context: FieldOverrideEnv) {
|
||||
if (defaults) {
|
||||
const keys = Object.keys(defaults);
|
||||
|
||||
for (const key of keys) {
|
||||
if (key === 'custom') {
|
||||
if (!context.custom) {
|
||||
@ -275,6 +272,11 @@ const processFieldConfigValue = (
|
||||
const currentConfig = destination[key];
|
||||
if (currentConfig === null || currentConfig === undefined) {
|
||||
const item = registry.getIfExists(key);
|
||||
if (!item) {
|
||||
console.warn(`No processor available for ${key} config property`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item && item.shouldApply(context.field!)) {
|
||||
const val = item.process(source[key], context, item.settings);
|
||||
if (val !== undefined && val !== null) {
|
||||
|
44
packages/grafana-ui/src/components/FieldConfigs/mappings.tsx
Normal file
44
packages/grafana-ui/src/components/FieldConfigs/mappings.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
|
||||
import { FieldOverrideContext, FieldOverrideEditorProps, FieldConfigEditorProps, ValueMapping } from '@grafana/data';
|
||||
import { ValueMappingsEditor } from '..';
|
||||
|
||||
export interface ValueMappingFieldConfigSettings {}
|
||||
|
||||
export const valueMappingsOverrideProcessor = (
|
||||
value: any,
|
||||
context: FieldOverrideContext,
|
||||
settings: ValueMappingFieldConfigSettings
|
||||
) => {
|
||||
return value as ValueMapping[]; // !!!! likely not !!!!
|
||||
};
|
||||
|
||||
export class ValueMappingsValueEditor extends React.PureComponent<
|
||||
FieldConfigEditorProps<ValueMapping[], ValueMappingFieldConfigSettings>
|
||||
> {
|
||||
constructor(props: FieldConfigEditorProps<ValueMapping[], ValueMappingFieldConfigSettings>) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { onChange } = this.props;
|
||||
let value = this.props.value;
|
||||
if (!value) {
|
||||
value = [];
|
||||
}
|
||||
|
||||
return <ValueMappingsEditor valueMappings={value} onChange={onChange} />;
|
||||
}
|
||||
}
|
||||
|
||||
export class ValueMappingsOverrideEditor extends React.PureComponent<
|
||||
FieldOverrideEditorProps<ValueMapping[], ValueMappingFieldConfigSettings>
|
||||
> {
|
||||
constructor(props: FieldOverrideEditorProps<ValueMapping[], ValueMappingFieldConfigSettings>) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>VALUE MAPPINGS OVERRIDE EDITOR {this.props.item.name}</div>;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { DataLink, FieldPropertyEditorItem, FieldType, ThresholdsConfig } from '@grafana/data';
|
||||
import { DataLink, FieldPropertyEditorItem, FieldType, ThresholdsConfig, ValueMapping } from '@grafana/data';
|
||||
import { StringFieldConfigSettings, StringOverrideEditor, stringOverrideProcessor, StringValueEditor } from './string';
|
||||
import { NumberFieldConfigSettings, NumberOverrideEditor, numberOverrideProcessor, NumberValueEditor } from './number';
|
||||
import { UnitOverrideEditor, UnitValueEditor } from './units';
|
||||
@ -9,6 +9,12 @@ import {
|
||||
ThresholdsValueEditor,
|
||||
} from './thresholds';
|
||||
import { DataLinksOverrideEditor, dataLinksOverrideProcessor, DataLinksValueEditor } from './links';
|
||||
import {
|
||||
ValueMappingFieldConfigSettings,
|
||||
ValueMappingsOverrideEditor,
|
||||
valueMappingsOverrideProcessor,
|
||||
ValueMappingsValueEditor,
|
||||
} from './mappings';
|
||||
|
||||
export const getStandardFieldConfigs = () => {
|
||||
const title: FieldPropertyEditorItem<string, StringFieldConfigSettings> = {
|
||||
@ -108,6 +114,21 @@ export const getStandardFieldConfigs = () => {
|
||||
shouldApply: field => field.type === FieldType.number,
|
||||
};
|
||||
|
||||
const mappings: FieldPropertyEditorItem<ValueMapping[], ValueMappingFieldConfigSettings> = {
|
||||
id: 'mappings', // Match field properties
|
||||
name: 'Value mappings',
|
||||
description: 'Manage value mappings',
|
||||
|
||||
editor: ValueMappingsValueEditor,
|
||||
override: ValueMappingsOverrideEditor,
|
||||
process: valueMappingsOverrideProcessor,
|
||||
settings: {
|
||||
// ??
|
||||
},
|
||||
|
||||
shouldApply: field => field.type === FieldType.number,
|
||||
};
|
||||
|
||||
const noValue: FieldPropertyEditorItem<string, StringFieldConfigSettings> = {
|
||||
id: 'noValue', // Match field properties
|
||||
name: 'No Value',
|
||||
@ -137,5 +158,5 @@ export const getStandardFieldConfigs = () => {
|
||||
shouldApply: () => true,
|
||||
};
|
||||
|
||||
return [unit, min, max, decimals, thresholds, title, noValue, links];
|
||||
return [unit, min, max, decimals, thresholds, mappings, title, noValue, links];
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user