diff --git a/public/app/features/dashboard/dashboard_model.ts b/public/app/features/dashboard/dashboard_model.ts index fb43d6741ef..743bf040424 100644 --- a/public/app/features/dashboard/dashboard_model.ts +++ b/public/app/features/dashboard/dashboard_model.ts @@ -404,46 +404,60 @@ export class DashboardModel { } } - toggleRow(row) { - let rowPanels = []; - let rowFound = false; + toggleRow(row: PanelModel) { + let rowIndex = _.indexOf(this.panels, row); - // if already collapsed - if (row.collapse) { - row.collapse = false; + if (row.collapsed) { + row.collapsed = false; - for (let panel of row.panels) { - this.panels.push(new PanelModel(panel)); - } + if (row.panels.length > 0) { + // Use first panel to figure out if it was moved or pushed + let firstPanel = row.panels[0]; + let yDiff = firstPanel.gridPos.y - (row.gridPos.y + row.gridPos.h); + // start inserting after row + let insertPos = rowIndex+1; - row.panels = []; - - } else { - - for (let index = 0; index < this.panels.length; index++) { - let panel = this.panels[index]; - - if (rowFound) { - // break when encountering another row - if (panel.type === 'row') { - break; - } - - // this panel must belong to row - rowPanels.push(panel); - } else if (panel === row) { - rowFound = true; + for (let panel of row.panels) { + // make sure y is adjusted (in case row moved while collapsed) + panel.gridPos.y -= yDiff; + // insert after row + this.panels.splice(insertPos, 0, new PanelModel(panel)); + insertPos += 1; } + + row.panels = []; } - // remove panels - _.pull(this.panels, ...rowPanels); - // save panel models inside row panel - row.panels = _.map(rowPanels, panel => panel.getSaveModel()); - row.collapse = true; + + // sort panels + this.sortPanelsByGridPos(); + + // emit change event + this.events.emit('row-expanded'); + return; } + let rowPanels = []; + + for (let index = rowIndex+1; index < this.panels.length; index++) { + let panel = this.panels[index]; + + // break when encountering another row + if (panel.type === 'row') { + break; + } + + // this panel must belong to row + rowPanels.push(panel); + } + + // remove panels + _.pull(this.panels, ...rowPanels); + // save panel models inside row panel + row.panels = _.map(rowPanels, panel => panel.getSaveModel()); + row.collapsed = true; + // emit change event - this.events.emit('row-collapse-changed'); + this.events.emit('row-collapsed'); } on(eventName, callback) { diff --git a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx index f3048577b14..d1c902db70e 100644 --- a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx @@ -70,7 +70,8 @@ export class DashboardGrid extends React.Component { this.dashboard.on('panel-removed', this.triggerForceUpdate.bind(this)); this.dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this)); this.dashboard.on('view-mode-changed', this.triggerForceUpdate.bind(this)); - this.dashboard.on('row-collapse-changed', this.triggerForceUpdate.bind(this)); + this.dashboard.on('row-collapsed', this.triggerForceUpdate.bind(this)); + this.dashboard.on('row-expanded', this.triggerForceUpdate.bind(this)); } buildLayout() { @@ -98,7 +99,7 @@ export class DashboardGrid extends React.Component { panelPos.w = GRID_COLUMN_COUNT; panelPos.h = 1; panelPos.isResizable = false; - panelPos.isDraggable = panel.collapse; + panelPos.isDraggable = panel.collapsed; } layout.push(panelPos); diff --git a/public/app/features/dashboard/dashgrid/DashboardRow.tsx b/public/app/features/dashboard/dashgrid/DashboardRow.tsx index 8abe23cf294..023ff5ca014 100644 --- a/public/app/features/dashboard/dashgrid/DashboardRow.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardRow.tsx @@ -13,7 +13,7 @@ export class DashboardRow extends React.Component { super(props); this.state = { - collapse: this.props.panel.collapse, + collapsed: this.props.panel.collapsed, }; this.toggle = this.toggle.bind(this); @@ -27,15 +27,15 @@ export class DashboardRow extends React.Component { dashboard.toggleRow(this.props.panel); this.setState(prevState => { - return {collapse: !prevState.collapse}; + return {collapsed: !prevState.collapsed}; }); } openSettings() {} render() { - const classes = classNames({'dashboard-row': true, 'dashboard-row--collapse': this.state.collapse}); - const chevronClass = classNames({'fa': true, 'fa-chevron-down': !this.state.collapse, 'fa-chevron-right': this.state.collapse}); + const classes = classNames({'dashboard-row': true, 'dashboard-row--collapsed': this.state.collapsed}); + const chevronClass = classNames({'fa': true, 'fa-chevron-down': !this.state.collapsed, 'fa-chevron-right': this.state.collapsed}); const hiddenPanels = this.props.panel.panels ? this.props.panel.panels.length : 0; return ( diff --git a/public/app/features/dashboard/dashnav/dashnav.ts b/public/app/features/dashboard/dashnav/dashnav.ts index a5f7bc549ef..98e34a3aa04 100644 --- a/public/app/features/dashboard/dashnav/dashnav.ts +++ b/public/app/features/dashboard/dashnav/dashnav.ts @@ -146,14 +146,14 @@ export class DashNavCtrl { } addPanel() { - if (this.dashboard.panels[0].type === 'add-panel') { + if (this.dashboard.panels.length > 0 && this.dashboard.panels[0].type === 'add-panel') { this.dashboard.removePanel(this.dashboard.panels[0]); return; } this.dashboard.addPanel({ type: 'add-panel', - gridPos: {x: 0, y: 0, w: 12, h: 9, static: true}, + gridPos: {x: 0, y: 0, w: 12, h: 9}, title: 'New Graph', }); } diff --git a/public/app/features/dashboard/panel_model.ts b/public/app/features/dashboard/panel_model.ts index 2c9b11b7ffc..caba10ba21b 100644 --- a/public/app/features/dashboard/panel_model.ts +++ b/public/app/features/dashboard/panel_model.ts @@ -27,7 +27,7 @@ export class PanelModel { repeatPanelId?: number; repeatDirection?: string; minSpan?: number; - collapse?: boolean; + collapsed?: boolean; panels?: any; // non persisted diff --git a/public/app/features/dashboard/specs/dashboard_model_specs.ts b/public/app/features/dashboard/specs/dashboard_model_specs.ts index 4d9b33fff3a..151725031d8 100644 --- a/public/app/features/dashboard/specs/dashboard_model_specs.ts +++ b/public/app/features/dashboard/specs/dashboard_model_specs.ts @@ -583,4 +583,41 @@ describe('DashboardModel', function() { }); + describe('When expanding row', function(ctx) { + var dashboard; + + beforeEach(function() { + 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: 2}, + collapsed: true, + panels: [ + {id: 3, type: 'graph', gridPos: {x: 0, y: 2, w: 12, h: 2}}, + {id: 4, type: 'graph', gridPos: {x: 12, y: 2, w: 12, h: 2}}, + ] + }, + ], + }); + dashboard.toggleRow(dashboard.panels[1]); + }); + + it('should add panels back', function() { + expect(dashboard.panels.length).to.eql(4); + }); + + it('should add them below row in array', function() { + expect(dashboard.panels[2].id).to.eql(3); + expect(dashboard.panels[3].id).to.eql(4); + }); + + it('should position them below row', function() { + expect(dashboard.panels[2].gridPos).to.eql({x: 0, y: 8, w: 12, h: 2}); + }); + + }); + }); diff --git a/public/sass/components/_row.scss b/public/sass/components/_row.scss index f341e0be940..60266bd75c0 100644 --- a/public/sass/components/_row.scss +++ b/public/sass/components/_row.scss @@ -4,7 +4,7 @@ height: 100%; - &--collapse { + &--collapsed { background: $panel-bg; .dashboard-row__panel_count {