Scenes/LibraryPanels: Fix transformSceneToSaveModel for library panel repeats (#83843)

This commit is contained in:
kay delaney
2024-03-05 14:09:24 +00:00
committed by GitHub
parent 2cce9aa2f7
commit 4b0547014a
4 changed files with 118 additions and 54 deletions
+1 -2
View File
@@ -2573,8 +2573,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Do not use any type assertions.", "4"],
[0, 0, 0, "Do not use any type assertions.", "5"],
[0, 0, 0, "Do not use any type assertions.", "6"],
[0, 0, 0, "Do not use any type assertions.", "7"]
[0, 0, 0, "Do not use any type assertions.", "6"]
],
"public/app/features/dashboard-scene/settings/variables/components/VariableSelectField.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@@ -1,3 +1,4 @@
import 'whatwg-fetch';
import { advanceTo } from 'jest-date-mock';
import { map, of } from 'rxjs';
@@ -18,6 +19,7 @@ import { getPluginLinkExtensions, setPluginImportUtils } from '@grafana/runtime'
import {
MultiValueVariable,
SceneDataLayers,
SceneGridItem,
SceneGridItemLike,
SceneGridLayout,
SceneGridRow,
@@ -29,6 +31,7 @@ import { getTimeRange } from 'app/features/dashboard/utils/timeRange';
import { reduceTransformRegistryItem } from 'app/features/transformers/editors/ReduceTransformerEditor';
import { SHARED_DASHBOARD_QUERY } from 'app/plugins/datasource/dashboard';
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
import { NEW_LINK } from '../settings/links/utils';
import { activateFullSceneTree, buildPanelRepeaterScene } from '../utils/test-utils';
@@ -315,24 +318,41 @@ describe('transformSceneToSaveModel', () => {
describe('Library panels', () => {
it('given a library panel', () => {
const panel = buildGridItemFromPanelSchema({
id: 4,
gridPos: {
h: 8,
w: 12,
x: 0,
y: 0,
},
libraryPanel: {
name: 'Some lib panel panel',
uid: 'lib-panel-uid',
},
// Not using buildGridItemFromPanelSchema since it strips options/fieldConfig
const libVizPanel = new LibraryVizPanel({
name: 'Some lib panel panel',
title: 'A panel',
transformations: [],
fieldConfig: {
defaults: {},
overrides: [],
},
uid: 'lib-panel-uid',
panelKey: 'lib-panel',
panel: new VizPanel({
key: 'panel-4',
title: 'Panel blahh blah',
fieldConfig: {
defaults: {},
overrides: [],
},
options: {
legend: {
calcs: [],
displayMode: 'list',
placement: 'bottom',
showLegend: true,
},
tooltip: {
maxHeight: 600,
mode: 'single',
sort: 'none',
},
},
}),
});
const panel = new SceneGridItem({
body: libVizPanel,
y: 0,
x: 0,
width: 12,
height: 8,
});
const result = gridItemToPanel(panel);
@@ -351,6 +371,7 @@ describe('transformSceneToSaveModel', () => {
expect(result.title).toBe('A panel');
expect(result.transformations).toBeUndefined();
expect(result.fieldConfig).toBeUndefined();
expect(result.options).toBeUndefined();
});
it('given a library panel widget', () => {
@@ -769,6 +790,53 @@ describe('transformSceneToSaveModel', () => {
expect(result[1].title).toEqual('Panel $server');
});
it('handles repeated library panels', () => {
const { scene, repeater } = buildPanelRepeaterScene(
{ variableQueryTime: 0, numberOfOptions: 2 },
new LibraryVizPanel({
name: 'Some lib panel panel',
title: 'A panel',
uid: 'lib-panel-uid',
panelKey: 'lib-panel',
panel: new VizPanel({
key: 'panel-4',
title: 'Panel blahh blah',
fieldConfig: {
defaults: {},
overrides: [],
},
options: {
legend: {
calcs: [],
displayMode: 'list',
placement: 'bottom',
showLegend: true,
},
tooltip: {
maxHeight: 600,
mode: 'single',
sort: 'none',
},
},
}),
})
);
activateFullSceneTree(scene);
const result = panelRepeaterToPanels(repeater, true);
expect(result).toHaveLength(1);
expect(result[0]).toMatchObject({
id: 4,
title: 'A panel',
libraryPanel: {
name: 'Some lib panel panel',
uid: 'lib-panel-uid',
},
});
});
it('handles row repeats ', () => {
const { scene, row } = buildPanelRepeaterScene({
variableQueryTime: 0,
@@ -139,6 +139,22 @@ export function transformSceneToSaveModel(scene: DashboardScene, isSnapshot = fa
return sortedDeepCloneWithoutNulls(dashboard);
}
export function libraryVizPanelToPanel(libPanel: LibraryVizPanel, gridPos: GridPos): Panel {
if (!libPanel.state.panel) {
throw new Error('Library panel has no panel');
}
return {
id: getPanelIdForVizPanel(libPanel.state.panel),
title: libPanel.state.title,
gridPos: gridPos,
libraryPanel: {
name: libPanel.state.name,
uid: libPanel.state.uid,
},
} as Panel;
}
export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false): Panel {
let vizPanel: VizPanel | undefined;
let x = 0,
@@ -154,18 +170,7 @@ export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false)
w = gridItem.state.width ?? 0;
h = gridItem.state.height ?? 0;
if (!gridItem.state.body.state.panel) {
throw new Error('Library panel has no panel');
}
return {
id: getPanelIdForVizPanel(gridItem.state.body.state.panel),
title: gridItem.state.body.state.title,
gridPos: { x, y, w, h },
libraryPanel: {
name: gridItem.state.body.state.name,
uid: gridItem.state.body.state.uid,
},
} as Panel;
return libraryVizPanelToPanel(gridItem.state.body, { x, y, w, h });
}
// Handle library panel widget as well and exit early
@@ -194,16 +199,16 @@ export function gridItemToPanel(gridItem: SceneGridItemLike, isSnapshot = false)
}
if (gridItem instanceof PanelRepeaterGridItem) {
if (gridItem.state.source instanceof LibraryVizPanel) {
vizPanel = gridItem.state.source.state.panel;
} else {
vizPanel = gridItem.state.source;
}
x = gridItem.state.x ?? 0;
y = gridItem.state.y ?? 0;
w = gridItem.state.width ?? 0;
h = gridItem.state.height ?? 0;
if (gridItem.state.source instanceof LibraryVizPanel) {
return libraryVizPanelToPanel(gridItem.state.source, { x, y, w, h });
} else {
vizPanel = gridItem.state.source;
}
}
if (!vizPanel) {
@@ -323,18 +328,7 @@ export function panelRepeaterToPanels(repeater: PanelRepeaterGridItem, isSnapsho
} else {
if (repeater.state.source instanceof LibraryVizPanel) {
const { x = 0, y = 0, width: w = 0, height: h = 0 } = repeater.state;
return [
{
id: getPanelIdForVizPanel(repeater.state.source),
title: repeater.state.source.state.title,
gridPos: { x, y, w, h },
libraryPanel: {
name: repeater.state.source.state.name,
uid: repeater.state.source.state.uid,
},
} as Panel,
];
return [libraryVizPanelToPanel(repeater.state.source, { x, y, w, h })];
}
if (repeater.state.repeatedPanels) {
@@ -15,6 +15,7 @@ import { DashboardLoaderSrv, setDashboardLoaderSrv } from 'app/features/dashboar
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/constants';
import { DashboardDTO } from 'app/types';
import { LibraryVizPanel } from '../scene/LibraryVizPanel';
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
import { PanelRepeaterGridItem, RepeatDirection } from '../scene/PanelRepeaterGridItem';
import { RowRepeaterBehavior } from '../scene/RowRepeaterBehavior';
@@ -99,7 +100,7 @@ interface SceneOptions {
useRowRepeater?: boolean;
}
export function buildPanelRepeaterScene(options: SceneOptions) {
export function buildPanelRepeaterScene(options: SceneOptions, source?: VizPanel | LibraryVizPanel) {
const defaults = { usePanelRepeater: true, ...options };
const repeater = new PanelRepeaterGridItem({
@@ -108,10 +109,12 @@ export function buildPanelRepeaterScene(options: SceneOptions) {
repeatDirection: options.repeatDirection,
maxPerRow: options.maxPerRow,
itemHeight: options.itemHeight,
source: new VizPanel({
title: 'Panel $server',
pluginId: 'timeseries',
}),
source:
source ??
new VizPanel({
title: 'Panel $server',
pluginId: 'timeseries',
}),
x: options.x || 0,
y: options.y || 0,
});