diff --git a/src/app/controllers/row.js b/src/app/controllers/row.js
index 364cf051dac..587c7de42d7 100644
--- a/src/app/controllers/row.js
+++ b/src/app/controllers/row.js
@@ -32,36 +32,13 @@ function (angular, app, _) {
}
};
- $scope.rowSpan = function(row) {
- return _.reduce(row.panels, function(p,v) {
- return p + v.span;
- },0);
- };
-
- // This can be overridden by individual panels
+ // This can be overridden by individual panels
$scope.close_edit = function() {
$scope.$broadcast('render');
};
$scope.add_panel = function(panel) {
- var rowSpan = $scope.rowSpan($scope.row);
- var panelCount = $scope.row.panels.length;
- var space = (12 - rowSpan) - panel.span;
-
- // try to make room of there is no space left
- if (space <= 0) {
- if (panelCount === 1) {
- $scope.row.panels[0].span = 6;
- panel.span = 6;
- }
- else if (panelCount === 2) {
- $scope.row.panels[0].span = 4;
- $scope.row.panels[1].span = 4;
- panel.span = 4;
- }
- }
-
- $scope.row.panels.push(panel);
+ $scope.dashboard.add_panel(panel, $scope.row);
};
$scope.delete_row = function() {
@@ -100,45 +77,17 @@ function (angular, app, _) {
};
$scope.duplicatePanel = function(panel, row) {
- row = row || $scope.row;
- var currentRowSpan = $scope.rowSpan(row);
- if (currentRowSpan <= 9) {
- row.panels.push(angular.copy(panel));
- }
- else {
- var rowsList = $scope.dashboard.rows;
- var rowIndex = _.indexOf(rowsList, row);
- if (rowIndex === rowsList.length - 1) {
- var newRow = angular.copy($scope.row);
- newRow.panels = [];
- $scope.dashboard.rows.push(newRow);
- $scope.duplicatePanel(panel, newRow);
- }
- else {
- $scope.duplicatePanel(panel, rowsList[rowIndex+1]);
- }
- }
+ $scope.dashboard.duplicatePanel(panel, row || $scope.row);
};
$scope.reset_panel = function(type) {
- var
- defaultSpan = 12,
- _as = 12-$scope.rowSpan($scope.row);
+ var defaultSpan = 12;
+ var _as = 12 - $scope.dashboard.rowSpan($scope.row);
$scope.panel = {
error : false,
- /** @scratch /panels/1
- * span:: A number, 1-12, that describes the width of the panel.
- */
span : _as < defaultSpan && _as > 0 ? _as : defaultSpan,
- /** @scratch /panels/1
- * editable:: Enable or disable the edit button the the panel
- */
editable: true,
- /** @scratch /panels/1
- * type:: The type of panel this object contains. Each panel type will require additional
- * properties. See the panel types list to the right.
- */
type : type
};
@@ -155,10 +104,6 @@ function (angular, app, _) {
$scope.row.height = fixRowHeight($scope.row.height);
};
- /** @scratch /panels/2
- * --
- */
-
$scope.init();
});
diff --git a/src/app/partials/dashboard.html b/src/app/partials/dashboard.html
index 013b924c77a..b6a7287f536 100644
--- a/src/app/partials/dashboard.html
+++ b/src/app/partials/dashboard.html
@@ -105,7 +105,7 @@
-
+
diff --git a/src/app/partials/roweditor.html b/src/app/partials/roweditor.html
index 583c664a3cb..eb3bc9258a6 100644
--- a/src/app/partials/roweditor.html
+++ b/src/app/partials/roweditor.html
@@ -27,7 +27,7 @@
Title |
Type |
- Span ({{rowSpan(row)}}/12) |
+ Span ({{dashboard.rowSpan(row)}}/12) |
Delete |
Move |
|
@@ -49,7 +49,7 @@
Select Panel Type
diff --git a/src/app/services/dashboard/dashboardSrv.js b/src/app/services/dashboard/dashboardSrv.js
index 9910f1ebfe8..4f72338dbb1 100644
--- a/src/app/services/dashboard/dashboardSrv.js
+++ b/src/app/services/dashboard/dashboardSrv.js
@@ -49,6 +49,65 @@ function (angular, $, kbn, _) {
var p = DashboardModel.prototype;
+ p.getNextPanelId = function() {
+ var i, j, row, panel, max = 0;
+ for (i = 0; i < this.rows.length; i++) {
+ row = this.rows[i];
+ for (j = 0; j < row.panels.length; j++) {
+ panel = row.panels[j];
+ if (panel.id > max) { max = panel.id; }
+ }
+ }
+ return max + 1;
+ };
+
+ p.rowSpan = function(row) {
+ return _.reduce(row.panels, function(p,v) {
+ return p + v.span;
+ },0);
+ };
+
+ p.add_panel = function(panel, row) {
+ var rowSpan = this.rowSpan(row);
+ var panelCount = row.panels.length;
+ var space = (12 - rowSpan) - panel.span;
+ panel.id = this.getNextPanelId();
+
+ // try to make room of there is no space left
+ if (space <= 0) {
+ if (panelCount === 1) {
+ row.panels[0].span = 6;
+ panel.span = 6;
+ }
+ else if (panelCount === 2) {
+ row.panels[0].span = 4;
+ row.panels[1].span = 4;
+ panel.span = 4;
+ }
+ }
+
+ row.panels.push(panel);
+ };
+
+ p.duplicatePanel = function(panel, row) {
+ var rowIndex = _.indexOf(this.rows, row);
+ var newPanel = angular.copy(panel);
+ newPanel.id = this.getNextPanelId();
+
+ while(rowIndex < this.rows.length) {
+ var currentRow = this.rows[rowIndex];
+ if (this.rowSpan(currentRow) <= 9) {
+ currentRow.panels.push(newPanel);
+ return;
+ }
+ rowIndex++;
+ }
+
+ var newRow = angular.copy(row);
+ newRow.panels = [newPanel];
+ this.rows.push(newRow);
+ };
+
p.emit_refresh = function() {
$rootScope.$broadcast('refresh');
};
@@ -86,13 +145,15 @@ function (angular, $, kbn, _) {
// Version 3 schema changes
// ensure panel ids
- var panelId = 1;
+ var maxId = this.getNextPanelId();
for (i = 0; i < this.rows.length; i++) {
row = this.rows[i];
for (j = 0; j < row.panels.length; j++) {
panel = row.panels[j];
- panel.id = panelId;
- panelId += 1;
+ if (!panel.id) {
+ panel.id = maxId;
+ maxId += 1;
+ }
}
}
diff --git a/src/test/specs/dashboardSrv-specs.js b/src/test/specs/dashboardSrv-specs.js
index 5b09fc1d65a..5e4e96401de 100644
--- a/src/test/specs/dashboardSrv-specs.js
+++ b/src/test/specs/dashboardSrv-specs.js
@@ -7,7 +7,6 @@ define([
var model;
beforeEach(module('grafana.services'));
-
beforeEach(inject(function(dashboardSrv) {
model = dashboardSrv.create({});
}));
@@ -24,12 +23,71 @@ define([
});
+ describe('when getting next panel id', function() {
+ var model;
+
+ beforeEach(module('grafana.services'));
+ beforeEach(inject(function(dashboardSrv) {
+ model = dashboardSrv.create({
+ rows: [{ panels: [{ id: 5 }]}]
+ });
+ }));
+
+ it('should return max id + 1', function() {
+ expect(model.getNextPanelId()).to.be(6);
+ });
+ });
+
+ describe('row and panel manipulation', function() {
+ var dashboard;
+
+ beforeEach(module('grafana.services'));
+ beforeEach(inject(function(dashboardSrv) {
+ dashboard = dashboardSrv.create({});
+ }));
+
+ it('row span should sum spans', function() {
+ var spanLeft = dashboard.rowSpan({ panels: [{ span: 2 }, { span: 3 }] });
+ expect(spanLeft).to.be(5);
+ });
+
+ it('adding default should split span in half', function() {
+ dashboard.rows = [{ panels: [{ span: 12, id: 7 }] }];
+ dashboard.add_panel({span: 4}, dashboard.rows[0]);
+
+ expect(dashboard.rows[0].panels[0].span).to.be(6);
+ expect(dashboard.rows[0].panels[1].span).to.be(6);
+ expect(dashboard.rows[0].panels[1].id).to.be(8);
+ });
+
+ it('duplicate panel should try to add it to same row', function() {
+ var panel = { span: 4, attr: '123', id: 10 };
+ dashboard.rows = [{ panels: [panel] }];
+ dashboard.duplicatePanel(panel, dashboard.rows[0]);
+
+ expect(dashboard.rows[0].panels[0].span).to.be(4);
+ expect(dashboard.rows[0].panels[1].span).to.be(4);
+ expect(dashboard.rows[0].panels[1].attr).to.be('123');
+ expect(dashboard.rows[0].panels[1].id).to.be(11);
+ });
+
+ it('duplicate should add row if there is no space left', function() {
+ var panel = { span: 12, attr: '123' };
+ dashboard.rows = [{ panels: [panel] }];
+ dashboard.duplicatePanel(panel, dashboard.rows[0]);
+
+ expect(dashboard.rows[0].panels[0].span).to.be(12);
+ expect(dashboard.rows[0].panels.length).to.be(1);
+ expect(dashboard.rows[1].panels[0].attr).to.be('123');
+ });
+
+ });
+
describe('when creating dashboard with old schema', function() {
var model;
var graph;
beforeEach(module('grafana.services'));
-
beforeEach(inject(function(dashboardSrv) {
model = dashboardSrv.create({
services: { filter: { time: { from: 'now-1d', to: 'now'}, list: [1] }},
diff --git a/src/test/specs/helpers.js b/src/test/specs/helpers.js
index 465e5344779..cd31779cc99 100644
--- a/src/test/specs/helpers.js
+++ b/src/test/specs/helpers.js
@@ -26,6 +26,7 @@ define([
self.scope.panel = {};
self.scope.row = { panels:[] };
self.scope.filter = new FilterSrvStub();
+ self.scope.dashboard = {};
self.scope.dashboardViewState = new DashboardViewStateStub();
$rootScope.colors = [];
diff --git a/src/test/specs/row-ctrl-specs.js b/src/test/specs/row-ctrl-specs.js
index de149b70fac..41543784f40 100644
--- a/src/test/specs/row-ctrl-specs.js
+++ b/src/test/specs/row-ctrl-specs.js
@@ -12,50 +12,6 @@ define([
beforeEach(ctx.providePhase());
beforeEach(ctx.createControllerPhase('RowCtrl'));
- describe('when getting rowSpan', function() {
- it('should return sum of panels spans', function() {
- var spanLeft = ctx.scope.rowSpan({ panels: [{ span: 2 }, { span: 3 }] });
- expect(spanLeft).to.be(5);
- });
- });
-
- describe('when adding panel to row with 12 span panel', function() {
- it('should split span in half and add panel with defaults', function() {
- ctx.scope.row = { panels: [{ span: 12 }] };
- ctx.scope.add_panel_default('graph');
-
- expect(ctx.scope.row.panels[0].span).to.be(6);
- expect(ctx.scope.row.panels[1].span).to.be(6);
- expect(ctx.scope.row.panels[1].type).to.be('graph');
- });
- });
-
- describe('when duplicating panel', function() {
- it('should try to add it to same row', function() {
- var panel = { span: 4, attr: '123' };
- ctx.scope.row = { panels: [panel] };
- ctx.scope.duplicatePanel(panel, ctx.scope.row);
-
- expect(ctx.scope.row.panels[0].span).to.be(4);
- expect(ctx.scope.row.panels[1].span).to.be(4);
- expect(ctx.scope.row.panels[1].attr).to.be('123');
- });
- });
-
- describe('when duplicating panel', function() {
- it('should add row if there is no space left', function() {
- var panel = { span: 12, attr: '123' };
- ctx.scope.row = { panels: [panel] };
- ctx.scope.dashboard = { rows: [ctx.scope.row] };
-
- ctx.scope.duplicatePanel(panel, ctx.scope.row);
-
- expect(ctx.scope.row.panels[0].span).to.be(12);
- expect(ctx.scope.row.panels.length).to.be(1);
- expect(ctx.scope.dashboard.rows[1].panels[0].attr).to.be('123');
- });
- });
-
});
});