diff --git a/public/app/features/dashboard/state/DashboardModel.test.ts b/public/app/features/dashboard/state/DashboardModel.test.ts index e321af4c294..34d47fb8b09 100644 --- a/public/app/features/dashboard/state/DashboardModel.test.ts +++ b/public/app/features/dashboard/state/DashboardModel.test.ts @@ -464,6 +464,46 @@ describe('DashboardModel', () => { }); }); + describe('When expanding row with panels that do not contain an x and y pos', () => { + let dashboard: DashboardModel; + + beforeEach(() => { + dashboard = new DashboardModel({ + panels: [ + { id: 1, type: 'graph', gridPos: { x: 0, y: 0, w: 24, h: 6 } }, + { + id: 2, + type: 'row', + gridPos: { x: 0, y: 6, w: 24, h: 1 }, + collapsed: true, + panels: [ + { id: 3, type: 'graph', gridPos: { w: 12, h: 2 } }, + { id: 4, type: 'graph', gridPos: { w: 12, h: 2 } }, + ], + }, + { id: 5, type: 'row', gridPos: { x: 0, y: 7, w: 1, h: 1 } }, + ], + }); + dashboard.toggleRow(dashboard.panels[1]); + }); + + it('should correctly set the x and y values for the inner panels', () => { + expect(dashboard.panels[2].gridPos).toMatchObject({ + x: 0, + y: 7, + w: 12, + h: 2, + }); + + expect(dashboard.panels[3].gridPos).toMatchObject({ + x: 0, + y: 7, + w: 12, + h: 2, + }); + }); + }); + describe('Given model with time', () => { let model: DashboardModel; diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index 63a73ebfe75..119d581eeb6 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -942,8 +942,10 @@ export class DashboardModel { if (row.panels.length > 0) { // Use first panel to figure out if it was moved or pushed - const firstPanel = row.panels[0]; - const yDiff = firstPanel.gridPos.y - (row.gridPos.y + row.gridPos.h); + // If the panel doesn't have gridPos.y, use the row gridPos.y instead. + // This can happen for some generated dashboards. + const firstPanelYPos = row.panels[0].gridPos.y ?? row.gridPos.y; + const yDiff = firstPanelYPos - (row.gridPos.y + row.gridPos.h); // start inserting after row let insertPos = rowIndex + 1; @@ -952,8 +954,9 @@ export class DashboardModel { let yMax = row.gridPos.y; for (const panel of row.panels) { + // set the y gridPos if it wasn't already set + panel.gridPos.y ??= row.gridPos.y; // make sure y is adjusted (in case row moved while collapsed) - // console.log('yDiff', yDiff); panel.gridPos.y -= yDiff; // insert after row this.panels.splice(insertPos, 0, new PanelModel(panel));