mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(influxdb): more work on influxdb editor
This commit is contained in:
parent
31e2a8b8e9
commit
c9ba856c52
@ -6,16 +6,6 @@ import queryPart = require('./query_part');
|
|||||||
|
|
||||||
declare var InfluxQueryBuilder: any;
|
declare var InfluxQueryBuilder: any;
|
||||||
|
|
||||||
class InfluxSelectModel {
|
|
||||||
modelParts: any[];
|
|
||||||
persistedParts: any[];
|
|
||||||
|
|
||||||
constructor(persistedParts: any[]) {
|
|
||||||
this.persistedParts = persistedParts;
|
|
||||||
this.modelParts = _.map(persistedParts, queryPart.create);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class InfluxQuery {
|
class InfluxQuery {
|
||||||
target: any;
|
target: any;
|
||||||
selectModels: any[];
|
selectModels: any[];
|
||||||
@ -40,7 +30,15 @@ class InfluxQuery {
|
|||||||
|
|
||||||
updateSelectParts() {
|
updateSelectParts() {
|
||||||
this.selectModels = _.map(this.target.select, function(parts: any) {
|
this.selectModels = _.map(this.target.select, function(parts: any) {
|
||||||
return new InfluxSelectModel(parts);
|
return _.map(parts, queryPart.create);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePersistedParts() {
|
||||||
|
this.target.select = _.map(this.selectModels, function(selectParts) {
|
||||||
|
return _.map(selectParts, function(part: any) {
|
||||||
|
return {name: part.def.name, params: part.params};
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,16 +47,16 @@ class InfluxQuery {
|
|||||||
this.updateSelectParts();
|
this.updateSelectParts();
|
||||||
}
|
}
|
||||||
|
|
||||||
removeSelectPart(selectModel, part) {
|
removeSelectPart(selectParts, part) {
|
||||||
var partIndex = _.indexOf(selectModel.modelParts, part);
|
var partIndex = _.indexOf(selectParts, part);
|
||||||
selectModel.persistedParts.splice(partIndex, 1);
|
selectParts.splice(partIndex, 1);
|
||||||
this.updateSelectParts();
|
this.updatePersistedParts();
|
||||||
}
|
}
|
||||||
|
|
||||||
addSelectPart(selectModel, name) {
|
addSelectPart(selectParts, name) {
|
||||||
var partModel = queryPart.create({name: name});
|
var partModel = queryPart.create({name: name});
|
||||||
selectModel.persistedParts.push(partModel.part);
|
partModel.def.addStrategy(selectParts, partModel);
|
||||||
selectModel.modelParts.push(partModel);
|
this.updatePersistedParts();
|
||||||
}
|
}
|
||||||
|
|
||||||
addSelect() {
|
addSelect() {
|
||||||
@ -113,7 +111,7 @@ class InfluxQuery {
|
|||||||
var query = 'SELECT ';
|
var query = 'SELECT ';
|
||||||
var i, y;
|
var i, y;
|
||||||
for (i = 0; i < this.selectModels.length; i++) {
|
for (i = 0; i < this.selectModels.length; i++) {
|
||||||
let parts = this.selectModels[i].modelParts;
|
let parts = this.selectModels[i];
|
||||||
var selectText = "";
|
var selectText = "";
|
||||||
for (y = 0; y < parts.length; y++) {
|
for (y = 0; y < parts.length; y++) {
|
||||||
let part = parts[y];
|
let part = parts[y];
|
||||||
|
@ -65,15 +65,15 @@
|
|||||||
|
|
||||||
<div ng-hide="target.rawQuery">
|
<div ng-hide="target.rawQuery">
|
||||||
|
|
||||||
<div class="tight-form" ng-repeat="selectModel in queryModel.selectModels">
|
<div class="tight-form" ng-repeat="selectParts in queryModel.selectModels">
|
||||||
<ul class="tight-form-list">
|
<ul class="tight-form-list">
|
||||||
<li class="tight-form-item query-keyword tight-form-align" style="width: 75px;">
|
<li class="tight-form-item query-keyword tight-form-align" style="width: 75px;">
|
||||||
<span ng-show="$index === 0">SELECT</span>
|
<span ng-show="$index === 0">SELECT</span>
|
||||||
</li>
|
</li>
|
||||||
<li ng-repeat="part in selectModel.modelParts">
|
<li ng-repeat="part in selectParts">
|
||||||
<influx-query-part-editor part="part" class="tight-form-item tight-form-func" remove-action="removeSelectPart(selectModel, part)" part-updated="selectPartUpdated(selectModel, part)"></influx-query-part-editor>
|
<influx-query-part-editor part="part" class="tight-form-item tight-form-func" remove-action="removeSelectPart(selectParts, part)" part-updated="selectPartUpdated(selectParts, part)"></influx-query-part-editor>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown" dropdown-typeahead="selectMenu" dropdown-typeahead-on-select="selectMenuAction(selectModel, $item, $subItem)">
|
<li class="dropdown" dropdown-typeahead="selectMenu" dropdown-typeahead-on-select="addSelectPart(selectParts, $item, $subItem)">
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<div class="tight-form-func-controls">
|
<div class="tight-form-func-controls">
|
||||||
<span class="pointer fa fa-question-circle"></span>
|
<span class="pointer fa fa-remove" ng-click="removeActionInternal()" ></span>
|
||||||
<span class="pointer fa fa-remove" ng-click="removeAction()" ></span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a ng-click="toggleControls()">{{part.def.name}}</a><span>(</span><span class="query-part-parameters"></span><span>)</span>
|
<a ng-click="toggleControls()">{{part.def.name}}</a><span>(</span><span class="query-part-parameters"></span><span>)</span>
|
||||||
|
@ -62,13 +62,13 @@ function (angular, _, InfluxQueryBuilder, InfluxQuery, queryPart) {
|
|||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.selectMenuAction = function(selectModel, cat, subitem) {
|
$scope.addSelectPart = function(selectParts, cat, subitem) {
|
||||||
$scope.queryModel.addSelectPart(selectModel, subitem.value);
|
$scope.queryModel.addSelectPart(selectParts, subitem.value);
|
||||||
$scope.get_data();
|
$scope.get_data();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.removeSelectPart = function(selectModel, part) {
|
$scope.removeSelectPart = function(selectParts, part) {
|
||||||
$scope.queryModel.removeSelectPart(selectModel, part);
|
$scope.queryModel.removeSelectPart(selectParts, part);
|
||||||
$scope.get_data();
|
$scope.get_data();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,17 +11,23 @@ var categories = {
|
|||||||
Fields: [],
|
Fields: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var groupByTimeFunctions = [];
|
||||||
|
|
||||||
class QueryPartDef {
|
class QueryPartDef {
|
||||||
name: string;
|
name: string;
|
||||||
params: any[];
|
params: any[];
|
||||||
defaultParams: any[];
|
defaultParams: any[];
|
||||||
renderer: any;
|
renderer: any;
|
||||||
|
category: any;
|
||||||
|
addStrategy: any;
|
||||||
|
|
||||||
constructor(options: any) {
|
constructor(options: any) {
|
||||||
this.name = options.name;
|
this.name = options.name;
|
||||||
this.params = options.params;
|
this.params = options.params;
|
||||||
this.defaultParams = options.defaultParams;
|
this.defaultParams = options.defaultParams;
|
||||||
this.renderer = options.renderer;
|
this.renderer = options.renderer;
|
||||||
|
this.category = options.category;
|
||||||
|
this.addStrategy = options.addStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static register(options: any) {
|
static register(options: any) {
|
||||||
@ -65,6 +71,67 @@ function quotedIdentityRenderer(part, innerExpr) {
|
|||||||
return '"' + part.params[0] + '"';
|
return '"' + part.params[0] + '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function replaceAggregationAddStrategy(selectParts, partModel) {
|
||||||
|
// look for existing aggregation
|
||||||
|
for (var i = 0; i < selectParts.length; i++) {
|
||||||
|
var part = selectParts[i];
|
||||||
|
if (part.def.category === categories.Aggregations) {
|
||||||
|
selectParts[i] = partModel;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectParts.splice(1, 0, partModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTransformationStrategy(selectParts, partModel) {
|
||||||
|
var i;
|
||||||
|
// look for index to add transformation
|
||||||
|
for (i = 0; i < selectParts.length; i++) {
|
||||||
|
var part = selectParts[i];
|
||||||
|
if (part.def.category === categories.Math || part.def.category === categories.Aliasing) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectParts.splice(i, 0, partModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMathStrategy(selectParts, partModel) {
|
||||||
|
var partCount = selectParts.length;
|
||||||
|
if (partCount > 0) {
|
||||||
|
// if last is math, replace it
|
||||||
|
if (selectParts[partCount-1].def.name === 'math') {
|
||||||
|
selectParts[partCount-1] = partModel;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if next to last is math, replace it
|
||||||
|
if (selectParts[partCount-2].def.name === 'math') {
|
||||||
|
selectParts[partCount-2] = partModel;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// if last is alias add it before
|
||||||
|
else if (selectParts[partCount-1].def.name === 'alias') {
|
||||||
|
selectParts.splice(partCount-1, 0, partModel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectParts.push(partModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addAliasStrategy(selectParts, partModel) {
|
||||||
|
var partCount = selectParts.length;
|
||||||
|
if (partCount > 0) {
|
||||||
|
// if last is alias, replace it
|
||||||
|
if (selectParts[partCount-1].def.name === 'alias') {
|
||||||
|
selectParts[partCount-1] = partModel;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectParts.push(partModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QueryPartDef.register({
|
QueryPartDef.register({
|
||||||
name: 'field',
|
name: 'field',
|
||||||
category: categories.Fields,
|
category: categories.Fields,
|
||||||
@ -75,6 +142,7 @@ QueryPartDef.register({
|
|||||||
|
|
||||||
QueryPartDef.register({
|
QueryPartDef.register({
|
||||||
name: 'mean',
|
name: 'mean',
|
||||||
|
addStrategy: replaceAggregationAddStrategy,
|
||||||
category: categories.Aggregations,
|
category: categories.Aggregations,
|
||||||
params: [],
|
params: [],
|
||||||
defaultParams: [],
|
defaultParams: [],
|
||||||
@ -83,6 +151,7 @@ QueryPartDef.register({
|
|||||||
|
|
||||||
QueryPartDef.register({
|
QueryPartDef.register({
|
||||||
name: 'sum',
|
name: 'sum',
|
||||||
|
addStrategy: replaceAggregationAddStrategy,
|
||||||
category: categories.Aggregations,
|
category: categories.Aggregations,
|
||||||
params: [],
|
params: [],
|
||||||
defaultParams: [],
|
defaultParams: [],
|
||||||
@ -91,6 +160,7 @@ QueryPartDef.register({
|
|||||||
|
|
||||||
QueryPartDef.register({
|
QueryPartDef.register({
|
||||||
name: 'derivative',
|
name: 'derivative',
|
||||||
|
addStrategy: addTransformationStrategy,
|
||||||
category: categories.Transformations,
|
category: categories.Transformations,
|
||||||
params: [{ name: "duration", type: "interval", options: ['1s', '10s', '1m', '5min', '10m', '15m', '1h']}],
|
params: [{ name: "duration", type: "interval", options: ['1s', '10s', '1m', '5min', '10m', '15m', '1h']}],
|
||||||
defaultParams: ['10s'],
|
defaultParams: ['10s'],
|
||||||
@ -99,7 +169,7 @@ QueryPartDef.register({
|
|||||||
|
|
||||||
QueryPartDef.register({
|
QueryPartDef.register({
|
||||||
name: 'time',
|
name: 'time',
|
||||||
category: categories.Transformations,
|
category: groupByTimeFunctions,
|
||||||
params: [{ name: "rate", type: "interval", options: ['$interval', '1s', '10s', '1m', '5min', '10m', '15m', '1h'] }],
|
params: [{ name: "rate", type: "interval", options: ['$interval', '1s', '10s', '1m', '5min', '10m', '15m', '1h'] }],
|
||||||
defaultParams: ['$interval'],
|
defaultParams: ['$interval'],
|
||||||
renderer: functionRenderer,
|
renderer: functionRenderer,
|
||||||
@ -107,6 +177,7 @@ QueryPartDef.register({
|
|||||||
|
|
||||||
QueryPartDef.register({
|
QueryPartDef.register({
|
||||||
name: 'math',
|
name: 'math',
|
||||||
|
addStrategy: addMathStrategy,
|
||||||
category: categories.Math,
|
category: categories.Math,
|
||||||
params: [{ name: "expr", type: "string"}],
|
params: [{ name: "expr", type: "string"}],
|
||||||
defaultParams: [' / 100'],
|
defaultParams: [' / 100'],
|
||||||
@ -115,6 +186,7 @@ QueryPartDef.register({
|
|||||||
|
|
||||||
QueryPartDef.register({
|
QueryPartDef.register({
|
||||||
name: 'alias',
|
name: 'alias',
|
||||||
|
addStrategy: addAliasStrategy,
|
||||||
category: categories.Aliasing,
|
category: categories.Aliasing,
|
||||||
params: [{ name: "name", type: "string", quote: 'double'}],
|
params: [{ name: "name", type: "string", quote: 'double'}],
|
||||||
defaultParams: ['alias'],
|
defaultParams: ['alias'],
|
||||||
|
@ -117,6 +117,11 @@ function (angular, _, $) {
|
|||||||
$controlsContainer.show();
|
$controlsContainer.show();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.removeActionInternal = function() {
|
||||||
|
$scope.toggleControls();
|
||||||
|
$scope.removeAction();
|
||||||
|
};
|
||||||
|
|
||||||
function addElementsAndCompile() {
|
function addElementsAndCompile() {
|
||||||
_.each(partDef.params, function(param, index) {
|
_.each(partDef.params, function(param, index) {
|
||||||
if (param.optional && part.params.length <= index) {
|
if (param.optional && part.params.length <= index) {
|
||||||
|
@ -34,4 +34,63 @@ describe.only('InfluxQuery', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('when adding select part', function() {
|
||||||
|
|
||||||
|
it('should add mean after after field', function() {
|
||||||
|
var query = new InfluxQuery({
|
||||||
|
measurement: 'cpu',
|
||||||
|
select: [[{name: 'field', params: ['value']}]]
|
||||||
|
});
|
||||||
|
|
||||||
|
query.addSelectPart(query.selectModels[0], 'mean');
|
||||||
|
expect(query.target.select[0].length).to.be(2);
|
||||||
|
expect(query.target.select[0][1].name).to.be('mean');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should replace sum by mean', function() {
|
||||||
|
var query = new InfluxQuery({
|
||||||
|
measurement: 'cpu',
|
||||||
|
select: [[{name: 'field', params: ['value']}, {name: 'mean'}]]
|
||||||
|
});
|
||||||
|
|
||||||
|
query.addSelectPart(query.selectModels[0], 'sum');
|
||||||
|
expect(query.target.select[0].length).to.be(2);
|
||||||
|
expect(query.target.select[0][1].name).to.be('sum');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add math before alias', function() {
|
||||||
|
var query = new InfluxQuery({
|
||||||
|
measurement: 'cpu',
|
||||||
|
select: [[{name: 'field', params: ['value']}, {name: 'mean'}, {name: 'alias'}]]
|
||||||
|
});
|
||||||
|
|
||||||
|
query.addSelectPart(query.selectModels[0], 'math');
|
||||||
|
expect(query.target.select[0].length).to.be(4);
|
||||||
|
expect(query.target.select[0][2].name).to.be('math');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add math last', function() {
|
||||||
|
var query = new InfluxQuery({
|
||||||
|
measurement: 'cpu',
|
||||||
|
select: [[{name: 'field', params: ['value']}, {name: 'mean'}]]
|
||||||
|
});
|
||||||
|
|
||||||
|
query.addSelectPart(query.selectModels[0], 'math');
|
||||||
|
expect(query.target.select[0].length).to.be(3);
|
||||||
|
expect(query.target.select[0][2].name).to.be('math');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should replace math', function() {
|
||||||
|
var query = new InfluxQuery({
|
||||||
|
measurement: 'cpu',
|
||||||
|
select: [[{name: 'field', params: ['value']}, {name: 'mean'}, {name: 'math'}]]
|
||||||
|
});
|
||||||
|
|
||||||
|
query.addSelectPart(query.selectModels[0], 'math');
|
||||||
|
expect(query.target.select[0].length).to.be(3);
|
||||||
|
expect(query.target.select[0][2].name).to.be('math');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user