From dd9c727e6050c515c62b5a97955b4a16c606eec5 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Wed, 29 Nov 2017 14:14:43 +0300 Subject: [PATCH] repeat row: handle collapsed rows --- .../app/features/dashboard/dashboard_model.ts | 71 +++++++++++++------ .../features/dashboard/specs/repeat.jest.ts | 56 ++++++++++++++- 2 files changed, 104 insertions(+), 23 deletions(-) diff --git a/public/app/features/dashboard/dashboard_model.ts b/public/app/features/dashboard/dashboard_model.ts index 9481ef6d63b..cc5c743cb41 100644 --- a/public/app/features/dashboard/dashboard_model.ts +++ b/public/app/features/dashboard/dashboard_model.ts @@ -181,6 +181,14 @@ export class DashboardModel { if (panel.id > max) { max = panel.id; } + + if (panel.collapsed) { + for (let rowPanel of panel.panels) { + if (rowPanel.id > max) { + max = rowPanel.id; + } + } + } } return max + 1; @@ -266,6 +274,7 @@ export class DashboardModel { this.sortPanelsByGridPos(); this.events.emit('repeats-processed'); + console.log(this.panels); } getPanelRepeatClone(sourcePanel, valueIndex, sourcePanelIndex) { @@ -279,11 +288,18 @@ export class DashboardModel { if (sourcePanel.type === 'row') { // for row clones we need to figure out panels under row to clone and where to insert clone - let rowPanels = this.getRowPanels(sourcePanelIndex); - clone.panels = _.map(rowPanels, panel => panel.getSaveModel()); - - // insert copied row after preceding row's panels - let insertPos = sourcePanelIndex + ((rowPanels.length + 1)*valueIndex); + let rowPanels, insertPos; + if (sourcePanel.collapsed) { + rowPanels = sourcePanel.panels; + clone.panels = _.cloneDeep(rowPanels); + // insert copied row after preceding row + insertPos = sourcePanelIndex + valueIndex; + } else { + rowPanels = this.getRowPanels(sourcePanelIndex); + clone.panels = _.map(rowPanels, panel => panel.getSaveModel()); + // insert copied row after preceding row's panels + insertPos = sourcePanelIndex + ((rowPanels.length + 1)*valueIndex); + } this.panels.splice(insertPos, 0, clone); } else { // insert after source panel + value index @@ -324,27 +340,42 @@ export class DashboardModel { copy.scopedVars[variable.name] = option; if (copy.type === 'row') { - // place row below row panels let rowHeight = this.getRowHeight(copy); if (rowHeight) { - copy.gridPos.y += rowHeight * index; + let panelsBelowIndex; let rowPanels = copy.panels; - // insert after preceding row's panels + // insert after 'row' panel let insertPos = panelIndex + ((rowPanels.length + 1) * index) + 1; - _.each(rowPanels, (rowPanel, i) => { - let cloneRowPanel = new PanelModel(rowPanel); - cloneRowPanel.id = this.getNextPanelId(); - cloneRowPanel.repeatIteration = this.iteration; - cloneRowPanel.repeatPanelId = rowPanel.id; - cloneRowPanel.repeat = null; - cloneRowPanel.gridPos.y += rowHeight * index; - this.panels.splice(insertPos+i, 0, cloneRowPanel); - }); - copy.panels = []; - yPos += rowHeight; + + if (copy.collapsed) { + copy.gridPos.y += index; + yPos += index; + panelsBelowIndex = panelIndex + index + 1; + _.each(copy.panels, (panel, i) => { + panel.id = this.getNextPanelId(); + panel.repeatIteration = this.iteration; + panel.repeatPanelId = rowPanels[i].id; + panel.repeat = null; + copy.panels[i] = panel; + }); + } else { + _.each(rowPanels, (rowPanel, i) => { + let cloneRowPanel = new PanelModel(rowPanel); + cloneRowPanel.id = this.getNextPanelId(); + cloneRowPanel.repeatIteration = this.iteration; + cloneRowPanel.repeatPanelId = rowPanel.id; + cloneRowPanel.repeat = null; + cloneRowPanel.gridPos.y += rowHeight * index; + this.panels.splice(insertPos+i, 0, cloneRowPanel); + }); + copy.panels = []; + copy.gridPos.y += rowHeight * index; + yPos += rowHeight; + panelsBelowIndex = insertPos+rowPanels.length; + } // Update gridPos for panels below - for (let i = insertPos+rowPanels.length; i< this.panels.length; i++) { + for (let i = panelsBelowIndex; i< this.panels.length; i++) { this.panels[i].gridPos.y += yPos; } } diff --git a/public/app/features/dashboard/specs/repeat.jest.ts b/public/app/features/dashboard/specs/repeat.jest.ts index 7f5d382fe9c..cb1da3e767a 100644 --- a/public/app/features/dashboard/specs/repeat.jest.ts +++ b/public/app/features/dashboard/specs/repeat.jest.ts @@ -148,10 +148,10 @@ describe('given dashboard with panel repeat in vertical direction', function() { }); describe('given dashboard with row repeat', function() { - var dashboard; + let dashboard, dashboardJSON; beforeEach(function() { - dashboard = new DashboardModel({ + dashboardJSON = { panels: [ {id: 1, type: 'row', repeat: 'apps', gridPos: {x: 0, y: 0, h: 1 , w: 24}}, {id: 2, type: 'graph', gridPos: {x: 0, y: 1, h: 1 , w: 6}}, @@ -173,7 +173,8 @@ describe('given dashboard with row repeat', function() { ] }] } - }); + }; + dashboard = new DashboardModel(dashboardJSON); dashboard.processRepeats(); }); @@ -186,6 +187,55 @@ describe('given dashboard with row repeat', function() { ]); }); + it('should repeat only row if it is collapsed', function() { + dashboardJSON.panels = [ + { + id: 1, type: 'row', collapsed: true, repeat: 'apps', gridPos: {x: 0, y: 0, h: 1 , w: 24}, + panels: [ + {id: 2, type: 'graph', gridPos: {x: 0, y: 1, h: 1 , w: 6}}, + {id: 3, type: 'graph', gridPos: {x: 6, y: 1, h: 1 , w: 6}}, + ] + }, + {id: 4, type: 'row', gridPos: {x: 0, y: 1, h: 1 , w: 24}}, + {id: 5, type: 'graph', gridPos: {x: 0, y: 2, h: 1 , w: 12}}, + ]; + dashboard = new DashboardModel(dashboardJSON); + dashboard.processRepeats(); + + const panel_types = _.map(dashboard.panels, 'type'); + expect(panel_types).toEqual([ + 'row', 'row', 'row', 'graph' + ]); + expect(dashboard.panels[0].panels).toHaveLength(2); + expect(dashboard.panels[1].panels).toHaveLength(2); + }); + + it('should assign unique ids for repeated panels', function() { + dashboardJSON.panels = [ + { + id: 1, type: 'row', collapsed: true, repeat: 'apps', gridPos: {x: 0, y: 0, h: 1 , w: 24}, + panels: [ + {id: 2, type: 'graph', gridPos: {x: 0, y: 1, h: 1 , w: 6}}, + {id: 3, type: 'graph', gridPos: {x: 6, y: 1, h: 1 , w: 6}}, + ] + }, + {id: 4, type: 'row', gridPos: {x: 0, y: 1, h: 1 , w: 24}}, + {id: 5, type: 'graph', gridPos: {x: 0, y: 2, h: 1 , w: 12}}, + ]; + dashboard = new DashboardModel(dashboardJSON); + dashboard.processRepeats(); + + const panel_ids = _.flattenDeep(_.map(dashboard.panels, (panel) => { + let ids = []; + if (panel.panels && panel.panels.length) { + ids = _.map(panel.panels, 'id'); + } + ids.push(panel.id); + return ids; + })); + expect(panel_ids.length).toEqual(_.uniq(panel_ids).length); + }); + // it('should set scopedVars on panels', function() { // expect(dashboard.panels[1].scopedVars).toMatchObject({apps: {text: 'se1', value: 'se1'}}) // });