From 9e7c55728fdb8c46b1c710a19cd84e611839a0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 6 Sep 2014 18:05:54 +0200 Subject: [PATCH 01/59] small cleanup of unused code --- src/app/controllers/dashboardCtrl.js | 10 +--------- src/app/partials/paneladd.html | 6 ------ src/app/services/dashboard/dashboardKeyBindings.js | 2 +- 3 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 src/app/partials/paneladd.html diff --git a/src/app/controllers/dashboardCtrl.js b/src/app/controllers/dashboardCtrl.js index 8ccbb170d8a..b9893b2dcda 100644 --- a/src/app/controllers/dashboardCtrl.js +++ b/src/app/controllers/dashboardCtrl.js @@ -44,7 +44,7 @@ function (angular, $, config, _) { $scope.setupDashboard = function(event, dashboardData) { $rootScope.performance.dashboardLoadStart = new Date().getTime(); $rootScope.performance.panelsInitialized = 0; - $rootScope.performance.panelsRendered= 0; + $rootScope.performance.panelsRendered = 0; $scope.dashboard = dashboardSrv.create(dashboardData); $scope.dashboardViewState = dashboardViewStateSrv.create($scope); @@ -93,14 +93,6 @@ function (angular, $, config, _) { }; }; - $scope.panel_path =function(type) { - if(type) { - return 'app/panels/'+type.replace(".","/"); - } else { - return false; - } - }; - $scope.edit_path = function(type) { var p = $scope.panel_path(type); if(p) { diff --git a/src/app/partials/paneladd.html b/src/app/partials/paneladd.html deleted file mode 100644 index f902bbce561..00000000000 --- a/src/app/partials/paneladd.html +++ /dev/null @@ -1,6 +0,0 @@ -
-
-
-
{{tab.title}}
-
-
\ No newline at end of file diff --git a/src/app/services/dashboard/dashboardKeyBindings.js b/src/app/services/dashboard/dashboardKeyBindings.js index 27bbe8ee027..ba8dcaf0f23 100644 --- a/src/app/services/dashboard/dashboardKeyBindings.js +++ b/src/app/services/dashboard/dashboardKeyBindings.js @@ -18,8 +18,8 @@ function(angular, $) { keyboardManager.unbind('ctrl+s'); keyboardManager.unbind('ctrl+r'); keyboardManager.unbind('ctrl+z'); + keyboardManager.unbind('esc'); }); - keyboardManager.unbind('esc'); keyboardManager.bind('ctrl+f', function() { scope.emitAppEvent('show-dash-editor', { src: 'app/partials/search.html' }); From bbc5dae1d2308edb487f82ed755cd1ada2cee895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sun, 7 Sep 2014 11:55:26 +0200 Subject: [PATCH 02/59] Working on better handling of variables and url init and state --- src/test/specs/helpers.js | 2 ++ src/test/specs/templateValuesSrv-specs.js | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/test/specs/helpers.js b/src/test/specs/helpers.js index 35cde542de6..81f0df7be7e 100644 --- a/src/test/specs/helpers.js +++ b/src/test/specs/helpers.js @@ -51,6 +51,7 @@ define([ self.templateSrv = new TemplateSrvStub(); self.timeSrv = new TimeSrvStub(); self.datasourceSrv = {}; + self.$routeParams = {}; this.providePhase = function(mocks) { return module(function($provide) { @@ -103,6 +104,7 @@ define([ this.replace = function(text) { return _.template(text, this.data, this.templateSettings); }; + this.init = function() {}; this.updateTemplateData = function() { }; this.variableExists = function() { return false; }; this.highlightVariablesAsHtml = function(str) { return str; }; diff --git a/src/test/specs/templateValuesSrv-specs.js b/src/test/specs/templateValuesSrv-specs.js index eb1b0225618..c0674a5cd75 100644 --- a/src/test/specs/templateValuesSrv-specs.js +++ b/src/test/specs/templateValuesSrv-specs.js @@ -10,7 +10,7 @@ define([ var ctx = new helpers.ServiceTestContext(); beforeEach(module('grafana.services')); - beforeEach(ctx.providePhase(['datasourceSrv', 'timeSrv', 'templateSrv'])); + beforeEach(ctx.providePhase(['datasourceSrv', 'timeSrv', 'templateSrv', "$routeParams"])); beforeEach(ctx.createService('templateValuesSrv')); describe('update interval variable options', function() { @@ -27,6 +27,20 @@ define([ }); }); + describe.only('should init values', function() { + var variables = [ + { name: 'test', current: { value: 'hej' }} + ]; + var dashboard = { templating: { list: variables } }; + + beforeEach(function() { + ctx.service.init(dashboard); + }); + + it('should update options array', function() { + }); + }); + function describeUpdateVariable(desc, fn) { describe(desc, function() { var scenario = {}; From e0c9ddbfba44b23277c2badf6ec637d706803fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 8 Sep 2014 11:03:14 +0200 Subject: [PATCH 03/59] Worked on variable initilization and sync to from url, #772 --- CHANGELOG.md | 2 + src/app/controllers/dashboardCtrl.js | 2 +- src/app/directives/graphiteSegment.js | 2 +- .../dashboard/dashboardViewStateSrv.js | 55 +++++++++++-------- src/app/services/templateSrv.js | 15 ++--- src/app/services/templateValuesSrv.js | 24 +++++--- src/css/less/overrides.less | 5 ++ src/test/specs/dashboardViewStateSrv-specs.js | 2 + src/test/specs/templateSrv-specs.js | 18 ++++++ src/test/specs/templateValuesSrv-specs.js | 30 +--------- 10 files changed, 84 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fb7ec258ea..16b11573fd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ - [Issue #262](https://github.com/grafana/grafana/issues/262). Templating: Ability to use template variables for function parameters via custom variable type, can be used as parameter for movingAverage or scaleToSeconds for example - [Issue #312](https://github.com/grafana/grafana/issues/312). Templating: Can now use template variables in panel titles - [Issue #613](https://github.com/grafana/grafana/issues/613). Templating: Full support for InfluxDB, filter by part of series names, extract series substrings, nested queries, multipe where clauses! +- Template variables can be initialized from url, with var-my_varname=value, breaking change, before it was just my_varname. +- Templating and url state sync has some issues that are not solved for this release, see [Issue #772](https://github.com/grafana/grafana/issues/772) for more details. **InfluxDB Breaking changes** - To better support templating, fill(0) and group by time low limit some changes has been made to the editor and query model schema diff --git a/src/app/controllers/dashboardCtrl.js b/src/app/controllers/dashboardCtrl.js index b9893b2dcda..f4d057e77e5 100644 --- a/src/app/controllers/dashboardCtrl.js +++ b/src/app/controllers/dashboardCtrl.js @@ -51,7 +51,7 @@ function (angular, $, config, _) { // init services timeSrv.init($scope.dashboard); - templateValuesSrv.init($scope.dashboard); + templateValuesSrv.init($scope.dashboard, $scope.dashboardViewState); panelMoveSrv.init($scope.dashboard, $scope); $scope.checkFeatureToggles(); diff --git a/src/app/directives/graphiteSegment.js b/src/app/directives/graphiteSegment.js index 032ea99c39a..f0116bc8847 100644 --- a/src/app/directives/graphiteSegment.js +++ b/src/app/directives/graphiteSegment.js @@ -94,7 +94,7 @@ function (angular, app, _, $) { }; $input.attr('data-provide', 'typeahead'); - $input.typeahead({ source: $scope.source, minLength: 0, items: 100, updater: $scope.updater }); + $input.typeahead({ source: $scope.source, minLength: 0, items: 10000, updater: $scope.updater }); var typeahead = $input.data('typeahead'); typeahead.lookup = function () { diff --git a/src/app/services/dashboard/dashboardViewStateSrv.js b/src/app/services/dashboard/dashboardViewStateSrv.js index 64d217f3dec..2f85da5d27a 100644 --- a/src/app/services/dashboard/dashboardViewStateSrv.js +++ b/src/app/services/dashboard/dashboardViewStateSrv.js @@ -14,9 +14,12 @@ function (angular, _, $) { // like fullscreen panel & edit function DashboardViewState($scope) { var self = this; + self.state = {}; + self.panelScopes = []; + self.$scope = $scope; $scope.exitFullscreen = function() { - if (self.fullscreen) { + if (self.state.fullscreen) { self.update({ fullscreen: false }); } }; @@ -28,42 +31,48 @@ function (angular, _, $) { } }); - this.panelScopes = []; - this.$scope = $scope; - this.update(this.getQueryStringState(), true); } DashboardViewState.prototype.needsSync = function(urlState) { - if (urlState.fullscreen !== this.fullscreen) { return true; } - if (urlState.edit !== this.edit) { return true; } - if (urlState.panelId !== this.panelId) { return true; } - return false; + return _.isEqual(this.state, urlState) === false; }; DashboardViewState.prototype.getQueryStringState = function() { var queryParams = $location.search(); - return { + var urlState = { panelId: parseInt(queryParams.panelId) || null, fullscreen: queryParams.fullscreen ? true : false, - edit: queryParams.edit ? true : false + edit: queryParams.edit ? true : false, }; + + _.each(queryParams, function(value, key) { + if (key.indexOf('var-') !== 0) { return; } + urlState[key] = value; + }); + + return urlState; + }; + + DashboardViewState.prototype.serializeToUrl = function() { + var urlState = _.clone(this.state); + urlState.fullscreen = this.state.fullscreen ? true : null, + urlState.edit = this.state.edit ? true : null; + + return urlState; }; DashboardViewState.prototype.update = function(state, skipUrlSync) { - _.extend(this, state); + _.extend(this.state, state); + this.fullscreen = this.state.fullscreen; - if (!this.fullscreen) { - this.panelId = null; - this.edit = false; + if (!this.state.fullscreen) { + this.state.panelId = null; + this.state.edit = false; } if (!skipUrlSync) { - $location.search({ - fullscreen: this.fullscreen ? true : null, - panelId: this.panelId, - edit: this.edit ? true : null - }); + $location.search(this.serializeToUrl()); } this.syncState(); @@ -76,7 +85,7 @@ function (angular, _, $) { if (this.fullscreenPanel) { this.leaveFullscreen(false); } - var panelScope = this.getPanelScope(this.panelId); + var panelScope = this.getPanelScope(this.state.panelId); this.enterFullscreen(panelScope); return; } @@ -118,8 +127,8 @@ function (angular, _, $) { var fullscreenHeight = Math.floor(docHeight * 0.7); this.oldTimeRange = panelScope.range; - panelScope.height = this.edit ? editHeight : fullscreenHeight; - panelScope.editMode = this.edit; + panelScope.height = this.state.edit ? editHeight : fullscreenHeight; + panelScope.editMode = this.state.edit; this.fullscreenPanel = panelScope; $(window).scrollTop(0); @@ -135,7 +144,7 @@ function (angular, _, $) { var self = this; self.panelScopes.push(panelScope); - if (self.panelId === panelScope.panel.id) { + if (self.state.panelId === panelScope.panel.id) { self.enterFullscreen(panelScope); } diff --git a/src/app/services/templateSrv.js b/src/app/services/templateSrv.js index f8247d1c5cb..d63a9df34d4 100644 --- a/src/app/services/templateSrv.js +++ b/src/app/services/templateSrv.js @@ -7,7 +7,7 @@ function (angular, _) { var module = angular.module('grafana.services'); - module.service('templateSrv', function($q, $routeParams) { + module.service('templateSrv', function() { var self = this; this._regex = /\$(\w+)|\[\[([\s\S]+?)\]\]/g; @@ -19,17 +19,10 @@ function (angular, _) { this.updateTemplateData(true); }; - this.updateTemplateData = function(initial) { + this.updateTemplateData = function() { var data = {}; _.each(this.variables, function(variable) { - if (initial) { - var urlValue = $routeParams[ variable.name ]; - if (urlValue) { - variable.current = { text: urlValue, value: urlValue }; - } - } - if (!variable.current || !variable.current.value) { return; } @@ -50,6 +43,10 @@ function (angular, _) { return match && (self._templateData[match[1] || match[2]] !== void 0); }; + this.containsVariable = function(str, variableName) { + return str.indexOf('$' + variableName) !== -1 || str.indexOf('[[' + variableName + ']]') !== -1; + }; + this.highlightVariablesAsHtml = function(str) { if (!str || !_.isString(str)) { return str; } diff --git a/src/app/services/templateValuesSrv.js b/src/app/services/templateValuesSrv.js index 511d5bfb495..cf2d766edc4 100644 --- a/src/app/services/templateValuesSrv.js +++ b/src/app/services/templateValuesSrv.js @@ -18,17 +18,24 @@ function (angular, _, kbn) { } }); - this.init = function(dashboard) { + this.init = function(dashboard, viewstate) { this.variables = dashboard.templating.list; + this.viewstate = viewstate; templateSrv.init(this.variables); for (var i = 0; i < this.variables.length; i++) { - var param = this.variables[i]; - if (param.refresh) { - this.updateOptions(param); + var variable = this.variables[i]; + var urlValue = viewstate.state['var-' + variable.name]; + if (urlValue !== void 0) { + var option = _.findWhere(variable.options, { text: urlValue }); + option = option || { text: urlValue, value: urlValue }; + this.setVariableValue(variable, option, true); } - else if (param.type === 'interval') { - this.updateAutoInterval(param); + else if (variable.refresh) { + this.updateOptions(variable); + } + else if (variable.type === 'interval') { + this.updateAutoInterval(variable); } } }; @@ -63,7 +70,7 @@ function (angular, _, kbn) { if (otherVariable === updatedVariable) { return; } - if (otherVariable.query.indexOf('[[' + updatedVariable.name + ']]') !== -1) { + if (templateSrv.containsVariable(otherVariable.query, updatedVariable.name)) { return self.updateOptions(otherVariable); } }); @@ -92,7 +99,6 @@ function (angular, _, kbn) { var datasource = datasourceSrv.get(variable.datasource); return datasource.metricFindQuery(variable.query) .then(function (results) { - variable.options = self.metricNamesToVariableValues(variable, results); if (variable.includeAll) { @@ -102,7 +108,7 @@ function (angular, _, kbn) { // if parameter has current value // if it exists in options array keep value if (variable.current) { - var currentExists = _.findWhere(variable.options, { value: variable.current.value }); + var currentExists = _.findWhere(variable.options, { text: variable.current.text }); if (currentExists) { return self.setVariableValue(variable, variable.current, true); } diff --git a/src/css/less/overrides.less b/src/css/less/overrides.less index 4415c85d3c0..58e72ef43fa 100644 --- a/src/css/less/overrides.less +++ b/src/css/less/overrides.less @@ -516,6 +516,11 @@ div.flot-text { } } +// typeahead max height +.typeahead { + max-height: 300px; + overflow-y: auto; +} // Labels & Badges .label-tag { diff --git a/src/test/specs/dashboardViewStateSrv-specs.js b/src/test/specs/dashboardViewStateSrv-specs.js index 92e444d55d0..82ccfe51363 100644 --- a/src/test/specs/dashboardViewStateSrv-specs.js +++ b/src/test/specs/dashboardViewStateSrv-specs.js @@ -20,6 +20,7 @@ define([ viewState.update(updateState); expect(location.search()).to.eql(updateState); expect(viewState.fullscreen).to.be(true); + expect(viewState.state.fullscreen).to.be(true); }); }); @@ -29,6 +30,7 @@ define([ viewState.update({fullscreen: false}); expect(location.search()).to.eql({}); expect(viewState.fullscreen).to.be(false); + expect(viewState.state.fullscreen).to.be(false); }); }); diff --git a/src/test/specs/templateSrv-specs.js b/src/test/specs/templateSrv-specs.js index ac711dce66a..938d8bfe0a1 100644 --- a/src/test/specs/templateSrv-specs.js +++ b/src/test/specs/templateSrv-specs.js @@ -62,6 +62,24 @@ define([ }); + describe('when checking if a string contains a variable', function() { + beforeEach(function() { + _templateSrv.init([{ name: 'test', current: { value: 'muuuu' } }]); + _templateSrv.updateTemplateData(); + }); + + it('should find it with $var syntax', function() { + var contains = _templateSrv.containsVariable('this.$test.filters', 'test'); + expect(contains).to.be(true); + }); + + it('should find it with [[var]] syntax', function() { + var contains = _templateSrv.containsVariable('this.[[test]].filters', 'test'); + expect(contains).to.be(true); + }); + + }); + describe('updateTemplateData with simple value', function() { beforeEach(function() { _templateSrv.init([{ name: 'test', current: { value: 'muuuu' } }]); diff --git a/src/test/specs/templateValuesSrv-specs.js b/src/test/specs/templateValuesSrv-specs.js index c0674a5cd75..bc0de36e959 100644 --- a/src/test/specs/templateValuesSrv-specs.js +++ b/src/test/specs/templateValuesSrv-specs.js @@ -27,20 +27,6 @@ define([ }); }); - describe.only('should init values', function() { - var variables = [ - { name: 'test', current: { value: 'hej' }} - ]; - var dashboard = { templating: { list: variables } }; - - beforeEach(function() { - ctx.service.init(dashboard); - }); - - it('should update options array', function() { - }); - }); - function describeUpdateVariable(desc, fn) { describe(desc, function() { var scenario = {}; @@ -139,12 +125,12 @@ define([ describeUpdateVariable('and existing value still exists in options', function(scenario) { scenario.setup(function() { scenario.variable = { type: 'query', query: 'apps.*', name: 'test' }; - scenario.variable.current = { value: 'backend2'}; + scenario.variable.current = { text: 'backend2'}; scenario.queryResult = [{text: 'backend1'}, {text: 'backend2'}]; }); it('should keep variable value', function() { - expect(scenario.variable.current.value).to.be('backend2'); + expect(scenario.variable.current.text).to.be('backend2'); }); }); @@ -196,18 +182,6 @@ define([ }); }); - describeUpdateVariable('and existing value still exists in options', function(scenario) { - scenario.setup(function() { - scenario.variable = { type: 'query', query: 'apps.*', name: 'test' }; - scenario.variable.current = { value: 'backend2'}; - scenario.queryResult = [{text: 'backend1'}, {text: 'backend2'}]; - }); - - it('should keep variable value', function() { - expect(scenario.variable.current.value).to.be('backend2'); - }); - }); - describeUpdateVariable('with include All glob syntax', function(scenario) { scenario.setup(function() { scenario.variable = { type: 'query', query: 'apps.*', name: 'test', includeAll: true, allFormat: 'glob' }; From a9d96ccc8cef20b07c84f1ed4a0160f5b2ba1aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 8 Sep 2014 18:03:10 +0200 Subject: [PATCH 04/59] Fixed ids for panels in default.json welcome to grafana dashboard --- src/app/dashboards/default.json | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/app/dashboards/default.json b/src/app/dashboards/default.json index 015ede1d7dc..4fcdf570d53 100644 --- a/src/app/dashboards/default.json +++ b/src/app/dashboards/default.json @@ -11,7 +11,7 @@ "collapse": false, "panels": [ { - "error": false, + "id": 1, "span": 12, "editable": true, "type": "text", @@ -28,20 +28,17 @@ "collapse": false, "panels": [ { - "error": false, + "id": 2, "span": 6, - "editable": true, "type": "text", - "loadingEditor": false, "mode": "html", "content": "
\n\n
\n
\n \n
\n
\n \n
\n
", "style": {}, "title": "Documentation Links" }, { - "error": false, + "id": 3, "span": 6, - "editable": true, "type": "text", "mode": "html", "content": "
\n\n
\n
\n
    \n
  • Ctrl+S saves the current dashboard
  • \n
  • Ctrl+F Opens the dashboard finder
  • \n
  • Ctrl+H Hide/show row controls
  • \n
  • Click and drag graph title to move panel
  • \n
  • Hit Escape to exit graph when in fullscreen or edit mode
  • \n
  • Click the colored icon in the legend to change series color
  • \n
  • Ctrl or Shift + Click legend name to hide other series
  • \n
\n
\n
\n", @@ -56,8 +53,8 @@ "collapse": false, "panels": [ { + "id": 4, "span": 12, - "editable": true, "type": "graph", "x-axis": true, "y-axis": true, From 4798aa4789d673363bb6a9af53bddca10827e8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 9 Sep 2014 08:24:04 +0200 Subject: [PATCH 05/59] Fixes to requirejs build task to include all modules, Fixes #779 --- tasks/options/requirejs.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tasks/options/requirejs.js b/tasks/options/requirejs.js index b3bc4f97909..c1a718c3397 100644 --- a/tasks/options/requirejs.js +++ b/tasks/options/requirejs.js @@ -1,4 +1,6 @@ module.exports = function(config,grunt) { + 'use strict'; + var _c = { build: { options: { @@ -59,12 +61,15 @@ module.exports = function(config,grunt) { 'directives/all', 'jquery.flot.pie', 'angular-dragdrop', + 'controllers/all', + 'routes/all', + 'components/partials', ] } ]; var fs = require('fs'); - var panelPath = config.srcDir+'/app/panels' + var panelPath = config.srcDir+'/app/panels'; // create a module for each directory in src/app/panels/ fs.readdirSync(panelPath).forEach(function (panelName) { From 0f88b470e8e2f35e18d23384d2f37840458828d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 9 Sep 2014 08:50:01 +0200 Subject: [PATCH 06/59] Fix for elasticsearch annotations when timestamp is a field and not in source, Fixes #777 --- src/app/partials/annotations_editor.html | 3 +++ src/app/services/elasticsearch/es-datasource.js | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/app/partials/annotations_editor.html b/src/app/partials/annotations_editor.html index cb9db2244d6..c72194b6f6a 100644 --- a/src/app/partials/annotations_editor.html +++ b/src/app/partials/annotations_editor.html @@ -16,6 +16,9 @@
+
+ No annotations defined +
diff --git a/src/app/services/elasticsearch/es-datasource.js b/src/app/services/elasticsearch/es-datasource.js index 34db3b50d8a..721ba00881b 100644 --- a/src/app/services/elasticsearch/es-datasource.js +++ b/src/app/services/elasticsearch/es-datasource.js @@ -76,7 +76,11 @@ function (angular, _, $, config, kbn, moment) { var queryInterpolated = templateSrv.replace(queryString); var filter = { "bool": { "must": [{ "range": range }] } }; var query = { "bool": { "should": [{ "query_string": { "query": queryInterpolated } }] } }; - var data = { "query" : { "filtered": { "query" : query, "filter": filter } }, "size": 100 }; + var data = { + "fields": [timeField, "_source"], + "query" : { "filtered": { "query" : query, "filter": filter } }, + "size": 100 + }; return this._request('POST', '/_search', annotation.index, data).then(function(results) { var list = []; @@ -84,9 +88,16 @@ function (angular, _, $, config, kbn, moment) { for (var i = 0; i < hits.length; i++) { var source = hits[i]._source; + var fields = hits[i].fields; + var time = source[timeField]; + + if (_.isString(fields[timeField]) || _.isNumber(fields[timeField])) { + time = fields[timeField]; + } + var event = { annotation: annotation, - time: moment.utc(source[timeField]).valueOf(), + time: moment.utc(time).valueOf(), title: source[titleField], }; From 71a307270aea56158d64c2182ff738a85cb70067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 9 Sep 2014 09:16:00 +0200 Subject: [PATCH 07/59] Fixed text color in json text area for white theme, #735 --- src/app/partials/edit_json.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/partials/edit_json.html b/src/app/partials/edit_json.html index c4fa5fd950f..a43e1d56bcd 100644 --- a/src/app/partials/edit_json.html +++ b/src/app/partials/edit_json.html @@ -8,7 +8,7 @@
- +
-
+
+ +
    +
  • + +
  • - cacheTimeout Graphite parameter to overwride memcache default timeout (unit is seconds) + cacheTimeout
  • + class="input-mini grafana-target-segment-input" + ng-model="panel.cacheTimeout" + bs-tooltip="'Graphite parameter to overwride memcache default timeout (unit is seconds)'" + data-placement="right" + spellcheck='false' + placeholder="60">
-
+
+
+ +
+
+
+ +
+
Shorter legend names
+
    +
  • alias() function to specify a custom series name
  • +
  • aliasByNode(2) to alias by a specific part of your metric path
  • +
  • aliasByNode(2, -1) you can add multiple segment paths, and use negative index
  • +
  • groupByNode(2, 'sum') is useful if you have 2 wildcards in your metric path and want to sumSeries and group by
  • +
+
+ +
+
Series as parameter
+
    +
  • Some graphite functions allow you to have many series arguments
  • +
  • Use #[A-Z] to use a graphite query as parameter to a function
  • +
  • + Examples: +
      +
    • asPercent(#A, #B)
    • +
    • prod.srv-01.counters.count - asPercent(#A) : percentage of count in comparison with A query
    • +
    • prod.srv-01.counters.count - sumSeries(#A) : sum count and series A
    • +
    • divideSeries(#A, #B)
    • +
    +
  • +
  • If a query is added only to be used as a parameter, hide it from the graph with the eye icon
  • +
+
+ +
+
Stacking
+
    +
  • You find the stacking option under Display Styles tab
  • +
  • When stacking is enabled make sure null point mode is set to 'null as zero'
  • +
+
+ +
+
Templating
+
    +
  • You can use a template variable in place of metric names
  • +
  • You can use a template variable in place of function parameters
  • +
  • You enable the templating feature in Dashboard settings / Feature toggles
  • +
+
+ +
diff --git a/src/app/partials/influxdb/editor.html b/src/app/partials/influxdb/editor.html index 70da2fbf282..4fd13645d3d 100644 --- a/src/app/partials/influxdb/editor.html +++ b/src/app/partials/influxdb/editor.html @@ -181,8 +181,8 @@
    -
  • - +
  • +
  • group by time @@ -227,8 +227,8 @@
    -
    - Alias patterns: +
    +
    Alias patterns
    • $s = series name
    • $g = group by
    • @@ -236,8 +236,8 @@
    -
    - Stacking and fill: +
    +
    Stacking and fill
    • When stacking is enabled it important that points align
    • If there are missing points for one series it can cause gaps or missing bars
    • @@ -247,8 +247,8 @@
    -
    - Group by time: +
    +
    Group by time
    • Group by time is important, otherwise the query could return many thousands of datapoints that will slow down Grafana
    • Leave the group by time field empty for each query and it will be calculated based on time range and pixel width of the graph
    • diff --git a/src/css/less/grafana.less b/src/css/less/grafana.less index 022319a1042..7c17e6967db 100644 --- a/src/css/less/grafana.less +++ b/src/css/less/grafana.less @@ -485,3 +485,22 @@ select.grafana-target-segment-input { color: @variable; } +.grafana-info-box:before { + content: "\f05a"; + font-family:'FontAwesome'; + position: absolute; + top: -8px; + left: -8px; + font-size: 20px; + color: @blue; +} + +.grafana-info-box { + position: relative; + padding: 5px 15px; + background-color: @grafanaTargetBackground; + border: 1px solid @grafanaTargetBorder; + h5 { + margin-top: 5px; + } +} From b1abe72ab65190cf9611372bb000eb6655107846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Sep 2014 11:34:32 +0200 Subject: [PATCH 25/59] small update to text panel editor --- src/app/panels/text/editor.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/panels/text/editor.html b/src/app/panels/text/editor.html index 6af4dc069c2..b3b8afbbec0 100644 --- a/src/app/panels/text/editor.html +++ b/src/app/panels/text/editor.html @@ -9,10 +9,9 @@
    - -
    \ No newline at end of file +
    From 4883b2a2960a56aac3e19f490e948aa7228ae531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Sep 2014 13:54:59 +0200 Subject: [PATCH 26/59] Fixed issue with using template variables in panel titles, and text panel, when selecting All option in variable --- package.json | 2 +- src/app/filters/all.js | 2 +- src/app/services/templateSrv.js | 41 ++++++++++++++++++++--------- src/test/specs/templateSrv-specs.js | 17 ++++++++++++ 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 8de8f05cf8a..f84ca9cf8c6 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "company": "Coding Instinct AB" }, "name": "grafana", - "version": "1.8.0", + "version": "1.8.0-rc1", "repository": { "type": "git", "url": "http://github.com/torkelo/grafana.git" diff --git a/src/app/filters/all.js b/src/app/filters/all.js index b2729d120dd..eb9a736d0ce 100755 --- a/src/app/filters/all.js +++ b/src/app/filters/all.js @@ -57,7 +57,7 @@ define(['angular', 'jquery', 'lodash', 'moment'], function (angular, $, _, momen module.filter('interpolateTemplateVars', function(templateSrv) { return function(text) { - return templateSrv.replace(text); + return templateSrv.replaceWithText(text); }; }); diff --git a/src/app/services/templateSrv.js b/src/app/services/templateSrv.js index d63a9df34d4..c201147becf 100644 --- a/src/app/services/templateSrv.js +++ b/src/app/services/templateSrv.js @@ -11,26 +11,25 @@ function (angular, _) { var self = this; this._regex = /\$(\w+)|\[\[([\s\S]+?)\]\]/g; - this._templateData = {}; + this._values = {}; + this._texts = {}; this._grafanaVariables = {}; this.init = function(variables) { this.variables = variables; - this.updateTemplateData(true); + this.updateTemplateData(); }; this.updateTemplateData = function() { - var data = {}; + this._values = {}; + this._texts = {}; _.each(this.variables, function(variable) { - if (!variable.current || !variable.current.value) { - return; - } + if (!variable.current || !variable.current.value) { return; } - data[variable.name] = variable.current.value; - }); - - this._templateData = data; + this._values[variable.name] = variable.current.value; + this._texts[variable.name] = variable.current.text; + }, this); }; this.setGrafanaVariable = function (name, value) { @@ -40,7 +39,7 @@ function (angular, _) { this.variableExists = function(expression) { this._regex.lastIndex = 0; var match = this._regex.exec(expression); - return match && (self._templateData[match[1] || match[2]] !== void 0); + return match && (self._values[match[1] || match[2]] !== void 0); }; this.containsVariable = function(str, variableName) { @@ -52,7 +51,7 @@ function (angular, _) { this._regex.lastIndex = 0; return str.replace(this._regex, function(match, g1, g2) { - if (self._templateData[g1 || g2]) { + if (self._values[g1 || g2]) { return '' + match + ''; } return match; @@ -66,13 +65,29 @@ function (angular, _) { this._regex.lastIndex = 0; return target.replace(this._regex, function(match, g1, g2) { - value = self._templateData[g1 || g2]; + value = self._values[g1 || g2]; if (!value) { return match; } return self._grafanaVariables[value] || value; }); }; + this.replaceWithText = function(target) { + if (!target) { return; } + + var value; + var text; + this._regex.lastIndex = 0; + + return target.replace(this._regex, function(match, g1, g2) { + value = self._values[g1 || g2]; + text = self._texts[g1 || g2]; + if (!value) { return match; } + + return self._grafanaVariables[value] || text; + }); + }; + }); }); diff --git a/src/test/specs/templateSrv-specs.js b/src/test/specs/templateSrv-specs.js index 938d8bfe0a1..f740ef6d544 100644 --- a/src/test/specs/templateSrv-specs.js +++ b/src/test/specs/templateSrv-specs.js @@ -92,6 +92,23 @@ define([ }); }); + describe('replaceWithText', function() { + beforeEach(function() { + _templateSrv.init([ + { name: 'server', current: { value: '{asd,asd2}', text: 'All' } }, + { name: 'period', current: { value: '$__auto_interval', text: 'auto' } } + ]); + _templateSrv.setGrafanaVariable('$__auto_interval', '13m'); + _templateSrv.updateTemplateData(); + }); + + it('should replace with text except for grafanaVariables', function() { + var target = _templateSrv.replaceWithText('Server: $server, period: $period'); + expect(target).to.be('Server: All, period: 13m'); + }); + }); + + }); }); From a65c61442ede3d656c3ef648538e89730670a6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Sep 2014 14:01:37 +0200 Subject: [PATCH 27/59] minifix for spacing of question sign tooltips when html is minified --- src/app/directives/tip.js | 4 ++-- src/app/panels/graph/styleEditor.html | 2 +- src/css/less/grafana.less | 4 ++++ src/css/less/variables.dark.less | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/app/directives/tip.js b/src/app/directives/tip.js index 975a4c02228..974ed98a637 100644 --- a/src/app/directives/tip.js +++ b/src/app/directives/tip.js @@ -11,10 +11,10 @@ function (angular, kbn) { return { restrict: 'E', link: function(scope, elem, attrs) { - var _t = ''; elem.replaceWith($compile(angular.element(_t))(scope)); } }; }); -}); \ No newline at end of file +}); diff --git a/src/app/panels/graph/styleEditor.html b/src/app/panels/graph/styleEditor.html index b8c80473ebd..cd83f23f197 100644 --- a/src/app/panels/graph/styleEditor.html +++ b/src/app/panels/graph/styleEditor.html @@ -27,7 +27,7 @@
    - +
    diff --git a/src/css/less/grafana.less b/src/css/less/grafana.less index 7c17e6967db..3e52b7fc94c 100644 --- a/src/css/less/grafana.less +++ b/src/css/less/grafana.less @@ -504,3 +504,7 @@ select.grafana-target-segment-input { margin-top: 5px; } } + +.grafana-tip { + padding-left: 5px; +} diff --git a/src/css/less/variables.dark.less b/src/css/less/variables.dark.less index 608dfb609b0..f3817ef454d 100644 --- a/src/css/less/variables.dark.less +++ b/src/css/less/variables.dark.less @@ -35,7 +35,7 @@ // Graphite Target Editor @grafanaTargetBorder: @black; -@grafanaTargetBackground: @grayDark; +@grafana-info-box grafanaTargetBackground: @grayDark; @grafanaTargetColor: #c8c8c8; @grafanaTargetColorHide: darken(#c8c8c8, 25%); @grafanaTargetSegmentBorder: #050505; From 762dab618afb31f071488be6d1155cfa87443d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Sep 2014 14:07:27 +0200 Subject: [PATCH 28/59] Small change to datasourceSrv, if datasource is not found, return default datasource --- src/app/services/datasourceSrv.js | 2 +- src/css/less/variables.dark.less | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/services/datasourceSrv.js b/src/app/services/datasourceSrv.js index 5d26ebdc28c..effb3d1a7dc 100644 --- a/src/app/services/datasourceSrv.js +++ b/src/app/services/datasourceSrv.js @@ -80,7 +80,7 @@ function (angular, _, config) { if (!name) { return this.default; } if (datasources[name]) { return datasources[name]; } - throw "Unable to find datasource: " + name; + return this.default; }; this.getAnnotationSources = function() { diff --git a/src/css/less/variables.dark.less b/src/css/less/variables.dark.less index f3817ef454d..608dfb609b0 100644 --- a/src/css/less/variables.dark.less +++ b/src/css/less/variables.dark.less @@ -35,7 +35,7 @@ // Graphite Target Editor @grafanaTargetBorder: @black; -@grafana-info-box grafanaTargetBackground: @grayDark; +@grafanaTargetBackground: @grayDark; @grafanaTargetColor: #c8c8c8; @grafanaTargetColorHide: darken(#c8c8c8, 25%); @grafanaTargetSegmentBorder: #050505; From 6ca73f6df0d99e7bea0cdd84875ab990b7593c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Sep 2014 14:25:20 +0200 Subject: [PATCH 29/59] Do not render graph when width is zero, avoids plot errors --- src/app/directives/grafanaGraph.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/app/directives/grafanaGraph.js b/src/app/directives/grafanaGraph.js index 9bb302bf671..15f1556aa62 100755 --- a/src/app/directives/grafanaGraph.js +++ b/src/app/directives/grafanaGraph.js @@ -15,7 +15,7 @@ function (angular, $, kbn, moment, _) { restrict: 'A', template: '
    ', link: function(scope, elem) { - var data, plot, annotations; + var data, annotations; var hiddenData = {}; var dashboard = scope.dashboard; var legendSideLastValue = null; @@ -82,6 +82,10 @@ function (angular, $, kbn, moment, _) { render_panel_as_graphite_png(data); return true; } + + if (elem.width() === 0) { + return; + } } // Function for rendering panel @@ -165,18 +169,22 @@ function (angular, $, kbn, moment, _) { var sortedSeries = _.sortBy(data, function(series) { return series.zindex; }); - // if legend is to the right delay plot draw a few milliseconds - // so the legend width calculation can be done + function callPlot() { + try { + $.plot(elem, sortedSeries, options); + } catch (e) { + console.log('flotcharts error', e); + } + + addAxisLabels(); + } + if (shouldDelayDraw(panel)) { + setTimeout(callPlot, 50); legendSideLastValue = panel.legend.rightSide; - setTimeout(function() { - plot = $.plot(elem, sortedSeries, options); - addAxisLabels(); - }, 50); } else { - plot = $.plot(elem, sortedSeries, options); - addAxisLabels(); + callPlot(); } } From 5a3db0505fb3a95ab925045b8d0e0813722ef683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Sep 2014 16:00:59 +0200 Subject: [PATCH 30/59] Small fix to elasticsearch save error handling --- src/app/services/elasticsearch/es-datasource.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/services/elasticsearch/es-datasource.js b/src/app/services/elasticsearch/es-datasource.js index 4d1f6272720..80e3c5d0100 100644 --- a/src/app/services/elasticsearch/es-datasource.js +++ b/src/app/services/elasticsearch/es-datasource.js @@ -170,8 +170,8 @@ function (angular, _, config, kbn, moment) { .then(function(results) { self._removeUnslugifiedDashboard(results, title); return { title: title, url: '/dashboard/db/' + id }; - }, function(err) { - throw 'Failed to save to elasticsearch ' + err.data; + }, function() { + throw 'Failed to save to elasticsearch'; }); } }; From 2c6ea276c1c0bfc684e7ed29d80d79e65e21716f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Sep 2014 17:19:39 +0200 Subject: [PATCH 31/59] Fixed small bug in graphite target controller when having variable for single parameter function --- src/app/controllers/graphiteTarget.js | 2 +- src/test/specs/graphiteTargetCtrl-specs.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/app/controllers/graphiteTarget.js b/src/app/controllers/graphiteTarget.js index cd13926cc80..cd8462ac62d 100644 --- a/src/app/controllers/graphiteTarget.js +++ b/src/app/controllers/graphiteTarget.js @@ -90,7 +90,7 @@ function (angular, _, config, gfunc, Parser) { break; case 'metric': if ($scope.segments.length > 0) { - if ($scope.segments[0].length !== 1) { + if (astNode.segments.length !== 1) { throw { message: 'Multiple metric params not supported, use text editor.' }; } addFunctionParameter(func, astNode.segments[0].value, index, true); diff --git a/src/test/specs/graphiteTargetCtrl-specs.js b/src/test/specs/graphiteTargetCtrl-specs.js index 57f3870cb5d..27be0d92b26 100644 --- a/src/test/specs/graphiteTargetCtrl-specs.js +++ b/src/test/specs/graphiteTargetCtrl-specs.js @@ -99,6 +99,25 @@ define([ }); + describe('when initializing a target with single param func using variable', function() { + beforeEach(function() { + ctx.scope.target.target = 'movingAverage(prod.count, $var)'; + ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([])); + ctx.scope.init(); + ctx.scope.$digest(); + ctx.scope.$parent = { get_data: sinon.spy() }; + }); + + it('should add 2 segments', function() { + expect(ctx.scope.segments.length).to.be(2); + }); + + it('should add function param', function() { + expect(ctx.scope.functions[0].params.length).to.be(1); + }); + + }); + describe('when initalizing target without metric expression and function with series-ref', function() { beforeEach(function() { ctx.scope.target.target = 'asPercent(metric.node.count, #A)'; From 48eb2083f25566995575dd7773ca80fd08a4c140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 11 Sep 2014 17:25:59 +0200 Subject: [PATCH 32/59] Fix for graphite query letter assignment --- src/app/controllers/graphiteTarget.js | 2 +- src/app/partials/graphite/editor.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/controllers/graphiteTarget.js b/src/app/controllers/graphiteTarget.js index cd8462ac62d..27299474bc0 100644 --- a/src/app/controllers/graphiteTarget.js +++ b/src/app/controllers/graphiteTarget.js @@ -15,7 +15,7 @@ function (angular, _, config, gfunc, Parser) { $scope.init = function() { $scope.target.target = $scope.target.target || ''; - $scope.targetLetter = targetLetters[$scope.$index]; + $scope.targetLetters = targetLetters; parseTarget(); }; diff --git a/src/app/partials/graphite/editor.html b/src/app/partials/graphite/editor.html index 46e7d081884..4d670255bc0 100755 --- a/src/app/partials/graphite/editor.html +++ b/src/app/partials/graphite/editor.html @@ -41,7 +41,7 @@
    • - {{targetLetter}} + {{targetLetters[$index]}}
    • Date: Fri, 12 Sep 2014 13:15:06 +0200 Subject: [PATCH 33/59] Small fix to scripted async dashboard example --- src/app/dashboards/scripted_async.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/app/dashboards/scripted_async.js b/src/app/dashboards/scripted_async.js index 84e5d976f6b..31d23f2dde2 100644 --- a/src/app/dashboards/scripted_async.js +++ b/src/app/dashboards/scripted_async.js @@ -35,11 +35,9 @@ return function(callback) { // Set a title dashboard.title = 'Scripted dash'; - dashboard.services.filter = { - time: { - from: "now-" + (ARGS.from || timspan), - to: "now" - } + dashboard.time = { + from: "now-" + (ARGS.from || timspan), + to: "now" }; var rows = 1; @@ -78,4 +76,4 @@ return function(callback) { callback(dashboard); }); -} \ No newline at end of file +} From bf9eaea33450c8c322e70056efd3b0e46192fd1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 12 Sep 2014 13:19:17 +0200 Subject: [PATCH 34/59] Updated lastest.json --- latest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/latest.json b/latest.json index 38e862a643a..c66de1bc179 100644 --- a/latest.json +++ b/latest.json @@ -1,4 +1,4 @@ { - "version": "1.7.0", - "url": "http://grafanarel.s3.amazonaws.com/grafana-1.7.0" + "version": "1.8.0-rc1", + "url": "http://grafanarel.s3.amazonaws.com/grafana-1.8.0-rc1" } From 15f2b2cf9a8a8318fbe0a5d52377cd32286a18ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 13 Sep 2014 16:19:33 +0200 Subject: [PATCH 35/59] Annotations: fixed InfluxDB annotation query, added unit test for annotation query, Fixes #802 --- CHANGELOG.md | 7 ++++- .../services/influxdb/influxdbDatasource.js | 2 +- src/test/specs/influxdb-datasource-specs.js | 26 ++++++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a182bbf6cad..6d6c63ee023 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -# 1.8.0 (unreleased) +# 1.8.0 (2014-09-12) + +**Fixes** +- [Issue #802](https://github.com/grafana/grafana/issues/802). Annotations: Fix when using InfluxDB datasource + +# 1.8.0-RC1 (2014-09-12) **UI polish / changes** - [Issue #725](https://github.com/grafana/grafana/issues/725). UI: All modal editors are removed and replaced by an edit pane under menu. The look of editors is also updated and polished. Search dropdown is also shown as pane under menu and has seen some UI polish. diff --git a/src/app/services/influxdb/influxdbDatasource.js b/src/app/services/influxdb/influxdbDatasource.js index d9a7d8b378c..c076fb2c5e1 100644 --- a/src/app/services/influxdb/influxdbDatasource.js +++ b/src/app/services/influxdb/influxdbDatasource.js @@ -64,7 +64,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) { InfluxDatasource.prototype.annotationQuery = function(annotation, rangeUnparsed) { var timeFilter = getTimeFilter({ range: rangeUnparsed }); var query = annotation.query.replace('$timeFilter', timeFilter); - query = templateSrv.replace(annotation.query); + query = templateSrv.replace(query); return this._seriesQuery(query).then(function(results) { return new InfluxSeries({ seriesList: results, annotation: annotation }).getAnnotations(); diff --git a/src/test/specs/influxdb-datasource-specs.js b/src/test/specs/influxdb-datasource-specs.js index ddf7db48282..3851b0cd898 100644 --- a/src/test/specs/influxdb-datasource-specs.js +++ b/src/test/specs/influxdb-datasource-specs.js @@ -8,7 +8,7 @@ define([ var ctx = new helpers.ServiceTestContext(); beforeEach(module('grafana.services')); - beforeEach(ctx.providePhase()); + beforeEach(ctx.providePhase(['templateSrv'])); beforeEach(ctx.createService('InfluxDatasource')); beforeEach(function() { ctx.ds = new ctx.service({ urls: [''], user: 'test', password: 'mupp' }); @@ -70,6 +70,30 @@ define([ }); + describe('When issuing annotation query', function() { + var results; + var urlExpected = "/series?p=mupp&q=select+title+from+events.backend_01"+ + "+where+time+%3E+now()+-+1h&time_precision=s"; + + var range = { from: 'now-1h', to: 'now' }; + var annotation = { query: 'select title from events.$server where $timeFilter' }; + var response = []; + + beforeEach(function() { + ctx.templateSrv.replace = function(str) { + return str.replace('$server', 'backend_01'); + }; + ctx.$httpBackend.expect('GET', urlExpected).respond(response); + ctx.ds.annotationQuery(annotation, range).then(function(data) { results = data; }); + ctx.$httpBackend.flush(); + }); + + it('should generate the correct query', function() { + ctx.$httpBackend.verifyNoOutstandingExpectation(); + }); + + }); + }); }); From 96a0d0aefa0005211d35f2c2af43731e1fa2384e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 13 Sep 2014 16:38:01 +0200 Subject: [PATCH 36/59] fixed changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d6c63ee023..2301c2b35a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.8.0 (2014-09-12) +# 1.8.0 (unreleased) **Fixes** - [Issue #802](https://github.com/grafana/grafana/issues/802). Annotations: Fix when using InfluxDB datasource From 92bec31ccb158a5edd234e302adae2262cb46ff1 Mon Sep 17 00:00:00 2001 From: starshayayord Date: Mon, 15 Sep 2014 18:51:58 +0600 Subject: [PATCH 37/59] Update index.html disable google translate plugin --- src/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.html b/src/index.html index 63e837abfcd..d47f9df9196 100644 --- a/src/index.html +++ b/src/index.html @@ -5,6 +5,7 @@ + Grafana From 32a41a8422b8b5c4381efd0aacbe989e747b4d8c Mon Sep 17 00:00:00 2001 From: Lorenzo Pierfederici Date: Mon, 15 Sep 2014 18:12:20 -0700 Subject: [PATCH 38/59] add override options to allow multiple stacks --- src/app/panels/graph/seriesOverridesCtrl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/panels/graph/seriesOverridesCtrl.js b/src/app/panels/graph/seriesOverridesCtrl.js index 4f54c6d0e6f..1b6b1dfc144 100644 --- a/src/app/panels/graph/seriesOverridesCtrl.js +++ b/src/app/panels/graph/seriesOverridesCtrl.js @@ -70,7 +70,7 @@ define([ $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.addOverrideOption('Stack', 'stack', [true, false, 2, 3, 4, 5]); $scope.addOverrideOption('Y-axis', 'yaxis', [1, 2]); $scope.addOverrideOption('Z-index', 'zindex', [-1,-2,-3,0,1,2,3]); $scope.updateCurrentOverrides(); From ff91430fcc9e539671cde35e27a04101a8b202bb Mon Sep 17 00:00:00 2001 From: Torkel Odegaard Date: Tue, 16 Sep 2014 08:01:18 +0200 Subject: [PATCH 39/59] added favicons --- src/app/partials/dashboard_topnav.html | 2 +- src/img/fav16.png | Bin 0 -> 639 bytes src/img/fav32.png | Bin 0 -> 1344 bytes src/index.html | 1 + 4 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 src/img/fav16.png create mode 100644 src/img/fav32.png diff --git a/src/app/partials/dashboard_topnav.html b/src/app/partials/dashboard_topnav.html index 15ea694058c..689b8374b1c 100644 --- a/src/app/partials/dashboard_topnav.html +++ b/src/app/partials/dashboard_topnav.html @@ -1,7 +1,7 @@