mirror of https://github.com/grafana/grafana
FieldConfig: Unify the custom and standard registry (#23307)
* FieldConfig: Unifying standard and custom registry * Adding path to option items to make id be prefixed for custom options * Code updates progress * Add docs back * Fix TS * ld overrides tests from ui to data * Refactor - rename * Gauge and table cleanup * F-I-X e2e Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>pull/23374/head
parent
6347a1f1eb
commit
b10392733d
@ -0,0 +1,4 @@ |
||||
import { Registry } from '../utils'; |
||||
import { FieldPropertyEditorItem } from '../types'; |
||||
|
||||
export class FieldConfigOptionsRegistry extends Registry<FieldPropertyEditorItem> {} |
||||
@ -0,0 +1,170 @@ |
||||
import { identityOverrideProcessor } from '../../field'; |
||||
import { ThresholdsMode } from '../../types'; |
||||
|
||||
export const mockStandardProperties = () => { |
||||
const title = { |
||||
id: 'title', |
||||
path: 'title', |
||||
name: 'Title', |
||||
description: "Field's title", |
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
settings: { |
||||
placeholder: 'none', |
||||
expandTemplateVars: true, |
||||
}, |
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const unit = { |
||||
id: 'unit', |
||||
path: 'unit', |
||||
name: 'Unit', |
||||
description: 'Value units', |
||||
|
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
|
||||
settings: { |
||||
placeholder: 'none', |
||||
}, |
||||
|
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const min = { |
||||
id: 'min', |
||||
path: 'min', |
||||
name: 'Min', |
||||
description: 'Minimum expected value', |
||||
|
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
|
||||
settings: { |
||||
placeholder: 'auto', |
||||
}, |
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const max = { |
||||
id: 'max', |
||||
path: 'max', |
||||
name: 'Max', |
||||
description: 'Maximum expected value', |
||||
|
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
|
||||
settings: { |
||||
placeholder: 'auto', |
||||
}, |
||||
|
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const decimals = { |
||||
id: 'decimals', |
||||
path: 'decimals', |
||||
name: 'Decimals', |
||||
description: 'Number of decimal to be shown for a value', |
||||
|
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
|
||||
settings: { |
||||
placeholder: 'auto', |
||||
min: 0, |
||||
max: 15, |
||||
integer: true, |
||||
}, |
||||
|
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const thresholds = { |
||||
id: 'thresholds', |
||||
path: 'thresholds', |
||||
name: 'Thresholds', |
||||
description: 'Manage thresholds', |
||||
|
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
settings: {}, |
||||
defaultValue: { |
||||
mode: ThresholdsMode.Absolute, |
||||
steps: [ |
||||
{ value: -Infinity, color: 'green' }, |
||||
{ value: 80, color: 'red' }, |
||||
], |
||||
}, |
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const mappings = { |
||||
id: 'mappings', |
||||
path: 'mappings', |
||||
name: 'Value mappings', |
||||
description: 'Manage value mappings', |
||||
|
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
settings: {}, |
||||
defaultValue: [], |
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const noValue = { |
||||
id: 'noValue', |
||||
path: 'noValue', |
||||
name: 'No Value', |
||||
description: 'What to show when there is no value', |
||||
|
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
|
||||
settings: { |
||||
placeholder: '-', |
||||
}, |
||||
// ??? any optionsUi with no value
|
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const links = { |
||||
id: 'links', |
||||
path: 'links', |
||||
name: 'DataLinks', |
||||
description: 'Manage date links', |
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
settings: { |
||||
placeholder: '-', |
||||
}, |
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
const color = { |
||||
id: 'color', |
||||
path: 'color', |
||||
name: 'Color', |
||||
description: 'Customise color', |
||||
editor: () => null, |
||||
override: () => null, |
||||
process: identityOverrideProcessor, |
||||
settings: { |
||||
placeholder: '-', |
||||
}, |
||||
shouldApply: () => true, |
||||
}; |
||||
|
||||
return [unit, min, max, decimals, title, noValue, thresholds, mappings, links, color]; |
||||
}; |
||||
@ -1,126 +0,0 @@ |
||||
import { |
||||
FieldConfig, |
||||
FieldConfigSource, |
||||
InterpolateFunction, |
||||
GrafanaTheme, |
||||
FieldMatcherID, |
||||
MutableDataFrame, |
||||
DataFrame, |
||||
FieldType, |
||||
applyFieldOverrides, |
||||
toDataFrame, |
||||
standardFieldConfigEditorRegistry, |
||||
standardEditorsRegistry, |
||||
} from '@grafana/data'; |
||||
|
||||
import { getTheme } from '../../themes'; |
||||
import { getStandardFieldConfigs, getStandardOptionEditors } from '../../utils'; |
||||
|
||||
describe('FieldOverrides', () => { |
||||
beforeAll(() => { |
||||
standardEditorsRegistry.setInit(getStandardOptionEditors); |
||||
standardFieldConfigEditorRegistry.setInit(getStandardFieldConfigs); |
||||
}); |
||||
|
||||
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: [ |
||||
{ prop: 'decimals', value: 1 }, // Numeric
|
||||
{ prop: 'title', value: 'Kittens' }, // Text
|
||||
], |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
it('will merge FieldConfig with default values', () => { |
||||
const field: FieldConfig = { |
||||
min: 0, |
||||
max: 100, |
||||
}; |
||||
const f1 = { |
||||
unit: 'ms', |
||||
dateFormat: '', // should be ignored
|
||||
max: parseFloat('NOPE'), // should be ignored
|
||||
min: null, // should alo be ignored!
|
||||
}; |
||||
|
||||
const f: DataFrame = toDataFrame({ |
||||
fields: [{ type: FieldType.number, name: 'x', config: field, values: [] }], |
||||
}); |
||||
const processed = applyFieldOverrides({ |
||||
data: [f], |
||||
standard: standardFieldConfigEditorRegistry, |
||||
fieldOptions: { |
||||
defaults: f1 as FieldConfig, |
||||
overrides: [], |
||||
}, |
||||
replaceVariables: v => v, |
||||
theme: getTheme(), |
||||
})[0]; |
||||
const out = processed.fields[0].config; |
||||
|
||||
expect(out.min).toEqual(0); |
||||
expect(out.max).toEqual(100); |
||||
expect(out.unit).toEqual('ms'); |
||||
}); |
||||
|
||||
it('will apply field overrides', () => { |
||||
const data = applyFieldOverrides({ |
||||
data: [f0], // the frame
|
||||
fieldOptions: src as FieldConfigSource, // 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); |
||||
|
||||
// Don't Automatically pick the min value
|
||||
expect(config.min).toEqual(undefined); |
||||
|
||||
// The default value applied
|
||||
expect(config.unit).toEqual('xyz'); |
||||
|
||||
// The default value applied
|
||||
expect(config.title).toEqual('Kittens'); |
||||
|
||||
// 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 FieldConfigSource, // 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); |
||||
}); |
||||
}); |
||||
@ -1,11 +1,8 @@ |
||||
import { PanelPlugin, FieldConfigProperty } from '@grafana/data'; |
||||
import { PanelPlugin } from '@grafana/data'; |
||||
import { PieChartPanelEditor } from './PieChartPanelEditor'; |
||||
import { PieChartPanel } from './PieChartPanel'; |
||||
import { PieChartOptions, defaults } from './types'; |
||||
|
||||
export const plugin = new PanelPlugin<PieChartOptions>(PieChartPanel) |
||||
.setDefaults(defaults) |
||||
.useStandardFieldConfig(null, { |
||||
[FieldConfigProperty.Unit]: 'short', |
||||
}) |
||||
.setEditor(PieChartPanelEditor); |
||||
|
||||
Loading…
Reference in new issue