mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
grid: progress on row support
This commit is contained in:
parent
61459b287c
commit
9f945578b8
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
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});
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<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;">
|
||||
|
Loading…
Reference in New Issue
Block a user