diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts index 908dbbcca4c..212dbfbb7bf 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts @@ -186,12 +186,26 @@ describe('transformSaveModelToScene', () => { gridPos: { x: 1, y: 0, w: 12, h: 8 }, }) as Panel; + const widgetLibPanel = { + title: 'Widget Panel', + type: 'add-library-panel', + }; + + const libPanel = createPanelSaveModel({ + title: 'Library Panel', + gridPos: { x: 0, y: 0, w: 12, h: 8 }, + libraryPanel: { + uid: '123', + name: 'My Panel', + }, + }); + const row = createPanelSaveModel({ title: 'test', type: 'row', gridPos: { x: 0, y: 0, w: 12, h: 1 }, collapsed: true, - panels: [panel], + panels: [panel, widgetLibPanel, libPanel], }) as unknown as RowPanel; const dashboard = { @@ -210,8 +224,12 @@ describe('transformSaveModelToScene', () => { expect(rowScene.state.title).toEqual(row.title); expect(rowScene.state.y).toEqual(row.gridPos!.y); expect(rowScene.state.isCollapsed).toEqual(row.collapsed); - expect(rowScene.state.children).toHaveLength(1); + expect(rowScene.state.children).toHaveLength(3); expect(rowScene.state.children[0]).toBeInstanceOf(SceneGridItem); + expect(rowScene.state.children[1]).toBeInstanceOf(SceneGridItem); + expect(rowScene.state.children[2]).toBeInstanceOf(SceneGridItem); + expect((rowScene.state.children[1] as SceneGridItem).state.body!).toBeInstanceOf(AddLibraryPanelWidget); + expect((rowScene.state.children[2] as SceneGridItem).state.body!).toBeInstanceOf(LibraryVizPanel); }); it('should create panels within expanded row', () => { @@ -224,6 +242,24 @@ describe('transformSaveModelToScene', () => { y: 0, }, }); + const widgetLibPanelOutOfRow = { + title: 'Widget Panel', + type: 'add-library-panel', + gridPos: { + h: 8, + w: 12, + x: 12, + y: 0, + }, + }; + const libPanelOutOfRow = createPanelSaveModel({ + title: 'Library Panel', + gridPos: { x: 0, y: 8, w: 12, h: 8 }, + libraryPanel: { + uid: '123', + name: 'My Panel', + }, + }); const rowWithPanel = createPanelSaveModel({ title: 'Row with panel', type: 'row', @@ -233,7 +269,7 @@ describe('transformSaveModelToScene', () => { h: 1, w: 24, x: 0, - y: 8, + y: 16, }, // This panels array is not used if the row is not collapsed panels: [], @@ -243,17 +279,35 @@ describe('transformSaveModelToScene', () => { h: 8, w: 12, x: 0, - y: 9, + y: 17, }, title: 'In row 1', }); + const widgetLibPanelInRow = { + title: 'Widget Panel', + type: 'add-library-panel', + gridPos: { + h: 8, + w: 12, + x: 12, + y: 17, + }, + }; + const libPanelInRow = createPanelSaveModel({ + title: 'Library Panel', + gridPos: { x: 0, y: 25, w: 12, h: 8 }, + libraryPanel: { + uid: '123', + name: 'My Panel', + }, + }); const emptyRow = createPanelSaveModel({ collapsed: false, gridPos: { h: 1, w: 24, x: 0, - y: 17, + y: 26, }, // This panels array is not used if the row is not collapsed panels: [], @@ -262,7 +316,16 @@ describe('transformSaveModelToScene', () => { }); const dashboard = { ...defaultDashboard, - panels: [panelOutOfRow, rowWithPanel, panelInRow, emptyRow], + panels: [ + panelOutOfRow, + widgetLibPanelOutOfRow, + libPanelOutOfRow, + rowWithPanel, + panelInRow, + widgetLibPanelInRow, + libPanelInRow, + emptyRow, + ], }; const oldModel = new DashboardModel(dashboard); @@ -270,25 +333,37 @@ describe('transformSaveModelToScene', () => { const scene = createDashboardSceneFromDashboardModel(oldModel); const body = scene.state.body as SceneGridLayout; - expect(body.state.children).toHaveLength(3); + expect(body.state.children).toHaveLength(5); expect(body).toBeInstanceOf(SceneGridLayout); // Panel out of row expect(body.state.children[0]).toBeInstanceOf(SceneGridItem); const panelOutOfRowVizPanel = body.state.children[0] as SceneGridItem; expect((panelOutOfRowVizPanel.state.body as VizPanel)?.state.title).toBe(panelOutOfRow.title); - // Row with panel - expect(body.state.children[1]).toBeInstanceOf(SceneGridRow); - const rowWithPanelsScene = body.state.children[1] as SceneGridRow; + // widget lib panel out of row + expect(body.state.children[1]).toBeInstanceOf(SceneGridItem); + const panelOutOfRowWidget = body.state.children[1] as SceneGridItem; + expect(panelOutOfRowWidget.state.body!).toBeInstanceOf(AddLibraryPanelWidget); + // lib panel out of row + expect(body.state.children[2]).toBeInstanceOf(SceneGridItem); + const panelOutOfRowLibVizPanel = body.state.children[2] as SceneGridItem; + expect(panelOutOfRowLibVizPanel.state.body!).toBeInstanceOf(LibraryVizPanel); + // Row with panels + expect(body.state.children[3]).toBeInstanceOf(SceneGridRow); + const rowWithPanelsScene = body.state.children[3] as SceneGridRow; expect(rowWithPanelsScene.state.title).toBe(rowWithPanel.title); expect(rowWithPanelsScene.state.key).toBe('panel-10'); - expect(rowWithPanelsScene.state.children).toHaveLength(1); + expect(rowWithPanelsScene.state.children).toHaveLength(3); + const widget = rowWithPanelsScene.state.children[1] as SceneGridItem; + expect(widget.state.body!).toBeInstanceOf(AddLibraryPanelWidget); + const libPanel = rowWithPanelsScene.state.children[2] as SceneGridItem; + expect(libPanel.state.body!).toBeInstanceOf(LibraryVizPanel); // Panel within row expect(rowWithPanelsScene.state.children[0]).toBeInstanceOf(SceneGridItem); const panelInRowVizPanel = rowWithPanelsScene.state.children[0] as SceneGridItem; expect((panelInRowVizPanel.state.body as VizPanel).state.title).toBe(panelInRow.title); // Empty row - expect(body.state.children[2]).toBeInstanceOf(SceneGridRow); - const emptyRowScene = body.state.children[2] as SceneGridRow; + expect(body.state.children[4]).toBeInstanceOf(SceneGridRow); + const emptyRowScene = body.state.children[4] as SceneGridRow; expect(emptyRowScene.state.title).toBe(emptyRow.title); expect(emptyRowScene.state.children).toHaveLength(0); }); diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts index 1957b83104c..2ecd10085d7 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts @@ -114,12 +114,25 @@ export function createSceneObjectsForPanels(oldPanels: PanelModel[]): SceneGridI } else if (panel.type === 'add-library-panel') { const gridItem = buildGridItemForLibraryPanelWidget(panel); - if (gridItem) { + if (!gridItem) { + continue; + } + + if (currentRow) { + currentRowPanels.push(gridItem); + } else { panels.push(gridItem); } } else if (panel.libraryPanel?.uid && !('model' in panel.libraryPanel)) { const gridItem = buildGridItemForLibPanel(panel); - if (gridItem) { + + if (!gridItem) { + continue; + } + + if (currentRow) { + currentRowPanels.push(gridItem); + } else { panels.push(gridItem); } } else { @@ -155,6 +168,25 @@ function createRowFromPanelModel(row: PanelModel, content: SceneGridItemLike[]): if (!(saveModel instanceof PanelModel)) { saveModel = new PanelModel(saveModel); } + + if (saveModel.type === 'add-library-panel') { + const gridItem = buildGridItemForLibraryPanelWidget(saveModel); + + if (!gridItem) { + throw new Error('Failed to build grid item for library panel widget'); + } + + return gridItem; + } else if (saveModel.libraryPanel?.uid && !('model' in saveModel.libraryPanel)) { + const gridItem = buildGridItemForLibPanel(saveModel); + + if (!gridItem) { + throw new Error('Failed to build grid item for library panel'); + } + + return gridItem; + } + return buildGridItemForPanel(saveModel); }); }