Commit 55c6b4b9 by Torkel Ödegaard

started on rows as panels in single grid

parent 301ae2ea
...@@ -7,6 +7,62 @@ import config from 'app/core/config'; ...@@ -7,6 +7,62 @@ import config from 'app/core/config';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import {UnknownPanelCtrl} from 'app/plugins/panel/unknown/module'; import {UnknownPanelCtrl} from 'app/plugins/panel/unknown/module';
export class PanelRow {
static template = `
<h2 class="panel-header">Row</h2>
<a ng-click="ctrl.collapse()">Collapse</a>
`;
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 **/ /** @ngInject **/
function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $templateCache) { function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $templateCache) {
...@@ -55,6 +111,15 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ ...@@ -55,6 +111,15 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
} }
function loadPanelComponentInfo(scope, attrs) { 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 = { var componentInfo: any = {
name: 'panel-plugin-' + scope.panel.type, name: 'panel-plugin-' + scope.panel.type,
bindings: {dashboard: "=", panel: "=", row: "="}, bindings: {dashboard: "=", panel: "=", row: "="},
......
...@@ -10,7 +10,7 @@ import 'gridstack.jquery-ui'; ...@@ -10,7 +10,7 @@ import 'gridstack.jquery-ui';
const template = ` const template = `
<div class="grid-stack"> <div class="grid-stack">
<dash-grid-item ng-repeat="panel in ctrl.row.panels track by panel.id" <dash-grid-item ng-repeat="panel in ctrl.dashboard.panels track by panel.id"
class="grid-stack-item" class="grid-stack-item"
grid-ctrl="ctrl" grid-ctrl="ctrl"
panel="panel"> panel="panel">
...@@ -24,7 +24,6 @@ var rowIndex = 0; ...@@ -24,7 +24,6 @@ var rowIndex = 0;
export class GridCtrl { export class GridCtrl {
options: any; options: any;
row: any;
dashboard: any; dashboard: any;
panels: any; panels: any;
gridstack: any; gridstack: any;
...@@ -35,6 +34,7 @@ export class GridCtrl { ...@@ -35,6 +34,7 @@ export class GridCtrl {
/** @ngInject */ /** @ngInject */
constructor(private $scope, private $element, private $timeout) { constructor(private $scope, private $element, private $timeout) {
console.log(this.dashboard);
this.index = rowIndex; this.index = rowIndex;
rowIndex += 1; rowIndex += 1;
} }
...@@ -71,71 +71,39 @@ export class GridCtrl { ...@@ -71,71 +71,39 @@ export class GridCtrl {
onGridStackItemAdded(item) { onGridStackItemAdded(item) {
console.log('row: ' + this.index + ' item added', 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) { onGridStackItemRemoved(item) {
console.log('row: ' + this.index + ' item removed', item.id, 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) { onGridStackItemsChanged(items) {
console.log('row: ' +this.index + ' changes', items);
for (let item of 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 // find panel
var panelInfo = this.dashboard.getPanelInfoById(parseInt(item.id)); var panel = this.dashboard.getPanelById(parseInt(item.id));
if (!panelInfo) { if (!panel) {
console.log('row: ' + this.index + ' item change but no panel found for item', item); console.log('item change but no panel found for item', item);
continue; continue;
} }
// update panel model position // update panel model position
let panel = panelInfo.panel;
panel.x = item.x; panel.x = item.x;
panel.y = item.y; panel.y = item.y;
panel.width = item.width; panel.width = item.width;
panel.height = item.height; panel.height = item.height;
// wait a bit before adding console.log('updating panel: ' + panel.id + ' x: ' + panel.x + ' y: ' + panel.y);
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);
}
} }
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'); this.$scope.$broadcast('render');
} }
...@@ -155,7 +123,6 @@ export function dashGrid($timeout) { ...@@ -155,7 +123,6 @@ export function dashGrid($timeout) {
bindToController: true, bindToController: true,
controllerAs: 'ctrl', controllerAs: 'ctrl',
scope: { scope: {
row: "=",
dashboard: "=", dashboard: "=",
}, },
link: function(scope, elem, attrs, ctrl) { link: function(scope, elem, attrs, ctrl) {
...@@ -181,6 +148,7 @@ export function dashGridItem($timeout, $rootScope) { ...@@ -181,6 +148,7 @@ export function dashGridItem($timeout, $rootScope) {
link: function (scope, element, attrs) { link: function (scope, element, attrs) {
let gridCtrl = scope.gridCtrl; let gridCtrl = scope.gridCtrl;
let panel = scope.panel; let panel = scope.panel;
let gridStackNode = null;
element.attr({ element.attr({
'data-gs-id': panel.id, 'data-gs-id': panel.id,
...@@ -210,15 +178,19 @@ export function dashGridItem($timeout, $rootScope) { ...@@ -210,15 +178,19 @@ export function dashGridItem($timeout, $rootScope) {
return; return;
} }
let node = element.data('_gridstack_node'); if (gridStackNode) {
if (node) {
console.log('grid-item scope $destroy removeWidget'); console.log('grid-item scope $destroy removeWidget');
node._grid.removeWidget(element); gridStackNode._grid.removeWidget(element);
} }
}); });
if (gridCtrl.isInitialized) { if (gridCtrl.isInitialized) {
gridCtrl.gridstack.makeWidget(element); gridCtrl.gridstack.makeWidget(element);
gridStackNode = element.data('_gridstack_node');
} else {
setTimeout(function() {
gridStackNode = element.data('_gridstack_node');
}, 500);
} }
// scope.onItemRemoved({item: item}); // scope.onItemRemoved({item: item});
......
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
</li> </li>
</ul> </ul>
</li> </li>
<li class="navbar-mini-btn-wrapper"> <li class="navbar-mini-btn-wrapper" ng-show="::ctrl.dashboard.meta.canSave">
<button class="btn btn-secondary btn-mini" ng-click="ctrl.openEditView('add-panel')"> <button class="btn btn-secondary btn-mini" ng-click="ctrl.openEditView('add-panel')">
<i class="fa fa-plus-circle"></i> Add Panel <i class="fa fa-plus-circle"></i> Add Panel
</button> </button>
......
...@@ -16,6 +16,8 @@ export interface Panel { ...@@ -16,6 +16,8 @@ export interface Panel {
y: number; y: number;
width: number; width: number;
height: number; height: number;
type: string;
title: string;
} }
export const CELL_HEIGHT = 60; export const CELL_HEIGHT = 60;
...@@ -48,6 +50,7 @@ export class DashboardModel { ...@@ -48,6 +50,7 @@ export class DashboardModel {
events: any; events: any;
editMode: boolean; editMode: boolean;
folderId: number; folderId: number;
panels: Panel[];
constructor(data, meta?) { constructor(data, meta?) {
if (!data) { if (!data) {
...@@ -77,14 +80,9 @@ export class DashboardModel { ...@@ -77,14 +80,9 @@ export class DashboardModel {
this.links = data.links || []; this.links = data.links || [];
this.gnetId = data.gnetId || null; this.gnetId = data.gnetId || null;
this.folderId = data.folderId || null; this.folderId = data.folderId || null;
this.panels = data.panels || [];
this.rows = []; this.rows = [];
if (data.rows) {
for (let row of data.rows) {
this.rows.push(new DashboardRow(row));
}
}
this.initMeta(meta); this.initMeta(meta);
this.updateSchema(data); this.updateSchema(data);
} }
...@@ -158,25 +156,17 @@ export class DashboardModel { ...@@ -158,25 +156,17 @@ export class DashboardModel {
} }
forEachPanel(callback) { forEachPanel(callback) {
var i, j, row; for (let i = 0; i < this.panels.length; i++) {
for (i = 0; i < this.rows.length; i++) { callback(this.panels[i], i);
row = this.rows[i];
for (j = 0; j < row.panels.length; j++) {
callback(row.panels[j], j, row, i);
}
} }
} }
getPanelById(id) { getPanelById(id) {
for (var i = 0; i < this.rows.length; i++) { for (let panel of this.panels) {
var row = this.rows[i];
for (var j = 0; j < row.panels.length; j++) {
var panel = row.panels[j];
if (panel.id === id) { if (panel.id === id) {
return panel; return panel;
} }
} }
}
return null; return null;
} }
...@@ -185,25 +175,32 @@ export class DashboardModel { ...@@ -185,25 +175,32 @@ export class DashboardModel {
row.addPanel(panel); row.addPanel(panel);
} }
removeRow(row, force?) { removePanel(panel, ask?) {
var index = _.indexOf(this.rows, row); // confirm deletion
if (ask !== false) {
if (!row.panels.length || force) { var text2, confirmText;
this.rows.splice(index, 1); if (panel.alert) {
row.destroy(); text2 = "Panel includes an alert rule, removing panel will also remove alert rule";
return; confirmText = "YES";
} }
appEvents.emit('confirm-modal', { appEvents.emit('confirm-modal', {
title: 'Remove Row', title: 'Remove Panel',
text: 'Are you sure you want to remove this row?', text: 'Are you sure you want to remove this panel?',
text2: text2,
icon: 'fa-trash', icon: 'fa-trash',
yesText: 'Delete', confirmText: confirmText,
yesText: 'Remove',
onConfirm: () => { onConfirm: () => {
this.rows.splice(index, 1); this.removePanel(panel, false);
row.destroy();
} }
}); });
return;
}
var index = _.indexOf(this.panels, panel);
this.panels.splice(index, 1);
this.events.emit('panel-removed', panel);
} }
setPanelFocus(id) { setPanelFocus(id) {
...@@ -626,7 +623,7 @@ export class DashboardModel { ...@@ -626,7 +623,7 @@ export class DashboardModel {
} }
if (oldVersion < 15) { if (oldVersion < 15) {
this.upgradeToGridLayout(); this.upgradeToGridLayout(old);
} }
if (panelUpgrades.length === 0) { if (panelUpgrades.length === 0) {
...@@ -643,14 +640,28 @@ export class DashboardModel { ...@@ -643,14 +640,28 @@ export class DashboardModel {
} }
} }
upgradeToGridLayout() { upgradeToGridLayout(old) {
let yPos = 0; 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 xPos = 0;
let height: any = row.height; 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)) { if (_.isString(height)) {
height = parseInt(height.replace('px', ''), 10); height = parseInt(height.replace('px', ''), 10);
} }
...@@ -671,21 +682,13 @@ export class DashboardModel { ...@@ -671,21 +682,13 @@ export class DashboardModel {
delete panel.span; delete panel.span;
xPos += panel.width; xPos += panel.width;
this.panels.push(panel);
} }
if (!this.meta.keepRows) {
yPos += height; yPos += height;
// add to first row
if (row !== firstRow) {
firstRow.panels = firstRow.panels.concat(row.panels);
}
}
} }
if (!this.meta.keepRows) { console.log('panels', this.panels);
this.rows = [firstRow];
}
} }
} }
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
<!-- <span ng&#45;class="ctrl.row.titleSize">{{ctrl.row.title | interpolateTemplateVars:this}}</span> --> <!-- <span ng&#45;class="ctrl.row.titleSize">{{ctrl.row.title | interpolateTemplateVars:this}}</span> -->
<!-- </a> --> <!-- </a> -->
<!-- </div> --> <!-- </div> -->
<!-- -->
<!-- <dash&#45;grid ng&#45;if="!ctrl.row.collapse" row="ctrl.row" dashboard="ctrl.dashboard"></dash&#45;grid> -->
<!-- -->
<dash-grid ng-if="!ctrl.row.collapse" row="ctrl.row" dashboard="ctrl.dashboard"></dash-grid> <h2>Row</h2>
...@@ -8,14 +8,8 @@ ...@@ -8,14 +8,8 @@
<dashboard-submenu ng-if="dashboard.meta.submenuEnabled" dashboard="dashboard"></dashboard-submenu> <dashboard-submenu ng-if="dashboard.meta.submenuEnabled" dashboard="dashboard"></dashboard-submenu>
<div class="clearfix"></div> <dash-grid dashboard="dashboard"></dash-grid>
<dashboard-submenu ng-if="dashboard.meta.submenuEnabled" dashboard="dashboard"></dashboard-submenu>
<div class="clearfix"></div>
<dash-row class="dash-row" ng-repeat="row in dashboard.rows" row="row" dashboard="dashboard">
</dash-row>
</div> </div>
</div> </div>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment