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",
|
"nullPointMode": "null",
|
||||||
"options-gauge": {
|
"options-gauge": {
|
||||||
"baseColor": "#299c46",
|
"baseColor": "#299c46",
|
||||||
"decimals": "2",
|
"decimals": 2,
|
||||||
"maxValue": 100,
|
"maxValue": 100,
|
||||||
"minValue": 0,
|
"minValue": 0,
|
||||||
"options": {
|
"options": {
|
||||||
@ -111,7 +111,7 @@
|
|||||||
"nullPointMode": "null",
|
"nullPointMode": "null",
|
||||||
"options-gauge": {
|
"options-gauge": {
|
||||||
"baseColor": "#299c46",
|
"baseColor": "#299c46",
|
||||||
"decimals": "",
|
"decimals": null,
|
||||||
"maxValue": 100,
|
"maxValue": 100,
|
||||||
"minValue": 0,
|
"minValue": 0,
|
||||||
"options": {
|
"options": {
|
||||||
@ -178,7 +178,7 @@
|
|||||||
"nullPointMode": "null",
|
"nullPointMode": "null",
|
||||||
"options-gauge": {
|
"options-gauge": {
|
||||||
"baseColor": "#299c46",
|
"baseColor": "#299c46",
|
||||||
"decimals": "",
|
"decimals": null,
|
||||||
"maxValue": 100,
|
"maxValue": 100,
|
||||||
"minValue": 0,
|
"minValue": 0,
|
||||||
"options": {
|
"options": {
|
||||||
|
@ -104,7 +104,7 @@ export const fieldReducers = new Registry<FieldReducerInfo>(() => [
|
|||||||
name: 'Last (not null)',
|
name: 'Last (not null)',
|
||||||
description: 'Last non-null value',
|
description: 'Last non-null value',
|
||||||
standard: true,
|
standard: true,
|
||||||
alias: 'current',
|
aliasIds: ['current'],
|
||||||
reduce: calculateLastNotNull,
|
reduce: calculateLastNotNull,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -124,14 +124,14 @@ export const fieldReducers = new Registry<FieldReducerInfo>(() => [
|
|||||||
},
|
},
|
||||||
{ id: ReducerID.min, name: 'Min', description: 'Minimum Value', standard: true },
|
{ id: ReducerID.min, name: 'Min', description: 'Minimum Value', standard: true },
|
||||||
{ id: ReducerID.max, name: 'Max', description: 'Maximum 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,
|
id: ReducerID.sum,
|
||||||
name: 'Total',
|
name: 'Total',
|
||||||
description: 'The sum of all values',
|
description: 'The sum of all values',
|
||||||
emptyInputResult: 0,
|
emptyInputResult: 0,
|
||||||
standard: true,
|
standard: true,
|
||||||
alias: 'total',
|
aliasIds: ['total'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: ReducerID.count,
|
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 { VizOrientation, PanelModel } from '../../types/panel';
|
||||||
import { FieldDisplayOptions } from '../../utils/fieldDisplay';
|
import { FieldDisplayOptions } from '../../utils/fieldDisplay';
|
||||||
import { Field, fieldReducers, Threshold, sortThresholds } from '@grafana/data';
|
import { fieldReducers, Threshold, sortThresholds } from '@grafana/data';
|
||||||
|
|
||||||
export interface SingleStatBaseOptions {
|
export interface SingleStatBaseOptions {
|
||||||
fieldOptions: FieldDisplayOptions;
|
fieldOptions: FieldDisplayOptions;
|
||||||
@ -25,26 +25,67 @@ export const sharedSingleStatOptionsCheck = (
|
|||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sharedSingleStatMigrationCheck = (panel: PanelModel<SingleStatBaseOptions>) => {
|
export function sharedSingleStatMigrationCheck(panel: PanelModel<SingleStatBaseOptions>) {
|
||||||
if (!panel.options) {
|
if (!panel.options) {
|
||||||
// This happens on the first load or when migrating from angular
|
// This happens on the first load or when migrating from angular
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// This migration aims to keep the most recent changes up-to-date
|
const previousVersion = parseFloat(panel.pluginVersion || '6.1');
|
||||||
// Plugins should explicitly migrate for known version changes and only use this
|
let options = panel.options as any;
|
||||||
// as a backup
|
|
||||||
const old = panel.options as any;
|
if (previousVersion < 6.2) {
|
||||||
if (old.valueOptions) {
|
options = migrateFromValueOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousVersion < 6.3) {
|
||||||
|
options = moveThresholdsAndMappingsToField(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return options as SingleStatBaseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function moveThresholdsAndMappingsToField(old: any) {
|
||||||
|
const { fieldOptions } = old;
|
||||||
|
|
||||||
|
if (!fieldOptions) {
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
const { valueOptions } = old;
|
||||||
|
if (!valueOptions) {
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
const fieldOptions = (old.fieldOptions = {} as FieldDisplayOptions);
|
const fieldOptions: any = {};
|
||||||
|
const fieldDefaults: any = {};
|
||||||
|
|
||||||
const field = (fieldOptions.defaults = {} as Field);
|
fieldOptions.mappings = old.valueMappings;
|
||||||
field.mappings = old.valueMappings;
|
fieldOptions.thresholds = old.thresholds;
|
||||||
field.thresholds = migrateOldThresholds(old.thresholds);
|
fieldOptions.defaults = fieldDefaults;
|
||||||
field.unit = valueOptions.unit;
|
|
||||||
field.decimals = valueOptions.decimals;
|
fieldDefaults.unit = valueOptions.unit;
|
||||||
|
fieldDefaults.decimals = valueOptions.decimals;
|
||||||
|
|
||||||
// Make sure the stats have a valid name
|
// Make sure the stats have a valid name
|
||||||
if (valueOptions.stat) {
|
if (valueOptions.stat) {
|
||||||
@ -54,25 +95,16 @@ export const sharedSingleStatMigrationCheck = (panel: PanelModel<SingleStatBaseO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field.min = old.minValue;
|
fieldDefaults.min = old.minValue;
|
||||||
field.max = old.maxValue;
|
fieldDefaults.max = old.maxValue;
|
||||||
|
|
||||||
// remove old props
|
const newOptions = {
|
||||||
return omit(old, 'valueMappings', 'thresholds', 'valueOptions', 'minValue', 'maxValue');
|
...old,
|
||||||
} else if (old.fieldOptions) {
|
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;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
return panel.options;
|
return omit(newOptions, 'valueMappings', 'thresholds', 'valueOptions', 'minValue', 'maxValue');
|
||||||
};
|
}
|
||||||
|
|
||||||
export function migrateOldThresholds(thresholds?: any[]): Threshold[] | undefined {
|
export function migrateOldThresholds(thresholds?: any[]): Threshold[] | undefined {
|
||||||
if (!thresholds || !thresholds.length) {
|
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 = () => {
|
onRefresh = () => {
|
||||||
const { panel, isInView, width } = this.props;
|
const { panel, isInView, width } = this.props;
|
||||||
|
|
||||||
console.log('onRefresh', panel.id);
|
|
||||||
|
|
||||||
if (!isInView) {
|
if (!isInView) {
|
||||||
console.log('Refresh when panel is visible', panel.id);
|
console.log('Refresh when panel is visible', panel.id);
|
||||||
this.setState({ refreshWhenInView: true });
|
this.setState({ refreshWhenInView: true });
|
||||||
|
@ -247,8 +247,6 @@ export class PanelModel {
|
|||||||
pluginLoaded(plugin: PanelPlugin) {
|
pluginLoaded(plugin: PanelPlugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
|
||||||
this.applyPluginOptionDefaults(plugin);
|
|
||||||
|
|
||||||
if (plugin.panel && plugin.onPanelMigration) {
|
if (plugin.panel && plugin.onPanelMigration) {
|
||||||
const version = getPluginVersion(plugin);
|
const version = getPluginVersion(plugin);
|
||||||
if (version !== this.pluginVersion) {
|
if (version !== this.pluginVersion) {
|
||||||
@ -256,6 +254,8 @@ export class PanelModel {
|
|||||||
this.pluginVersion = version;
|
this.pluginVersion = version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.applyPluginOptionDefaults(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
changePlugin(newPlugin: PanelPlugin) {
|
changePlugin(newPlugin: PanelPlugin) {
|
||||||
|
@ -40,18 +40,7 @@ describe('BarGauge Panel Migrations', () => {
|
|||||||
orientation: 'vertical',
|
orientation: 'vertical',
|
||||||
},
|
},
|
||||||
pluginVersion: '6.2.0',
|
pluginVersion: '6.2.0',
|
||||||
targets: [
|
targets: [],
|
||||||
{
|
|
||||||
refId: 'A',
|
|
||||||
scenarioId: 'random_walk',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
refId: 'B',
|
|
||||||
scenarioId: 'random_walk',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
timeFrom: null,
|
|
||||||
timeShift: null,
|
|
||||||
title: 'Usage',
|
title: 'Usage',
|
||||||
type: 'bargauge',
|
type: 'bargauge',
|
||||||
} as PanelModel;
|
} as PanelModel;
|
||||||
|
@ -1,36 +1,7 @@
|
|||||||
import { PanelModel } from '@grafana/ui';
|
import { PanelModel } from '@grafana/ui';
|
||||||
import {
|
import { sharedSingleStatMigrationCheck } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||||
sharedSingleStatMigrationCheck,
|
|
||||||
migrateOldThresholds,
|
|
||||||
} from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
|
||||||
import { BarGaugeOptions } from './types';
|
import { BarGaugeOptions } from './types';
|
||||||
|
|
||||||
export const barGaugePanelMigrationCheck = (panel: PanelModel<BarGaugeOptions>): Partial<BarGaugeOptions> => {
|
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);
|
return sharedSingleStatMigrationCheck(panel);
|
||||||
};
|
};
|
||||||
|
@ -1,60 +1,7 @@
|
|||||||
import { Field, fieldReducers } from '@grafana/data';
|
import { PanelModel } from '@grafana/ui';
|
||||||
import { PanelModel, FieldDisplayOptions } from '@grafana/ui';
|
|
||||||
import { GaugeOptions } from './types';
|
import { GaugeOptions } from './types';
|
||||||
import {
|
import { sharedSingleStatMigrationCheck } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||||
sharedSingleStatMigrationCheck,
|
|
||||||
migrateOldThresholds,
|
|
||||||
} from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
|
||||||
|
|
||||||
export const gaugePanelMigrationCheck = (panel: PanelModel<GaugeOptions>): Partial<GaugeOptions> => {
|
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);
|
return sharedSingleStatMigrationCheck(panel);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user