diff --git a/public/app/core/directives/plugin_component.ts b/public/app/core/directives/plugin_component.ts
index d0f21501e7e..07d275edde4 100644
--- a/public/app/core/directives/plugin_component.ts
+++ b/public/app/core/directives/plugin_component.ts
@@ -7,6 +7,62 @@ import config from 'app/core/config';
import coreModule from 'app/core/core_module';
import {UnknownPanelCtrl} from 'app/plugins/panel/unknown/module';
+export class PanelRow {
+ static template = `
+
+ Collapse
+ `;
+
+ dashboard: any;
+ panel: any;
+
+ constructor(private $rootScope) {
+ console.log(this);
+ this.panel.hiddenPanels = this.panel.hiddenPanels || [];
+ }
+
+ collapse() {
+ if (this.panel.hiddenPanels.length > 0) {
+ let panelIndex = _.indexOf(this.dashboard.panels, this.panel);
+
+ for (let child of this.panel.hiddenPanels) {
+ this.dashboard.panels.splice(panelIndex+1, 0, child);
+ child.y = this.panel.y+1;
+ console.log('restoring child', child);
+ }
+
+ this.panel.hiddenPanels = [];
+ return;
+ }
+
+ let foundRow = false;
+ for (let i = 0; i < this.dashboard.panels.length; i++) {
+ let panel = this.dashboard.panels[i];
+
+ if (panel === this.panel) {
+ console.log('found row');
+ foundRow = true;
+ continue;
+ }
+
+ if (!foundRow) {
+ continue;
+ }
+
+ if (panel.type === 'row') {
+ break;
+ }
+
+ this.panel.hiddenPanels.push(panel);
+ console.log('hiding child', panel.id);
+ }
+
+ for (let hiddenPanel of this.panel.hiddenPanels) {
+ this.dashboard.removePanel(hiddenPanel, false);
+ }
+ }
+}
+
/** @ngInject **/
function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $templateCache) {
@@ -55,6 +111,15 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
}
function loadPanelComponentInfo(scope, attrs) {
+ if (scope.panel.type === 'row') {
+ return $q.when({
+ name: 'panel-row',
+ bindings: {dashboard: "=", panel: "="},
+ attrs: {dashboard: "ctrl.dashboard", panel: "panel"},
+ Component: PanelRow,
+ });
+ }
+
var componentInfo: any = {
name: 'panel-plugin-' + scope.panel.type,
bindings: {dashboard: "=", panel: "=", row: "="},
diff --git a/public/app/features/dashboard/dashgrid/dashgrid.ts b/public/app/features/dashboard/dashgrid/dashgrid.ts
index 0da2ce5ced5..a948006f724 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 = `
-
@@ -24,7 +24,6 @@ var rowIndex = 0;
export class GridCtrl {
options: any;
- row: any;
dashboard: any;
panels: any;
gridstack: any;
@@ -35,6 +34,7 @@ export class GridCtrl {
/** @ngInject */
constructor(private $scope, private $element, private $timeout) {
+ console.log(this.dashboard);
this.index = rowIndex;
rowIndex += 1;
}
@@ -71,71 +71,39 @@ export class GridCtrl {
onGridStackItemAdded(item) {
console.log('row: ' + this.index + ' item added', item);
- // if item has id dont need to do anything
- if (item.id) {
- return;
- }
-
- // if this comes from another row we need to remove it
- this.$timeout(() => this.gridstack.removeWidget(item.el, true));
}
onGridStackItemRemoved(item) {
console.log('row: ' + this.index + ' item removed', item.id, item);
- // ignore items that have no panel id
- // if (!item.id) {
- // return;
- // }
- //
- // let panel = this.dashboard.getPanelById(parseInt(item.id));
- //
- // if (panel) {
- // panelChangingRow = panel
- // this.row.removePanel(panel, false);
- // }
}
onGridStackItemsChanged(items) {
- console.log('row: ' +this.index + ' changes', items);
-
for (let item of items) {
- let isFromOtherRow = false;
-
- if (!item.id) {
- item.id = parseInt(item.el.attr('data-gs-id'));
- isFromOtherRow = true;
- }
-
// find panel
- var panelInfo = this.dashboard.getPanelInfoById(parseInt(item.id));
+ var panel = this.dashboard.getPanelById(parseInt(item.id));
- if (!panelInfo) {
- console.log('row: ' + this.index + ' item change but no panel found for item', item);
+ if (!panel) {
+ console.log('item change but no panel found for item', item);
continue;
}
// update panel model position
- let panel = panelInfo.panel;
panel.x = item.x;
panel.y = item.y;
panel.width = item.width;
panel.height = item.height;
- // wait a bit before adding
- if (isFromOtherRow) {
- let movePanelFn = (panel, row) => {
- return this.$timeout(() => {
- console.log('moving panel movel to another row', panel);
- // remove from source row
- row.removePanel(panel, false);
- // add this this row
- this.row.panels.push(panel);
- });
- };
- movePanelFn(panelInfo.panel, panelInfo.row);
- }
+ console.log('updating panel: ' + panel.id + ' x: ' + panel.x + ' y: ' + panel.y);
}
+ this.dashboard.panels.sort(function (a, b) {
+ let aScore = a.x + (a.y * 12);
+ let bScore = b.x + (b.y * 12);
+ if (aScore < bScore) { return -1; }
+ if (aScore > bScore) { return 1; }
+ return 0;
+ });
+
this.$scope.$broadcast('render');
}
@@ -155,7 +123,6 @@ export function dashGrid($timeout) {
bindToController: true,
controllerAs: 'ctrl',
scope: {
- row: "=",
dashboard: "=",
},
link: function(scope, elem, attrs, ctrl) {
@@ -181,6 +148,7 @@ export function dashGridItem($timeout, $rootScope) {
link: function (scope, element, attrs) {
let gridCtrl = scope.gridCtrl;
let panel = scope.panel;
+ let gridStackNode = null;
element.attr({
'data-gs-id': panel.id,
@@ -210,15 +178,19 @@ export function dashGridItem($timeout, $rootScope) {
return;
}
- let node = element.data('_gridstack_node');
- if (node) {
+ if (gridStackNode) {
console.log('grid-item scope $destroy removeWidget');
- node._grid.removeWidget(element);
+ gridStackNode._grid.removeWidget(element);
}
});
if (gridCtrl.isInitialized) {
gridCtrl.gridstack.makeWidget(element);
+ gridStackNode = element.data('_gridstack_node');
+ } else {
+ setTimeout(function() {
+ gridStackNode = element.data('_gridstack_node');
+ }, 500);
}
// scope.onItemRemoved({item: item});
diff --git a/public/app/features/dashboard/dashnav/dashnav.html b/public/app/features/dashboard/dashnav/dashnav.html
index 2d3c68965cb..fd1ee180248 100644
--- a/public/app/features/dashboard/dashnav/dashnav.html
+++ b/public/app/features/dashboard/dashnav/dashnav.html
@@ -69,7 +69,7 @@
-
+
diff --git a/public/app/features/dashboard/model.ts b/public/app/features/dashboard/model.ts
index e9026447dab..a8bbd2f3409 100644
--- a/public/app/features/dashboard/model.ts
+++ b/public/app/features/dashboard/model.ts
@@ -16,6 +16,8 @@ export interface Panel {
y: number;
width: number;
height: number;
+ type: string;
+ title: string;
}
export const CELL_HEIGHT = 60;
@@ -48,6 +50,7 @@ export class DashboardModel {
events: any;
editMode: boolean;
folderId: number;
+ panels: Panel[];
constructor(data, meta?) {
if (!data) {
@@ -77,14 +80,9 @@ export class DashboardModel {
this.links = data.links || [];
this.gnetId = data.gnetId || null;
this.folderId = data.folderId || null;
+ this.panels = data.panels || [];
this.rows = [];
- if (data.rows) {
- for (let row of data.rows) {
- this.rows.push(new DashboardRow(row));
- }
- }
-
this.initMeta(meta);
this.updateSchema(data);
}
@@ -158,23 +156,15 @@ export class DashboardModel {
}
forEachPanel(callback) {
- var i, j, row;
- for (i = 0; i < this.rows.length; i++) {
- row = this.rows[i];
- for (j = 0; j < row.panels.length; j++) {
- callback(row.panels[j], j, row, i);
- }
+ for (let i = 0; i < this.panels.length; i++) {
+ callback(this.panels[i], i);
}
}
getPanelById(id) {
- 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;
- }
+ for (let panel of this.panels) {
+ if (panel.id === id) {
+ return panel;
}
}
return null;
@@ -185,25 +175,32 @@ export class DashboardModel {
row.addPanel(panel);
}
- removeRow(row, force?) {
- var index = _.indexOf(this.rows, row);
+ 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";
+ }
- if (!row.panels.length || force) {
- this.rows.splice(index, 1);
- row.destroy();
+ 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;
}
- appEvents.emit('confirm-modal', {
- title: 'Remove Row',
- text: 'Are you sure you want to remove this row?',
- icon: 'fa-trash',
- yesText: 'Delete',
- onConfirm: () => {
- this.rows.splice(index, 1);
- row.destroy();
- }
- });
+ var index = _.indexOf(this.panels, panel);
+ this.panels.splice(index, 1);
+ this.events.emit('panel-removed', panel);
}
setPanelFocus(id) {
@@ -626,7 +623,7 @@ export class DashboardModel {
}
if (oldVersion < 15) {
- this.upgradeToGridLayout();
+ this.upgradeToGridLayout(old);
}
if (panelUpgrades.length === 0) {
@@ -643,14 +640,28 @@ export class DashboardModel {
}
}
- upgradeToGridLayout() {
+ upgradeToGridLayout(old) {
let yPos = 0;
- let firstRow = this.rows[0];
+ let rowIds = 1000;
- for (let row of this.rows) {
+ for (let row of old.rows) {
let xPos = 0;
let height: any = row.height;
+ if (this.meta.keepRows) {
+ this.panels.push({
+ id: rowIds++,
+ type: 'row',
+ title: row.title,
+ x: 0,
+ y: yPos,
+ height: 1,
+ width: 12
+ });
+
+ yPos += 1;
+ }
+
if (_.isString(height)) {
height = parseInt(height.replace('px', ''), 10);
}
@@ -671,21 +682,13 @@ export class DashboardModel {
delete panel.span;
xPos += panel.width;
+
+ this.panels.push(panel);
}
- if (!this.meta.keepRows) {
- yPos += height;
-
- // add to first row
- if (row !== firstRow) {
- firstRow.panels = firstRow.panels.concat(row.panels);
- }
- }
+ yPos += height;
}
- if (!this.meta.keepRows) {
- this.rows = [firstRow];
- }
+ console.log('panels', this.panels);
}
}
-
diff --git a/public/app/features/dashboard/row/row.html b/public/app/features/dashboard/row/row.html
index f173aaf79af..3d4f3eca048 100644
--- a/public/app/features/dashboard/row/row.html
+++ b/public/app/features/dashboard/row/row.html
@@ -7,6 +7,8 @@
+
+
+
-
-
+Row
diff --git a/public/app/partials/dashboard.html b/public/app/partials/dashboard.html
index 516c9005db5..16218f1916c 100644
--- a/public/app/partials/dashboard.html
+++ b/public/app/partials/dashboard.html
@@ -8,14 +8,8 @@
-
+
-
-
-
-
-
-