diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e12da99428..6cef10f2c88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ vNext - improved asset (css/js) build pipeline, added revision to css and js. Will remove issues related to the browser cache when upgrading grafana and improve load performance (Fixes #418) - Partial support for url encoded metrics when using Graphite datasource (PR #327) - thx @axe-felix +- Improvement to InfluxDB query editor and function/value column selection (Issue #473) +- Initial support for filtering (templated queries) for InfluxDB (PR #375) - thx @mavimo # Fixes - Filter option loading when having muliple nested filters now works better. diff --git a/src/app/controllers/influxTargetCtrl.js b/src/app/controllers/influxTargetCtrl.js index 0be0abedb36..a7dcbf85828 100644 --- a/src/app/controllers/influxTargetCtrl.js +++ b/src/app/controllers/influxTargetCtrl.js @@ -11,9 +11,8 @@ function (angular) { module.controller('InfluxTargetCtrl', function($scope, $timeout) { $scope.init = function() { - if (!$scope.target.function) { - $scope.target.function = 'mean'; - } + $scope.target.function = $scope.target.function || 'mean'; + $scope.target.column = $scope.target.column || 'value'; $scope.rawQuery = false; @@ -44,6 +43,11 @@ function (angular) { } }; + $scope.changeFunction = function(func) { + $scope.target.function = func; + $scope.get_data(); + }; + // called outside of digest $scope.listColumns = function(query, callback) { if (!$scope.columnList) { diff --git a/src/app/directives/all.js b/src/app/directives/all.js index 01fed7c4b2f..8688c5d9539 100644 --- a/src/app/directives/all.js +++ b/src/app/directives/all.js @@ -15,5 +15,6 @@ define([ './bodyClass', './addGraphiteFunc', './graphiteFuncEditor', - './grafanaVersionCheck' + './grafanaVersionCheck', + './influxdbFuncEditor' ], function () {}); \ No newline at end of file diff --git a/src/app/directives/influxdbFuncEditor.js b/src/app/directives/influxdbFuncEditor.js new file mode 100644 index 00000000000..e10dad85127 --- /dev/null +++ b/src/app/directives/influxdbFuncEditor.js @@ -0,0 +1,137 @@ +define([ + 'angular', + 'underscore', + 'jquery', +], +function (angular, _, $) { + 'use strict'; + + angular + .module('kibana.directives') + .directive('influxdbFuncEditor', function($compile) { + + var funcSpanTemplate = '{{target.function}}('; + + var paramTemplate = ''; + + return { + restrict: 'A', + link: function postLink($scope, elem) { + var $funcLink = $(funcSpanTemplate); + + $scope.functionMenu = _.map($scope.functions, function(func) { + return { + text: func, + click: "changeFunction('" + func + "');" + }; + }); + + function clickFuncParam() { + /*jshint validthis:true */ + + var $link = $(this); + var $input = $link.next(); + + $input.val($scope.target.column); + $input.css('width', ($link.width() + 16) + 'px'); + + $link.hide(); + $input.show(); + $input.focus(); + $input.select(); + + var typeahead = $input.data('typeahead'); + if (typeahead) { + $input.val(''); + typeahead.lookup(); + } + } + + function inputBlur() { + /*jshint validthis:true */ + + var $input = $(this); + var $link = $input.prev(); + + if ($input.val() !== '') { + $link.text($input.val()); + + $scope.target.column = $input.val(); + $scope.$apply($scope.get_data); + } + + $input.hide(); + $link.show(); + } + + function inputKeyPress(e) { + /*jshint validthis:true */ + + if(e.which === 13) { + inputBlur.call(this); + } + } + + function inputKeyDown() { + /*jshint validthis:true */ + this.style.width = (3 + this.value.length) * 8 + 'px'; + } + + function addTypeahead($input) { + $input.attr('data-provide', 'typeahead'); + + $input.typeahead({ + source: function () { + return $scope.listColumns.apply(null, arguments); + }, + minLength: 0, + items: 20, + updater: function (value) { + setTimeout(function() { + inputBlur.call($input[0]); + }, 0); + return value; + } + }); + + var typeahead = $input.data('typeahead'); + typeahead.lookup = function () { + var items; + this.query = this.$element.val() || ''; + items = this.source(this.query, $.proxy(this.process, this)); + return items ? this.process(items) : items; + }; + } + + function addElementsAndCompile() { + $funcLink.appendTo(elem); + + var $paramLink = $('' + $scope.target.column + ''); + var $input = $(paramTemplate); + + $paramLink.appendTo(elem); + $input.appendTo(elem); + + $input.blur(_.partial(inputBlur)); + $input.keyup(inputKeyDown); + $input.keypress(_.partial(inputKeyPress)); + $paramLink.click(_.partial(clickFuncParam)); + + addTypeahead($input); + + $(')').appendTo(elem); + + $compile(elem.contents())($scope); + } + + addElementsAndCompile(); + + } + }; + + }); + + +}); \ No newline at end of file diff --git a/src/app/partials/influxdb/editor.html b/src/app/partials/influxdb/editor.html index 07f6ad52b7b..7026aa87438 100644 --- a/src/app/partials/influxdb/editor.html +++ b/src/app/partials/influxdb/editor.html @@ -53,13 +53,9 @@ ng-show="target.rawQuery"> diff --git a/src/app/services/influxdb/influxdbDatasource.js b/src/app/services/influxdb/influxdbDatasource.js index 3aa5fcc3956..01ef1ae9d44 100644 --- a/src/app/services/influxdb/influxdbDatasource.js +++ b/src/app/services/influxdb/influxdbDatasource.js @@ -26,6 +26,7 @@ function (angular, _, kbn) { InfluxDatasource.prototype.query = function(filterSrv, options) { var promises = _.map(options.targets, function(target) { var query; + var alias = ''; if (target.hide || !((target.series && target.column) || target.query)) { return []; @@ -80,10 +81,15 @@ function (angular, _, kbn) { query = _.template(template, templateData, this.templateSettings); query = filterSrv.applyTemplateToTarget(query); + + if (target.alias) { + alias = filterSrv.applyTemplateToTarget(target.alias); + } + target.query = query; } - return this.doInfluxRequest(query, target.alias).then(handleInfluxQueryResponse); + return this.doInfluxRequest(query, alias).then(handleInfluxQueryResponse); }, this); @@ -185,9 +191,11 @@ function (angular, _, kbn) { var target = data.alias || series.name + "." + column; var datapoints = []; + var value; for(var i = 0; i < series.points.length; i++) { - datapoints[i] = [series.points[i][index], series.points[i][timeCol]]; + value = isNaN(series.points[i][index]) ? null : series.points[i][index]; + datapoints[i] = [value, series.points[i][timeCol]]; } output.push({ target:target, datapoints:datapoints });