FieldOverrides: Add value mappings editor to standard config properties registry (#22648)

This commit is contained in:
Dominik Prokop 2020-03-09 15:09:32 +01:00 committed by GitHub
parent 9716289196
commit 9d858220ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 141 additions and 5 deletions

View File

@ -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 {

View File

@ -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) {

View 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>;
}
}

View File

@ -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];
}; };