mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
grid: progress on new grid, resize & saving layouts works
This commit is contained in:
parent
207773e07e
commit
10a3504309
@ -1,11 +1,62 @@
|
|||||||
|
import {Emitter} from 'app/core/core';
|
||||||
|
|
||||||
export interface PanelModel {
|
export interface GridPos {
|
||||||
id: number;
|
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
width: number;
|
w: number;
|
||||||
height: number;
|
h: number;
|
||||||
type: string;
|
}
|
||||||
title: string;
|
|
||||||
|
const notPersistedProperties: {[str: string]: boolean} = {
|
||||||
|
"model": true,
|
||||||
|
"events": true,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class PanelModel {
|
||||||
|
id: number;
|
||||||
|
gridPos: GridPos;
|
||||||
|
type: string;
|
||||||
|
title: string;
|
||||||
|
events: Emitter;
|
||||||
|
|
||||||
|
constructor(private model) {
|
||||||
|
// copy properties from persisted model
|
||||||
|
for (var property in model) {
|
||||||
|
this[property] = model[property];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.events = new Emitter();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSaveModel() {
|
||||||
|
this.model = {};
|
||||||
|
for (var property in this) {
|
||||||
|
if (notPersistedProperties[property] || !this.hasOwnProperty(property)) {
|
||||||
|
console.log('PanelModel.getSaveModel() skiping property', property);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.model[property] = this[property];
|
||||||
|
}
|
||||||
|
return this.model;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGridPos(newPos: GridPos) {
|
||||||
|
let sizeChanged = false;
|
||||||
|
|
||||||
|
if (this.gridPos.w !== newPos.w || this.gridPos.h !== newPos.h) {
|
||||||
|
sizeChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gridPos.x = newPos.x;
|
||||||
|
this.gridPos.y = newPos.y;
|
||||||
|
this.gridPos.w = newPos.w;
|
||||||
|
this.gridPos.h = newPos.h;
|
||||||
|
|
||||||
|
if (sizeChanged) {
|
||||||
|
console.log('PanelModel sizeChanged event and render events fired');
|
||||||
|
this.events.emit('panel-size-changed');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +121,8 @@ export class DashboardCtrl implements PanelContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
panelPossitionUpdated(panel: PanelModel) {
|
panelPossitionUpdated(panel: PanelModel) {
|
||||||
console.log('panel pos updated', panel);
|
//console.log('panel pos updated', panel);
|
||||||
|
//this.$rootScope.$broadcast('render');
|
||||||
}
|
}
|
||||||
|
|
||||||
timezoneChanged() {
|
timezoneChanged() {
|
||||||
|
@ -4,6 +4,7 @@ import ReactGridLayout from 'react-grid-layout';
|
|||||||
import {CELL_HEIGHT, CELL_VMARGIN} from '../model';
|
import {CELL_HEIGHT, CELL_VMARGIN} from '../model';
|
||||||
import {DashboardPanel} from './DashboardPanel';
|
import {DashboardPanel} from './DashboardPanel';
|
||||||
import {PanelContainer} from './PanelContainer';
|
import {PanelContainer} from './PanelContainer';
|
||||||
|
import {PanelModel} from '../PanelModel';
|
||||||
import sizeMe from 'react-sizeme';
|
import sizeMe from 'react-sizeme';
|
||||||
|
|
||||||
const COLUMN_COUNT = 12;
|
const COLUMN_COUNT = 12;
|
||||||
@ -22,6 +23,8 @@ function GridWrapper({size, layout, onLayoutChange, children}) {
|
|||||||
isDraggable={true}
|
isDraggable={true}
|
||||||
isResizable={true}
|
isResizable={true}
|
||||||
measureBeforeMount={false}
|
measureBeforeMount={false}
|
||||||
|
containerPadding={[0, 0]}
|
||||||
|
useCSSTransforms={true}
|
||||||
margin={[CELL_VMARGIN, CELL_VMARGIN]}
|
margin={[CELL_VMARGIN, CELL_VMARGIN]}
|
||||||
cols={COLUMN_COUNT}
|
cols={COLUMN_COUNT}
|
||||||
rowHeight={CELL_HEIGHT}
|
rowHeight={CELL_HEIGHT}
|
||||||
@ -42,6 +45,7 @@ export interface DashboardGridProps {
|
|||||||
export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
||||||
gridToPanelMap: any;
|
gridToPanelMap: any;
|
||||||
panelContainer: PanelContainer;
|
panelContainer: PanelContainer;
|
||||||
|
panelMap: {[id: string]: PanelModel};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -52,22 +56,34 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
|||||||
buildLayout() {
|
buildLayout() {
|
||||||
const layout = [];
|
const layout = [];
|
||||||
const panels = this.panelContainer.getPanels();
|
const panels = this.panelContainer.getPanels();
|
||||||
|
this.panelMap = {};
|
||||||
|
|
||||||
for (let panel of panels) {
|
for (let panel of panels) {
|
||||||
|
let stringId = panel.id.toString();
|
||||||
|
this.panelMap[stringId] = panel;
|
||||||
|
|
||||||
|
if (!panel.gridPos) {
|
||||||
|
console.log('panel without gridpos');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
layout.push({
|
layout.push({
|
||||||
i: panel.id.toString(),
|
i: stringId,
|
||||||
x: panel.x,
|
x: panel.gridPos.x,
|
||||||
y: panel.y,
|
y: panel.gridPos.y,
|
||||||
w: panel.width,
|
w: panel.gridPos.w,
|
||||||
h: panel.height,
|
h: panel.gridPos.h,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('layout', layout);
|
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayoutChange() {}
|
onLayoutChange(newLayout) {
|
||||||
|
for (const newPos of newLayout) {
|
||||||
|
this.panelMap[newPos.i].updateGridPos(newPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderPanels() {
|
renderPanels() {
|
||||||
const panels = this.panelContainer.getPanels();
|
const panels = this.panelContainer.getPanels();
|
||||||
@ -76,10 +92,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
|||||||
for (let panel of panels) {
|
for (let panel of panels) {
|
||||||
panelElements.push(
|
panelElements.push(
|
||||||
<div key={panel.id.toString()} className="panel">
|
<div key={panel.id.toString()} className="panel">
|
||||||
<DashboardPanel
|
<DashboardPanel panel={panel} getPanelContainer={this.props.getPanelContainer} />
|
||||||
panel={panel}
|
|
||||||
getPanelContainer={this.props.getPanelContainer}
|
|
||||||
/>
|
|
||||||
</div>,
|
</div>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,211 +0,0 @@
|
|||||||
// ///<reference path="../../../headers/common.d.ts" />
|
|
||||||
//
|
|
||||||
// import coreModule from 'app/core/core_module';
|
|
||||||
// import {CELL_HEIGHT, CELL_VMARGIN} from '../model';
|
|
||||||
//
|
|
||||||
// import 'jquery-ui';
|
|
||||||
// import 'gridstack/dist/jquery.jQueryUI';
|
|
||||||
// import 'gridstack';
|
|
||||||
//
|
|
||||||
// const template = `
|
|
||||||
// <div class="grid-stack">
|
|
||||||
// <dash-grid-item ng-repeat="panel in ctrl.dashboard.panels track by panel.id"
|
|
||||||
// class="grid-stack-item"
|
|
||||||
// grid-ctrl="ctrl"
|
|
||||||
// panel="panel">
|
|
||||||
// <plugin-component type="panel" class="grid-stack-item-content">
|
|
||||||
// </plugin-component>
|
|
||||||
// </dash-grid-item>
|
|
||||||
// </div>
|
|
||||||
// `;
|
|
||||||
//
|
|
||||||
// var rowIndex = 0;
|
|
||||||
//
|
|
||||||
// export class GridCtrl {
|
|
||||||
// options: any;
|
|
||||||
// dashboard: any;
|
|
||||||
// panels: any;
|
|
||||||
// gridstack: any;
|
|
||||||
// gridElem: any;
|
|
||||||
// isInitialized: boolean;
|
|
||||||
// isDestroyed: boolean;
|
|
||||||
// index: number;
|
|
||||||
// changeRenderPromise: any;
|
|
||||||
//
|
|
||||||
// #<{(|* @ngInject |)}>#
|
|
||||||
// constructor(private $scope, private $element, private $timeout) {
|
|
||||||
// console.log(this.dashboard);
|
|
||||||
// this.index = rowIndex;
|
|
||||||
// rowIndex += 1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// init() {
|
|
||||||
// this.gridElem = this.$element.find('.grid-stack');
|
|
||||||
//
|
|
||||||
// this.gridstack = this.gridElem.gridstack({
|
|
||||||
// animate: true,
|
|
||||||
// cellHeight: CELL_HEIGHT,
|
|
||||||
// verticalMargin: CELL_VMARGIN,
|
|
||||||
// acceptWidgets: '.grid-stack-item',
|
|
||||||
// handle: '.grid-drag-handle'
|
|
||||||
// }).data('gridstack');
|
|
||||||
//
|
|
||||||
// this.isInitialized = true;
|
|
||||||
//
|
|
||||||
// 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.onGridStackItemsChanged(items), 50);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// onGridStackItemAdded(item) {
|
|
||||||
// console.log('row: ' + this.index + ' item added', item);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// onGridStackItemRemoved(item) {
|
|
||||||
// console.log('row: ' + this.index + ' item removed', item.id, item);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// onGridStackItemsChanged(items) {
|
|
||||||
// console.log('onGridStackItemsChanged');
|
|
||||||
//
|
|
||||||
// for (let item of items) {
|
|
||||||
// // find panel
|
|
||||||
// var panel = this.dashboard.getPanelById(parseInt(item.id));
|
|
||||||
//
|
|
||||||
// if (!panel) {
|
|
||||||
// console.log('item change but no panel found for item', item);
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // update panel model position
|
|
||||||
// panel.x = item.x;
|
|
||||||
// panel.y = item.y;
|
|
||||||
// panel.width = item.width;
|
|
||||||
// panel.height = item.height;
|
|
||||||
//
|
|
||||||
// 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;
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// if (this.changeRenderPromise) {
|
|
||||||
// this.$timeout.cancel(this.changeRenderPromise);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// this.changeRenderPromise = this.$timeout(() => {
|
|
||||||
// console.log('broadcasting render');
|
|
||||||
// this.$scope.$broadcast('render');
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// destroy() {
|
|
||||||
// this.gridstack.destroy();
|
|
||||||
// this.gridstack = null;
|
|
||||||
// this.isDestroyed = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// #<{(|* @ngInject *|)}>#
|
|
||||||
// export function dashGrid($timeout) {
|
|
||||||
// return {
|
|
||||||
// restrict: 'E',
|
|
||||||
// template: template,
|
|
||||||
// controller: GridCtrl,
|
|
||||||
// bindToController: true,
|
|
||||||
// controllerAs: 'ctrl',
|
|
||||||
// scope: {
|
|
||||||
// dashboard: "=",
|
|
||||||
// },
|
|
||||||
// link: function(scope, elem, attrs, ctrl) {
|
|
||||||
// $timeout(function() {
|
|
||||||
// ctrl.init();
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// scope.$on('$destroy', () => {
|
|
||||||
// ctrl.destroy();
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// #<{(|* @ngInject *|)}>#
|
|
||||||
// export function dashGridItem($timeout, $rootScope) {
|
|
||||||
// return {
|
|
||||||
// restrict: "E",
|
|
||||||
// scope: {
|
|
||||||
// panel: '=',
|
|
||||||
// gridCtrl: '='
|
|
||||||
// },
|
|
||||||
// link: function (scope, element, attrs) {
|
|
||||||
// let gridCtrl = scope.gridCtrl;
|
|
||||||
// let panel = scope.panel;
|
|
||||||
// let gridStackNode = null;
|
|
||||||
//
|
|
||||||
// element.attr({
|
|
||||||
// 'data-gs-id': panel.id,
|
|
||||||
// 'data-gs-x': panel.x,
|
|
||||||
// 'data-gs-y': panel.y,
|
|
||||||
// 'data-gs-width': panel.width,
|
|
||||||
// 'data-gs-height': panel.height,
|
|
||||||
// 'data-gs-no-resize': panel.type === 'row',
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// $rootScope.onAppEvent('panel-fullscreen-exit', (evt, payload) => {
|
|
||||||
// if (panel.id !== payload.panelId) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// gridCtrl.gridstack.locked(element, false);
|
|
||||||
// element.removeClass('panel-fullscreen');
|
|
||||||
// }, scope);
|
|
||||||
//
|
|
||||||
// $rootScope.onAppEvent('panel-fullscreen-enter', (evt, payload) => {
|
|
||||||
// if (panel.id !== payload.panelId) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// element.addClass('panel-fullscreen');
|
|
||||||
// }, scope);
|
|
||||||
//
|
|
||||||
// scope.$on('$destroy', () => {
|
|
||||||
// console.log('grid-item scope $destroy');
|
|
||||||
// if (gridCtrl.isDestroyed) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (gridStackNode) {
|
|
||||||
// console.log('grid-item scope $destroy removeWidget');
|
|
||||||
// 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);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// coreModule.directive('dashGrid', dashGrid);
|
|
||||||
// coreModule.directive('dashGridItem', dashGridItem);
|
|
@ -1,232 +0,0 @@
|
|||||||
Skip to content
|
|
||||||
This repository
|
|
||||||
Search
|
|
||||||
Pull requests
|
|
||||||
Issues
|
|
||||||
Marketplace
|
|
||||||
Gist
|
|
||||||
@torkelo
|
|
||||||
Sign out
|
|
||||||
Unwatch 946
|
|
||||||
Unstar 17,021
|
|
||||||
Fork 2,862 grafana/grafana
|
|
||||||
Code Issues 1,079 Pull requests 46 Projects 1 Wiki Settings Insights
|
|
||||||
Branch: gridstack Find file Copy pathgrafana/public/app/core/components/dashgrid/dashgrid.ts
|
|
||||||
a6bbcb8 on Jun 13
|
|
||||||
@torkelo torkelo ux: gridstack poc
|
|
||||||
1 contributor
|
|
||||||
RawBlameHistory
|
|
||||||
213 lines (181 sloc) 5.45 KB
|
|
||||||
///<reference path="../../../headers/common.d.ts" />
|
|
||||||
|
|
||||||
import $ from 'jquery';
|
|
||||||
import coreModule from '../../core_module';
|
|
||||||
|
|
||||||
import 'jquery-ui';
|
|
||||||
import 'gridstack';
|
|
||||||
import 'gridstack.jquery-ui';
|
|
||||||
|
|
||||||
const template = `
|
|
||||||
<div gridstack gridstack-handler="ctrl.gridstack" class="grid-stack"
|
|
||||||
options="ctrl.options"
|
|
||||||
on-change="ctrl.onChange(event,items)"
|
|
||||||
on-drag-start="ctrl.onDragStart(event,ui)"
|
|
||||||
on-drag-stop="ctrl.onDragStop(event, ui)"
|
|
||||||
on-resize-start="ctrl.onResizeStart(event, ui)"
|
|
||||||
on-resize-stop="ctrl.onResizeStop(event, ui)">
|
|
||||||
<div gridstack-item ng-repeat="panel in ctrl.panels"
|
|
||||||
class="grid-stack-item"
|
|
||||||
gs-item-id="panel.id"
|
|
||||||
gs-item-x="panel.x"
|
|
||||||
gs-item-y="panel.y"
|
|
||||||
gs-item-width="panel.width"
|
|
||||||
gs-item-height="panel.height"
|
|
||||||
gs-item-autopos="1"
|
|
||||||
on-item-added="ctrl.onItemAdded(item)"
|
|
||||||
on-item-removed="ctrl.onItemRemoved(item)">
|
|
||||||
<plugin-component type="panel" class="panel-margin grid-stack-item-content">
|
|
||||||
</plugin-component>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
export class DashGridCtrl {
|
|
||||||
options: any;
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
constructor(private $rootScope) {
|
|
||||||
this.options = {
|
|
||||||
animate: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onResizeStop() {
|
|
||||||
this.$rootScope.$broadcast('render');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function dashGrid($timeout) {
|
|
||||||
return {
|
|
||||||
restrict: 'E',
|
|
||||||
template: template,
|
|
||||||
controller: DashGridCtrl,
|
|
||||||
bindToController: true,
|
|
||||||
controllerAs: 'ctrl',
|
|
||||||
scope: {
|
|
||||||
dashboard: "="
|
|
||||||
},
|
|
||||||
link: function(scope, elem, attrs, ctrl) {
|
|
||||||
|
|
||||||
ctrl.panels = [];
|
|
||||||
ctrl.dashboard.forEachPanel((panel, panelIndex, row, rowIndex) => {
|
|
||||||
panel.width = 4;
|
|
||||||
panel.height = 4;
|
|
||||||
panel.x = panelIndex * 4;
|
|
||||||
panel.y = rowIndex * 4;
|
|
||||||
ctrl.panels.push(panel);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
coreModule.controller('GridstackController', ['$scope', function($scope) {
|
|
||||||
|
|
||||||
var gridstack = null;
|
|
||||||
|
|
||||||
this.init = function(element, options) {
|
|
||||||
gridstack = element.gridstack(options).data('gridstack');
|
|
||||||
return gridstack;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.removeItem = function(element) {
|
|
||||||
if (gridstack) {
|
|
||||||
return gridstack.removeWidget(element, false);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.addItem = function(element) {
|
|
||||||
if (gridstack) {
|
|
||||||
gridstack.makeWidget(element);
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
}]);
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
coreModule.directive('gridstack', ['$timeout', function($timeout) {
|
|
||||||
return {
|
|
||||||
restrict: "A",
|
|
||||||
controller: 'GridstackController',
|
|
||||||
scope: {
|
|
||||||
onChange: '&',
|
|
||||||
onDragStart: '&',
|
|
||||||
onDragStop: '&',
|
|
||||||
onResizeStart: '&',
|
|
||||||
onResizeStop: '&',
|
|
||||||
gridstackHandler: '=',
|
|
||||||
options: '='
|
|
||||||
},
|
|
||||||
link: function (scope, element, attrs, controller, ngModel) {
|
|
||||||
|
|
||||||
var gridstack = controller.init(element, scope.options);
|
|
||||||
scope.gridstackHandler = gridstack;
|
|
||||||
|
|
||||||
element.on('change', function (e, items) {
|
|
||||||
$timeout(function() {
|
|
||||||
scope.$apply();
|
|
||||||
scope.onChange({event: e, items: items});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
element.on('dragstart', function(e, ui) {
|
|
||||||
scope.onDragStart({event: e, ui: ui});
|
|
||||||
});
|
|
||||||
|
|
||||||
element.on('dragstop', function(e, ui) {
|
|
||||||
$timeout(function() {
|
|
||||||
scope.$apply();
|
|
||||||
scope.onDragStop({event: e, ui: ui});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
element.on('resizestart', function(e, ui) {
|
|
||||||
scope.onResizeStart({event: e, ui: ui});
|
|
||||||
});
|
|
||||||
|
|
||||||
element.on('resizestop', function(e, ui) {
|
|
||||||
$timeout(function() {
|
|
||||||
scope.$apply();
|
|
||||||
scope.onResizeStop({event: e, ui: ui});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}]);
|
|
||||||
|
|
||||||
/** @ngInject */
|
|
||||||
coreModule.directive('gridstackItem', ['$timeout', function($timeout) {
|
|
||||||
|
|
||||||
return {
|
|
||||||
restrict: "A",
|
|
||||||
controller: 'GridstackController',
|
|
||||||
require: '^gridstack',
|
|
||||||
scope: {
|
|
||||||
gridstackItem: '=',
|
|
||||||
onItemAdded: '&',
|
|
||||||
onItemRemoved: '&',
|
|
||||||
gsItemId: '=',
|
|
||||||
gsItemX: '=',
|
|
||||||
gsItemY: '=',
|
|
||||||
gsItemWidth: '=',
|
|
||||||
gsItemHeight: '=',
|
|
||||||
gsItemAutopos: '='
|
|
||||||
},
|
|
||||||
link: function (scope, element, attrs, controller) {
|
|
||||||
$(element).attr('data-gs-id', scope.gsItemId);
|
|
||||||
$(element).attr('data-gs-x', scope.gsItemX);
|
|
||||||
$(element).attr('data-gs-y', scope.gsItemY);
|
|
||||||
$(element).attr('data-gs-width', scope.gsItemWidth);
|
|
||||||
$(element).attr('data-gs-height', scope.gsItemHeight);
|
|
||||||
$(element).attr('data-gs-auto-position', scope.gsItemAutopos);
|
|
||||||
var widget = controller.addItem(element);
|
|
||||||
var item = element.data('_gridstack_node');
|
|
||||||
$timeout(function() {
|
|
||||||
scope.onItemAdded({item: item});
|
|
||||||
});
|
|
||||||
scope.$watch(function () { return $(element).attr('data-gs-id'); }, function (val) {
|
|
||||||
scope.gsItemId = val;
|
|
||||||
});
|
|
||||||
scope.$watch(function(){ return $(element).attr('data-gs-x'); }, function(val) {
|
|
||||||
scope.gsItemX = val;
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.$watch(function(){ return $(element).attr('data-gs-y'); }, function(val) {
|
|
||||||
scope.gsItemY = val;
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.$watch(function(){ return $(element).attr('data-gs-width'); }, function(val) {
|
|
||||||
scope.gsItemWidth = val;
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.$watch(function(){ return $(element).attr('data-gs-height'); }, function(val) {
|
|
||||||
scope.gsItemHeight = val;
|
|
||||||
});
|
|
||||||
|
|
||||||
element.bind('$destroy', function() {
|
|
||||||
var item = element.data('_gridstack_node');
|
|
||||||
scope.onItemRemoved({item: item});
|
|
||||||
controller.removeItem(element);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}]);
|
|
||||||
|
|
||||||
coreModule.directive('dashGrid', dashGrid);
|
|
||||||
Contact GitHub API Training Shop Blog About
|
|
||||||
© 2017 GitHub, Inc. Terms Privacy Security Status Help
|
|
@ -69,8 +69,7 @@ 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.panels = _.map(data.panels || [], panelData => new PanelModel(panelData));
|
||||||
this.rows = [];
|
|
||||||
|
|
||||||
this.addBuiltInAnnotationQuery();
|
this.addBuiltInAnnotationQuery();
|
||||||
this.initMeta(meta);
|
this.initMeta(meta);
|
||||||
@ -123,34 +122,32 @@ export class DashboardModel {
|
|||||||
// temp remove stuff
|
// temp remove stuff
|
||||||
var events = this.events;
|
var events = this.events;
|
||||||
var meta = this.meta;
|
var meta = this.meta;
|
||||||
var rows = this.rows;
|
|
||||||
var variables = this.templating.list;
|
var variables = this.templating.list;
|
||||||
|
var panels = this.panels;
|
||||||
|
|
||||||
delete this.events;
|
delete this.events;
|
||||||
delete this.meta;
|
delete this.meta;
|
||||||
|
delete this.panels;
|
||||||
|
|
||||||
// prepare save model
|
// prepare save model
|
||||||
this.rows = _.map(rows, row => row.getSaveModel());
|
|
||||||
this.templating.list = _.map(variables, variable => variable.getSaveModel ? variable.getSaveModel() : variable);
|
this.templating.list = _.map(variables, variable => variable.getSaveModel ? variable.getSaveModel() : variable);
|
||||||
|
this.panels = _.map(panels, panel => panel.getSaveModel());
|
||||||
|
|
||||||
// make clone
|
// make clone
|
||||||
var copy = $.extend(true, {}, this);
|
var copy = $.extend(true, {}, this);
|
||||||
// sort clone
|
// sort clone
|
||||||
copy = sortByKeys(copy);
|
copy = sortByKeys(copy);
|
||||||
|
console.log(copy.panels);
|
||||||
|
|
||||||
// restore properties
|
// restore properties
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
this.rows = rows;
|
|
||||||
this.templating.list = variables;
|
this.templating.list = variables;
|
||||||
|
this.panels = panels;
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
addEmptyRow() {
|
|
||||||
this.rows.push(new DashboardRow({isNew: true}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private ensureListExist(data) {
|
private ensureListExist(data) {
|
||||||
if (!data) { data = {}; }
|
if (!data) { data = {}; }
|
||||||
if (!data.list) { data.list = []; }
|
if (!data.list) { data.list = []; }
|
||||||
@ -327,7 +324,7 @@ export class DashboardModel {
|
|||||||
var i, j, k;
|
var i, j, k;
|
||||||
var oldVersion = this.schemaVersion;
|
var oldVersion = this.schemaVersion;
|
||||||
var panelUpgrades = [];
|
var panelUpgrades = [];
|
||||||
this.schemaVersion = 15;
|
this.schemaVersion = 16;
|
||||||
|
|
||||||
if (oldVersion === this.schemaVersion) {
|
if (oldVersion === this.schemaVersion) {
|
||||||
return;
|
return;
|
||||||
@ -636,7 +633,7 @@ export class DashboardModel {
|
|||||||
this.graphTooltip = old.sharedCrosshair ? 1 : 0;
|
this.graphTooltip = old.sharedCrosshair ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldVersion < 15) {
|
if (oldVersion < 16) {
|
||||||
this.upgradeToGridLayout(old);
|
this.upgradeToGridLayout(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,60 +641,54 @@ export class DashboardModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < this.rows.length; i++) {
|
for (j = 0; j < this.panels.length; j++) {
|
||||||
var row = this.rows[i];
|
for (k = 0; k < panelUpgrades.length; k++) {
|
||||||
for (j = 0; j < row.panels.length; j++) {
|
panelUpgrades[k].call(this, this.panels[j]);
|
||||||
for (k = 0; k < panelUpgrades.length; k++) {
|
|
||||||
panelUpgrades[k].call(this, row.panels[j]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
upgradeToGridLayout(old) {
|
upgradeToGridLayout(old) {
|
||||||
let yPos = 0;
|
let yPos = 0;
|
||||||
let rowIds = 1000;
|
//let rowIds = 1000;
|
||||||
|
|
||||||
for (let row of old.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) {
|
// if (this.meta.keepRows) {
|
||||||
this.panels.push({
|
// this.panels.push({
|
||||||
id: rowIds++,
|
// id: rowIds++,
|
||||||
type: 'row',
|
// type: 'row',
|
||||||
title: row.title,
|
// title: row.title,
|
||||||
x: 0,
|
// x: 0,
|
||||||
y: yPos,
|
// y: yPos,
|
||||||
height: 1,
|
// height: 1,
|
||||||
width: 12
|
// width: 12
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
yPos += 1;
|
// yPos += 1;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (_.isString(height)) {
|
if (_.isString(height)) {
|
||||||
height = parseInt(height.replace('px', ''), 10);
|
height = parseInt(height.replace('px', ''), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
height = Math.ceil(height / CELL_HEIGHT);
|
const rowGridHeight = Math.ceil(height / CELL_HEIGHT);
|
||||||
|
|
||||||
for (let panel of row.panels) {
|
for (let panel of row.panels) {
|
||||||
// should wrap to next row?
|
// should wrap to next row?
|
||||||
if (xPos + panel.span >= 12) {
|
if (xPos + panel.span >= 12) {
|
||||||
yPos += height;
|
yPos += rowGridHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.x = xPos;
|
panel.gridPos = { x: xPos, y: yPos, w: panel.span, h: rowGridHeight };
|
||||||
panel.y = yPos;
|
|
||||||
panel.width = panel.span;
|
|
||||||
panel.height = height;
|
|
||||||
|
|
||||||
delete panel.span;
|
delete panel.span;
|
||||||
|
|
||||||
xPos += panel.width;
|
xPos += rowGridHeight;
|
||||||
|
|
||||||
this.panels.push(panel);
|
this.panels.push(new PanelModel(panel));
|
||||||
}
|
}
|
||||||
|
|
||||||
yPos += height;
|
yPos += height;
|
||||||
|
@ -55,11 +55,9 @@ export class SaveDashboardAsModalCtrl {
|
|||||||
// remove alerts if source dashboard is already persisted
|
// remove alerts if source dashboard is already persisted
|
||||||
// do not want to create alert dupes
|
// do not want to create alert dupes
|
||||||
if (dashboard.id > 0) {
|
if (dashboard.id > 0) {
|
||||||
this.clone.rows.forEach(row => {
|
this.clone.panels.forEach(panel => {
|
||||||
row.panels.forEach(panel => {
|
delete panel.thresholds;
|
||||||
delete panel.thresholds;
|
delete panel.alert;
|
||||||
delete panel.alert;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export class PanelCtrl {
|
|||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$timeout = $injector.get('$timeout');
|
this.$timeout = $injector.get('$timeout');
|
||||||
this.editorTabIndex = 0;
|
this.editorTabIndex = 0;
|
||||||
this.events = new Emitter();
|
this.events = this.panel.events;
|
||||||
this.timing = {};
|
this.timing = {};
|
||||||
|
|
||||||
var plugin = config.panels[this.panel.type];
|
var plugin = config.panels[this.panel.type];
|
||||||
@ -47,21 +47,14 @@ export class PanelCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$scope.$on("refresh", () => this.refresh());
|
$scope.$on("refresh", () => this.refresh());
|
||||||
$scope.$on("render", () => this.render());
|
|
||||||
$scope.$on("$destroy", () => {
|
$scope.$on("$destroy", () => {
|
||||||
this.events.emit('panel-teardown');
|
this.events.emit('panel-teardown');
|
||||||
this.events.removeAllListeners();
|
this.events.removeAllListeners();
|
||||||
});
|
});
|
||||||
|
|
||||||
// we should do something interesting
|
|
||||||
// with newly added panels
|
|
||||||
if (this.panel.isNew) {
|
|
||||||
delete this.panel.isNew;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.calculatePanelHeight();
|
this.events.on('panel-size-changed', this.onSizeChanged.bind(this));
|
||||||
this.publishAppEvent('panel-initialized', {scope: this.$scope});
|
this.publishAppEvent('panel-initialized', {scope: this.$scope});
|
||||||
this.events.emit('panel-initialized');
|
this.events.emit('panel-initialized');
|
||||||
}
|
}
|
||||||
@ -71,7 +64,7 @@ export class PanelCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
this.events.emit('refresh', null);
|
this.events.emit('refresh', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
publishAppEvent(evtName, evt) {
|
publishAppEvent(evtName, evt) {
|
||||||
@ -170,23 +163,24 @@ export class PanelCtrl {
|
|||||||
var fullscreenHeight = Math.floor(docHeight * 0.8);
|
var fullscreenHeight = Math.floor(docHeight * 0.8);
|
||||||
this.containerHeight = this.editMode ? editHeight : fullscreenHeight;
|
this.containerHeight = this.editMode ? editHeight : fullscreenHeight;
|
||||||
} else {
|
} else {
|
||||||
this.containerHeight = this.panel.height * CELL_HEIGHT + ((this.panel.height-1) * CELL_VMARGIN);
|
this.containerHeight = this.panel.gridPos.h * CELL_HEIGHT + ((this.panel.gridPos.h-1) * CELL_VMARGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.height = this.containerHeight - (PANEL_BORDER + PANEL_PADDING + (this.panel.title ? TITLE_HEIGHT : EMPTY_TITLE_HEIGHT));
|
this.height = this.containerHeight - (PANEL_BORDER + PANEL_PADDING + (this.panel.title ? TITLE_HEIGHT : EMPTY_TITLE_HEIGHT));
|
||||||
}
|
}
|
||||||
|
|
||||||
render(payload?) {
|
render(payload?) {
|
||||||
// ignore if other panel is in fullscreen mode
|
|
||||||
if (this.otherPanelInFullscreenMode()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.calculatePanelHeight();
|
|
||||||
this.timing.renderStart = new Date().getTime();
|
this.timing.renderStart = new Date().getTime();
|
||||||
this.events.emit('render', payload);
|
this.events.emit('render', payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onSizeChanged() {
|
||||||
|
this.calculatePanelHeight();
|
||||||
|
this.$timeout(() => {
|
||||||
|
this.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
duplicate() {
|
duplicate() {
|
||||||
this.dashboard.duplicatePanel(this.panel);
|
this.dashboard.duplicatePanel(this.panel);
|
||||||
this.$timeout(() => {
|
this.$timeout(() => {
|
||||||
|
@ -98,6 +98,7 @@ module.directive('grafanaPanel', function($rootScope, $document) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctrl.events.on('render', () => {
|
ctrl.events.on('render', () => {
|
||||||
|
console.log('panelDirective::render!');
|
||||||
if (lastHeight !== ctrl.containerHeight) {
|
if (lastHeight !== ctrl.containerHeight) {
|
||||||
panelContainer.css({minHeight: ctrl.containerHeight});
|
panelContainer.css({minHeight: ctrl.containerHeight});
|
||||||
lastHeight = ctrl.containerHeight;
|
lastHeight = ctrl.containerHeight;
|
||||||
|
@ -88,7 +88,7 @@ function panelHeader($compile) {
|
|||||||
let menuScope;
|
let menuScope;
|
||||||
|
|
||||||
elem.click(function(evt) {
|
elem.click(function(evt) {
|
||||||
const targetClass = evt.target.className;
|
//const targetClass = evt.target.className;
|
||||||
|
|
||||||
// remove existing scope
|
// remove existing scope
|
||||||
if (menuScope) {
|
if (menuScope) {
|
||||||
@ -100,10 +100,10 @@ function panelHeader($compile) {
|
|||||||
menuElem.html(menuHtml);
|
menuElem.html(menuHtml);
|
||||||
$compile(menuElem)(menuScope);
|
$compile(menuElem)(menuScope);
|
||||||
|
|
||||||
if (targetClass === 'panel-title-text' || targetClass === 'panel-title') {
|
// if (targetClass === 'panel-title-text' || targetClass === 'panel-title') {
|
||||||
evt.stopPropagation();
|
// evt.stopPropagation();
|
||||||
elem.find('[data-toggle=dropdown]').dropdown('toggle');
|
// elem.find('[data-toggle=dropdown]').dropdown('toggle');
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -54,6 +54,7 @@ function graphDirective($rootScope, timeSrv, popoverSrv, contextSrv) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ctrl.events.on('render', function(renderData) {
|
ctrl.events.on('render', function(renderData) {
|
||||||
|
console.log('graph render');
|
||||||
data = renderData || data;
|
data = renderData || data;
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
{
|
{
|
||||||
"content": "<div class=\"text-center dashboard-header\">\n <span>Home Dashboard</span>\n</div>",
|
"content": "<div class=\"text-center dashboard-header\">\n <span>Home Dashboard</span>\n</div>",
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"height": 2,
|
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"mode": "html",
|
"mode": "html",
|
||||||
@ -21,14 +20,16 @@
|
|||||||
"title": "",
|
"title": "",
|
||||||
"transparent": true,
|
"transparent": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"width": 12,
|
"gridPos": {
|
||||||
"x": 0,
|
"w": 12,
|
||||||
"y": 0
|
"h": 2,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"folderId": 0,
|
"folderId": 0,
|
||||||
"headings": true,
|
"headings": true,
|
||||||
"height": 17,
|
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"limit": 4,
|
"limit": 4,
|
||||||
"links": [],
|
"links": [],
|
||||||
@ -40,22 +41,27 @@
|
|||||||
"title": "",
|
"title": "",
|
||||||
"transparent": false,
|
"transparent": false,
|
||||||
"type": "dashlist",
|
"type": "dashlist",
|
||||||
"width": 7,
|
"gridPos": {
|
||||||
"x": 0,
|
"w": 7,
|
||||||
"y": 6
|
"h": 17,
|
||||||
|
"x": 0,
|
||||||
|
"y": 6
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"error": false,
|
"error": false,
|
||||||
"height": 17,
|
|
||||||
"id": 4,
|
"id": 4,
|
||||||
"links": [],
|
"links": [],
|
||||||
"title": "",
|
"title": "",
|
||||||
"transparent": false,
|
"transparent": false,
|
||||||
"type": "pluginlist",
|
"type": "pluginlist",
|
||||||
"width": 5,
|
"gridPos": {
|
||||||
"x": 7,
|
"w": 5,
|
||||||
"y": 6
|
"h": 17,
|
||||||
|
"x": 7,
|
||||||
|
"y": 6
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rows": [],
|
"rows": [],
|
||||||
|
Loading…
Reference in New Issue
Block a user