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 { GrafanaTheme } from '../types/theme';
|
||||||
import { MappingType, FieldConfig } from '../types';
|
import { MappingType, FieldConfig } from '../types';
|
||||||
import { validateFieldConfig } from './fieldOverrides';
|
import { validateFieldConfig } from './fieldOverrides';
|
||||||
|
import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRegistry';
|
||||||
|
|
||||||
describe('FieldDisplay', () => {
|
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', () => {
|
it('show first numeric values', () => {
|
||||||
const options = createDisplayOptions({
|
const options = createDisplayOptions({
|
||||||
fieldOptions: {
|
fieldOptions: {
|
||||||
@ -148,6 +165,58 @@ describe('FieldDisplay', () => {
|
|||||||
const display = getFieldDisplayValues(options);
|
const display = getFieldDisplayValues(options);
|
||||||
expect(display[0].display.numeric).toEqual(0);
|
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 {
|
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'
|
// Try harder to set a real value that is not 'other'
|
||||||
let type = field.type;
|
let type = field.type;
|
||||||
if (!type || type === FieldType.other) {
|
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) {
|
export function setFieldConfigDefaults(config: FieldConfig, defaults: FieldConfig, context: FieldOverrideEnv) {
|
||||||
if (defaults) {
|
if (defaults) {
|
||||||
const keys = Object.keys(defaults);
|
const keys = Object.keys(defaults);
|
||||||
|
|
||||||
for (const key of keys) {
|
for (const key of keys) {
|
||||||
if (key === 'custom') {
|
if (key === 'custom') {
|
||||||
if (!context.custom) {
|
if (!context.custom) {
|
||||||
@ -275,6 +272,11 @@ const processFieldConfigValue = (
|
|||||||
const currentConfig = destination[key];
|
const currentConfig = destination[key];
|
||||||
if (currentConfig === null || currentConfig === undefined) {
|
if (currentConfig === null || currentConfig === undefined) {
|
||||||
const item = registry.getIfExists(key);
|
const item = registry.getIfExists(key);
|
||||||
|
if (!item) {
|
||||||
|
console.warn(`No processor available for ${key} config property`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (item && item.shouldApply(context.field!)) {
|
if (item && item.shouldApply(context.field!)) {
|
||||||
const val = item.process(source[key], context, item.settings);
|
const val = item.process(source[key], context, item.settings);
|
||||||
if (val !== undefined && val !== null) {
|
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 { StringFieldConfigSettings, StringOverrideEditor, stringOverrideProcessor, StringValueEditor } from './string';
|
||||||
import { NumberFieldConfigSettings, NumberOverrideEditor, numberOverrideProcessor, NumberValueEditor } from './number';
|
import { NumberFieldConfigSettings, NumberOverrideEditor, numberOverrideProcessor, NumberValueEditor } from './number';
|
||||||
import { UnitOverrideEditor, UnitValueEditor } from './units';
|
import { UnitOverrideEditor, UnitValueEditor } from './units';
|
||||||
@ -9,6 +9,12 @@ import {
|
|||||||
ThresholdsValueEditor,
|
ThresholdsValueEditor,
|
||||||
} from './thresholds';
|
} from './thresholds';
|
||||||
import { DataLinksOverrideEditor, dataLinksOverrideProcessor, DataLinksValueEditor } from './links';
|
import { DataLinksOverrideEditor, dataLinksOverrideProcessor, DataLinksValueEditor } from './links';
|
||||||
|
import {
|
||||||
|
ValueMappingFieldConfigSettings,
|
||||||
|
ValueMappingsOverrideEditor,
|
||||||
|
valueMappingsOverrideProcessor,
|
||||||
|
ValueMappingsValueEditor,
|
||||||
|
} from './mappings';
|
||||||
|
|
||||||
export const getStandardFieldConfigs = () => {
|
export const getStandardFieldConfigs = () => {
|
||||||
const title: FieldPropertyEditorItem<string, StringFieldConfigSettings> = {
|
const title: FieldPropertyEditorItem<string, StringFieldConfigSettings> = {
|
||||||
@ -108,6 +114,21 @@ export const getStandardFieldConfigs = () => {
|
|||||||
shouldApply: field => field.type === FieldType.number,
|
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> = {
|
const noValue: FieldPropertyEditorItem<string, StringFieldConfigSettings> = {
|
||||||
id: 'noValue', // Match field properties
|
id: 'noValue', // Match field properties
|
||||||
name: 'No Value',
|
name: 'No Value',
|
||||||
@ -137,5 +158,5 @@ export const getStandardFieldConfigs = () => {
|
|||||||
shouldApply: () => true,
|
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