diff --git a/public/app/features/dashboard/dashboard_model.ts b/public/app/features/dashboard/dashboard_model.ts index 055b59065ae..e35f8f0d430 100644 --- a/public/app/features/dashboard/dashboard_model.ts +++ b/public/app/features/dashboard/dashboard_model.ts @@ -500,11 +500,12 @@ export class DashboardModel { if (!rowPanel.panels || rowPanel.panels.length === 0) { return 0; } + const rowYPos = rowPanel.gridPos.y; const positions = _.map(rowPanel.panels, 'gridPos'); const maxPos = _.maxBy(positions, pos => { return pos.y + pos.h; }); - return maxPos.h + 1; + return maxPos.y + maxPos.h - rowYPos; } removePanel(panel: PanelModel) { diff --git a/public/app/features/dashboard/specs/repeat.jest.ts b/public/app/features/dashboard/specs/repeat.jest.ts index 868db3b7246..09bb3b7c494 100644 --- a/public/app/features/dashboard/specs/repeat.jest.ts +++ b/public/app/features/dashboard/specs/repeat.jest.ts @@ -500,6 +500,22 @@ describe('given dashboard with row repeat', function() { ); expect(panel_ids.length).toEqual(_.uniq(panel_ids).length); }); + + it('should place new panels in proper order', function() { + dashboardJSON.panels = [ + { id: 1, type: 'row', gridPos: { x: 0, y: 0, h: 1, w: 24 }, repeat: 'apps' }, + { id: 2, type: 'graph', gridPos: { x: 0, y: 1, h: 3, w: 12 } }, + { id: 3, type: 'graph', gridPos: { x: 6, y: 1, h: 4, w: 12 } }, + { id: 4, type: 'graph', gridPos: { x: 0, y: 5, h: 2, w: 12 } }, + ]; + dashboard = new DashboardModel(dashboardJSON); + dashboard.processRepeats(); + + const panel_types = _.map(dashboard.panels, 'type'); + expect(panel_types).toEqual(['row', 'graph', 'graph', 'graph', 'row', 'graph', 'graph', 'graph']); + const panel_y_positions = _.map(dashboard.panels, p => p.gridPos.y); + expect(panel_y_positions).toEqual([0, 1, 1, 5, 7, 8, 8, 12]); + }); }); describe('given dashboard with row and panel repeat', () => {