Commit 9f945578 by Torkel Ödegaard

grid: progress on row support

parent 61459b28
......@@ -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);
});
......
......@@ -10,7 +10,7 @@ import 'gridstack.jquery-ui';
const template = `
<div class="grid-stack">
<dash-grid-item ng-repeat="panel in ctrl.panels"
<dash-grid-item ng-repeat="panel in ctrl.row.panels track by panel.id"
class="grid-stack-item"
grid-ctrl="ctrl"
panel="panel">
......@@ -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);
});
}
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);
});
}
itemsChanged(items) {
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});
......
......@@ -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,11 +168,15 @@ export class DashboardModel {
}
getPanelById(id) {
for (let panel of this.panels) {
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;
}
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];
}
}
}
......
<div class="dash-row-header" ng-if="ctrl.row.showTitle || ctrl.row.collapse">
<div class="dash-row-header">
<a class="dash-row-header-title" ng-click="ctrl.toggleCollapse()">
<span class="dash-row-collapse-toggle pointer">
<i class="fa fa-chevron-down" ng-show="!ctrl.row.collapse"></i>
......@@ -8,66 +8,5 @@
</a>
</div>
<div ng-if="ctrl.dropView === 1">
<dash-row-add-panel row-ctrl="ctrl"></dash-row-add-panel>
</div>
<div ng-if="ctrl.dropView === 2">
<dash-row-options row-ctrl="ctrl"></dash-row-options>
</div>
<div class="panels-wrapper" ng-if="!ctrl.row.collapse">
<div class="dash-row-menu-container" data-click-hide ng-hide="ctrl.dashboard.meta.fullscreen">
<ul class="dash-row-menu" role="menu">
<li>
<a ng-click="ctrl.toggleCollapse()">
<i class="fa fa-minus"></i> Collapse
</a>
</li>
<li ng-show="ctrl.dashboard.meta.canEdit">
<a ng-click="ctrl.onMenuAddPanel()">
<i class="fa fa-plus"></i> Add Panel
</a>
</li>
<li ng-show="ctrl.dashboard.meta.canEdit">
<a ng-click="ctrl.onMenuRowOptions()">
<i class="fa fa-cog"></i> Row Options
</a>
</li>
<li ng-show="ctrl.dashboard.meta.canEdit">
<a ng-click="ctrl.moveRow(-1)">
<i class="fa fa-arrow-up"></i> Move Up
</a>
</li>
<li ng-show="ctrl.dashboard.meta.canEdit">
<a ng-click="ctrl.moveRow(1)">
<i class="fa fa-arrow-down"></i> Move Down
</a>
</li>
<li ng-show="ctrl.dashboard.meta.canEdit">
<a ng-click="ctrl.onMenuDeleteRow()">
<i class="fa fa-trash"></i> Remove
</a>
</li>
</ul>
<div class="dash-row-menu-grip">
<i class="fa fa-ellipsis-v"></i>
</div>
</div>
<div ng-repeat="panel in ctrl.row.panels track by panel.id" class="panel" ui-draggable="!ctrl.dashboard.meta.fullscreen" drag="panel.id" ui-on-drop="ctrl.onDrop($data, panel)" drag-handle-class="drag-handle" panel-width>
<plugin-component type="panel" class="panel-margin">
</plugin-component>
</div>
<div panel-drop-zone class="panel panel-drop-zone" ui-on-drop="ctrl.onDrop($data)" data-drop="true">
<div class="panel-margin">
<div class="panel-container">
<div class="panel-drop-zone-text"></div>
</div>
</div>
</div>
<div class="clearfix"></div>
</div>
<dash-grid row="ctrl.row" dashboard="ctrl.dashboard"></dash-grid>
......@@ -16,98 +16,12 @@ export class DashRowCtrl {
/** @ngInject */
constructor(private $scope, private $rootScope, private $timeout) {
this.row.title = this.row.title || 'Row title';
if (this.row.isNew) {
this.dropView = 1;
}
}
onDrop(panelId, dropTarget) {
var dragObject;
// if string it's a panel type
if (_.isString(panelId)) {
// setup new panel
dragObject = {
row: this.row,
panel: {
title: config.new_panel_title,
type: panelId,
id: this.dashboard.getNextPanelId(),
isNew: true,
},
};
} else {
dragObject = this.dashboard.getPanelInfoById(panelId);
}
if (dropTarget) {
dropTarget = this.dashboard.getPanelInfoById(dropTarget.id);
// if draging new panel onto existing panel split it
if (dragObject.panel.isNew) {
dragObject.panel.span = dropTarget.panel.span = dropTarget.panel.span/2;
// insert after
dropTarget.row.panels.splice(dropTarget.index+1, 0, dragObject.panel);
} else if (this.row === dragObject.row) {
// just move element
this.row.movePanel(dragObject.index, dropTarget.index);
} else {
// split drop target space
dragObject.panel.span = dropTarget.panel.span = dropTarget.panel.span/2;
// insert after
dropTarget.row.panels.splice(dropTarget.index+1, 0, dragObject.panel);
// remove from source row
dragObject.row.removePanel(dragObject.panel, false);
}
} else {
dragObject.panel.span = 12 - this.row.span;
this.row.panels.push(dragObject.panel);
// if not new remove from source row
if (!dragObject.panel.isNew) {
dragObject.row.removePanel(dragObject.panel, false);
}
}
this.dropView = 0;
this.row.panelSpanChanged();
this.$timeout(() => {
this.$rootScope.$broadcast('render');
});
}
setHeight(height) {
this.row.height = height;
this.$scope.$broadcast('render');
}
moveRow(direction) {
var rowsList = this.dashboard.rows;
var rowIndex = _.indexOf(rowsList, this.row);
var newIndex = rowIndex + direction;
if (newIndex >= 0 && newIndex <= (rowsList.length - 1)) {
_.move(rowsList, rowIndex, newIndex);
}
}
toggleCollapse() {
this.closeDropView();
this.row.collapse = !this.row.collapse;
}
onMenuAddPanel() {
this.dropView = 1;
}
onMenuRowOptions() {
this.dropView = 2;
}
closeDropView() {
this.dropView = 0;
}
onMenuDeleteRow() {
this.dashboard.removeRow(this.row);
}
......@@ -127,116 +41,8 @@ coreModule.directive('dashRow', function($rootScope) {
link: function(scope, element) {
scope.$watchGroup(['ctrl.row.collapse', 'ctrl.row.height'], function() {
element.toggleClass('dash-row--collapse', scope.ctrl.row.collapse);
element.find('.panels-wrapper').css({minHeight: scope.ctrl.row.collapse ? '5px' : scope.ctrl.row.height});
});
$rootScope.onAppEvent('panel-fullscreen-enter', function(evt, info) {
var hasPanel = _.find(scope.ctrl.row.panels, {id: info.panelId});
if (!hasPanel) {
element.hide();
}
}, scope);
$rootScope.onAppEvent('panel-fullscreen-exit', function() {
element.show();
}, scope);
}
};
});
coreModule.directive('panelWidth', function($rootScope) {
return function(scope, element) {
var fullscreen = false;
function updateWidth() {
if (!fullscreen) {
element[0].style.width = ((scope.panel.span / 1.2) * 10) + '%';
}
}
$rootScope.onAppEvent('panel-fullscreen-enter', function(evt, info) {
fullscreen = true;
if (scope.panel.id !== info.panelId) {
element.hide();
} else {
element[0].style.width = '100%';
}
}, scope);
$rootScope.onAppEvent('panel-fullscreen-exit', function(evt, info) {
fullscreen = false;
if (scope.panel.id !== info.panelId) {
element.show();
}
updateWidth();
}, scope);
scope.$watch('panel.span', updateWidth);
if (fullscreen) {
element.hide();
}
};
});
coreModule.directive('panelDropZone', function($timeout) {
return function(scope, element) {
var row = scope.ctrl.row;
var dashboard = scope.ctrl.dashboard;
var indrag = false;
var textEl = element.find('.panel-drop-zone-text');
function showPanel(span, text) {
element.find('.panel-container').css('height', row.height);
element[0].style.width = ((span / 1.2) * 10) + '%';
textEl.text(text);
element.show();
}
function hidePanel() {
element.hide();
}
function updateState() {
if (row.panels.length === 0 && indrag === false) {
return showPanel(12, 'Empty Space');
}
var dropZoneSpan = 12 - row.span;
if (dropZoneSpan > 0) {
if (indrag) {
return showPanel(dropZoneSpan, 'Drop Here');
} else {
return showPanel(dropZoneSpan, 'Empty Space');
}
}
if (indrag === true) {
if (dropZoneSpan > 1) {
return showPanel(dropZoneSpan, 'Drop Here');
}
}
hidePanel();
}
row.events.on('span-changed', updateState, scope);
scope.$on("ANGULAR_DRAG_START", function() {
indrag = true;
updateState();
});
scope.$on("ANGULAR_DRAG_END", function() {
indrag = false;
updateState();
});
updateState();
};
});
......@@ -9,9 +9,8 @@
<div class="clearfix"></div>
<dash-grid dashboard="dashboard">
</dash-grid>
<dash-row class="dash-row" ng-repeat="row in dashboard.rows" row="row" dashboard="dashboard">
</dash-row>
<div ng-show='dashboard.meta.canEdit && !dashboard.meta.fullscreen' class="add-row-panel-hint">
<div class="span12" style="text-align:left;">
......
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