mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
FieldOverrides: Support changing display name in override and have it be matched by later rule (#35893)
* FieldOverrides: Support changing display name in override that can be matched by later rule * Fixed test
This commit is contained in:
parent
c56c1d73ed
commit
9e53b44f35
@ -314,7 +314,7 @@ describe('applyFieldOverrides', () => {
|
||||
data.fields[1].getLinks!({ valueRowIndex: 0 });
|
||||
|
||||
expect(data.fields[1].config.decimals).toEqual(1);
|
||||
expect(replaceVariablesCalls[0].__value.value.text).toEqual('100.0');
|
||||
expect(replaceVariablesCalls[3].__value.value.text).toEqual('100.0');
|
||||
});
|
||||
|
||||
it('creates a deep clone of field config', () => {
|
||||
@ -328,6 +328,33 @@ describe('applyFieldOverrides', () => {
|
||||
expect(data.fields[1].config).not.toBe(f0.fields[1].config);
|
||||
expect(data.fields[1].config.custom).not.toBe(f0.fields[1].config.custom);
|
||||
});
|
||||
|
||||
it('Can modify displayName and have it affect later overrides', () => {
|
||||
const config: FieldConfigSource = {
|
||||
defaults: {},
|
||||
overrides: [
|
||||
{
|
||||
matcher: { id: FieldMatcherID.byName, options: 'value' },
|
||||
properties: [{ id: 'displayName', value: 'Kittens' }],
|
||||
},
|
||||
{
|
||||
matcher: { id: FieldMatcherID.byName, options: 'Kittens' },
|
||||
properties: [{ id: 'displayName', value: 'Kittens improved' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const data = applyFieldOverrides({
|
||||
data: [f0], // the frame
|
||||
fieldConfig: config,
|
||||
replaceVariables: (str: string) => str,
|
||||
fieldConfigRegistry: customFieldRegistry,
|
||||
theme: createTheme(),
|
||||
})[0];
|
||||
|
||||
expect(data.fields[1].config.displayName).toBe('Kittens improved');
|
||||
expect(getFieldDisplayName(data.fields[1], data)).toBe('Kittens improved');
|
||||
});
|
||||
});
|
||||
|
||||
describe('setFieldConfigDefaults', () => {
|
||||
|
@ -28,7 +28,7 @@ import { FieldConfigOptionsRegistry } from './FieldConfigOptionsRegistry';
|
||||
import { DataLinkBuiltInVars, locationUtil } from '../utils';
|
||||
import { formattedValueToString } from '../valueFormats';
|
||||
import { getFieldDisplayValuesProxy } from './getFieldDisplayValuesProxy';
|
||||
import { getFieldDisplayName, getFrameDisplayName } from './fieldState';
|
||||
import { getFrameDisplayName } from './fieldState';
|
||||
import { getTimeField } from '../dataframe/processDataFrame';
|
||||
import { mapInternalLinkToExplore } from '../utils/dataLinks';
|
||||
import { getTemplateProxyForField } from './templateProxies';
|
||||
@ -97,33 +97,37 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra
|
||||
}
|
||||
}
|
||||
|
||||
return options.data.map((frame, index) => {
|
||||
return options.data.map((originalFrame, index) => {
|
||||
// Need to define this new frame here as it's passed to the getLinkSupplier function inside the fields loop
|
||||
const newFrame: DataFrame = { ...frame };
|
||||
const newFrame: DataFrame = { ...originalFrame };
|
||||
// Copy fields
|
||||
newFrame.fields = newFrame.fields.map((field) => {
|
||||
return {
|
||||
...field,
|
||||
config: cloneDeep(field.config),
|
||||
state: {
|
||||
...field.state,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const scopedVars: ScopedVars = {
|
||||
__series: { text: 'Series', value: { name: getFrameDisplayName(frame, index) } }, // might be missing
|
||||
__series: { text: 'Series', value: { name: getFrameDisplayName(newFrame, index) } }, // might be missing
|
||||
};
|
||||
|
||||
const fields: Field[] = frame.fields.map((field) => {
|
||||
// Config is mutable within this scope
|
||||
const fieldScopedVars = { ...scopedVars };
|
||||
const displayName = getFieldDisplayName(field, frame, options.data);
|
||||
for (const field of newFrame.fields) {
|
||||
const config = field.config;
|
||||
|
||||
fieldScopedVars['__field'] = {
|
||||
text: 'Field',
|
||||
value: getTemplateProxyForField(field, frame, options.data),
|
||||
field.state!.scopedVars = {
|
||||
...scopedVars,
|
||||
__field: {
|
||||
text: 'Field',
|
||||
value: getTemplateProxyForField(field, newFrame, options.data),
|
||||
},
|
||||
};
|
||||
|
||||
field.state = {
|
||||
...field.state,
|
||||
scopedVars: fieldScopedVars,
|
||||
displayName,
|
||||
};
|
||||
|
||||
const config: FieldConfig = { ...cloneDeep(field.config) };
|
||||
const context = {
|
||||
field,
|
||||
field: field,
|
||||
data: options.data!,
|
||||
dataFrameIndex: index,
|
||||
replaceVariables: options.replaceVariables,
|
||||
@ -133,9 +137,10 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra
|
||||
// Anything in the field config that's not set by the datasource
|
||||
// will be filled in by panel's field configuration
|
||||
setFieldConfigDefaults(config, source.defaults, context);
|
||||
|
||||
// Find any matching rules and then override
|
||||
for (const rule of override) {
|
||||
if (rule.match(field, frame, options.data!)) {
|
||||
if (rule.match(field, newFrame, options.data!)) {
|
||||
for (const prop of rule.properties) {
|
||||
// config.scopedVars is set already here
|
||||
setDynamicConfigValue(config, prop, context);
|
||||
@ -169,44 +174,32 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra
|
||||
seriesIndex++;
|
||||
}
|
||||
|
||||
// Overwrite the configs
|
||||
const newField: Field = {
|
||||
...field,
|
||||
config,
|
||||
type,
|
||||
state: {
|
||||
...field.state,
|
||||
displayName: null,
|
||||
seriesIndex,
|
||||
range,
|
||||
},
|
||||
};
|
||||
field.state!.seriesIndex = seriesIndex;
|
||||
field.state!.range = range;
|
||||
field.type = type;
|
||||
|
||||
// and set the display processor using it
|
||||
newField.display = getDisplayProcessor({
|
||||
field: newField,
|
||||
field.display = getDisplayProcessor({
|
||||
field: field,
|
||||
theme: options.theme,
|
||||
timeZone: options.timeZone,
|
||||
});
|
||||
|
||||
// Wrap the display with a cache to avoid double calls
|
||||
if (newField.config.unit !== 'dateTimeFromNow') {
|
||||
newField.display = cachingDisplayProcessor(newField.display, 2500);
|
||||
if (field.config.unit !== 'dateTimeFromNow') {
|
||||
field.display = cachingDisplayProcessor(field.display, 2500);
|
||||
}
|
||||
|
||||
// Attach data links supplier
|
||||
newField.getLinks = getLinksSupplier(
|
||||
field.getLinks = getLinksSupplier(
|
||||
newFrame,
|
||||
newField,
|
||||
fieldScopedVars,
|
||||
field,
|
||||
field.state!.scopedVars,
|
||||
context.replaceVariables,
|
||||
options.timeZone
|
||||
);
|
||||
}
|
||||
|
||||
return newField;
|
||||
});
|
||||
|
||||
newFrame.fields = fields;
|
||||
return newFrame;
|
||||
});
|
||||
}
|
||||
@ -236,6 +229,7 @@ export interface FieldOverrideEnv extends FieldOverrideContext {
|
||||
export function setDynamicConfigValue(config: FieldConfig, value: DynamicConfigValue, context: FieldOverrideEnv) {
|
||||
const reg = context.fieldConfigRegistry;
|
||||
const item = reg.getIfExists(value.id);
|
||||
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
@ -280,12 +274,12 @@ export function setFieldConfigDefaults(config: FieldConfig, defaults: FieldConfi
|
||||
validateFieldConfig(config);
|
||||
}
|
||||
|
||||
const processFieldConfigValue = (
|
||||
function processFieldConfigValue(
|
||||
destination: Record<string, any>, // it's mutable
|
||||
source: Record<string, any>,
|
||||
fieldConfigProperty: FieldConfigPropertyItem,
|
||||
context: FieldOverrideEnv
|
||||
) => {
|
||||
) {
|
||||
const currentConfig = get(destination, fieldConfigProperty.path);
|
||||
if (currentConfig === null || currentConfig === undefined) {
|
||||
const item = context.fieldConfigRegistry.getIfExists(fieldConfigProperty.id);
|
||||
@ -300,7 +294,7 @@ const processFieldConfigValue = (
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks that all options on FieldConfig make sense. It mutates any value that needs
|
||||
|
@ -24,6 +24,16 @@ export const numberOverrideProcessor = (
|
||||
return parseFloat(value);
|
||||
};
|
||||
|
||||
export const displayNameOverrideProcessor = (
|
||||
value: any,
|
||||
context: FieldOverrideContext,
|
||||
settings?: StringFieldConfigSettings
|
||||
) => {
|
||||
// clear the cached display name
|
||||
delete context.field?.state?.displayName;
|
||||
return stringOverrideProcessor(value, context, settings);
|
||||
};
|
||||
|
||||
export interface SliderFieldConfigSettings {
|
||||
min: number;
|
||||
max: number;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { identityOverrideProcessor } from '../../field';
|
||||
import { displayNameOverrideProcessor, identityOverrideProcessor } from '../../field';
|
||||
import { ThresholdsMode } from '../../types';
|
||||
|
||||
export const mockStandardProperties = () => {
|
||||
@ -9,7 +9,7 @@ export const mockStandardProperties = () => {
|
||||
description: "Field's display name",
|
||||
editor: () => null,
|
||||
override: () => null,
|
||||
process: identityOverrideProcessor,
|
||||
process: displayNameOverrideProcessor,
|
||||
settings: {
|
||||
placeholder: 'none',
|
||||
expandTemplateVars: true,
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
FieldColor,
|
||||
FieldColorConfigSettings,
|
||||
StatsPickerConfigSettings,
|
||||
displayNameOverrideProcessor,
|
||||
} from '@grafana/data';
|
||||
|
||||
import { Switch } from '../components/Switch/Switch';
|
||||
@ -55,7 +56,7 @@ export const getStandardFieldConfigs = () => {
|
||||
description: 'Change the field or series name',
|
||||
editor: standardEditorsRegistry.get('text').editor as any,
|
||||
override: standardEditorsRegistry.get('text').editor as any,
|
||||
process: stringOverrideProcessor,
|
||||
process: displayNameOverrideProcessor,
|
||||
settings: {
|
||||
placeholder: 'none',
|
||||
expandTemplateVars: true,
|
||||
|
@ -31,7 +31,7 @@ export function seriesVisibilityConfigFactory(
|
||||
|
||||
return {
|
||||
...fieldConfig,
|
||||
overrides: [override, ...fieldConfig.overrides],
|
||||
overrides: [...fieldConfig.overrides, override],
|
||||
};
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ export function seriesVisibilityConfigFactory(
|
||||
|
||||
return {
|
||||
...fieldConfig,
|
||||
overrides: [override, ...fieldConfig.overrides],
|
||||
overrides: [...fieldConfig.overrides, override],
|
||||
};
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ export function seriesVisibilityConfigFactory(
|
||||
|
||||
return {
|
||||
...fieldConfig,
|
||||
overrides: [override, ...overridesCopy],
|
||||
overrides: [...overridesCopy, override],
|
||||
};
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ export function seriesVisibilityConfigFactory(
|
||||
|
||||
return {
|
||||
...fieldConfig,
|
||||
overrides: [override, ...overridesCopy],
|
||||
overrides: [...overridesCopy, override],
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user