mirror of
https://github.com/grafana/grafana.git
synced 2024-11-25 18:30:41 -06:00
Working on new query editor for influxdb 0.9, #1525
This commit is contained in:
parent
a258e2e608
commit
11c8e80ea9
@ -12,7 +12,7 @@ define([
|
||||
'./bootstrap-tagsinput',
|
||||
'./bodyClass',
|
||||
'./variableValueSelect',
|
||||
'./graphiteSegment',
|
||||
'./metric.segment',
|
||||
'./grafanaVersionCheck',
|
||||
'./dropdown.typeahead',
|
||||
'./topnav',
|
||||
|
@ -9,7 +9,7 @@ function (angular, app, _, $) {
|
||||
|
||||
angular
|
||||
.module('grafana.directives')
|
||||
.directive('graphiteSegment', function($compile, $sce) {
|
||||
.directive('metricSegment', function($compile, $sce) {
|
||||
var inputTemplate = '<input type="text" data-provide="typeahead" ' +
|
||||
' class="tight-form-clear-input input-medium"' +
|
||||
' spellcheck="false" style="display:none"></input>';
|
||||
@ -17,6 +17,12 @@ function (angular, app, _, $) {
|
||||
var buttonTemplate = '<a class="tight-form-item" tabindex="1" focus-me="segment.focus" ng-bind-html="segment.html"></a>';
|
||||
|
||||
return {
|
||||
scope: {
|
||||
segment: "=",
|
||||
getAltSegments: "&",
|
||||
onValueChanged: "&"
|
||||
},
|
||||
|
||||
link: function($scope, elem) {
|
||||
var $input = $(inputTemplate);
|
||||
var $button = $(buttonTemplate);
|
||||
@ -46,7 +52,7 @@ function (angular, app, _, $) {
|
||||
segment.expandable = true;
|
||||
segment.fake = false;
|
||||
}
|
||||
$scope.segmentValueChanged(segment, $scope.$index);
|
||||
$scope.onValueChanged();
|
||||
});
|
||||
};
|
||||
|
||||
@ -69,7 +75,8 @@ function (angular, app, _, $) {
|
||||
if (options) { return options; }
|
||||
|
||||
$scope.$apply(function() {
|
||||
$scope.getAltSegments($scope.$index).then(function() {
|
||||
$scope.getAltSegments().then(function(altSegments) {
|
||||
$scope.altSegments = altSegments;
|
||||
options = _.map($scope.altSegments, function(alt) { return alt.value; });
|
||||
|
||||
// add custom values
|
@ -74,7 +74,9 @@
|
||||
ng-show="showTextEditor" />
|
||||
|
||||
<ul class="tight-form-list" role="menu" ng-hide="showTextEditor">
|
||||
<li ng-repeat="segment in segments" role="menuitem" graphite-segment></li>
|
||||
<li ng-repeat="segment in segments" role="menuitem">
|
||||
<metric-segment segment="segment" get-alt-segments="getAltSegments($index)" on-value-changed="segmentValueChanged(segment, $index)"></metric-segment>
|
||||
</li>
|
||||
<li ng-repeat="func in functions">
|
||||
<span graphite-func-editor class="tight-form-item tight-form-func">
|
||||
</span>
|
||||
|
@ -152,23 +152,18 @@ function (angular, _, config, gfunc, Parser) {
|
||||
}
|
||||
|
||||
$scope.getAltSegments = function (index) {
|
||||
$scope.altSegments = [];
|
||||
|
||||
var query = index === 0 ? '*' : getSegmentPathUpTo(index) + '.*';
|
||||
|
||||
return $scope.datasource.metricFindQuery(query)
|
||||
.then(function(segments) {
|
||||
$scope.altSegments = _.map(segments, function(segment) {
|
||||
return $scope.datasource.metricFindQuery(query).then(function(segments) {
|
||||
var altSegments = _.map(segments, function(segment) {
|
||||
return new MetricSegment({ value: segment.text, expandable: segment.expandable });
|
||||
});
|
||||
|
||||
if ($scope.altSegments.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (altSegments.length === 0) { return altSegments; }
|
||||
|
||||
// add template variables
|
||||
_.each(templateSrv.variables, function(variable) {
|
||||
$scope.altSegments.unshift(new MetricSegment({
|
||||
altSegments.unshift(new MetricSegment({
|
||||
type: 'template',
|
||||
value: '$' + variable.name,
|
||||
expandable: true,
|
||||
@ -176,10 +171,12 @@ function (angular, _, config, gfunc, Parser) {
|
||||
});
|
||||
|
||||
// add wildcard option
|
||||
$scope.altSegments.unshift(new MetricSegment('*'));
|
||||
altSegments.unshift(new MetricSegment('*'));
|
||||
return altSegments;
|
||||
})
|
||||
.then(null, function(err) {
|
||||
$scope.parserError = err.message || 'Failed to issue metric query';
|
||||
return [];
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -108,7 +108,7 @@ function (angular, _, $) {
|
||||
function addElementsAndCompile() {
|
||||
$funcLink.appendTo(elem);
|
||||
|
||||
var $paramLink = $('<a ng-click="" class="graphite-func-param-link">' + $scope.target.column + '</a>');
|
||||
var $paramLink = $('<a ng-click="" class="graphite-func-param-link">value</a>');
|
||||
var $input = $(paramTemplate);
|
||||
|
||||
$paramLink.appendTo(elem);
|
||||
|
@ -62,23 +62,54 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<input type="text"
|
||||
class="tight-form-clear-input span10"
|
||||
ng-model="target.query"
|
||||
focus-me="target.rawQuery"
|
||||
spellcheck='false'
|
||||
ng-model-onblur ng-change="targetTextChanged()"
|
||||
ng-show="target.rawQuery" />
|
||||
<input type="text" class="tight-form-clear-input span10" ng-model="target.query" focus-me="target.rawQuery"
|
||||
spellcheck='false' ng-model-onblur ng-change="targetTextChanged()" ng-show="target.rawQuery" />
|
||||
|
||||
<ul class="tight-form-list" role="menu" ng-hide="target.rawQuery">
|
||||
<li ng-repeat="segment in segments" role="menuitem" graphite-segment></li>
|
||||
<li ng-repeat="func in functions">
|
||||
<span graphite-func-editor class="tight-form-item tight-form-func">
|
||||
</span>
|
||||
</li>
|
||||
<li class="dropdown" graphite-add-func>
|
||||
</li>
|
||||
<li class="tight-form-item query-keyword">
|
||||
SELECT
|
||||
</li>
|
||||
<li class="dropdown tight-form-item">
|
||||
<a gf-dropdown="functionMenu" class="dropdown-toggle" data-toggle="dropdown">
|
||||
{{target.function}}<span>(value)</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="tight-form-item query-keyword">
|
||||
FROM
|
||||
</li>
|
||||
<li>
|
||||
<metric-segment segment="measurementSegment" get-alt-segments="getMeasurements()" on-value-changed="measurementChanged()"></metric-segment>
|
||||
</li>
|
||||
<li class="tight-form-item query-keyword">
|
||||
WHERE
|
||||
</li>
|
||||
<li>
|
||||
<input type="text" class="input-medium tight-form-input" ng-model="target.condition"
|
||||
bs-tooltip="'Add a where clause'" data-placement="right" spellcheck='false' placeholder="column ~= value" ng-blur="get_data()">
|
||||
</li>
|
||||
<li class="tight-form-item">
|
||||
<span class="query-keyword">GROUP BY</span>
|
||||
time($interval), <i class="fa fa-plus"></i>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a class="tight-form-item pointer" data-toggle="dropdown" bs-tooltip="'Insert missing values, important when stacking'" data-placement="right">
|
||||
<span ng-show="target.fill">
|
||||
fill ({{target.fill}})
|
||||
</span>
|
||||
<span ng-show="!target.fill">
|
||||
no fill
|
||||
</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a ng-click="target.fill = ''">no fill</a></li>
|
||||
<li><a ng-click="target.fill = 'null'">fill (null)</a></li>
|
||||
<li><a ng-click="target.fill = '0'">fill (0)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,19 +7,39 @@ function (angular, _) {
|
||||
|
||||
var module = angular.module('grafana.controllers');
|
||||
|
||||
module.controller('InfluxQueryCtrl', function($scope, $timeout, $sce, templateSrv, $q) {
|
||||
module.controller('InfluxQueryCtrl', function($scope, $timeout, $sce, templateSrv) {
|
||||
|
||||
$scope.functionList = [
|
||||
'count', 'mean', 'sum', 'min',
|
||||
'max', 'mode', 'distinct', 'median',
|
||||
'derivative', 'stddev', 'first', 'last',
|
||||
'difference'
|
||||
];
|
||||
|
||||
$scope.functionMenu = _.map($scope.functionList, function(func) {
|
||||
return { text: func, click: "changeFunction('" + func + "');" };
|
||||
});
|
||||
|
||||
$scope.init = function() {
|
||||
$scope.segments = $scope.target.segments || [];
|
||||
var target = $scope.target;
|
||||
target.function = target.function || 'mean';
|
||||
|
||||
$scope.functionsSelect = [
|
||||
'count', 'mean', 'sum', 'min',
|
||||
'max', 'mode', 'distinct', 'median',
|
||||
'derivative', 'stddev', 'first', 'last',
|
||||
'difference'
|
||||
];
|
||||
if (!target.measurement) {
|
||||
$scope.measurementSegment = MetricSegment.newSelectMeasurement();
|
||||
} else {
|
||||
$scope.measurementSegment = new MetricSegment(target.measurement);
|
||||
}
|
||||
};
|
||||
|
||||
checkOtherSegments(0);
|
||||
$scope.changeFunction = function(func) {
|
||||
$scope.target.function = func;
|
||||
$scope.$parent.get_data();
|
||||
};
|
||||
|
||||
$scope.measurementChanged = function() {
|
||||
$scope.target.measurement = $scope.measurementSegment.value;
|
||||
console.log('measurement updated', $scope.target.measurement);
|
||||
$scope.$parent.get_data();
|
||||
};
|
||||
|
||||
$scope.toggleQueryMode = function () {
|
||||
@ -35,103 +55,44 @@ function (angular, _) {
|
||||
$scope.panel.targets.push(clone);
|
||||
};
|
||||
|
||||
$scope.getAltSegments = function (index) {
|
||||
$scope.altSegments = [];
|
||||
|
||||
var measurement = $scope.segments[0].value;
|
||||
var queryType, query;
|
||||
if (index === 0) {
|
||||
queryType = 'MEASUREMENTS';
|
||||
query = 'SHOW MEASUREMENTS';
|
||||
} else if (index % 2 === 1) {
|
||||
queryType = 'TAG_KEYS';
|
||||
query = 'SHOW TAG KEYS FROM "' + measurement + '"';
|
||||
} else {
|
||||
queryType = 'TAG_VALUES';
|
||||
query = 'SHOW TAG VALUES FROM "' + measurement + '" WITH KEY = ' + $scope.segments[$scope.segments.length - 2].value;
|
||||
}
|
||||
|
||||
console.log('getAltSegments: query' , query);
|
||||
|
||||
return $scope.datasource.metricFindQuery(query, queryType).then(function(results) {
|
||||
$scope.getMeasurements = function () {
|
||||
// var measurement = $scope.segments[0].value;
|
||||
// var queryType, query;
|
||||
// if (index === 0) {
|
||||
// queryType = 'MEASUREMENTS';
|
||||
// query = 'SHOW MEASUREMENTS';
|
||||
// } else if (index % 2 === 1) {
|
||||
// queryType = 'TAG_KEYS';
|
||||
// query = 'SHOW TAG KEYS FROM "' + measurement + '"';
|
||||
// } else {
|
||||
// queryType = 'TAG_VALUES';
|
||||
// query = 'SHOW TAG VALUES FROM "' + measurement + '" WITH KEY = ' + $scope.segments[$scope.segments.length - 2].value;
|
||||
// }
|
||||
//
|
||||
// console.log('getAltSegments: query' , query);
|
||||
//
|
||||
console.log('get measurements');
|
||||
return $scope.datasource.metricFindQuery('SHOW MEASUREMENTS', 'MEASUREMENTS').then(function(results) {
|
||||
console.log('get alt segments: response', results);
|
||||
$scope.altSegments = _.map(results, function(segment) {
|
||||
var measurements = _.map(results, function(segment) {
|
||||
return new MetricSegment({ value: segment.text, expandable: segment.expandable });
|
||||
});
|
||||
|
||||
_.each(templateSrv.variables, function(variable) {
|
||||
$scope.altSegments.unshift(new MetricSegment({
|
||||
measurements.unshift(new MetricSegment({
|
||||
type: 'template',
|
||||
value: '$' + variable.name,
|
||||
expandable: true,
|
||||
}));
|
||||
});
|
||||
|
||||
return measurements;
|
||||
}, function(err) {
|
||||
$scope.parserError = err.message || 'Failed to issue metric query';
|
||||
return [];
|
||||
});
|
||||
};
|
||||
|
||||
$scope.segmentValueChanged = function (segment, segmentIndex) {
|
||||
delete $scope.parserError;
|
||||
|
||||
if (segment.expandable) {
|
||||
return checkOtherSegments(segmentIndex + 1).then(function () {
|
||||
setSegmentFocus(segmentIndex + 1);
|
||||
$scope.targetChanged();
|
||||
});
|
||||
}
|
||||
else {
|
||||
$scope.segments = $scope.segments.splice(0, segmentIndex + 1);
|
||||
}
|
||||
|
||||
setSegmentFocus(segmentIndex + 1);
|
||||
$scope.targetChanged();
|
||||
};
|
||||
|
||||
$scope.targetChanged = function() {
|
||||
if ($scope.parserError) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.target.measurement = '';
|
||||
$scope.target.tags = {};
|
||||
$scope.target.measurement = $scope.segments[0].value;
|
||||
|
||||
for (var i = 1; i+1 < $scope.segments.length; i += 2) {
|
||||
var key = $scope.segments[i].value;
|
||||
$scope.target.tags[key] = $scope.segments[i+1].value;
|
||||
}
|
||||
|
||||
$scope.$parent.get_data();
|
||||
};
|
||||
|
||||
function checkOtherSegments(fromIndex) {
|
||||
if (fromIndex === 0) {
|
||||
$scope.segments.push(MetricSegment.newSelectMetric());
|
||||
return;
|
||||
}
|
||||
|
||||
if ($scope.segments.length === 0) {
|
||||
throw('should always have a scope segment?');
|
||||
}
|
||||
|
||||
if (_.last($scope.segments).fake) {
|
||||
return $q.when([]);
|
||||
} else if ($scope.segments.length % 2 === 1) {
|
||||
$scope.segments.push(MetricSegment.newSelectTag());
|
||||
return $q.when([]);
|
||||
} else {
|
||||
$scope.segments.push(MetricSegment.newSelectTagValue());
|
||||
return $q.when([]);
|
||||
}
|
||||
}
|
||||
|
||||
function setSegmentFocus(segmentIndex) {
|
||||
_.each($scope.segments, function(segment, index) {
|
||||
segment.focus = segmentIndex === index;
|
||||
});
|
||||
}
|
||||
|
||||
function MetricSegment(options) {
|
||||
if (options === '*' || options.value === '*') {
|
||||
this.value = '*';
|
||||
@ -153,8 +114,8 @@ function (angular, _) {
|
||||
this.html = $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value));
|
||||
}
|
||||
|
||||
MetricSegment.newSelectMetric = function() {
|
||||
return new MetricSegment({value: 'select metric', fake: true});
|
||||
MetricSegment.newSelectMeasurement = function() {
|
||||
return new MetricSegment({value: 'select measurement', fake: true});
|
||||
};
|
||||
|
||||
MetricSegment.newSelectTag = function() {
|
||||
|
@ -337,3 +337,10 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.query-keyword {
|
||||
font-weight: bold;
|
||||
color: @blue;
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,13 +141,15 @@ define([
|
||||
ctx.scope.target.target = 'test.count';
|
||||
ctx.scope.datasource.metricFindQuery.returns(ctx.$q.when([]));
|
||||
ctx.scope.init();
|
||||
ctx.scope.getAltSegments(1);
|
||||
ctx.scope.getAltSegments(1).then(function(results) {
|
||||
ctx.altSegments = results;
|
||||
});
|
||||
ctx.scope.$digest();
|
||||
ctx.scope.$parent = { get_data: sinon.spy() };
|
||||
});
|
||||
|
||||
it('should have no segments', function() {
|
||||
expect(ctx.scope.altSegments.length).to.be(0);
|
||||
expect(ctx.altSegments.length).to.be(0);
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user