mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Gauge/BarGauge: Rewrite of how migrations are applied (#18375)
This commit is contained in:
parent
2514209083
commit
541981c341
@ -44,7 +44,7 @@
|
||||
"nullPointMode": "null",
|
||||
"options-gauge": {
|
||||
"baseColor": "#299c46",
|
||||
"decimals": "2",
|
||||
"decimals": 2,
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"options": {
|
||||
@ -111,7 +111,7 @@
|
||||
"nullPointMode": "null",
|
||||
"options-gauge": {
|
||||
"baseColor": "#299c46",
|
||||
"decimals": "",
|
||||
"decimals": null,
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"options": {
|
||||
@ -178,7 +178,7 @@
|
||||
"nullPointMode": "null",
|
||||
"options-gauge": {
|
||||
"baseColor": "#299c46",
|
||||
"decimals": "",
|
||||
"decimals": null,
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"options": {
|
||||
|
@ -104,7 +104,7 @@ export const fieldReducers = new Registry<FieldReducerInfo>(() => [
|
||||
name: 'Last (not null)',
|
||||
description: 'Last non-null value',
|
||||
standard: true,
|
||||
alias: 'current',
|
||||
aliasIds: ['current'],
|
||||
reduce: calculateLastNotNull,
|
||||
},
|
||||
{
|
||||
@ -124,14 +124,14 @@ export const fieldReducers = new Registry<FieldReducerInfo>(() => [
|
||||
},
|
||||
{ id: ReducerID.min, name: 'Min', description: 'Minimum Value', standard: true },
|
||||
{ id: ReducerID.max, name: 'Max', description: 'Maximum Value', standard: true },
|
||||
{ id: ReducerID.mean, name: 'Mean', description: 'Average Value', standard: true, alias: 'avg' },
|
||||
{ id: ReducerID.mean, name: 'Mean', description: 'Average Value', standard: true, aliasIds: ['avg'] },
|
||||
{
|
||||
id: ReducerID.sum,
|
||||
name: 'Total',
|
||||
description: 'The sum of all values',
|
||||
emptyInputResult: 0,
|
||||
standard: true,
|
||||
alias: 'total',
|
||||
aliasIds: ['total'],
|
||||
},
|
||||
{
|
||||
id: ReducerID.count,
|
||||
|
@ -0,0 +1,39 @@
|
||||
import { sharedSingleStatMigrationCheck } from './SingleStatBaseOptions';
|
||||
|
||||
describe('sharedSingleStatMigrationCheck', () => {
|
||||
it('from old valueOptions model without pluginVersion', () => {
|
||||
const panel = {
|
||||
options: {
|
||||
valueOptions: {
|
||||
unit: 'watt',
|
||||
stat: 'last',
|
||||
decimals: 5,
|
||||
},
|
||||
minValue: 10,
|
||||
maxValue: 100,
|
||||
valueMappings: [{ type: 1, value: '1', text: 'OK' }],
|
||||
thresholds: [
|
||||
{
|
||||
color: 'green',
|
||||
index: 0,
|
||||
value: null,
|
||||
},
|
||||
{
|
||||
color: 'orange',
|
||||
index: 1,
|
||||
value: 40,
|
||||
},
|
||||
{
|
||||
color: 'red',
|
||||
index: 2,
|
||||
value: 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
title: 'Usage',
|
||||
type: 'bargauge',
|
||||
};
|
||||
|
||||
expect(sharedSingleStatMigrationCheck(panel as any)).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -3,7 +3,7 @@ import omit from 'lodash/omit';
|
||||
|
||||
import { VizOrientation, PanelModel } from '../../types/panel';
|
||||
import { FieldDisplayOptions } from '../../utils/fieldDisplay';
|
||||
import { Field, fieldReducers, Threshold, sortThresholds } from '@grafana/data';
|
||||
import { fieldReducers, Threshold, sortThresholds } from '@grafana/data';
|
||||
|
||||
export interface SingleStatBaseOptions {
|
||||
fieldOptions: FieldDisplayOptions;
|
||||
@ -25,54 +25,86 @@ export const sharedSingleStatOptionsCheck = (
|
||||
return options;
|
||||
};
|
||||
|
||||
export const sharedSingleStatMigrationCheck = (panel: PanelModel<SingleStatBaseOptions>) => {
|
||||
export function sharedSingleStatMigrationCheck(panel: PanelModel<SingleStatBaseOptions>) {
|
||||
if (!panel.options) {
|
||||
// This happens on the first load or when migrating from angular
|
||||
return {};
|
||||
}
|
||||
|
||||
// This migration aims to keep the most recent changes up-to-date
|
||||
// Plugins should explicitly migrate for known version changes and only use this
|
||||
// as a backup
|
||||
const old = panel.options as any;
|
||||
if (old.valueOptions) {
|
||||
const { valueOptions } = old;
|
||||
const previousVersion = parseFloat(panel.pluginVersion || '6.1');
|
||||
let options = panel.options as any;
|
||||
|
||||
const fieldOptions = (old.fieldOptions = {} as FieldDisplayOptions);
|
||||
if (previousVersion < 6.2) {
|
||||
options = migrateFromValueOptions(options);
|
||||
}
|
||||
|
||||
const field = (fieldOptions.defaults = {} as Field);
|
||||
field.mappings = old.valueMappings;
|
||||
field.thresholds = migrateOldThresholds(old.thresholds);
|
||||
field.unit = valueOptions.unit;
|
||||
field.decimals = valueOptions.decimals;
|
||||
if (previousVersion < 6.3) {
|
||||
options = moveThresholdsAndMappingsToField(options);
|
||||
}
|
||||
|
||||
// Make sure the stats have a valid name
|
||||
if (valueOptions.stat) {
|
||||
const reducer = fieldReducers.get(valueOptions.stat);
|
||||
if (reducer) {
|
||||
fieldOptions.calcs = [reducer.id];
|
||||
}
|
||||
}
|
||||
return options as SingleStatBaseOptions;
|
||||
}
|
||||
|
||||
field.min = old.minValue;
|
||||
field.max = old.maxValue;
|
||||
export function moveThresholdsAndMappingsToField(old: any) {
|
||||
const { fieldOptions } = old;
|
||||
|
||||
// remove old props
|
||||
return omit(old, 'valueMappings', 'thresholds', 'valueOptions', 'minValue', 'maxValue');
|
||||
} else if (old.fieldOptions) {
|
||||
// Move mappins & thresholds to field defautls (6.4+)
|
||||
const { mappings, thresholds, ...fieldOptions } = old.fieldOptions;
|
||||
fieldOptions.defaults = {
|
||||
mappings,
|
||||
thresholds: migrateOldThresholds(thresholds),
|
||||
...fieldOptions.defaults,
|
||||
};
|
||||
old.fieldOptions = fieldOptions;
|
||||
if (!fieldOptions) {
|
||||
return old;
|
||||
}
|
||||
|
||||
return panel.options;
|
||||
};
|
||||
const { mappings, thresholds, ...rest } = old.fieldOptions;
|
||||
|
||||
return {
|
||||
...old,
|
||||
fieldOptions: {
|
||||
...rest,
|
||||
defaults: {
|
||||
...fieldOptions.defaults,
|
||||
mappings,
|
||||
thresholds: migrateOldThresholds(thresholds),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Moves valueMappings and thresholds from root to new fieldOptions object
|
||||
* Renames valueOptions to to defaults and moves it under fieldOptions
|
||||
*/
|
||||
export function migrateFromValueOptions(old: any) {
|
||||
const { valueOptions } = old;
|
||||
if (!valueOptions) {
|
||||
return old;
|
||||
}
|
||||
|
||||
const fieldOptions: any = {};
|
||||
const fieldDefaults: any = {};
|
||||
|
||||
fieldOptions.mappings = old.valueMappings;
|
||||
fieldOptions.thresholds = old.thresholds;
|
||||
fieldOptions.defaults = fieldDefaults;
|
||||
|
||||
fieldDefaults.unit = valueOptions.unit;
|
||||
fieldDefaults.decimals = valueOptions.decimals;
|
||||
|
||||
// Make sure the stats have a valid name
|
||||
if (valueOptions.stat) {
|
||||
const reducer = fieldReducers.get(valueOptions.stat);
|
||||
if (reducer) {
|
||||
fieldOptions.calcs = [reducer.id];
|
||||
}
|
||||
}
|
||||
|
||||
fieldDefaults.min = old.minValue;
|
||||
fieldDefaults.max = old.maxValue;
|
||||
|
||||
const newOptions = {
|
||||
...old,
|
||||
fieldOptions,
|
||||
};
|
||||
|
||||
return omit(newOptions, 'valueMappings', 'thresholds', 'valueOptions', 'minValue', 'maxValue');
|
||||
}
|
||||
|
||||
export function migrateOldThresholds(thresholds?: any[]): Threshold[] | undefined {
|
||||
if (!thresholds || !thresholds.length) {
|
||||
|
@ -0,0 +1,38 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`sharedSingleStatMigrationCheck from old valueOptions model without pluginVersion 1`] = `
|
||||
Object {
|
||||
"fieldOptions": Object {
|
||||
"calcs": Array [
|
||||
"last",
|
||||
],
|
||||
"defaults": Object {
|
||||
"decimals": 5,
|
||||
"mappings": Array [
|
||||
Object {
|
||||
"text": "OK",
|
||||
"type": 1,
|
||||
"value": "1",
|
||||
},
|
||||
],
|
||||
"max": 100,
|
||||
"min": 10,
|
||||
"thresholds": Array [
|
||||
Object {
|
||||
"color": "green",
|
||||
"value": -Infinity,
|
||||
},
|
||||
Object {
|
||||
"color": "orange",
|
||||
"value": 40,
|
||||
},
|
||||
Object {
|
||||
"color": "red",
|
||||
"value": 80,
|
||||
},
|
||||
],
|
||||
"unit": "watt",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
@ -152,8 +152,6 @@ export class PanelChrome extends PureComponent<Props, State> {
|
||||
onRefresh = () => {
|
||||
const { panel, isInView, width } = this.props;
|
||||
|
||||
console.log('onRefresh', panel.id);
|
||||
|
||||
if (!isInView) {
|
||||
console.log('Refresh when panel is visible', panel.id);
|
||||
this.setState({ refreshWhenInView: true });
|
||||
|
@ -247,8 +247,6 @@ export class PanelModel {
|
||||
pluginLoaded(plugin: PanelPlugin) {
|
||||
this.plugin = plugin;
|
||||
|
||||
this.applyPluginOptionDefaults(plugin);
|
||||
|
||||
if (plugin.panel && plugin.onPanelMigration) {
|
||||
const version = getPluginVersion(plugin);
|
||||
if (version !== this.pluginVersion) {
|
||||
@ -256,6 +254,8 @@ export class PanelModel {
|
||||
this.pluginVersion = version;
|
||||
}
|
||||
}
|
||||
|
||||
this.applyPluginOptionDefaults(plugin);
|
||||
}
|
||||
|
||||
changePlugin(newPlugin: PanelPlugin) {
|
||||
|
@ -40,18 +40,7 @@ describe('BarGauge Panel Migrations', () => {
|
||||
orientation: 'vertical',
|
||||
},
|
||||
pluginVersion: '6.2.0',
|
||||
targets: [
|
||||
{
|
||||
refId: 'A',
|
||||
scenarioId: 'random_walk',
|
||||
},
|
||||
{
|
||||
refId: 'B',
|
||||
scenarioId: 'random_walk',
|
||||
},
|
||||
],
|
||||
timeFrom: null,
|
||||
timeShift: null,
|
||||
targets: [],
|
||||
title: 'Usage',
|
||||
type: 'bargauge',
|
||||
} as PanelModel;
|
||||
|
@ -1,36 +1,7 @@
|
||||
import { PanelModel } from '@grafana/ui';
|
||||
import {
|
||||
sharedSingleStatMigrationCheck,
|
||||
migrateOldThresholds,
|
||||
} from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||
import { sharedSingleStatMigrationCheck } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||
import { BarGaugeOptions } from './types';
|
||||
|
||||
export const barGaugePanelMigrationCheck = (panel: PanelModel<BarGaugeOptions>): Partial<BarGaugeOptions> => {
|
||||
if (!panel.options) {
|
||||
// This happens on the first load or when migrating from angular
|
||||
return {};
|
||||
}
|
||||
|
||||
// Move thresholds to field
|
||||
const previousVersion = panel.pluginVersion || '';
|
||||
if (previousVersion.startsWith('6.2') || previousVersion.startsWith('6.3')) {
|
||||
console.log('TRANSFORM', panel.options);
|
||||
const old = panel.options as any;
|
||||
const { fieldOptions } = old;
|
||||
if (fieldOptions) {
|
||||
const { mappings, thresholds, ...rest } = fieldOptions;
|
||||
rest.defaults = {
|
||||
mappings,
|
||||
thresholds: migrateOldThresholds(thresholds),
|
||||
...rest.defaults,
|
||||
};
|
||||
return {
|
||||
...old,
|
||||
fieldOptions: rest,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Default to the standard migration path
|
||||
return sharedSingleStatMigrationCheck(panel);
|
||||
};
|
||||
|
@ -1,60 +1,7 @@
|
||||
import { Field, fieldReducers } from '@grafana/data';
|
||||
import { PanelModel, FieldDisplayOptions } from '@grafana/ui';
|
||||
import { PanelModel } from '@grafana/ui';
|
||||
import { GaugeOptions } from './types';
|
||||
import {
|
||||
sharedSingleStatMigrationCheck,
|
||||
migrateOldThresholds,
|
||||
} from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||
import { sharedSingleStatMigrationCheck } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||
|
||||
export const gaugePanelMigrationCheck = (panel: PanelModel<GaugeOptions>): Partial<GaugeOptions> => {
|
||||
if (!panel.options) {
|
||||
// This happens on the first load or when migrating from angular
|
||||
return {};
|
||||
}
|
||||
|
||||
const previousVersion = panel.pluginVersion || '';
|
||||
if (!previousVersion || previousVersion.startsWith('6.1')) {
|
||||
const old = panel.options as any;
|
||||
const { valueOptions } = old;
|
||||
|
||||
const options = {} as GaugeOptions;
|
||||
options.showThresholdLabels = old.showThresholdLabels;
|
||||
options.showThresholdMarkers = old.showThresholdMarkers;
|
||||
options.orientation = old.orientation;
|
||||
|
||||
const fieldOptions = (options.fieldOptions = {} as FieldDisplayOptions);
|
||||
|
||||
const field = (fieldOptions.defaults = {} as Field);
|
||||
field.mappings = old.valueMappings;
|
||||
field.thresholds = migrateOldThresholds(old.thresholds);
|
||||
field.unit = valueOptions.unit;
|
||||
field.decimals = valueOptions.decimals;
|
||||
|
||||
// Make sure the stats have a valid name
|
||||
if (valueOptions.stat) {
|
||||
fieldOptions.calcs = [fieldReducers.get(valueOptions.stat).id];
|
||||
}
|
||||
field.min = old.minValue;
|
||||
field.max = old.maxValue;
|
||||
|
||||
return options;
|
||||
} else if (previousVersion.startsWith('6.2') || previousVersion.startsWith('6.3')) {
|
||||
const old = panel.options as any;
|
||||
const { fieldOptions } = old;
|
||||
if (fieldOptions) {
|
||||
const { mappings, thresholds, ...rest } = fieldOptions;
|
||||
rest.default = {
|
||||
mappings,
|
||||
thresholds: migrateOldThresholds(thresholds),
|
||||
...rest.defaults,
|
||||
};
|
||||
return {
|
||||
...old.options,
|
||||
fieldOptions: rest,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Default to the standard migration path
|
||||
return sharedSingleStatMigrationCheck(panel);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user