From 937ac84538492571367c71a0513439133b8792a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 18 Aug 2014 21:47:56 +0200 Subject: [PATCH 01/11] Began work on per series style overrides, #425 --- src/app/directives/addGraphiteFunc.js | 2 +- src/app/directives/grafanaGraph.js | 4 ++- src/app/panels/graph/module.js | 48 +++++++++++++++++++++++++++ src/app/panels/graph/styleEditor.html | 39 ++++++++++++++++++++-- src/app/services/panelSrv.js | 2 +- 5 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/app/directives/addGraphiteFunc.js b/src/app/directives/addGraphiteFunc.js index ca5943da508..6898b838845 100644 --- a/src/app/directives/addGraphiteFunc.js +++ b/src/app/directives/addGraphiteFunc.js @@ -97,4 +97,4 @@ function (angular, app, _, $, gfunc) { }; }); } -}); \ No newline at end of file +}); diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index a91967b967b..f0ffd14dd67 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -156,9 +156,11 @@ function (angular, $, kbn, moment, _) { for (var i = 0; i < data.length; i++) { var _d = data[i].getFlotPairs(panel.nullPointMode, panel.y_formats); data[i].data = _d; + data[0].lines = { show: false }; + data[0].bars = { show: true }; } - if (panel.bars && data.length && data[0].info.timeStep) { + if (data.length && data[0].info.timeStep) { options.series.bars.barWidth = data[0].info.timeStep / 1.5; } diff --git a/src/app/panels/graph/module.js b/src/app/panels/graph/module.js index 647e52c257e..d8a31f59312 100644 --- a/src/app/panels/graph/module.js +++ b/src/app/panels/graph/module.js @@ -180,6 +180,8 @@ function (angular, app, $, _, kbn, moment, timeSeries) { aliasColors: {}, aliasYAxis: {}, + + seriesOverrides: [], }; _.defaults($scope.panel,_d); @@ -357,7 +359,53 @@ function (angular, app, $, _, kbn, moment, timeSeries) { $scope.render(); }; + $scope.addSeriesOverride = function() { + $scope.panel.seriesOverrides.push({}); + }; + panelSrv.init($scope); }); + angular + .module('grafana.directives') + .directive('seriesOverrideOption', function($compile) { + var template = + ''; + + return { + scope: true, + link: function($scope, elem, attrs) { + var $template = $(template); + elem.append($template); + var $link = $(elem).find('a'); + + $scope.options = $scope.$eval(attrs.options); + $scope.options.unshift(null); + + $scope.options = _.map($scope.options, function(option, index) { + return { + text: option === null ? '' : String(option), + value: option, + click: 'setValue(' + index + ')' + }; + }); + + $scope.setValue = function(index) { + var value = $scope.options[index].value; + if (value === null) { + $link.html(''); + } + else { + $link.html(value); + } + }; + + $compile(elem.contents())($scope); + } + }; + }); + }); diff --git a/src/app/panels/graph/styleEditor.html b/src/app/panels/graph/styleEditor.html index ec18121cba7..c1b68e25beb 100644 --- a/src/app/panels/graph/styleEditor.html +++ b/src/app/panels/graph/styleEditor.html @@ -1,5 +1,3 @@ - -
Chart Options
@@ -64,3 +62,40 @@
+ +
+
+
Series specific overrides
+ + + + + + + + + + + + + + + + + + + + +
Series alias/regexBarsLinesPointsFillWidthRadiusStaircaseStackY-axisZ-indexColor
+ + + + + + + +
+ + +
+
diff --git a/src/app/services/panelSrv.js b/src/app/services/panelSrv.js index 3c362818f2d..cae4f14ff98 100644 --- a/src/app/services/panelSrv.js +++ b/src/app/services/panelSrv.js @@ -104,7 +104,7 @@ function (angular, _) { // Post init phase $scope.fullscreen = false; - $scope.editor = { index: 1 }; + $scope.editor = { index: 3 }; if ($scope.panelMeta.fullEditorTabs) { $scope.editorTabs = _.pluck($scope.panelMeta.fullEditorTabs, 'title'); } From c6489d9b0112b5a1268b9b8da645f157fae1a85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 19 Aug 2014 10:46:08 +0200 Subject: [PATCH 02/11] Lots of progress on per series overrides --- package.json | 2 +- src/app/directives/grafanaGraph.js | 2 +- src/app/panels/graph/module.html | 2 +- src/app/panels/graph/module.js | 63 ++----------------- src/app/panels/graph/seriesOverridesCtrl.js | 66 ++++++++++++++++++++ src/app/panels/graph/styleEditor.html | 67 +++++++++++--------- src/css/less/graph.less | 14 +++++ src/test/specs/grafanaGraph-specs.js | 68 +++++++++++++++++++++ src/test/specs/helpers.js | 2 +- src/test/specs/seriesOverridesCtrl-specs.js | 40 ++++++++++++ src/test/test-main.js | 2 + 11 files changed, 237 insertions(+), 91 deletions(-) create mode 100644 src/app/panels/graph/seriesOverridesCtrl.js create mode 100644 src/test/specs/grafanaGraph-specs.js create mode 100644 src/test/specs/seriesOverridesCtrl-specs.js diff --git a/package.json b/package.json index 31c552fe6c2..eecf826776e 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "grunt-string-replace": "~0.2.4", "grunt-usemin": "^2.1.1", "jshint-stylish": "~0.1.5", - "karma": "~0.12.16", + "karma": "~0.12.21", "karma-chrome-launcher": "~0.1.4", "karma-coffee-preprocessor": "~0.1.2", "karma-coverage": "^0.2.5", diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index f0ffd14dd67..c2be3d90d13 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -156,7 +156,7 @@ function (angular, $, kbn, moment, _) { for (var i = 0; i < data.length; i++) { var _d = data[i].getFlotPairs(panel.nullPointMode, panel.y_formats); data[i].data = _d; - data[0].lines = { show: false }; + data[0].lines = { show: false, dashes: true }; data[0].bars = { show: true }; } diff --git a/src/app/panels/graph/module.html b/src/app/panels/graph/module.html index 102cad84a40..0d418e5e8cd 100644 --- a/src/app/panels/graph/module.html +++ b/src/app/panels/graph/module.html @@ -27,7 +27,7 @@ -
+
diff --git a/src/app/panels/graph/module.js b/src/app/panels/graph/module.js index d8a31f59312..557503023a1 100644 --- a/src/app/panels/graph/module.js +++ b/src/app/panels/graph/module.js @@ -1,16 +1,3 @@ -/** @scratch /panels/5 - * include::panels/histogram.asciidoc[] - */ - -/** @scratch /panels/histogram/0 - * == Histogram - * Status: *Stable* - * - * The histogram panel allow for the display of time charts. It includes several modes and tranformations - * to display event counts, mean, min, max and total of numeric fields, and derivatives of counter - * fields. - * - */ define([ 'angular', 'app', @@ -19,6 +6,7 @@ define([ 'kbn', 'moment', './timeSeries', + './seriesOverridesCtrl', 'services/panelSrv', 'services/annotationsSrv', 'services/datasourceSrv', @@ -30,10 +18,9 @@ define([ 'jquery.flot.stackpercent' ], function (angular, app, $, _, kbn, moment, timeSeries) { - 'use strict'; - var module = angular.module('grafana.panels.graph', []); + var module = angular.module('grafana.panels.graph'); app.useModule(module); module.controller('GraphCtrl', function($scope, $rootScope, $timeout, panelSrv, annotationsSrv) { @@ -363,49 +350,11 @@ function (angular, app, $, _, kbn, moment, timeSeries) { $scope.panel.seriesOverrides.push({}); }; + $scope.removeSeriesOverride = function(override) { + $scope.panel.seriesOverrides = _.without($scope.panel.seriesOverrides, override); + }; + panelSrv.init($scope); }); - angular - .module('grafana.directives') - .directive('seriesOverrideOption', function($compile) { - var template = - ''; - - return { - scope: true, - link: function($scope, elem, attrs) { - var $template = $(template); - elem.append($template); - var $link = $(elem).find('a'); - - $scope.options = $scope.$eval(attrs.options); - $scope.options.unshift(null); - - $scope.options = _.map($scope.options, function(option, index) { - return { - text: option === null ? '' : String(option), - value: option, - click: 'setValue(' + index + ')' - }; - }); - - $scope.setValue = function(index) { - var value = $scope.options[index].value; - if (value === null) { - $link.html(''); - } - else { - $link.html(value); - } - }; - - $compile(elem.contents())($scope); - } - }; - }); - }); diff --git a/src/app/panels/graph/seriesOverridesCtrl.js b/src/app/panels/graph/seriesOverridesCtrl.js new file mode 100644 index 00000000000..2123510400b --- /dev/null +++ b/src/app/panels/graph/seriesOverridesCtrl.js @@ -0,0 +1,66 @@ +define([ + 'angular', + 'app', + 'lodash', +], function(angular, app, _) { + 'use strict'; + + var module = angular.module('grafana.panels.graph', []); + app.useModule(module); + + module.controller('SeriesOverridesCtrl', function($scope) { + $scope.overrideMenu = []; + $scope.currentOverrides = []; + $scope.override = $scope.override || {}; + + $scope.addOverrideOption = function(name, propertyName, values) { + var option = {}; + option.text = name; + option.propertyName = propertyName; + option.index = $scope.overrideMenu.length; + option.values = values; + + option.submenu = _.map(values, function(value, index) { + return { + text: String(value), + click: 'setOverride(' + option.index + ',' + index + ')' + }; + }); + + $scope.overrideMenu.push(option); + }; + + $scope.setOverride = function(optionIndex, valueIndex) { + var option = $scope.overrideMenu[optionIndex]; + var value = option.values[valueIndex]; + $scope.override[option.propertyName] = value; + $scope.updateCurrentOverrides(); + }; + + $scope.removeOverride = function(option) { + delete $scope.override[option.propertyName]; + $scope.updateCurrentOverrides(); + }; + + $scope.updateCurrentOverrides = function() { + $scope.currentOverrides = []; + _.each($scope.overrideMenu, function(option) { + if (!_.isUndefined($scope.override[option.propertyName])) { + $scope.currentOverrides.push({ + name: option.text, + propertyName: option.propertyName, + value: String($scope.override[option.propertyName]) + }); + } + }); + }; + + $scope.addOverrideOption('Bars', 'bars', [true, false]); + $scope.addOverrideOption('Lines', 'lines', [true, false]); + $scope.addOverrideOption('Points', 'points', [true, false]); + $scope.addOverrideOption('Line fill', 'fill', [1,2,3,4,5,6,7,8]); + $scope.updateCurrentOverrides(); + + }); + +}); diff --git a/src/app/panels/graph/styleEditor.html b/src/app/panels/graph/styleEditor.html index c1b68e25beb..c436ba10ceb 100644 --- a/src/app/panels/graph/styleEditor.html +++ b/src/app/panels/graph/styleEditor.html @@ -66,36 +66,43 @@
Series specific overrides
- - - - - - - - - - - - - - - - - - - - -
Series alias/regexBarsLinesPointsFillWidthRadiusStaircaseStackY-axisZ-indexColor
- - - - - - - -
- +
+
+
+ + + +
    +
  • + alias or regex +
  • +
  • + +
  • +
  • + + + + {{option.name}}: {{option.value}} +
  • + +
+
+
+
+
+ +
diff --git a/src/css/less/graph.less b/src/css/less/graph.less index 79e87ab8f47..8f049a44ae5 100644 --- a/src/css/less/graph.less +++ b/src/css/less/graph.less @@ -154,3 +154,17 @@ .annotation-tags { color: @purple; } + +.graph-series-override { + input { + float: left; + margin-right: 10px; + } + .graph-series-override-option { + float: left; + padding: 2px 6px; + } + .graph-series-override-selector { + float: left; + } +} diff --git a/src/test/specs/grafanaGraph-specs.js b/src/test/specs/grafanaGraph-specs.js new file mode 100644 index 00000000000..f8b5878ce66 --- /dev/null +++ b/src/test/specs/grafanaGraph-specs.js @@ -0,0 +1,68 @@ +define([ + './helpers', + 'angular', + 'jquery', + 'directives/grafanaGraph' +], function(helpers, angular, $) { + 'use strict'; + + describe('grafanaGraph', function() { + + beforeEach(module('grafana.directives')); + + function graphScenario(desc, func) { + describe(desc, function() { + var ctx = {}; + ctx.setup = function (setupFunc) { + beforeEach(inject(function($rootScope, $compile) { + var scope = $rootScope.$new(); + var element = angular.element("
"); + + scope.height = '200px'; + scope.panel = { + legend: {}, + grid: {}, + y_formats: [] + }; + scope.dashboard = { timezone: 'browser' }; + scope.range = { + from: new Date('2014-08-09 10:00:00'), + to: new Date('2014-09-09 13:00:00') + }; + + setupFunc(scope); + + $compile(element)(scope); + scope.$digest(); + $.plot = ctx.plotSpy = sinon.spy(); + + scope.$emit('render', []); + ctx.plotData = ctx.plotSpy.getCall(0).args[1]; + ctx.plotOptions = ctx.plotSpy.getCall(0).args[2]; + })); + }; + + func(ctx); + }); + } + + graphScenario('simple lines options', function(ctx) { + ctx.setup(function(scope) { + scope.panel.lines = true; + scope.panel.fill = 5; + scope.panel.linewidth = 3; + scope.panel.steppedLine = true; + }); + + it('should configure plot with correct options', function() { + expect(ctx.plotOptions.series.lines.show).to.be(true); + expect(ctx.plotOptions.series.lines.fill).to.be(0.5); + expect(ctx.plotOptions.series.lines.lineWidth).to.be(3); + expect(ctx.plotOptions.series.lines.steps).to.be(true); + }); + + }); + + }); +}); + diff --git a/src/test/specs/helpers.js b/src/test/specs/helpers.js index cd31779cc99..de2be527f9f 100644 --- a/src/test/specs/helpers.js +++ b/src/test/specs/helpers.js @@ -69,7 +69,7 @@ define([ } return { from : kbn.parseDate(this.time.from), - to : kbn.parseDate(this.time.to) + to : kbn.parseDate(this.time.to) }; }; diff --git a/src/test/specs/seriesOverridesCtrl-specs.js b/src/test/specs/seriesOverridesCtrl-specs.js new file mode 100644 index 00000000000..04f0dcdca99 --- /dev/null +++ b/src/test/specs/seriesOverridesCtrl-specs.js @@ -0,0 +1,40 @@ +define([ + './helpers', + 'panels/graph/seriesOverridesCtrl' +], function(helpers) { + 'use strict'; + + describe('SeriesOverridesCtrl', function() { + var ctx = new helpers.ControllerTestContext(); + + beforeEach(module('grafana.services')); + beforeEach(module('grafana.panels.graph')); + + beforeEach(ctx.providePhase()); + beforeEach(ctx.createControllerPhase('SeriesOverridesCtrl')); + + describe('Controller should init overrideMenu', function() { + it('click should include option and value index', function() { + expect(ctx.scope.overrideMenu[1].submenu[1].click).to.be('setOverride(1,1)'); + }); + }); + + describe('When setting an override', function() { + beforeEach(function() { + ctx.scope.setOverride(1, 0); + }); + + it('should set override property', function() { + expect(ctx.scope.override.lines).to.be(true); + }); + + it('should update view model', function() { + expect(ctx.scope.currentOverrides[0].name).to.be('Lines'); + expect(ctx.scope.currentOverrides[0].value).to.be('true'); + }); + }); + + }); + +}); + diff --git a/src/test/test-main.js b/src/test/test-main.js index 9c7cfe73341..8d2014b0664 100644 --- a/src/test/test-main.js +++ b/src/test/test-main.js @@ -122,6 +122,8 @@ require([ 'specs/graphiteTargetCtrl-specs', 'specs/influxdb-datasource-specs', 'specs/graph-ctrl-specs', + 'specs/grafanaGraph-specs', + 'specs/seriesOverridesCtrl-specs', 'specs/filterSrv-specs', 'specs/kbn-format-specs', 'specs/dashboardSrv-specs', From 048763053c534bc9d2bf58c4e3be40bd2c624862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 19 Aug 2014 16:22:18 +0200 Subject: [PATCH 03/11] Began work on applying per series options to flot options --- .../graph => components}/timeSeries.js | 13 ++++--- src/app/directives/grafanaGraph.js | 20 ++++++++--- src/app/panels/graph/module.js | 6 ++-- src/app/panels/graph/seriesOverridesCtrl.js | 1 + src/app/panels/graph/styleEditor.html | 2 +- src/test/specs/grafanaGraph-specs.js | 36 ++++++++++++++++--- src/test/specs/seriesOverridesCtrl-specs.js | 3 ++ 7 files changed, 62 insertions(+), 19 deletions(-) rename src/app/{panels/graph => components}/timeSeries.js (92%) diff --git a/src/app/panels/graph/timeSeries.js b/src/app/components/timeSeries.js similarity index 92% rename from src/app/panels/graph/timeSeries.js rename to src/app/components/timeSeries.js index f1794cd6a30..8858b01a139 100644 --- a/src/app/panels/graph/timeSeries.js +++ b/src/app/components/timeSeries.js @@ -5,15 +5,13 @@ define([ function (_, kbn) { 'use strict'; - var ts = {}; - - ts.ZeroFilled = function (opts) { + function TimeSeries(opts) { this.datapoints = opts.datapoints; this.info = opts.info; this.label = opts.info.alias; - }; + } - ts.ZeroFilled.prototype.getFlotPairs = function (fillStyle, yFormats) { + TimeSeries.prototype.getFlotPairs = function (fillStyle, yFormats) { var result = []; this.color = this.info.color; @@ -74,5 +72,6 @@ function (_, kbn) { return result; }; - return ts; -}); \ No newline at end of file + return TimeSeries; + +}); diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index c2be3d90d13..21d47bcdf63 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -154,10 +154,9 @@ function (angular, $, kbn, moment, _) { }; for (var i = 0; i < data.length; i++) { - var _d = data[i].getFlotPairs(panel.nullPointMode, panel.y_formats); - data[i].data = _d; - data[0].lines = { show: false, dashes: true }; - data[0].bars = { show: true }; + var series = data[i]; + series.data = series.getFlotPairs(panel.nullPointMode, panel.y_formats); + applySeriesOverrideOptions(series); } if (data.length && data[0].info.timeStep) { @@ -184,6 +183,19 @@ function (angular, $, kbn, moment, _) { } } + function applySeriesOverrideOptions(series) { + for (var i = 0; i < scope.panel.seriesOverrides.length; i++) { + var override = scope.panel.seriesOverrides[i]; + if (override.alias === series.info.alias) { + if (!_.isUndefined(override.fill)) { + series.lines = { + fill: override.fill === 0 ? 0.001 : override.fill/10 + }; + } + } + } + } + function shouldDelayDraw(panel) { if (panel.legend.rightSide) { return true; diff --git a/src/app/panels/graph/module.js b/src/app/panels/graph/module.js index 557503023a1..9d2253b0147 100644 --- a/src/app/panels/graph/module.js +++ b/src/app/panels/graph/module.js @@ -5,7 +5,7 @@ define([ 'lodash', 'kbn', 'moment', - './timeSeries', + 'components/timeSeries', './seriesOverridesCtrl', 'services/panelSrv', 'services/annotationsSrv', @@ -17,7 +17,7 @@ define([ 'jquery.flot.stack', 'jquery.flot.stackpercent' ], -function (angular, app, $, _, kbn, moment, timeSeries) { +function (angular, app, $, _, kbn, moment, TimeSeries) { 'use strict'; var module = angular.module('grafana.panels.graph'); @@ -258,7 +258,7 @@ function (angular, app, $, _, kbn, moment, timeSeries) { $scope.legend.push(seriesInfo); - var series = new timeSeries.ZeroFilled({ + var series = new TimeSeries({ datapoints: datapoints, info: seriesInfo, }); diff --git a/src/app/panels/graph/seriesOverridesCtrl.js b/src/app/panels/graph/seriesOverridesCtrl.js index 2123510400b..ed2e27fdf7c 100644 --- a/src/app/panels/graph/seriesOverridesCtrl.js +++ b/src/app/panels/graph/seriesOverridesCtrl.js @@ -35,6 +35,7 @@ define([ var value = option.values[valueIndex]; $scope.override[option.propertyName] = value; $scope.updateCurrentOverrides(); + $scope.render(); }; $scope.removeOverride = function(option) { diff --git a/src/app/panels/graph/styleEditor.html b/src/app/panels/graph/styleEditor.html index c436ba10ceb..9b0d2b4fbba 100644 --- a/src/app/panels/graph/styleEditor.html +++ b/src/app/panels/graph/styleEditor.html @@ -84,7 +84,7 @@ alias or regex
  • - +
  • diff --git a/src/test/specs/grafanaGraph-specs.js b/src/test/specs/grafanaGraph-specs.js index f8b5878ce66..63f5055f238 100644 --- a/src/test/specs/grafanaGraph-specs.js +++ b/src/test/specs/grafanaGraph-specs.js @@ -2,8 +2,9 @@ define([ './helpers', 'angular', 'jquery', + 'components/timeSeries', 'directives/grafanaGraph' -], function(helpers, angular, $) { +], function(helpers, angular, $, TimeSeries) { 'use strict'; describe('grafanaGraph', function() { @@ -22,21 +23,31 @@ define([ scope.panel = { legend: {}, grid: {}, - y_formats: [] + y_formats: [], + seriesOverrides: [] }; scope.dashboard = { timezone: 'browser' }; scope.range = { from: new Date('2014-08-09 10:00:00'), to: new Date('2014-09-09 13:00:00') }; + ctx.data = []; + ctx.data.push(new TimeSeries({ + datapoints: [[1,1],[2,2]], + info: { alias: 'series1', enable: true } + })); + ctx.data.push(new TimeSeries({ + datapoints: [[1,1],[2,2]], + info: { alias: 'series2', enable: true } + })); - setupFunc(scope); + setupFunc(scope, ctx.data); $compile(element)(scope); scope.$digest(); $.plot = ctx.plotSpy = sinon.spy(); - scope.$emit('render', []); + scope.$emit('render', ctx.data); ctx.plotData = ctx.plotSpy.getCall(0).args[1]; ctx.plotOptions = ctx.plotSpy.getCall(0).args[2]; })); @@ -63,6 +74,23 @@ define([ }); + graphScenario('series option fill override', function(ctx) { + ctx.setup(function(scope, data) { + scope.panel.lines = true; + scope.panel.fill = 5; + scope.panel.seriesOverrides = [ + { alias: 'test', fill: 0 } + ]; + + data[1].info.alias = 'test'; + }); + + it('should match second series and set line fill', function() { + expect(ctx.plotOptions.series.lines.fill).to.be(0.5); + expect(ctx.plotData[1].lines.fill).to.be(0.001); + }); + + }); }); }); diff --git a/src/test/specs/seriesOverridesCtrl-specs.js b/src/test/specs/seriesOverridesCtrl-specs.js index 04f0dcdca99..e029c8a30cd 100644 --- a/src/test/specs/seriesOverridesCtrl-specs.js +++ b/src/test/specs/seriesOverridesCtrl-specs.js @@ -12,6 +12,9 @@ define([ beforeEach(ctx.providePhase()); beforeEach(ctx.createControllerPhase('SeriesOverridesCtrl')); + beforeEach(function() { + ctx.scope.render = function() {}; + }); describe('Controller should init overrideMenu', function() { it('click should include option and value index', function() { From cdcbb872d58fba33d5ccad07c9867c3898e841b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 19 Aug 2014 16:57:33 +0200 Subject: [PATCH 04/11] options per series is starting to work nicely --- src/app/directives/grafanaGraph.js | 20 +++++++++++------ src/app/panels/graph/module.js | 1 + src/app/panels/graph/seriesOverridesCtrl.js | 4 +++- src/app/panels/graph/styleEditor.html | 5 ++++- src/test/specs/grafanaGraph-specs.js | 24 ++++++++++++++++++--- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index 21d47bcdf63..e4f527bb2f3 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -184,18 +184,26 @@ function (angular, $, kbn, moment, _) { } function applySeriesOverrideOptions(series) { + series.lines = {}; + series.points = {}; + series.bars = {}; + for (var i = 0; i < scope.panel.seriesOverrides.length; i++) { var override = scope.panel.seriesOverrides[i]; - if (override.alias === series.info.alias) { - if (!_.isUndefined(override.fill)) { - series.lines = { - fill: override.fill === 0 ? 0.001 : override.fill/10 - }; - } + if (override.alias !== series.info.alias) { + continue; } + if (override.lines !== void 0) { series.lines.show = override.lines; } + if (override.points !== void 0) { series.points.show = override.points; } + if (override.bars !== void 0) { series.bars.show = override.bars; } + if (override.fill !== void 0) { series.lines.fill = translateFillOption(override.fill); } } } + function translateFillOption(fill) { + return fill === 0 ? 0.001 : fill/10; + } + function shouldDelayDraw(panel) { if (panel.legend.rightSide) { return true; diff --git a/src/app/panels/graph/module.js b/src/app/panels/graph/module.js index 9d2253b0147..b0de8f190c7 100644 --- a/src/app/panels/graph/module.js +++ b/src/app/panels/graph/module.js @@ -352,6 +352,7 @@ function (angular, app, $, _, kbn, moment, TimeSeries) { $scope.removeSeriesOverride = function(override) { $scope.panel.seriesOverrides = _.without($scope.panel.seriesOverrides, override); + $scope.render(); }; panelSrv.init($scope); diff --git a/src/app/panels/graph/seriesOverridesCtrl.js b/src/app/panels/graph/seriesOverridesCtrl.js index ed2e27fdf7c..9f42f3ef75d 100644 --- a/src/app/panels/graph/seriesOverridesCtrl.js +++ b/src/app/panels/graph/seriesOverridesCtrl.js @@ -41,6 +41,7 @@ define([ $scope.removeOverride = function(option) { delete $scope.override[option.propertyName]; $scope.updateCurrentOverrides(); + $scope.render(); }; $scope.updateCurrentOverrides = function() { @@ -59,7 +60,8 @@ define([ $scope.addOverrideOption('Bars', 'bars', [true, false]); $scope.addOverrideOption('Lines', 'lines', [true, false]); $scope.addOverrideOption('Points', 'points', [true, false]); - $scope.addOverrideOption('Line fill', 'fill', [1,2,3,4,5,6,7,8]); + $scope.addOverrideOption('Line fill', 'fill', [0,1,2,3,4,5,6,7,8,9,10]); + $scope.addOverrideOption('Line width', 'linewidth', [0,1,2,3,4,5,6,7,8,9,10]); $scope.updateCurrentOverrides(); }); diff --git a/src/app/panels/graph/styleEditor.html b/src/app/panels/graph/styleEditor.html index 9b0d2b4fbba..ca7ec99180d 100644 --- a/src/app/panels/graph/styleEditor.html +++ b/src/app/panels/graph/styleEditor.html @@ -84,7 +84,10 @@ alias or regex
  • - +
  • diff --git a/src/test/specs/grafanaGraph-specs.js b/src/test/specs/grafanaGraph-specs.js index 63f5055f238..b070c03ec44 100644 --- a/src/test/specs/grafanaGraph-specs.js +++ b/src/test/specs/grafanaGraph-specs.js @@ -74,23 +74,41 @@ define([ }); - graphScenario('series option fill override', function(ctx) { + graphScenario('series option overrides, fill & points', function(ctx) { ctx.setup(function(scope, data) { scope.panel.lines = true; scope.panel.fill = 5; scope.panel.seriesOverrides = [ - { alias: 'test', fill: 0 } + { alias: 'test', fill: 0, points: true } ]; data[1].info.alias = 'test'; }); - it('should match second series and set line fill', function() { + it('should match second series and fill zero, and enable points', function() { expect(ctx.plotOptions.series.lines.fill).to.be(0.5); expect(ctx.plotData[1].lines.fill).to.be(0.001); + expect(ctx.plotData[1].points.show).to.be(true); + }); + }); + + graphScenario('series option overrides, bars, true & lines false', function(ctx) { + ctx.setup(function(scope, data) { + scope.panel.lines = true; + scope.panel.seriesOverrides = [ + { alias: 'test', bars: true, lines: false } + ]; + + data[1].info.alias = 'test'; }); + it('should match second series and disable lines, and enable bars', function() { + expect(ctx.plotOptions.series.lines.show).to.be(true); + expect(ctx.plotData[1].lines.show).to.be(false); + expect(ctx.plotData[1].bars.show).to.be(true); + }); }); + }); }); From 062fe72030ebf466cec4d06cbb1d131505f50666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 19 Aug 2014 17:24:37 +0200 Subject: [PATCH 05/11] More options can now be set on pre series basis, this is awesome! --- src/app/directives/grafanaGraph.js | 5 +++ src/app/panels/graph/seriesOverridesCtrl.js | 5 ++- src/test/specs/grafanaGraph-specs.js | 36 +++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index e4f527bb2f3..f624c90494d 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -187,6 +187,7 @@ function (angular, $, kbn, moment, _) { series.lines = {}; series.points = {}; series.bars = {}; + delete series.stack; for (var i = 0; i < scope.panel.seriesOverrides.length; i++) { var override = scope.panel.seriesOverrides[i]; @@ -197,6 +198,10 @@ function (angular, $, kbn, moment, _) { if (override.points !== void 0) { series.points.show = override.points; } if (override.bars !== void 0) { series.bars.show = override.bars; } if (override.fill !== void 0) { series.lines.fill = translateFillOption(override.fill); } + if (override.stack !== void 0) { series.stack = override.stack; } + if (override.linewidth !== void 0) { series.lines.lineWidth = override.linewidth; } + if (override.pointradius !== void 0) { series.points.radius = override.pointradius; } + if (override.steppedLine !== void 0) { series.lines.steps = override.steppedLine; } } } diff --git a/src/app/panels/graph/seriesOverridesCtrl.js b/src/app/panels/graph/seriesOverridesCtrl.js index 9f42f3ef75d..d2f083b2699 100644 --- a/src/app/panels/graph/seriesOverridesCtrl.js +++ b/src/app/panels/graph/seriesOverridesCtrl.js @@ -59,9 +59,12 @@ define([ $scope.addOverrideOption('Bars', 'bars', [true, false]); $scope.addOverrideOption('Lines', 'lines', [true, false]); - $scope.addOverrideOption('Points', 'points', [true, false]); $scope.addOverrideOption('Line fill', 'fill', [0,1,2,3,4,5,6,7,8,9,10]); $scope.addOverrideOption('Line width', 'linewidth', [0,1,2,3,4,5,6,7,8,9,10]); + $scope.addOverrideOption('Staircase line', 'steppedLine', [true, false]); + $scope.addOverrideOption('Points', 'points', [true, false]); + $scope.addOverrideOption('Points Radius', 'pointradius', [1,2,3,4,5]); + $scope.addOverrideOption('Stack', 'stack', [true, false]); $scope.updateCurrentOverrides(); }); diff --git a/src/test/specs/grafanaGraph-specs.js b/src/test/specs/grafanaGraph-specs.js index b070c03ec44..162ad278ce3 100644 --- a/src/test/specs/grafanaGraph-specs.js +++ b/src/test/specs/grafanaGraph-specs.js @@ -109,6 +109,42 @@ define([ }); }); + graphScenario('series option overrides, linewidth, stack', function(ctx) { + ctx.setup(function(scope, data) { + scope.panel.lines = true; + scope.panel.stack = true; + scope.panel.linewidth = 2; + scope.panel.seriesOverrides = [ + { alias: 'test', linewidth: 5, stack: false } + ]; + + data[1].info.alias = 'test'; + }); + + it('should match second series and disable stack, and set lineWidth', function() { + expect(ctx.plotOptions.series.stack).to.be(true); + expect(ctx.plotData[1].stack).to.be(false); + expect(ctx.plotData[1].lines.lineWidth).to.be(5); + }); + }); + + graphScenario('series option overrides, pointradius, steppedLine', function(ctx) { + ctx.setup(function(scope, data) { + scope.panel.seriesOverrides = [ + { alias: 'test', pointradius: 5, steppedLine: true } + ]; + + data[1].info.alias = 'test'; + }); + + it('should match second series and set pointradius, and set steppedLine', function() { + expect(ctx.plotData[1].points.radius).to.be(5); + expect(ctx.plotData[1].lines.steps).to.be(true); + }); + }); + + + }); }); From 939e957fda02d6794307fabd6811c13fb74b2d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 20 Aug 2014 08:35:17 +0200 Subject: [PATCH 06/11] Made regex match work for per series overrides, #425, #700 --- src/app/directives/grafanaGraph.js | 12 +++++++++++- src/app/panels/graph/seriesOverridesCtrl.js | 14 +++++++------- src/app/panels/graph/styleEditor.html | 2 +- src/test/specs/grafanaGraph-specs.js | 14 ++++++++++++++ src/test/specs/seriesOverridesCtrl-specs.js | 8 ++++++++ 5 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index f624c90494d..1affce16e5c 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -183,6 +183,16 @@ function (angular, $, kbn, moment, _) { } } + function matchSeriesOverride(aliasOrRegex, seriesAlias) { + if (aliasOrRegex[0] === '/') { + var match = aliasOrRegex.match(new RegExp('^/(.*?)/(g?i?m?y?)$')); + var regex = new RegExp(match[1], match[2]); + return seriesAlias.match(regex) != null; + } + + return aliasOrRegex === seriesAlias; + } + function applySeriesOverrideOptions(series) { series.lines = {}; series.points = {}; @@ -191,7 +201,7 @@ function (angular, $, kbn, moment, _) { for (var i = 0; i < scope.panel.seriesOverrides.length; i++) { var override = scope.panel.seriesOverrides[i]; - if (override.alias !== series.info.alias) { + if (!matchSeriesOverride(override.alias, series.info.alias)) { continue; } if (override.lines !== void 0) { series.lines.show = override.lines; } diff --git a/src/app/panels/graph/seriesOverridesCtrl.js b/src/app/panels/graph/seriesOverridesCtrl.js index d2f083b2699..0d7f3b4838d 100644 --- a/src/app/panels/graph/seriesOverridesCtrl.js +++ b/src/app/panels/graph/seriesOverridesCtrl.js @@ -47,13 +47,13 @@ define([ $scope.updateCurrentOverrides = function() { $scope.currentOverrides = []; _.each($scope.overrideMenu, function(option) { - if (!_.isUndefined($scope.override[option.propertyName])) { - $scope.currentOverrides.push({ - name: option.text, - propertyName: option.propertyName, - value: String($scope.override[option.propertyName]) - }); - } + var value = $scope.override[option.propertyName]; + if (_.isUndefined(value)) { return; } + $scope.currentOverrides.push({ + name: option.text, + propertyName: option.propertyName, + value: String(value) + }); }); }; diff --git a/src/app/panels/graph/styleEditor.html b/src/app/panels/graph/styleEditor.html index ca7ec99180d..5a50f4995d0 100644 --- a/src/app/panels/graph/styleEditor.html +++ b/src/app/panels/graph/styleEditor.html @@ -65,7 +65,7 @@
    -
    Series specific overrides
    +
    Series specific overrides Regex match example: /server[0-3]/i
    diff --git a/src/test/specs/grafanaGraph-specs.js b/src/test/specs/grafanaGraph-specs.js index 162ad278ce3..6d83467daa7 100644 --- a/src/test/specs/grafanaGraph-specs.js +++ b/src/test/specs/grafanaGraph-specs.js @@ -143,7 +143,21 @@ define([ }); }); + graphScenario('override match on regex', function(ctx) { + ctx.setup(function(scope, data) { + scope.panel.lines = true; + scope.panel.seriesOverrides = [ + { alias: '/.*01/', lines: false } + ]; + data[1].info.alias = 'test_01'; + }); + + it('should match second series and set pointradius, and set steppedLine', function() { + expect(ctx.plotData[0].lines.show).to.be(undefined); + expect(ctx.plotData[1].lines.show).to.be(false); + }); + }); }); }); diff --git a/src/test/specs/seriesOverridesCtrl-specs.js b/src/test/specs/seriesOverridesCtrl-specs.js index e029c8a30cd..e211b6dab35 100644 --- a/src/test/specs/seriesOverridesCtrl-specs.js +++ b/src/test/specs/seriesOverridesCtrl-specs.js @@ -37,6 +37,14 @@ define([ }); }); + describe('When removing overide', function() { + it('click should include option and value index', function() { + ctx.scope.setOverride(1,0); + ctx.scope.removeOverride({ propertyName: 'lines' }); + expect(ctx.scope.currentOverrides.length).to.be(0); + }); + }); + }); }); From b2f9f81eaf0dd812c3a4decd6bcb0b7cae995c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 20 Aug 2014 09:31:22 +0200 Subject: [PATCH 07/11] Moved yaxis override from aliasYAxis map to the new seriesOverride array --- src/app/directives/grafanaGraph.js | 4 + src/app/panels/graph/module.js | 12 +- src/app/panels/graph/seriesOverridesCtrl.js | 1 + src/app/services/dashboard/dashboardSrv.js | 125 +++++++++++--------- src/test/specs/dashboardSrv-specs.js | 8 +- src/test/specs/grafanaGraph-specs.js | 17 ++- 6 files changed, 105 insertions(+), 62 deletions(-) diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index 1affce16e5c..6004b6e366c 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -212,6 +212,10 @@ function (angular, $, kbn, moment, _) { if (override.linewidth !== void 0) { series.lines.lineWidth = override.linewidth; } if (override.pointradius !== void 0) { series.points.radius = override.pointradius; } if (override.steppedLine !== void 0) { series.lines.steps = override.steppedLine; } + if (override.yaxis !== void 0) { + series.yaxis = override.yaxis; + series.info.yaxis = override.yaxis; + } } } diff --git a/src/app/panels/graph/module.js b/src/app/panels/graph/module.js index b0de8f190c7..6897cc090b0 100644 --- a/src/app/panels/graph/module.js +++ b/src/app/panels/graph/module.js @@ -166,7 +166,6 @@ function (angular, app, $, _, kbn, moment, TimeSeries) { targets: [{}], aliasColors: {}, - aliasYAxis: {}, seriesOverrides: [], }; @@ -247,13 +246,10 @@ function (angular, app, $, _, kbn, moment, TimeSeries) { var datapoints = seriesData.datapoints; var alias = seriesData.target; var color = $scope.panel.aliasColors[alias] || $rootScope.colors[index]; - var yaxis = $scope.panel.aliasYAxis[alias] || 1; var seriesInfo = { alias: alias, color: color, - enable: true, - yaxis: yaxis }; $scope.legend.push(seriesInfo); @@ -336,8 +332,12 @@ function (angular, app, $, _, kbn, moment, TimeSeries) { }; $scope.toggleYAxis = function(info) { - info.yaxis = info.yaxis === 2 ? 1 : 2; - $scope.panel.aliasYAxis[info.alias] = info.yaxis; + var override = _.findWhere($scope.panel.seriesOverrides, { alias: info.alias }); + if (!override) { + override = { alias: info.alias }; + $scope.panel.seriesOverrides.push(override); + } + override.yaxis = info.yaxis === 2 ? 1 : 2; $scope.render(); }; diff --git a/src/app/panels/graph/seriesOverridesCtrl.js b/src/app/panels/graph/seriesOverridesCtrl.js index 0d7f3b4838d..4616e6ac1f8 100644 --- a/src/app/panels/graph/seriesOverridesCtrl.js +++ b/src/app/panels/graph/seriesOverridesCtrl.js @@ -65,6 +65,7 @@ define([ $scope.addOverrideOption('Points', 'points', [true, false]); $scope.addOverrideOption('Points Radius', 'pointradius', [1,2,3,4,5]); $scope.addOverrideOption('Stack', 'stack', [true, false]); + $scope.addOverrideOption('Y-axis', 'yaxis', [1, 2]); $scope.updateCurrentOverrides(); }); diff --git a/src/app/services/dashboard/dashboardSrv.js b/src/app/services/dashboard/dashboardSrv.js index ff1e149c3b7..f2d67bf1839 100644 --- a/src/app/services/dashboard/dashboardSrv.js +++ b/src/app/services/dashboard/dashboardSrv.js @@ -144,80 +144,97 @@ function (angular, $, kbn, _, moment) { }; p.updateSchema = function(old) { - var i, j, row, panel; var oldVersion = this.version; - this.version = 3; + var panelUpgrades = []; + this.version = 4; - if (oldVersion === 3) { + if (oldVersion === 4) { return; } - // Version 3 schema changes - // ensure panel ids - 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]; - if (!panel.id) { - panel.id = maxId; - maxId += 1; + // version 2 schema changes + if (oldVersion < 2) { + + if (old.services) { + if (old.services.filter) { + this.time = old.services.filter.time; + this.templating.list = old.services.filter.list; } + delete this.services; } - } - if (oldVersion === 2) { - return; - } - - // Version 2 schema changes - if (old.services) { - if (old.services.filter) { - this.time = old.services.filter.time; - this.templating.list = old.services.filter.list; - } - delete this.services; - } - - for (i = 0; i < this.rows.length; i++) { - row = this.rows[i]; - for (j = 0; j < row.panels.length; j++) { - panel = row.panels[j]; + panelUpgrades.push(function(panel) { + // rename panel type if (panel.type === 'graphite') { panel.type = 'graph'; } - if (panel.type === 'graph') { - if (_.isBoolean(panel.legend)) { - panel.legend = { show: panel.legend }; + if (panel.type !== 'graph') { + return; + } + + if (_.isBoolean(panel.legend)) { panel.legend = { show: panel.legend }; } + + if (panel.grid) { + if (panel.grid.min) { + panel.grid.leftMin = panel.grid.min; + delete panel.grid.min; } - if (panel.grid) { - if (panel.grid.min) { - panel.grid.leftMin = panel.grid.min; - delete panel.grid.min; - } - - if (panel.grid.max) { - panel.grid.leftMax = panel.grid.max; - delete panel.grid.max; - } + if (panel.grid.max) { + panel.grid.leftMax = panel.grid.max; + delete panel.grid.max; } + } - if (panel.y_format) { - panel.y_formats[0] = panel.y_format; - delete panel.y_format; - } + if (panel.y_format) { + panel.y_formats[0] = panel.y_format; + delete panel.y_format; + } - if (panel.y2_format) { - panel.y_formats[1] = panel.y2_format; - delete panel.y2_format; - } + if (panel.y2_format) { + panel.y_formats[1] = panel.y2_format; + delete panel.y2_format; + } + }); + } + + // schema version 3 changes + if (oldVersion < 3) { + // ensure panel ids + var maxId = this.getNextPanelId(); + panelUpgrades.push(function(panel) { + if (!panel.id) { + panel.id = maxId; + maxId += 1; + } + }); + } + + // schema version 4 changes + if (oldVersion < 4) { + // move aliasYAxis changes + panelUpgrades.push(function(panel) { + if (panel.type !== 'graph') { return; } + _.each(panel.aliasYAxis, function(value, key) { + panel.seriesOverrides = [{ alias: key, yaxis: value }]; + }); + delete panel.aliasYAxis; + }); + } + + if (panelUpgrades.length === 0) { + return; + } + + for (var i = 0; i < this.rows.length; i++) { + var row = this.rows[i]; + for (var j = 0; j < row.panels.length; j++) { + for (var k = 0; k < panelUpgrades.length; k++) { + panelUpgrades[k](row.panels[j]); } } } - - this.version = 3; }; return { diff --git a/src/test/specs/dashboardSrv-specs.js b/src/test/specs/dashboardSrv-specs.js index 5e4e96401de..a2c7c1772f6 100644 --- a/src/test/specs/dashboardSrv-specs.js +++ b/src/test/specs/dashboardSrv-specs.js @@ -97,6 +97,7 @@ define([ { type: 'graphite', legend: true, + aliasYAxis: { test: 2 }, grid: { min: 1, max: 10 } } ] @@ -134,8 +135,13 @@ define([ expect(graph.grid.leftMax).to.be(10); }); + it('move aliasYAxis to series override', function() { + expect(graph.seriesOverrides[0].alias).to.be("test"); + expect(graph.seriesOverrides[0].yaxis).to.be(2); + }); + it('dashboard schema version should be set to latest', function() { - expect(model.version).to.be(3); + expect(model.version).to.be(4); }); }); diff --git a/src/test/specs/grafanaGraph-specs.js b/src/test/specs/grafanaGraph-specs.js index 6d83467daa7..f5ad344c1c5 100644 --- a/src/test/specs/grafanaGraph-specs.js +++ b/src/test/specs/grafanaGraph-specs.js @@ -153,12 +153,27 @@ define([ data[1].info.alias = 'test_01'; }); - it('should match second series and set pointradius, and set steppedLine', function() { + it('should match second series', function() { expect(ctx.plotData[0].lines.show).to.be(undefined); expect(ctx.plotData[1].lines.show).to.be(false); }); }); + graphScenario('override series y-axis', function(ctx) { + ctx.setup(function(scope, data) { + scope.panel.lines = true; + scope.panel.seriesOverrides = [ + { alias: 'test', yaxis: 2 } + ]; + + data[1].info.alias = 'test'; + }); + + it('should match second series and set yaxis', function() { + expect(ctx.plotData[1].yaxis).to.be(2); + }); + }); + }); }); From 3ec053bea70f99d2f125de1063a8f391cb35fd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 20 Aug 2014 10:27:30 +0200 Subject: [PATCH 08/11] Moved series override code to TimeSeries --- src/app/components/timeSeries.js | 40 ++++++++++ src/app/directives/grafanaGraph.js | 40 +--------- src/app/panels/graph/legend.html | 4 +- src/test/specs/grafanaGraph-specs.js | 82 -------------------- src/test/specs/timeSeries-specs.js | 111 +++++++++++++++++++++++++++ src/test/test-main.js | 1 + 6 files changed, 156 insertions(+), 122 deletions(-) create mode 100644 src/test/specs/timeSeries-specs.js diff --git a/src/app/components/timeSeries.js b/src/app/components/timeSeries.js index 8858b01a139..e49b45e17e4 100644 --- a/src/app/components/timeSeries.js +++ b/src/app/components/timeSeries.js @@ -11,6 +11,46 @@ function (_, kbn) { this.label = opts.info.alias; } + function matchSeriesOverride(aliasOrRegex, seriesAlias) { + if (aliasOrRegex[0] === '/') { + var match = aliasOrRegex.match(new RegExp('^/(.*?)/(g?i?m?y?)$')); + var regex = new RegExp(match[1], match[2]); + return seriesAlias.match(regex) != null; + } + + return aliasOrRegex === seriesAlias; + } + + function translateFillOption(fill) { + return fill === 0 ? 0.001 : fill/10; + } + + TimeSeries.prototype.applySeriesOverrides = function(overrides) { + this.lines = {}; + this.points = {}; + this.bars = {}; + this.info.yaxis = 1; + delete this.stack; + + for (var i = 0; i < overrides.length; i++) { + var override = overrides[i]; + if (!matchSeriesOverride(override.alias, this.info.alias)) { + continue; + } + if (override.lines !== void 0) { this.lines.show = override.lines; } + if (override.points !== void 0) { this.points.show = override.points; } + if (override.bars !== void 0) { this.bars.show = override.bars; } + if (override.fill !== void 0) { this.lines.fill = translateFillOption(override.fill); } + if (override.stack !== void 0) { this.stack = override.stack; } + if (override.linewidth !== void 0) { this.lines.lineWidth = override.linewidth; } + if (override.pointradius !== void 0) { this.points.radius = override.pointradius; } + if (override.steppedLine !== void 0) { this.lines.steps = override.steppedLine; } + if (override.yaxis !== void 0) { + this.info.yaxis = override.yaxis; + } + } + }; + TimeSeries.prototype.getFlotPairs = function (fillStyle, yFormats) { var result = []; diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index 6004b6e366c..3525e3a98f4 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -118,7 +118,7 @@ function (angular, $, kbn, moment, _) { lines: { show: panel.lines, zero: false, - fill: panel.fill === 0 ? 0.001 : panel.fill/10, + fill: translateFillOption(panel.fill), lineWidth: panel.linewidth, steps: panel.steppedLine }, @@ -155,8 +155,8 @@ function (angular, $, kbn, moment, _) { for (var i = 0; i < data.length; i++) { var series = data[i]; + series.applySeriesOverrides(panel.seriesOverrides); series.data = series.getFlotPairs(panel.nullPointMode, panel.y_formats); - applySeriesOverrideOptions(series); } if (data.length && data[0].info.timeStep) { @@ -183,42 +183,6 @@ function (angular, $, kbn, moment, _) { } } - function matchSeriesOverride(aliasOrRegex, seriesAlias) { - if (aliasOrRegex[0] === '/') { - var match = aliasOrRegex.match(new RegExp('^/(.*?)/(g?i?m?y?)$')); - var regex = new RegExp(match[1], match[2]); - return seriesAlias.match(regex) != null; - } - - return aliasOrRegex === seriesAlias; - } - - function applySeriesOverrideOptions(series) { - series.lines = {}; - series.points = {}; - series.bars = {}; - delete series.stack; - - for (var i = 0; i < scope.panel.seriesOverrides.length; i++) { - var override = scope.panel.seriesOverrides[i]; - if (!matchSeriesOverride(override.alias, series.info.alias)) { - continue; - } - if (override.lines !== void 0) { series.lines.show = override.lines; } - if (override.points !== void 0) { series.points.show = override.points; } - if (override.bars !== void 0) { series.bars.show = override.bars; } - if (override.fill !== void 0) { series.lines.fill = translateFillOption(override.fill); } - if (override.stack !== void 0) { series.stack = override.stack; } - if (override.linewidth !== void 0) { series.lines.lineWidth = override.linewidth; } - if (override.pointradius !== void 0) { series.points.radius = override.pointradius; } - if (override.steppedLine !== void 0) { series.lines.steps = override.steppedLine; } - if (override.yaxis !== void 0) { - series.yaxis = override.yaxis; - series.info.yaxis = override.yaxis; - } - } - } - function translateFillOption(fill) { return fill === 0 ? 0.001 : fill/10; } diff --git a/src/app/panels/graph/legend.html b/src/app/panels/graph/legend.html index 5524a8047fe..0e5edc459ce 100755 --- a/src/app/panels/graph/legend.html +++ b/src/app/panels/graph/legend.html @@ -34,12 +34,12 @@
    - -
  • - - - + {{option.name}}: {{option.value}}
  • + diff --git a/src/test/specs/grafanaGraph-specs.js b/src/test/specs/grafanaGraph-specs.js index 449d8db4c39..5f3ad0dd413 100644 --- a/src/test/specs/grafanaGraph-specs.js +++ b/src/test/specs/grafanaGraph-specs.js @@ -92,8 +92,8 @@ define([ }); graphScenario('should order series order according to zindex', function(ctx) { - ctx.setup(function(scope, data) { - data[0].zindex = 2; + ctx.setup(function(scope) { + scope.panel.seriesOverrides = [{ alias: 'series1', zindex: 2 }]; }); it('should move zindex 2 last', function() { diff --git a/src/test/specs/timeSeries-specs.js b/src/test/specs/timeSeries-specs.js index f5fa980c491..cf28c1aa450 100644 --- a/src/test/specs/timeSeries-specs.js +++ b/src/test/specs/timeSeries-specs.js @@ -101,8 +101,8 @@ define([ it('should set yaxis', function() { expect(series.info.yaxis).to.be(2); - }); + it('should set zindex', function() { expect(series.zindex).to.be(2); }); From a9cfb160c91d8b1bfcc57d768e88d39d218a0170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 20 Aug 2014 11:48:00 +0200 Subject: [PATCH 11/11] Added typeahead to series overrides, #425 --- src/app/components/timeSeries.js | 2 ++ src/app/panels/graph/seriesOverridesCtrl.js | 6 ++++++ src/app/panels/graph/styleEditor.html | 8 +++++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/app/components/timeSeries.js b/src/app/components/timeSeries.js index c64b5931e7f..85c27f1da88 100644 --- a/src/app/components/timeSeries.js +++ b/src/app/components/timeSeries.js @@ -12,6 +12,8 @@ function (_, kbn) { } function matchSeriesOverride(aliasOrRegex, seriesAlias) { + if (!aliasOrRegex) { return false; } + if (aliasOrRegex[0] === '/') { var match = aliasOrRegex.match(new RegExp('^/(.*?)/(g?i?m?y?)$')); var regex = new RegExp(match[1], match[2]); diff --git a/src/app/panels/graph/seriesOverridesCtrl.js b/src/app/panels/graph/seriesOverridesCtrl.js index cc6b240d474..4f54c6d0e6f 100644 --- a/src/app/panels/graph/seriesOverridesCtrl.js +++ b/src/app/panels/graph/seriesOverridesCtrl.js @@ -44,6 +44,12 @@ define([ $scope.render(); }; + $scope.getSeriesNames = function() { + return _.map($scope.legend, function(info) { + return info.alias; + }); + }; + $scope.updateCurrentOverrides = function() { $scope.currentOverrides = []; _.each($scope.overrideMenu, function(option) { diff --git a/src/app/panels/graph/styleEditor.html b/src/app/panels/graph/styleEditor.html index ec4f59b50b4..de7318d4500 100644 --- a/src/app/panels/graph/styleEditor.html +++ b/src/app/panels/graph/styleEditor.html @@ -72,8 +72,8 @@
      -
    • +
    • +
    @@ -84,7 +84,9 @@