mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 10:03:33 -06:00
* PanelOptions: Refactoring on applying panel and field options from PanelModel * Progress * Filtering out props * downgraded prettier * Fixes * Initial simple remember and restore for custom and overrides * clearing custom options and overrides and restoring works * actually use the function * Added type for options cache * minor fix * Updated with new prettier * Added old field config to panel type change handler * Update public/app/features/dashboard/state/getPanelOptionsWithDefaults.test.ts Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com> Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
196 lines
5.6 KiB
TypeScript
196 lines
5.6 KiB
TypeScript
import {
|
|
ConfigOverrideRule,
|
|
DynamicConfigValue,
|
|
FieldColorConfigSettings,
|
|
FieldColorModeId,
|
|
fieldColorModeRegistry,
|
|
FieldConfigOptionsRegistry,
|
|
FieldConfigProperty,
|
|
FieldConfigSource,
|
|
PanelPlugin,
|
|
ThresholdsConfig,
|
|
ThresholdsMode,
|
|
} from '@grafana/data';
|
|
import { mergeWith, isArray, isObject, unset, isEqual } from 'lodash';
|
|
|
|
export interface Props {
|
|
plugin: PanelPlugin;
|
|
currentFieldConfig: FieldConfigSource;
|
|
currentOptions: Record<string, any>;
|
|
}
|
|
|
|
export interface OptionDefaults {
|
|
options: any;
|
|
fieldConfig: FieldConfigSource;
|
|
}
|
|
|
|
export function getPanelOptionsWithDefaults({ plugin, currentOptions, currentFieldConfig }: Props): OptionDefaults {
|
|
const optionsWithDefaults = mergeWith(
|
|
{},
|
|
plugin.defaults,
|
|
currentOptions || {},
|
|
(objValue: any, srcValue: any): any => {
|
|
if (isArray(srcValue)) {
|
|
return srcValue;
|
|
}
|
|
}
|
|
);
|
|
|
|
const fieldConfigWithDefaults = applyFieldConfigDefaults(currentFieldConfig, plugin);
|
|
const fieldConfigWithOptimalColorMode = adaptFieldColorMode(plugin, fieldConfigWithDefaults);
|
|
|
|
return { options: optionsWithDefaults, fieldConfig: fieldConfigWithOptimalColorMode };
|
|
}
|
|
|
|
function applyFieldConfigDefaults(existingFieldConfig: FieldConfigSource, plugin: PanelPlugin): FieldConfigSource {
|
|
const pluginDefaults = plugin.fieldConfigDefaults;
|
|
|
|
const result: FieldConfigSource = {
|
|
defaults: mergeWith(
|
|
{},
|
|
pluginDefaults.defaults,
|
|
existingFieldConfig ? existingFieldConfig.defaults : {},
|
|
(objValue: any, srcValue: any): any => {
|
|
if (isArray(srcValue)) {
|
|
return srcValue;
|
|
}
|
|
}
|
|
),
|
|
overrides: existingFieldConfig?.overrides ?? [],
|
|
};
|
|
|
|
cleanProperties(result.defaults, '', plugin.fieldConfigRegistry);
|
|
|
|
// Thresholds base values are null in JSON but need to be converted to -Infinity
|
|
if (result.defaults.thresholds) {
|
|
fixThresholds(result.defaults.thresholds);
|
|
}
|
|
|
|
// Filter out overrides for properties that cannot be found in registry
|
|
result.overrides = filterFieldConfigOverrides(result.overrides, (prop) => {
|
|
return plugin.fieldConfigRegistry.getIfExists(prop.id) !== undefined;
|
|
});
|
|
|
|
for (const override of result.overrides) {
|
|
for (const property of override.properties) {
|
|
if (property.id === 'thresholds') {
|
|
fixThresholds(property.value as ThresholdsConfig);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export function filterFieldConfigOverrides(
|
|
overrides: ConfigOverrideRule[],
|
|
condition: (value: DynamicConfigValue) => boolean
|
|
): ConfigOverrideRule[] {
|
|
return overrides
|
|
.map((x) => {
|
|
const properties = x.properties.filter(condition);
|
|
|
|
return {
|
|
...x,
|
|
properties,
|
|
};
|
|
})
|
|
.filter((x) => x.properties.length > 0);
|
|
}
|
|
|
|
function cleanProperties(obj: any, parentPath: string, fieldConfigRegistry: FieldConfigOptionsRegistry) {
|
|
for (const propName of Object.keys(obj)) {
|
|
const value = obj[propName];
|
|
const fullPath = `${parentPath}${propName}`;
|
|
const existsInRegistry = !!fieldConfigRegistry.getIfExists(fullPath);
|
|
|
|
// need to check early here as some standard properties have nested properies
|
|
if (existsInRegistry) {
|
|
continue;
|
|
}
|
|
|
|
if (isArray(value) || !isObject(value)) {
|
|
if (!existsInRegistry) {
|
|
unset(obj, propName);
|
|
}
|
|
} else {
|
|
cleanProperties(value, `${fullPath}.`, fieldConfigRegistry);
|
|
}
|
|
}
|
|
}
|
|
|
|
function adaptFieldColorMode(plugin: PanelPlugin, fieldConfig: FieldConfigSource): FieldConfigSource {
|
|
// adjust to prefered field color setting if needed
|
|
const color = plugin.fieldConfigRegistry.getIfExists(FieldConfigProperty.Color);
|
|
|
|
if (color && color.settings) {
|
|
const colorSettings = color.settings as FieldColorConfigSettings;
|
|
const mode = fieldColorModeRegistry.getIfExists(fieldConfig.defaults.color?.mode);
|
|
|
|
// When no support fo value colors, use classic palette
|
|
if (!colorSettings.byValueSupport) {
|
|
if (!mode || mode.isByValue) {
|
|
fieldConfig.defaults.color = { mode: FieldColorModeId.PaletteClassic };
|
|
return fieldConfig;
|
|
}
|
|
}
|
|
|
|
// When supporting value colors and prefering thresholds, use Thresholds mode.
|
|
// Otherwise keep current mode
|
|
if (colorSettings.byValueSupport && colorSettings.preferThresholdsMode) {
|
|
if (!mode || !mode.isByValue) {
|
|
fieldConfig.defaults.color = { mode: FieldColorModeId.Thresholds };
|
|
return fieldConfig;
|
|
}
|
|
}
|
|
}
|
|
return fieldConfig;
|
|
}
|
|
|
|
function fixThresholds(thresholds: ThresholdsConfig) {
|
|
if (!thresholds.mode) {
|
|
thresholds.mode = ThresholdsMode.Absolute;
|
|
}
|
|
|
|
if (!thresholds.steps) {
|
|
thresholds.steps = [];
|
|
} else if (thresholds.steps.length) {
|
|
// First value is always -Infinity
|
|
// JSON saves it as null
|
|
thresholds.steps[0].value = -Infinity;
|
|
}
|
|
}
|
|
|
|
export function restoreCustomOverrideRules(current: FieldConfigSource, old: FieldConfigSource): FieldConfigSource {
|
|
const result = {
|
|
defaults: {
|
|
...current.defaults,
|
|
custom: old.defaults.custom,
|
|
},
|
|
overrides: [...current.overrides],
|
|
};
|
|
|
|
for (const override of old.overrides) {
|
|
for (const prop of override.properties) {
|
|
if (isCustomFieldProp(prop)) {
|
|
const currentOverride = result.overrides.find((o) => isEqual(o.matcher, override.matcher));
|
|
if (currentOverride) {
|
|
currentOverride.properties.push(prop);
|
|
} else {
|
|
result.overrides.push(override);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export function isCustomFieldProp(prop: DynamicConfigValue): boolean {
|
|
return prop.id.startsWith('custom.');
|
|
}
|
|
|
|
export function isStandardFieldProp(prop: DynamicConfigValue): boolean {
|
|
return !isCustomFieldProp(prop);
|
|
}
|