mirror of
https://github.com/grafana/grafana.git
synced 2025-02-03 12:11:09 -06:00
Field config: Add support for paths in default field config setup (#27570)
* Add support for paths in default field config setup * Typecheck fix
This commit is contained in:
parent
e350e1fff6
commit
e04e3e7d46
@ -1,13 +1,13 @@
|
|||||||
import React, { useCallback, ReactNode } from 'react';
|
import React, { ReactNode, useCallback } from 'react';
|
||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import {
|
import {
|
||||||
DataFrame,
|
DataFrame,
|
||||||
|
DocsId,
|
||||||
FieldConfigPropertyItem,
|
FieldConfigPropertyItem,
|
||||||
FieldConfigSource,
|
FieldConfigSource,
|
||||||
PanelPlugin,
|
PanelPlugin,
|
||||||
SelectableValue,
|
SelectableValue,
|
||||||
VariableSuggestionsScope,
|
VariableSuggestionsScope,
|
||||||
DocsId,
|
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { Container, Counter, FeatureInfoBox, Field, fieldMatchersUI, Label, useTheme, ValuePicker } from '@grafana/ui';
|
import { Container, Counter, FeatureInfoBox, Field, fieldMatchersUI, Label, useTheme, ValuePicker } from '@grafana/ui';
|
||||||
import { getDataLinksVariableSuggestions } from '../../../panel/panellinks/link_srv';
|
import { getDataLinksVariableSuggestions } from '../../../panel/panellinks/link_srv';
|
||||||
@ -17,6 +17,7 @@ import { OptionsGroup } from './OptionsGroup';
|
|||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { getDocsLink } from 'app/core/utils/docsLinks';
|
import { getDocsLink } from 'app/core/utils/docsLinks';
|
||||||
|
import { updateDefaultFieldConfigValue } from './utils';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
plugin: PanelPlugin;
|
plugin: PanelPlugin;
|
||||||
@ -32,6 +33,7 @@ interface Props {
|
|||||||
export const OverrideFieldConfigEditor: React.FC<Props> = props => {
|
export const OverrideFieldConfigEditor: React.FC<Props> = props => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { config } = props;
|
const { config } = props;
|
||||||
|
|
||||||
const onOverrideChange = (index: number, override: any) => {
|
const onOverrideChange = (index: number, override: any) => {
|
||||||
const { config } = props;
|
const { config } = props;
|
||||||
let overrides = cloneDeep(config.overrides);
|
let overrides = cloneDeep(config.overrides);
|
||||||
@ -128,32 +130,9 @@ export const OverrideFieldConfigEditor: React.FC<Props> = props => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const DefaultFieldConfigEditor: React.FC<Props> = ({ data, onChange, config, plugin }) => {
|
export const DefaultFieldConfigEditor: React.FC<Props> = ({ data, onChange, config, plugin }) => {
|
||||||
const setDefaultValue = useCallback(
|
const onDefaultValueChange = useCallback(
|
||||||
(name: string, value: any, isCustom: boolean | undefined) => {
|
(name: string, value: any, isCustom: boolean | undefined) => {
|
||||||
const defaults = { ...config.defaults };
|
onChange(updateDefaultFieldConfigValue(config, name, value, isCustom));
|
||||||
const remove = value === undefined || value === null || '';
|
|
||||||
|
|
||||||
if (isCustom) {
|
|
||||||
if (defaults.custom) {
|
|
||||||
if (remove) {
|
|
||||||
defaults.custom = { ...defaults.custom };
|
|
||||||
delete defaults.custom[name];
|
|
||||||
} else {
|
|
||||||
defaults.custom = { ...defaults.custom, [name]: value };
|
|
||||||
}
|
|
||||||
} else if (!remove) {
|
|
||||||
defaults.custom = { [name]: value };
|
|
||||||
}
|
|
||||||
} else if (remove) {
|
|
||||||
delete (defaults as any)[name];
|
|
||||||
} else {
|
|
||||||
(defaults as any)[name] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange({
|
|
||||||
...config,
|
|
||||||
defaults,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
[config, onChange]
|
[config, onChange]
|
||||||
);
|
);
|
||||||
@ -187,7 +166,7 @@ export const DefaultFieldConfigEditor: React.FC<Props> = ({ data, onChange, conf
|
|||||||
<item.editor
|
<item.editor
|
||||||
item={item}
|
item={item}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={v => setDefaultValue(item.path, v, item.isCustom)}
|
onChange={v => onDefaultValueChange(item.path, v, item.isCustom)}
|
||||||
context={{
|
context={{
|
||||||
data,
|
data,
|
||||||
getSuggestions: (scope?: VariableSuggestionsScope) => getDataLinksVariableSuggestions(data, scope),
|
getSuggestions: (scope?: VariableSuggestionsScope) => getDataLinksVariableSuggestions(data, scope),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { FieldConfig, PanelPlugin, standardFieldConfigEditorRegistry } from '@grafana/data';
|
import { FieldConfig, FieldConfigSource, PanelPlugin, standardFieldConfigEditorRegistry } from '@grafana/data';
|
||||||
import { supportsDataQuery } from './utils';
|
import { supportsDataQuery, updateDefaultFieldConfigValue } from './utils';
|
||||||
|
|
||||||
describe('standardFieldConfigEditorRegistry', () => {
|
describe('standardFieldConfigEditorRegistry', () => {
|
||||||
const dummyConfig: FieldConfig = {
|
const dummyConfig: FieldConfig = {
|
||||||
@ -50,3 +50,39 @@ describe('supportsDataQuery', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('updateDefaultFieldConfigValue', () => {
|
||||||
|
it.each`
|
||||||
|
property | isCustom | newValue | expected
|
||||||
|
${'a'} | ${false} | ${2} | ${{ a: 2, b: { c: 'nested default' }, custom: { d: 1, e: { f: 'nested custom' } } }}
|
||||||
|
${'b.c'} | ${false} | ${'nested default updated'} | ${{ a: 1, b: { c: 'nested default updated' }, custom: { d: 1, e: { f: 'nested custom' } } }}
|
||||||
|
${'a'} | ${false} | ${undefined} | ${{ b: { c: 'nested default' }, custom: { d: 1, e: { f: 'nested custom' } } }}
|
||||||
|
${'b'} | ${false} | ${undefined} | ${{ a: 1, custom: { d: 1, e: { f: 'nested custom' } } }}
|
||||||
|
${'b.c'} | ${false} | ${undefined} | ${{ a: 1, b: {}, custom: { d: 1, e: { f: 'nested custom' } } }}
|
||||||
|
${'d'} | ${true} | ${2} | ${{ a: 1, b: { c: 'nested default' }, custom: { d: 2, e: { f: 'nested custom' } } }}
|
||||||
|
${'e.f'} | ${true} | ${'nested custom updated'} | ${{ a: 1, b: { c: 'nested default' }, custom: { d: 1, e: { f: 'nested custom updated' } } }}
|
||||||
|
${'d'} | ${true} | ${undefined} | ${{ a: 1, b: { c: 'nested default' }, custom: { e: { f: 'nested custom' } } }}
|
||||||
|
${'e'} | ${true} | ${undefined} | ${{ a: 1, b: { c: 'nested default' }, custom: { d: 1 } }}
|
||||||
|
${'e.f'} | ${true} | ${undefined} | ${{ a: 1, b: { c: 'nested default' }, custom: { d: 1, e: {} } }}
|
||||||
|
`(
|
||||||
|
'when updating property:$property (is custom: $isCustom) with $newValue',
|
||||||
|
({ property, isCustom, newValue, expected }) => {
|
||||||
|
const config = {
|
||||||
|
defaults: {
|
||||||
|
a: 1,
|
||||||
|
b: {
|
||||||
|
c: 'nested default',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
d: 1,
|
||||||
|
e: { f: 'nested custom' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
overrides: [],
|
||||||
|
};
|
||||||
|
expect(updateDefaultFieldConfigValue(config as FieldConfigSource, property, newValue, isCustom).defaults).toEqual(
|
||||||
|
expected
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { CSSProperties } from 'react';
|
import { CSSProperties } from 'react';
|
||||||
|
import { set as lodashSet, omit } from 'lodash';
|
||||||
|
import { FieldConfigSource, PanelPlugin } from '@grafana/data';
|
||||||
import { PanelModel } from '../../state/PanelModel';
|
import { PanelModel } from '../../state/PanelModel';
|
||||||
import { DisplayMode } from './types';
|
import { DisplayMode } from './types';
|
||||||
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT } from 'app/core/constants';
|
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT } from 'app/core/constants';
|
||||||
import { PanelPlugin } from '@grafana/data';
|
|
||||||
|
|
||||||
export function calculatePanelSize(mode: DisplayMode, width: number, height: number, panel: PanelModel): CSSProperties {
|
export function calculatePanelSize(mode: DisplayMode, width: number, height: number, panel: PanelModel): CSSProperties {
|
||||||
if (mode === DisplayMode.Fill) {
|
if (mode === DisplayMode.Fill) {
|
||||||
@ -29,3 +30,34 @@ export function calculatePanelSize(mode: DisplayMode, width: number, height: num
|
|||||||
export function supportsDataQuery(plugin: PanelPlugin | undefined): boolean {
|
export function supportsDataQuery(plugin: PanelPlugin | undefined): boolean {
|
||||||
return plugin?.meta.skipDataQuery === false;
|
return plugin?.meta.skipDataQuery === false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const updateDefaultFieldConfigValue = (
|
||||||
|
config: FieldConfigSource,
|
||||||
|
name: string,
|
||||||
|
value: any,
|
||||||
|
isCustom?: boolean
|
||||||
|
) => {
|
||||||
|
let defaults = { ...config.defaults };
|
||||||
|
const remove = value === undefined || value === null || '';
|
||||||
|
|
||||||
|
if (isCustom) {
|
||||||
|
if (defaults.custom) {
|
||||||
|
if (remove) {
|
||||||
|
defaults.custom = omit(defaults.custom, name);
|
||||||
|
} else {
|
||||||
|
defaults.custom = lodashSet({ ...defaults.custom }, name, value);
|
||||||
|
}
|
||||||
|
} else if (!remove) {
|
||||||
|
defaults.custom = lodashSet({ ...defaults.custom }, name, value);
|
||||||
|
}
|
||||||
|
} else if (remove) {
|
||||||
|
defaults = omit(defaults, name);
|
||||||
|
} else {
|
||||||
|
defaults = lodashSet({ ...defaults }, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
defaults,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user