diff --git a/public/app/core/routes/dashboard_loaders.js b/public/app/core/routes/dashboard_loaders.js
index 869f486fbfd..91bbff84100 100644
--- a/public/app/core/routes/dashboard_loaders.js
+++ b/public/app/core/routes/dashboard_loaders.js
@@ -21,6 +21,9 @@ function (coreModule) {
}
dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug).then(function(result) {
+ if ($routeParams.keepRows) {
+ result.meta.keepRows = true;
+ }
$scope.initDashboard(result, $scope);
});
diff --git a/public/app/features/dashboard/dashgrid/dashgrid.ts b/public/app/features/dashboard/dashgrid/dashgrid.ts
index 6b9c6c360b8..ccadf1c0592 100644
--- a/public/app/features/dashboard/dashgrid/dashgrid.ts
+++ b/public/app/features/dashboard/dashgrid/dashgrid.ts
@@ -10,7 +10,7 @@ import 'gridstack.jquery-ui';
const template = `
-
@@ -22,6 +22,7 @@ const template = `
export class GridCtrl {
options: any;
+ row: any;
dashboard: any;
panels: any;
gridstack: any;
@@ -29,7 +30,6 @@ export class GridCtrl {
/** @ngInject */
constructor(private $rootScope, private $element, private $timeout) {
- this.panels = this.dashboard.panels;
}
init() {
@@ -39,14 +39,48 @@ export class GridCtrl {
animate: true,
cellHeight: CELL_HEIGHT,
verticalMargin: CELL_VMARGIN,
+ acceptWidgets: '.grid-stack-item',
+ handle: '.panel-header'
}).data('gridstack');
+ this.gridElem.on('added', (e, items) => {
+ for (let item of items) {
+ this.onGridStackItemAdded(item);
+ }
+ });
+
+ this.gridElem.on('removed', (e, items) => {
+ for (let item of items) {
+ this.onGridStackItemRemoved(item);
+ }
+ });
+
this.gridElem.on('change', (e, items) => {
- this.$timeout(() => this.itemsChanged(items), 50);
+ this.$timeout(() => this.onGridStackItemsChanged(items), 50);
});
}
- itemsChanged(items) {
+ onGridStackItemAdded(item) {
+ console.log('item added', item);
+ if (this.dashboard.tempPanel) {
+ //this.gridstack.removeWidget(item.el, false);
+
+ this.$timeout(() => {
+ this.row.panels.push(this.dashboard.tempPanel);
+ });
+ }
+ }
+
+ onGridStackItemRemoved(item) {
+ console.log('item removed', item.id);
+ let panel = this.dashboard.getPanelById(parseInt(item.id));
+ this.dashboard.tempPanel = panel;
+ this.$timeout(() => {
+ this.row.removePanel(panel, false);
+ });
+ }
+
+ onGridStackItemsChanged(items) {
for (let item of items) {
var panel = this.dashboard.getPanelById(parseInt(item.id));
panel.x = item.x;
@@ -63,7 +97,8 @@ export class GridCtrl {
}
}
- removeItem(element) {
+ itemScopeDestroyed(element) {
+ console.log('itemScopeDestroyed');
if (this.gridstack) {
this.gridstack.removeWidget(element, false);
}
@@ -84,7 +119,8 @@ export function dashGrid($timeout) {
bindToController: true,
controllerAs: 'ctrl',
scope: {
- dashboard: "="
+ row: "=",
+ dashboard: "=",
},
link: function(scope, elem, attrs, ctrl) {
$timeout(function() {
@@ -133,7 +169,7 @@ export function dashGridItem($timeout, $rootScope) {
}, scope);
scope.$on('$destroy', () => {
- gridCtrl.removeItem(element);
+ gridCtrl.itemScopeDestroyed(element);
});
// scope.onItemRemoved({item: item});
diff --git a/public/app/features/dashboard/model.ts b/public/app/features/dashboard/model.ts
index 635485952d1..e9026447dab 100644
--- a/public/app/features/dashboard/model.ts
+++ b/public/app/features/dashboard/model.ts
@@ -47,7 +47,6 @@ export class DashboardModel {
meta: any;
events: any;
editMode: boolean;
- panels: Panel[];
folderId: number;
constructor(data, meta?) {
@@ -77,18 +76,17 @@ export class DashboardModel {
this.version = data.version || 0;
this.links = data.links || [];
this.gnetId = data.gnetId || null;
- this.panels = data.panels || [];
this.folderId = data.folderId || null;
-
this.rows = [];
+
if (data.rows) {
for (let row of data.rows) {
this.rows.push(new DashboardRow(row));
}
}
- this.updateSchema(data);
this.initMeta(meta);
+ this.updateSchema(data);
}
private initMeta(meta) {
@@ -170,9 +168,13 @@ export class DashboardModel {
}
getPanelById(id) {
- for (let panel of this.panels) {
- if (panel.id === id) {
- return panel;
+ for (var i = 0; i < this.rows.length; i++) {
+ var row = this.rows[i];
+ for (var j = 0; j < row.panels.length; j++) {
+ var panel = row.panels[j];
+ if (panel.id === id) {
+ return panel;
+ }
}
}
return null;
@@ -302,34 +304,6 @@ export class DashboardModel {
});
}
- removePanel(panel, ask?) {
- // confirm deletion
- if (ask !== false) {
- var text2, confirmText;
- if (panel.alert) {
- text2 = "Panel includes an alert rule, removing panel will also remove alert rule";
- confirmText = "YES";
- }
-
- appEvents.emit('confirm-modal', {
- title: 'Remove Panel',
- text: 'Are you sure you want to remove this panel?',
- text2: text2,
- icon: 'fa-trash',
- confirmText: confirmText,
- yesText: 'Remove',
- onConfirm: () => {
- this.removePanel(panel, false);
- }
- });
- return;
- }
-
- var index = _.indexOf(this.panels, panel);
- this.panels.splice(index, 1);
- this.events.emit('panel-removed', panel);
- }
-
isTimezoneUtc() {
return this.getTimezone() === 'utc';
}
@@ -671,6 +645,7 @@ export class DashboardModel {
upgradeToGridLayout() {
let yPos = 0;
+ let firstRow = this.rows[0];
for (let row of this.rows) {
let xPos = 0;
@@ -693,12 +668,23 @@ export class DashboardModel {
panel.width = panel.span;
panel.height = height;
- this.panels.push(panel);
+ delete panel.span;
xPos += panel.width;
}
- yPos += height;
+ if (!this.meta.keepRows) {
+ yPos += height;
+
+ // add to first row
+ if (row !== firstRow) {
+ firstRow.panels = firstRow.panels.concat(row.panels);
+ }
+ }
+ }
+
+ if (!this.meta.keepRows) {
+ this.rows = [firstRow];
}
}
}
diff --git a/public/app/features/dashboard/row/row.html b/public/app/features/dashboard/row/row.html
index 3beddaf7844..4d2fbd9e4cd 100644
--- a/public/app/features/dashboard/row/row.html
+++ b/public/app/features/dashboard/row/row.html
@@ -1,4 +1,4 @@
-