Skip to content

Commit 4d420a0

Browse files
committed
refactor(): dashboard row model and hunting down memory leak
1 parent 57cbefd commit 4d420a0

File tree

20 files changed

+364
-45
lines changed

20 files changed

+364
-45
lines changed

public/app/core/components/info_popover.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ export function infoPopover() {
4444
}
4545
});
4646

47-
scope.$on('$destroy', function() {
47+
var unbind = scope.$on('$destroy', function() {
4848
drop.destroy();
49+
unbind();
4950
});
5051

5152
});

public/app/core/core.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ import './filters/filters';
4242
import coreModule from './core_module';
4343
import appEvents from './app_events';
4444
import colors from './utils/colors';
45+
import {assignModelProperties} from './utils/model_utils';
46+
import {contextSrv} from './services/context_srv';
4547

4648

4749
export {
@@ -62,4 +64,6 @@ export {
6264
queryPartEditorDirective,
6365
WizardFlow,
6466
colors,
67+
assignModelProperties,
68+
contextSrv,
6569
};

public/app/core/utils/emitter.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,17 @@ export class Emitter {
2323
this.emitter.on(name, handler);
2424

2525
if (scope) {
26-
scope.$on('$destroy', () => {
26+
var unbind = scope.$on('$destroy', () => {
2727
this.emitter.off(name, handler);
28+
unbind();
2829
});
2930
}
3031
}
3132

33+
removeAllListeners(evt?) {
34+
this.emitter.removeAllListeners(evt);
35+
}
36+
3237
off(name, handler) {
3338
this.emitter.off(name, handler);
3439
}

public/app/core/utils/model_utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function assignModelProperties(target, source, defaults) {
2+
for (var key in defaults) {
3+
if (!defaults.hasOwnProperty(key)) {
4+
continue;
5+
}
6+
7+
target[key] = source[key] === undefined ? defaults[key] : source[key];
8+
}
9+
}
10+

public/app/features/alerting/alert_tab_ctrl.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ export class AlertTabCtrl {
5252
var thresholdChangedEventHandler = this.graphThresholdChanged.bind(this);
5353
this.panelCtrl.events.on('threshold-changed', thresholdChangedEventHandler);
5454

55-
// set panel alert edit mode
56-
this.$scope.$on("$destroy", () => {
55+
// set panel alert edit mode
56+
var unbind = this.$scope.$on("$destroy", () => {
5757
this.panelCtrl.events.off("threshold-changed", thresholdChangedEventHandler);
5858
this.panelCtrl.editingThresholds = false;
5959
this.panelCtrl.render();
60+
unbind();
6061
});
6162

6263
// build notification model

public/app/features/dashboard/dashboard_ctrl.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,7 @@ export class DashboardCtrl {
102102
};
103103

104104
$scope.addRowDefault = function() {
105-
$scope.dashboard.rows.push({
106-
title: 'New row',
107-
panels: [],
108-
height: '250px',
109-
isNew: true,
110-
});
105+
$scope.dashboard.addEmptyRow();
111106
};
112107

113108
$scope.showJsonEditor = function(evt, options) {
@@ -122,8 +117,9 @@ export class DashboardCtrl {
122117
$timeout.cancel(resizeEventTimeout);
123118
resizeEventTimeout = $timeout(function() { $scope.$broadcast('render'); }, 200);
124119
});
125-
$scope.$on('$destroy', function() {
120+
var unbind = $scope.$on('$destroy', function() {
126121
angular.element(window).unbind('resize');
122+
unbind();
127123
});
128124
};
129125

public/app/features/dashboard/keybindings.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ function(angular, $) {
1111

1212
this.shortcuts = function(scope) {
1313

14-
scope.$on('$destroy', function() {
14+
var unbindDestroy = scope.$on('$destroy', function() {
1515
keyboardManager.unbindAll();
16+
unbindDestroy();
1617
});
1718

1819
var helpModalScope = null;
@@ -28,7 +29,11 @@ function(angular, $) {
2829
keyboard: false
2930
});
3031

31-
helpModalScope.$on('$destroy', function() { helpModalScope = null; });
32+
var unbindModalDestroy = helpModalScope.$on('$destroy', function() {
33+
helpModalScope = null;
34+
unbindModalDestroy();
35+
});
36+
3237
$q.when(helpModal).then(function(modalEl) { modalEl.modal('show'); });
3338

3439
}, { inputDisabled: true });

public/app/features/dashboard/model.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import moment from 'moment';
66
import _ from 'lodash';
77
import $ from 'jquery';
88

9-
import {Emitter} from 'app/core/core';
10-
import {contextSrv} from 'app/core/services/context_srv';
9+
import {Emitter, contextSrv} from 'app/core/core';
10+
import {DashboardRow} from './row/row_model';
1111

1212
export class DashboardModel {
1313
id: any;
@@ -19,7 +19,7 @@ export class DashboardModel {
1919
timezone: any;
2020
editable: any;
2121
sharedCrosshair: any;
22-
rows: any;
22+
rows: DashboardRow[];
2323
time: any;
2424
timepicker: any;
2525
templating: any;
@@ -51,7 +51,6 @@ export class DashboardModel {
5151
this.timezone = data.timezone || '';
5252
this.editable = data.editable !== false;
5353
this.sharedCrosshair = data.sharedCrosshair || false;
54-
this.rows = data.rows || [];
5554
this.time = data.time || { from: 'now-6h', to: 'now' };
5655
this.timepicker = data.timepicker || {};
5756
this.templating = this.ensureListExist(data.templating);
@@ -63,10 +62,15 @@ export class DashboardModel {
6362
this.links = data.links || [];
6463
this.gnetId = data.gnetId || null;
6564

65+
this.rows = [];
66+
if (data.rows) {
67+
for (let row of data.rows) {
68+
this.rows.push(new DashboardRow(row));
69+
}
70+
}
71+
6672
this.updateSchema(data);
6773
this.initMeta(meta);
68-
69-
this.editMode = this.meta.isNew;
7074
}
7175

7276
private initMeta(meta) {
@@ -84,25 +88,35 @@ export class DashboardModel {
8488
}
8589

8690
this.meta = meta;
91+
this.editMode = this.meta.isNew;
8792
}
8893

8994
// cleans meta data and other non peristent state
9095
getSaveModelClone() {
9196
// temp remove stuff
9297
var events = this.events;
9398
var meta = this.meta;
99+
var rows = this.rows;
94100
delete this.events;
95101
delete this.meta;
96102

103+
// prepare save model
104+
this.rows = _.map(this.rows, row => row.getSaveModel());
97105
events.emit('prepare-save-model');
106+
98107
var copy = $.extend(true, {}, this);
99108

100109
// restore properties
101110
this.events = events;
102111
this.meta = meta;
112+
this.rows = rows;
103113
return copy;
104114
}
105115

116+
addEmptyRow() {
117+
this.rows.push(new DashboardRow({isNew: true}));
118+
}
119+
106120
private ensureListExist(data) {
107121
if (!data) { data = {}; }
108122
if (!data.list) { data.list = []; }

public/app/features/dashboard/row/row.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export class DashRowCtrl {
1919
constructor(private $scope, private $rootScope, private $timeout, private uiSegmentSrv, private $q) {
2020
this.row.title = this.row.title || 'Row title';
2121

22-
if (this.dashboard.meta.isNew) {
22+
if (this.row.isNew) {
2323
this.dropView = 1;
2424
delete this.row.isNew;
2525
}
@@ -200,13 +200,19 @@ coreModule.directive('panelDropZone', function($timeout) {
200200
}
201201

202202
if (indrag === true) {
203-
return showPanel(dropZoneSpan, 'Drop Here');
203+
var dropZoneSpan = 12 - scope.ctrl.dashboard.rowSpan(scope.ctrl.row);
204+
if (dropZoneSpan > 1) {
205+
return showPanel(dropZoneSpan, 'Drop Here');
206+
}
204207
}
205208

206209
hidePanel();
207210
}
208211

209-
scope.$watchGroup(['ctrl.row.panels.length', 'ctrl.dashboard.editMode', 'ctrl.row.span'], updateState);
212+
row.events.on('panel-added', updateState);
213+
row.events.on('span-changed', updateState);
214+
215+
//scope.$watchGroup(['ctrl.row.panels.length', 'ctrl.dashboard.editMode', 'ctrl.row.span'], updateState);
210216

211217
scope.$on("ANGULAR_DRAG_START", function() {
212218
indrag = true;
@@ -220,6 +226,7 @@ coreModule.directive('panelDropZone', function($timeout) {
220226
});
221227

222228
scope.$on("ANGULAR_DRAG_END", function() {
229+
console.log('drag end');
223230
indrag = false;
224231
updateState();
225232
});

0 commit comments

Comments
 (0)