refactor(): dashboard row model and hunting down memory leak
This commit is contained in:
@@ -44,8 +44,9 @@ export function infoPopover() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.$on('$destroy', function() {
|
var unbind = scope.$on('$destroy', function() {
|
||||||
drop.destroy();
|
drop.destroy();
|
||||||
|
unbind();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ import './filters/filters';
|
|||||||
import coreModule from './core_module';
|
import coreModule from './core_module';
|
||||||
import appEvents from './app_events';
|
import appEvents from './app_events';
|
||||||
import colors from './utils/colors';
|
import colors from './utils/colors';
|
||||||
|
import {assignModelProperties} from './utils/model_utils';
|
||||||
|
import {contextSrv} from './services/context_srv';
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -62,4 +64,6 @@ export {
|
|||||||
queryPartEditorDirective,
|
queryPartEditorDirective,
|
||||||
WizardFlow,
|
WizardFlow,
|
||||||
colors,
|
colors,
|
||||||
|
assignModelProperties,
|
||||||
|
contextSrv,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,12 +23,17 @@ export class Emitter {
|
|||||||
this.emitter.on(name, handler);
|
this.emitter.on(name, handler);
|
||||||
|
|
||||||
if (scope) {
|
if (scope) {
|
||||||
scope.$on('$destroy', () => {
|
var unbind = scope.$on('$destroy', () => {
|
||||||
this.emitter.off(name, handler);
|
this.emitter.off(name, handler);
|
||||||
|
unbind();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeAllListeners(evt?) {
|
||||||
|
this.emitter.removeAllListeners(evt);
|
||||||
|
}
|
||||||
|
|
||||||
off(name, handler) {
|
off(name, handler) {
|
||||||
this.emitter.off(name, handler);
|
this.emitter.off(name, handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
export function assignModelProperties(target, source, defaults) {
|
||||||
|
for (var key in defaults) {
|
||||||
|
if (!defaults.hasOwnProperty(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
target[key] = source[key] === undefined ? defaults[key] : source[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -52,11 +52,12 @@ export class AlertTabCtrl {
|
|||||||
var thresholdChangedEventHandler = this.graphThresholdChanged.bind(this);
|
var thresholdChangedEventHandler = this.graphThresholdChanged.bind(this);
|
||||||
this.panelCtrl.events.on('threshold-changed', thresholdChangedEventHandler);
|
this.panelCtrl.events.on('threshold-changed', thresholdChangedEventHandler);
|
||||||
|
|
||||||
// set panel alert edit mode
|
// set panel alert edit mode
|
||||||
this.$scope.$on("$destroy", () => {
|
var unbind = this.$scope.$on("$destroy", () => {
|
||||||
this.panelCtrl.events.off("threshold-changed", thresholdChangedEventHandler);
|
this.panelCtrl.events.off("threshold-changed", thresholdChangedEventHandler);
|
||||||
this.panelCtrl.editingThresholds = false;
|
this.panelCtrl.editingThresholds = false;
|
||||||
this.panelCtrl.render();
|
this.panelCtrl.render();
|
||||||
|
unbind();
|
||||||
});
|
});
|
||||||
|
|
||||||
// build notification model
|
// build notification model
|
||||||
|
|||||||
@@ -102,12 +102,7 @@ export class DashboardCtrl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.addRowDefault = function() {
|
$scope.addRowDefault = function() {
|
||||||
$scope.dashboard.rows.push({
|
$scope.dashboard.addEmptyRow();
|
||||||
title: 'New row',
|
|
||||||
panels: [],
|
|
||||||
height: '250px',
|
|
||||||
isNew: true,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.showJsonEditor = function(evt, options) {
|
$scope.showJsonEditor = function(evt, options) {
|
||||||
@@ -122,8 +117,9 @@ export class DashboardCtrl {
|
|||||||
$timeout.cancel(resizeEventTimeout);
|
$timeout.cancel(resizeEventTimeout);
|
||||||
resizeEventTimeout = $timeout(function() { $scope.$broadcast('render'); }, 200);
|
resizeEventTimeout = $timeout(function() { $scope.$broadcast('render'); }, 200);
|
||||||
});
|
});
|
||||||
$scope.$on('$destroy', function() {
|
var unbind = $scope.$on('$destroy', function() {
|
||||||
angular.element(window).unbind('resize');
|
angular.element(window).unbind('resize');
|
||||||
|
unbind();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ function(angular, $) {
|
|||||||
|
|
||||||
this.shortcuts = function(scope) {
|
this.shortcuts = function(scope) {
|
||||||
|
|
||||||
scope.$on('$destroy', function() {
|
var unbindDestroy = scope.$on('$destroy', function() {
|
||||||
keyboardManager.unbindAll();
|
keyboardManager.unbindAll();
|
||||||
|
unbindDestroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
var helpModalScope = null;
|
var helpModalScope = null;
|
||||||
@@ -28,7 +29,11 @@ function(angular, $) {
|
|||||||
keyboard: false
|
keyboard: false
|
||||||
});
|
});
|
||||||
|
|
||||||
helpModalScope.$on('$destroy', function() { helpModalScope = null; });
|
var unbindModalDestroy = helpModalScope.$on('$destroy', function() {
|
||||||
|
helpModalScope = null;
|
||||||
|
unbindModalDestroy();
|
||||||
|
});
|
||||||
|
|
||||||
$q.when(helpModal).then(function(modalEl) { modalEl.modal('show'); });
|
$q.when(helpModal).then(function(modalEl) { modalEl.modal('show'); });
|
||||||
|
|
||||||
}, { inputDisabled: true });
|
}, { inputDisabled: true });
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import moment from 'moment';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
import {Emitter} from 'app/core/core';
|
import {Emitter, contextSrv} from 'app/core/core';
|
||||||
import {contextSrv} from 'app/core/services/context_srv';
|
import {DashboardRow} from './row/row_model';
|
||||||
|
|
||||||
export class DashboardModel {
|
export class DashboardModel {
|
||||||
id: any;
|
id: any;
|
||||||
@@ -19,7 +19,7 @@ export class DashboardModel {
|
|||||||
timezone: any;
|
timezone: any;
|
||||||
editable: any;
|
editable: any;
|
||||||
sharedCrosshair: any;
|
sharedCrosshair: any;
|
||||||
rows: any;
|
rows: DashboardRow[];
|
||||||
time: any;
|
time: any;
|
||||||
timepicker: any;
|
timepicker: any;
|
||||||
templating: any;
|
templating: any;
|
||||||
@@ -51,7 +51,6 @@ export class DashboardModel {
|
|||||||
this.timezone = data.timezone || '';
|
this.timezone = data.timezone || '';
|
||||||
this.editable = data.editable !== false;
|
this.editable = data.editable !== false;
|
||||||
this.sharedCrosshair = data.sharedCrosshair || false;
|
this.sharedCrosshair = data.sharedCrosshair || false;
|
||||||
this.rows = data.rows || [];
|
|
||||||
this.time = data.time || { from: 'now-6h', to: 'now' };
|
this.time = data.time || { from: 'now-6h', to: 'now' };
|
||||||
this.timepicker = data.timepicker || {};
|
this.timepicker = data.timepicker || {};
|
||||||
this.templating = this.ensureListExist(data.templating);
|
this.templating = this.ensureListExist(data.templating);
|
||||||
@@ -63,10 +62,15 @@ export class DashboardModel {
|
|||||||
this.links = data.links || [];
|
this.links = data.links || [];
|
||||||
this.gnetId = data.gnetId || null;
|
this.gnetId = data.gnetId || null;
|
||||||
|
|
||||||
|
this.rows = [];
|
||||||
|
if (data.rows) {
|
||||||
|
for (let row of data.rows) {
|
||||||
|
this.rows.push(new DashboardRow(row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.updateSchema(data);
|
this.updateSchema(data);
|
||||||
this.initMeta(meta);
|
this.initMeta(meta);
|
||||||
|
|
||||||
this.editMode = this.meta.isNew;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private initMeta(meta) {
|
private initMeta(meta) {
|
||||||
@@ -84,6 +88,7 @@ export class DashboardModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
|
this.editMode = this.meta.isNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleans meta data and other non peristent state
|
// cleans meta data and other non peristent state
|
||||||
@@ -91,18 +96,27 @@ 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;
|
||||||
delete this.events;
|
delete this.events;
|
||||||
delete this.meta;
|
delete this.meta;
|
||||||
|
|
||||||
|
// prepare save model
|
||||||
|
this.rows = _.map(this.rows, row => row.getSaveModel());
|
||||||
events.emit('prepare-save-model');
|
events.emit('prepare-save-model');
|
||||||
|
|
||||||
var copy = $.extend(true, {}, this);
|
var copy = $.extend(true, {}, this);
|
||||||
|
|
||||||
// restore properties
|
// restore properties
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
|
this.rows = rows;
|
||||||
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 = []; }
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export class DashRowCtrl {
|
|||||||
constructor(private $scope, private $rootScope, private $timeout, private uiSegmentSrv, private $q) {
|
constructor(private $scope, private $rootScope, private $timeout, private uiSegmentSrv, private $q) {
|
||||||
this.row.title = this.row.title || 'Row title';
|
this.row.title = this.row.title || 'Row title';
|
||||||
|
|
||||||
if (this.dashboard.meta.isNew) {
|
if (this.row.isNew) {
|
||||||
this.dropView = 1;
|
this.dropView = 1;
|
||||||
delete this.row.isNew;
|
delete this.row.isNew;
|
||||||
}
|
}
|
||||||
@@ -200,13 +200,19 @@ coreModule.directive('panelDropZone', function($timeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (indrag === true) {
|
if (indrag === true) {
|
||||||
return showPanel(dropZoneSpan, 'Drop Here');
|
var dropZoneSpan = 12 - scope.ctrl.dashboard.rowSpan(scope.ctrl.row);
|
||||||
|
if (dropZoneSpan > 1) {
|
||||||
|
return showPanel(dropZoneSpan, 'Drop Here');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hidePanel();
|
hidePanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.$watchGroup(['ctrl.row.panels.length', 'ctrl.dashboard.editMode', 'ctrl.row.span'], updateState);
|
row.events.on('panel-added', updateState);
|
||||||
|
row.events.on('span-changed', updateState);
|
||||||
|
|
||||||
|
//scope.$watchGroup(['ctrl.row.panels.length', 'ctrl.dashboard.editMode', 'ctrl.row.span'], updateState);
|
||||||
|
|
||||||
scope.$on("ANGULAR_DRAG_START", function() {
|
scope.$on("ANGULAR_DRAG_START", function() {
|
||||||
indrag = true;
|
indrag = true;
|
||||||
@@ -220,6 +226,7 @@ coreModule.directive('panelDropZone', function($timeout) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
scope.$on("ANGULAR_DRAG_END", function() {
|
scope.$on("ANGULAR_DRAG_END", function() {
|
||||||
|
console.log('drag end');
|
||||||
indrag = false;
|
indrag = false;
|
||||||
updateState();
|
updateState();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
///<reference path="../../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
import $ from 'jquery';
|
||||||
|
import angular from 'angular';
|
||||||
|
|
||||||
|
import config from 'app/core/config';
|
||||||
|
import {coreModule} from 'app/core/core';
|
||||||
|
|
||||||
|
import './options';
|
||||||
|
import './add_panel';
|
||||||
|
|
||||||
|
export class DashRowCtrl {
|
||||||
|
dashboard: any;
|
||||||
|
row: any;
|
||||||
|
dropView: number;
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
constructor(private $scope, private $rootScope, private $timeout, private uiSegmentSrv, private $q) {
|
||||||
|
this.row.title = this.row.title || 'Row title';
|
||||||
|
|
||||||
|
if (this.dashboard.meta.isNew) {
|
||||||
|
this.dropView = 1;
|
||||||
|
delete this.row.isNew;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDrop(panelId, dropTarget) {
|
||||||
|
var info = this.dashboard.getPanelInfoById(panelId);
|
||||||
|
if (dropTarget) {
|
||||||
|
var dropInfo = this.dashboard.getPanelInfoById(dropTarget.id);
|
||||||
|
dropInfo.row.panels[dropInfo.index] = info.panel;
|
||||||
|
info.row.panels[info.index] = dropTarget;
|
||||||
|
var dragSpan = info.panel.span;
|
||||||
|
info.panel.span = dropTarget.span;
|
||||||
|
dropTarget.span = dragSpan;
|
||||||
|
} else {
|
||||||
|
info.row.panels.splice(info.index, 1);
|
||||||
|
info.panel.span = 12 - this.dashboard.rowSpan(this.row);
|
||||||
|
this.row.panels.push(info.panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
switch (direction) {
|
||||||
|
case 'up': {
|
||||||
|
newIndex = rowIndex - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'down': {
|
||||||
|
newIndex = rowIndex + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'top': {
|
||||||
|
newIndex = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'bottom': {
|
||||||
|
newIndex = rowsList.length - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
newIndex = rowIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newIndex >= 0 && newIndex <= (rowsList.length - 1)) {
|
||||||
|
_.move(rowsList, rowIndex, newIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCollapse() {
|
||||||
|
this.dropView = 0;
|
||||||
|
this.row.collapse = !this.row.collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
showAddPanel() {
|
||||||
|
this.row.collapse = false;
|
||||||
|
this.dropView = this.dropView === 1 ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
showRowOptions() {
|
||||||
|
this.dropView = this.dropView === 2 ? 0 : 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rowDirective($rootScope) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
templateUrl: 'public/app/features/dashboard/row/row.html',
|
||||||
|
controller: DashRowCtrl,
|
||||||
|
bindToController: true,
|
||||||
|
controllerAs: 'ctrl',
|
||||||
|
scope: {
|
||||||
|
dashboard: "=",
|
||||||
|
row: "=",
|
||||||
|
},
|
||||||
|
link: function(scope, element) {
|
||||||
|
scope.$watchGroup(['ctrl.row.collapse', 'ctrl.row.height'], function() {
|
||||||
|
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('dashRow', rowDirective);
|
||||||
|
|
||||||
|
|
||||||
|
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 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();
|
||||||
|
// element.removeClass('panel-drop-zone--empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateState() {
|
||||||
|
if (scope.ctrl.dashboard.editMode) {
|
||||||
|
if (row.panels.length === 0 && indrag === false) {
|
||||||
|
return showPanel(12, 'Empty Space');
|
||||||
|
}
|
||||||
|
|
||||||
|
var dropZoneSpan = 12 - scope.ctrl.dashboard.rowSpan(scope.ctrl.row);
|
||||||
|
if (dropZoneSpan > 1) {
|
||||||
|
if (indrag) {
|
||||||
|
return showPanel(dropZoneSpan, 'Drop Here');
|
||||||
|
} else {
|
||||||
|
return showPanel(dropZoneSpan, 'Empty Space');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indrag === true) {
|
||||||
|
return showPanel(dropZoneSpan, 'Drop Here');
|
||||||
|
}
|
||||||
|
|
||||||
|
hidePanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.row.events.on('panel-added', updateState);
|
||||||
|
scope.row.events.on('span-changed', updateState);
|
||||||
|
|
||||||
|
scope.$watchGroup(['ctrl.row.panels.length', 'ctrl.dashboard.editMode', 'ctrl.row.span'], updateState);
|
||||||
|
|
||||||
|
scope.$on("ANGULAR_DRAG_START", function() {
|
||||||
|
indrag = true;
|
||||||
|
updateState();
|
||||||
|
// $timeout(function() {
|
||||||
|
// var dropZoneSpan = 12 - scope.ctrl.dashboard.rowSpan(scope.ctrl.row);
|
||||||
|
// if (dropZoneSpan > 0) {
|
||||||
|
// showPanel(dropZoneSpan, 'Panel Drop Zone');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
});
|
||||||
|
|
||||||
|
scope.$on("ANGULAR_DRAG_END", function() {
|
||||||
|
indrag = false;
|
||||||
|
updateState();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
///<reference path="../../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import {Emitter, contextSrv} from 'app/core/core';
|
||||||
|
import {assignModelProperties} from 'app/core/core';
|
||||||
|
|
||||||
|
export class DashboardRow {
|
||||||
|
panels: any;
|
||||||
|
title: any;
|
||||||
|
showTitle: any;
|
||||||
|
titleSize: any;
|
||||||
|
events: Emitter;
|
||||||
|
|
||||||
|
defaults = {
|
||||||
|
title: 'Dashboard Row',
|
||||||
|
panels: [],
|
||||||
|
showTitle: false,
|
||||||
|
titleSize: 'h6',
|
||||||
|
height: 250,
|
||||||
|
isNew: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(private model) {
|
||||||
|
assignModelProperties(this, model, this.defaults);
|
||||||
|
this.events = new Emitter();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSaveModel() {
|
||||||
|
assignModelProperties(this.model, this, this.defaults);
|
||||||
|
return this.model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -65,6 +65,7 @@ function(angular, _) {
|
|||||||
dash.time = 0;
|
dash.time = 0;
|
||||||
dash.refresh = 0;
|
dash.refresh = 0;
|
||||||
dash.schemaVersion = 0;
|
dash.schemaVersion = 0;
|
||||||
|
dash.editMode = false;
|
||||||
|
|
||||||
// filter row and panels properties that should be ignored
|
// filter row and panels properties that should be ignored
|
||||||
dash.rows = _.filter(dash.rows, function(row) {
|
dash.rows = _.filter(dash.rows, function(row) {
|
||||||
|
|||||||
@@ -199,8 +199,9 @@ function (angular, _, $) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panelScope.$on('$destroy', function() {
|
var unbind = panelScope.$on('$destroy', function() {
|
||||||
self.panelScopes = _.without(self.panelScopes, panelScope);
|
self.panelScopes = _.without(self.panelScopes, panelScope);
|
||||||
|
unbind();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,12 @@ export class PanelCtrl {
|
|||||||
|
|
||||||
$scope.$on("refresh", () => this.refresh());
|
$scope.$on("refresh", () => this.refresh());
|
||||||
$scope.$on("render", () => this.render());
|
$scope.$on("render", () => this.render());
|
||||||
$scope.$on("$destroy", () => this.events.emit('panel-teardown'));
|
|
||||||
|
var unbindDestroy = $scope.$on("$destroy", () => {
|
||||||
|
this.events.emit('panel-teardown');
|
||||||
|
this.events.removeAllListeners();
|
||||||
|
unbindDestroy();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ module.directive('grafanaPanel', function() {
|
|||||||
panelContainer.removeClass('panel-alert-state--' + lastAlertState);
|
panelContainer.removeClass('panel-alert-state--' + lastAlertState);
|
||||||
lastAlertState = null;
|
lastAlertState = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.$watchGroup(['ctrl.fullscreen', 'ctrl.containerHeight'], function() {
|
scope.$watchGroup(['ctrl.fullscreen', 'ctrl.containerHeight'], function() {
|
||||||
@@ -189,8 +188,9 @@ module.directive('panelResizer', function($rootScope) {
|
|||||||
|
|
||||||
elem.on('mousedown', dragStartHandler);
|
elem.on('mousedown', dragStartHandler);
|
||||||
|
|
||||||
scope.$on("$destroy", function() {
|
var unbind = scope.$on("$destroy", function() {
|
||||||
elem.off('mousedown', dragStartHandler);
|
elem.off('mousedown', dragStartHandler);
|
||||||
|
unbind();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import kbn from 'app/core/utils/kbn';
|
import kbn from 'app/core/utils/kbn';
|
||||||
|
import {assignModelProperties} from 'app/core/core';
|
||||||
|
|
||||||
export interface Variable {
|
export interface Variable {
|
||||||
setValue(option);
|
setValue(option);
|
||||||
@@ -13,12 +14,9 @@ export interface Variable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export var variableTypes = {};
|
export var variableTypes = {};
|
||||||
|
export {
|
||||||
export function assignModelProperties(target, source, defaults) {
|
assignModelProperties
|
||||||
_.forEach(defaults, function(value, key) {
|
};
|
||||||
target[key] = source[key] === undefined ? value : source[key];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function containsVariable(...args: any[]) {
|
export function containsVariable(...args: any[]) {
|
||||||
var variableName = args[args.length-1];
|
var variableName = args[args.length-1];
|
||||||
|
|||||||
@@ -34,6 +34,16 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
|||||||
var rootScope = scope.$root;
|
var rootScope = scope.$root;
|
||||||
var panelWidth = 0;
|
var panelWidth = 0;
|
||||||
var thresholdManager = new ThresholdManager(ctrl);
|
var thresholdManager = new ThresholdManager(ctrl);
|
||||||
|
var plot;
|
||||||
|
|
||||||
|
ctrl.events.on('panel-teardown', () => {
|
||||||
|
thresholdManager = null;
|
||||||
|
|
||||||
|
if (plot) {
|
||||||
|
plot.destroy();
|
||||||
|
plot = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
rootScope.onAppEvent('setCrosshair', function(event, info) {
|
rootScope.onAppEvent('setCrosshair', function(event, info) {
|
||||||
// do not need to to this if event is from this panel
|
// do not need to to this if event is from this panel
|
||||||
@@ -42,7 +52,6 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dashboard.sharedCrosshair) {
|
if (dashboard.sharedCrosshair) {
|
||||||
var plot = elem.data().plot;
|
|
||||||
if (plot) {
|
if (plot) {
|
||||||
plot.setCrosshair({ x: info.pos.x, y: info.pos.y });
|
plot.setCrosshair({ x: info.pos.x, y: info.pos.y });
|
||||||
}
|
}
|
||||||
@@ -50,10 +59,7 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
|||||||
}, scope);
|
}, scope);
|
||||||
|
|
||||||
rootScope.onAppEvent('clearCrosshair', function() {
|
rootScope.onAppEvent('clearCrosshair', function() {
|
||||||
var plot = elem.data().plot;
|
plot.clearCrosshair();
|
||||||
if (plot) {
|
|
||||||
plot.clearCrosshair();
|
|
||||||
}
|
|
||||||
}, scope);
|
}, scope);
|
||||||
|
|
||||||
// Receive render events
|
// Receive render events
|
||||||
@@ -287,7 +293,7 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
|||||||
|
|
||||||
function callPlot(incrementRenderCounter) {
|
function callPlot(incrementRenderCounter) {
|
||||||
try {
|
try {
|
||||||
$.plot(elem, sortedSeries, options);
|
plot = $.plot(elem, sortedSeries, options);
|
||||||
if (ctrl.renderError) {
|
if (ctrl.renderError) {
|
||||||
delete ctrl.error;
|
delete ctrl.error;
|
||||||
delete ctrl.inspector;
|
delete ctrl.inspector;
|
||||||
@@ -529,9 +535,9 @@ module.directive('grafanaGraph', function($rootScope, timeSrv) {
|
|||||||
return "%H:%M";
|
return "%H:%M";
|
||||||
}
|
}
|
||||||
|
|
||||||
new GraphTooltip(elem, dashboard, scope, function() {
|
// new GraphTooltip(elem, dashboard, scope, function() {
|
||||||
return sortedSeries;
|
// return sortedSeries;
|
||||||
});
|
// });
|
||||||
|
|
||||||
elem.bind("plotselected", function (event, ranges) {
|
elem.bind("plotselected", function (event, ranges) {
|
||||||
scope.$apply(function() {
|
scope.$apply(function() {
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ export class ThresholdManager {
|
|||||||
this.renderHandle(1, this.height-30);
|
this.renderHandle(1, this.height-30);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.placeholder.off('mousedown', '.alert-handle');
|
// this.placeholder.off('mousedown', '.alert-handle');
|
||||||
this.placeholder.on('mousedown', '.alert-handle', this.initDragging.bind(this));
|
// this.placeholder.on('mousedown', '.alert-handle', this.initDragging.bind(this));
|
||||||
this.needsCleanup = true;
|
this.needsCleanup = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ export class ThresholdFormCtrl {
|
|||||||
this.disabled = true;
|
this.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.$on("$destroy", () => {
|
var unbindDestroy = $scope.$on("$destroy", () => {
|
||||||
this.panelCtrl.editingThresholds = false;
|
this.panelCtrl.editingThresholds = false;
|
||||||
this.panelCtrl.render();
|
this.panelCtrl.render();
|
||||||
|
unbindDestroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.panelCtrl.editingThresholds = true;
|
this.panelCtrl.editingThresholds = true;
|
||||||
|
|||||||
@@ -212,8 +212,9 @@ class TablePanelCtrl extends MetricsPanelCtrl {
|
|||||||
|
|
||||||
elem.on('click', '.table-panel-page-link', switchPage);
|
elem.on('click', '.table-panel-page-link', switchPage);
|
||||||
|
|
||||||
scope.$on('$destroy', function() {
|
var unbindDestroy = scope.$on('$destroy', function() {
|
||||||
elem.off('click', '.table-panel-page-link');
|
elem.off('click', '.table-panel-page-link');
|
||||||
|
unbindDestroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
ctrl.events.on('render', function(renderData) {
|
ctrl.events.on('render', function(renderData) {
|
||||||
|
|||||||
Reference in New Issue
Block a user