State-timeline: support migrating from discrete panel (#35071)

This commit is contained in:
Ryan McKinley 2021-06-02 12:18:20 -07:00 committed by GitHub
parent f7893ca5cf
commit a9b5aa1088
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 303 additions and 0 deletions

View File

@ -0,0 +1,67 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Timeline Migrations from discrete panel 1`] = `
Object {
"fieldConfig": Object {
"defaults": Object {
"custom": Object {
"fillOpacity": 100,
"lineWidth": 0,
},
"mappings": Array [
Object {
"options": Object {
"1": Object {
"color": "#7EB26D",
},
"111": Object {
"text": "ONE",
},
"20": Object {
"color": "#EAB839",
},
"222": Object {
"text": "TWO",
},
"30": Object {
"color": "#EF843C",
},
"5": Object {
"color": "#E24D42",
},
"90": Object {
"color": "#6ED0E0",
},
},
"type": "value",
},
Object {
"options": Object {
"from": 1,
"result": Object {
"text": "AAA",
},
"to": 3,
},
"type": "range",
},
Object {
"options": Object {
"from": 4,
"result": Object {
"text": "BBB",
},
"to": 5,
},
"type": "range",
},
],
"unit": "currencyGBP",
},
"overrides": Array [],
},
"options": Object {
"mergeValues": true,
},
}
`;

View File

@ -0,0 +1,154 @@
import { PanelModel } from 'app/features/dashboard/state';
import { timelinePanelChangedHandler } from './migrations';
describe('Timeline Migrations', () => {
it('from discrete panel', () => {
const panel = {} as PanelModel;
panel.options = timelinePanelChangedHandler(panel, 'natel-discrete-panel', { angular: discreteInV8 });
expect(panel).toMatchSnapshot();
});
});
const discreteInV8 = {
id: 23763571993,
gridPos: {
h: 8,
w: 12,
x: 0,
y: 0,
},
type: 'natel-discrete-panel',
title: 'Panel Title',
backgroundColor: 'rgba(128,128,128,0.1)',
colorMaps: [
{
$$hashKey: 'object:365',
color: '#7EB26D',
text: '1',
},
{
$$hashKey: 'object:366',
color: '#EAB839',
text: '20',
},
{
$$hashKey: 'object:367',
color: '#6ED0E0',
text: '90',
},
{
$$hashKey: 'object:368',
color: '#EF843C',
text: '30',
},
{
$$hashKey: 'object:369',
color: '#E24D42',
text: '5',
},
],
crosshairColor: '#8F070C',
display: 'timeline',
extendLastValue: true,
highlightOnMouseover: true,
legendSortBy: '-ms',
lineColor: 'rgba(0,0,0,0.1)',
metricNameColor: '#000000',
rangeMaps: [
{
$$hashKey: 'object:267',
from: '1',
text: 'AAA',
to: '3',
},
{
from: '4',
to: '5',
text: 'BBB',
$$hashKey: 'object:544',
},
],
rowHeight: 50,
showLegend: true,
showLegendNames: true,
showLegendPercent: true,
showLegendValues: true,
showTimeAxis: true,
targets: [
{
refId: 'A',
scenarioId: 'csv_metric_values',
stringInput: '1,20,90,30,5,0',
},
{
scenarioId: 'csv_metric_values',
refId: 'B',
stringInput: '1,20,30,5,0',
hide: false,
},
],
textSize: 24,
textSizeTime: 12,
timeOptions: [
{
name: 'Years',
value: 'years',
},
{
name: 'Months',
value: 'months',
},
{
name: 'Weeks',
value: 'weeks',
},
{
name: 'Days',
value: 'days',
},
{
name: 'Hours',
value: 'hours',
},
{
name: 'Minutes',
value: 'minutes',
},
{
name: 'Seconds',
value: 'seconds',
},
{
name: 'Milliseconds',
value: 'milliseconds',
},
],
timePrecision: {
name: 'Minutes',
value: 'minutes',
},
timeTextColor: '#d8d9da',
units: 'currencyGBP',
valueMaps: [
{
$$hashKey: 'object:265',
op: '=',
text: 'ONE',
value: '111',
},
{
value: '222',
op: '=',
text: 'TWO',
$$hashKey: 'object:546',
},
],
valueTextColor: '#000000',
writeLastValue: true,
expandFromQueryS: 0,
use12HourClock: false,
useTimePrecision: false,
writeAllValues: false,
writeMetricNames: false,
datasource: null,
};

View File

@ -0,0 +1,80 @@
import { FieldConfigSource, MappingType, PanelModel, ValueMap } from '@grafana/data';
import { TimelineFieldConfig, TimelineOptions } from './types';
import { isArray } from 'lodash';
// This is called when the panel changes from another panel
export const timelinePanelChangedHandler = (
panel: PanelModel<Partial<TimelineOptions>> | any,
prevPluginId: string,
prevOptions: any
) => {
let options = (panel.options ?? {}) as TimelineOptions;
// Changing from angular singlestat
if (prevPluginId === 'natel-discrete-panel' && prevOptions.angular) {
const oldOptions = prevOptions.angular;
const fieldConfig: FieldConfigSource = panel.fieldConfig ?? { defaults: {}, overrides: [] };
if (oldOptions.units) {
fieldConfig.defaults.unit = oldOptions.units;
}
const custom: TimelineFieldConfig = {
fillOpacity: 100,
lineWidth: 0,
};
fieldConfig.defaults.custom = custom;
options.mergeValues = true;
// Convert mappings
const valuemap: ValueMap = { type: MappingType.ValueToText, options: {} };
fieldConfig.defaults.mappings = [valuemap];
if (isArray(oldOptions.colorMaps)) {
for (const p of oldOptions.colorMaps) {
const color = p.color as string;
if (color) {
valuemap.options[p.text as string] = { color };
}
}
}
if (isArray(oldOptions.valueMaps)) {
for (const p of oldOptions.valueMaps) {
const text = p.text as string;
const value = p.value as string;
if (text && value) {
let old = valuemap.options[value];
if (old) {
old.text = text;
} else {
valuemap.options[value] = { text };
}
}
}
}
if (isArray(oldOptions.rangeMaps)) {
for (const p of oldOptions.rangeMaps) {
let from = +p.from;
let to = +p.to;
const text = p.text as string;
if (text) {
fieldConfig.defaults.mappings.push({
type: MappingType.RangeToText,
options: {
from,
to,
result: { text },
},
});
}
}
}
// mutates the input
panel.fieldConfig = fieldConfig;
}
return options;
};

View File

@ -3,8 +3,10 @@ import { StateTimelinePanel } from './StateTimelinePanel';
import { TimelineOptions, TimelineFieldConfig, defaultPanelOptions, defaultTimelineFieldConfig } from './types';
import { BarValueVisibility } from '@grafana/ui';
import { addLegendOptions } from '@grafana/ui/src/options/builder';
import { timelinePanelChangedHandler } from './migrations';
export const plugin = new PanelPlugin<TimelineOptions, TimelineFieldConfig>(StateTimelinePanel)
.setPanelChangeHandler(timelinePanelChangedHandler)
.useFieldConfig({
standardOptions: {
[FieldConfigProperty.Color]: {