feat(templating): progress on variable system refactoring, #6048

This commit is contained in:
Torkel Ödegaard 2016-09-19 18:06:36 +02:00
parent 945b5ee3cf
commit 9d6ecc6361
9 changed files with 124 additions and 145 deletions

View File

@ -87,6 +87,7 @@ export class DashboardCtrl {
};
$scope.templateVariableUpdated = function() {
dynamicDashboardSrv.update($scope.dashboard);
};
$scope.updateSubmenuVisibility = function() {

View File

@ -23,13 +23,15 @@ export class CustomVariable implements Variable {
multi: false,
};
supportsMulti = true;
/** @ngInject */
constructor(private model, private timeSrv, private templateSrv, private variableSrv) {
assignModelProperties(this, model, this.defaults);
}
setValue(option) {
this.variableSrv.setOptionAsCurrent(this, option);
return this.variableSrv.setOptionAsCurrent(this, option);
}
getModel() {
@ -47,7 +49,7 @@ export class CustomVariable implements Variable {
this.addAllOption();
}
return Promise.resolve();
return this.variableSrv.validateVariableSelectionState(this);
}
addAllOption() {

View File

@ -15,7 +15,7 @@ export class DatasourceVariable implements Variable {
name: '',
hide: 0,
label: '',
current: {text: '', value: ''}
current: {text: '', value: ''},
regex: '',
options: [],
query: '',
@ -32,7 +32,7 @@ export class DatasourceVariable implements Variable {
}
setValue(option) {
this.variableSrv.setOptionAsCurrent(this, option);
return this.variableSrv.setOptionAsCurrent(this, option);
}
updateOptions() {
@ -63,6 +63,7 @@ export class DatasourceVariable implements Variable {
}
this.options = options;
return this.variableSrv.validateVariableSelectionState(this);
}
dependsOn(variable) {

View File

@ -10,7 +10,7 @@ import appEvents from 'app/core/app_events';
export class VariableEditorCtrl {
/** @ngInject */
constructor(private $scope, private datasourceSrv, private variableSrv) {
constructor(private $scope, private datasourceSrv, private variableSrv, templateSrv) {
$scope.variableTypes = [
{value: "query", text: "Query"},
{value: "adhoc", text: "Ad hoc filters"},
@ -27,7 +27,7 @@ export class VariableEditorCtrl {
];
$scope.sortOptions = [
{value: 0, text: "Query sort"},
{value: 0, text: "Disabled"},
{value: 1, text: "Alphabetical (asc)"},
{value: 2, text: "Alphabetical (desc)"},
{value: 3, text: "Numerical (asc)"},
@ -115,6 +115,7 @@ export class VariableEditorCtrl {
$scope.runQuery().then(function() {
$scope.reset();
$scope.mode = 'list';
templateSrv.updateTemplateData();
});
}
};
@ -124,18 +125,6 @@ export class VariableEditorCtrl {
$scope.current = variableSrv.createVariableFromModel({type: 'query'});
};
$scope.showSelectionOptions = function() {
if ($scope.current) {
if ($scope.current.type === 'query') {
return true;
}
if ($scope.current.type === 'custom') {
return true;
}
}
return false;
};
$scope.typeChanged = function() {
var old = $scope.current;
$scope.current = variableSrv.createVariableFromModel({type: $scope.current.type});
@ -147,27 +136,6 @@ export class VariableEditorCtrl {
if (oldIndex !== -1) {
this.variables[oldIndex] = $scope.current;
}
// if ($scope.current.type === 'interval') {
// $scope.current.query = '1m,10m,30m,1h,6h,12h,1d,7d,14d,30d';
// $scope.current.refresh = 0;
// }
//
// if ($scope.current.type === 'query') {
// $scope.current.query = '';
// }
//
// if ($scope.current.type === 'constant') {
// $scope.current.query = '';
// $scope.current.refresh = 0;
// $scope.current.hide = 2;
// }
//
// if ($scope.current.type === 'datasource') {
// $scope.current.query = $scope.datasourceTypes[0].value;
// $scope.current.regex = '';
// $scope.current.refresh = 1;
// }
};
$scope.removeVariable = function(variable) {

View File

@ -11,12 +11,14 @@ export class IntervalVariable implements Variable {
options: any;
auto: boolean;
query: string;
refresh: number;
defaults = {
type: 'interval',
name: '',
hide: 0,
label: '',
refresh: 2,
options: [],
current: {text: '', value: ''},
query: '1m,10m,30m,1h,6h,12h,1d,7d,14d,30d',
@ -28,6 +30,7 @@ export class IntervalVariable implements Variable {
/** @ngInject */
constructor(private model, private timeSrv, private templateSrv, private variableSrv) {
assignModelProperties(this, model, this.defaults);
this.refresh = 2;
}
getModel() {
@ -37,7 +40,7 @@ export class IntervalVariable implements Variable {
setValue(option) {
this.updateAutoValue();
this.variableSrv.setOptionAsCurrent(this, option);
return this.variableSrv.setOptionAsCurrent(this, option);
}
updateAutoValue() {
@ -61,6 +64,7 @@ export class IntervalVariable implements Variable {
});
this.updateAutoValue();
return this.variableSrv.validateVariableSelectionState(this);
}
dependsOn(variable) {

View File

@ -181,19 +181,8 @@
<select class="gf-form-input" ng-model="current.refresh" ng-options="f.value as f.text for f in refreshOptions"></select>
</div>
</div>
<div class="gf-form max-width-21">
<span class="gf-form-label width-7">
Sort
<info-popover mode="right-normal">
How to sort the values of this variable.
</info-popover>
</span>
<div class="gf-form-select-wrapper max-width-14">
<select class="gf-form-input" ng-model="current.sort" ng-options="f.value as f.text for f in sortOptions" ng-change="runQuery()"></select>
</div>
</div>
</div>
<div class="gf-form">
</div>
<div class="gf-form">
<span class="gf-form-label width-7">Query</span>
<input type="text" class="gf-form-input" ng-model='current.query' placeholder="metric name or tags query" ng-model-onblur ng-change="runQuery()"></input>
</div>
@ -206,35 +195,46 @@
</span>
<input type="text" class="gf-form-input" ng-model='current.regex' placeholder="/.*-(.*)-.*/" ng-model-onblur ng-change="runQuery()"></input>
</div>
</div>
<div class="gf-form max-width-21">
<span class="gf-form-label width-7">
Sort
<info-popover mode="right-normal">
How to sort the values of this variable.
</info-popover>
</span>
<div class="gf-form-select-wrapper max-width-14">
<select class="gf-form-input" ng-model="current.sort" ng-options="f.value as f.text for f in sortOptions" ng-change="runQuery()"></select>
</div>
</div>
</div>
<div ng-show="current.type === 'datasource'" class="gf-form-group">
<h5 class="section-heading">Data source options</h5>
<div ng-show="current.type === 'datasource'" class="gf-form-group">
<h5 class="section-heading">Data source options</h5>
<div class="gf-form">
<label class="gf-form-label width-12">Type</label>
<div class="gf-form-select-wrapper max-width-18">
<select class="gf-form-input" ng-model="current.query" ng-options="f.value as f.text for f in datasourceTypes" ng-change="runQuery()"></select>
</div>
</div>
<div class="gf-form">
<label class="gf-form-label width-12">Type</label>
<div class="gf-form-select-wrapper max-width-18">
<select class="gf-form-input" ng-model="current.query" ng-options="f.value as f.text for f in datasourceTypes" ng-change="runQuery()"></select>
</div>
</div>
<div class="gf-form">
<label class="gf-form-label width-12">
Instance name filter
<info-popover mode="right-normal">
Regex filter for which data source instances to choose from in
the variable value dropdown. Leave empty for all.
<br><br>
Example: <code>/^prod/</code>
<div class="gf-form">
<label class="gf-form-label width-12">
Instance name filter
<info-popover mode="right-normal">
Regex filter for which data source instances to choose from in
the variable value dropdown. Leave empty for all.
<br><br>
Example: <code>/^prod/</code>
</info-popover>
</label>
<input type="text" class="gf-form-input max-width-18" ng-model='current.regex' placeholder="/.*-(.*)-.*/" ng-model-onblur ng-change="runQuery()"></input>
</div>
</div>
</info-popover>
</label>
<input type="text" class="gf-form-input max-width-18" ng-model='current.regex' placeholder="/.*-(.*)-.*/" ng-model-onblur ng-change="runQuery()"></input>
</div>
</div>
<div ng-show="current.type === 'adhoc'" class="gf-form-group">
<h5 class="section-heading">Options</h5>
<h5 class="section-heading">Options</h5>
<div class="gf-form max-width-21">
<span class="gf-form-label width-8">Data source</span>
@ -242,58 +242,58 @@
<select class="gf-form-input" ng-model="current.datasource" ng-options="f.value as f.name for f in datasources"></select>
</div>
</div>
</div>
</div>
<div class="section gf-form-group" ng-show="showSelectionOptions()">
<h5 class="section-heading">Selection Options</h5>
<div class="section">
<gf-form-switch class="gf-form"
label="Multi-value"
label-class="width-10"
tooltip="Enables multiple values to be selected at the same time"
checked="current.multi"
on-change="runQuery()">
</gf-form-switch>
<gf-form-switch class="gf-form"
label="Include All option"
label-class="width-10"
checked="current.includeAll"
on-change="runQuery()">
</gf-form-switch>
</div>
<div class="gf-form" ng-if="current.includeAll">
<span class="gf-form-label width-10">Custom all value</span>
<input type="text" class="gf-form-input max-width-15" ng-model='current.allValue' placeholder="blank = auto"></input>
</div>
</div>
<div class="section gf-form-group" ng-show="current.supportsMulti">
<h5 class="section-heading">Selection Options</h5>
<div class="section">
<gf-form-switch class="gf-form"
label="Multi-value"
label-class="width-10"
tooltip="Enables multiple values to be selected at the same time"
checked="current.multi"
on-change="runQuery()">
</gf-form-switch>
<gf-form-switch class="gf-form"
label="Include All option"
label-class="width-10"
checked="current.includeAll"
on-change="runQuery()">
</gf-form-switch>
</div>
<div class="gf-form" ng-if="current.includeAll">
<span class="gf-form-label width-10">Custom all value</span>
<input type="text" class="gf-form-input max-width-15" ng-model='current.allValue' placeholder="blank = auto"></input>
</div>
</div>
<div class="gf-form-group" ng-if="current.type === 'query'">
<h5>Value groups/tags (Experimental feature)</h5>
<div class="gf-form">
<editor-checkbox text="Enable" model="current.useTags" change="runQuery()"></editor-checkbox>
</div>
<div class="gf-form last" ng-if="current.useTags">
<span class="gf-form-label width-10">Tags query</span>
<input type="text" class="gf-form-input" ng-model='current.tagsQuery' placeholder="metric name or tags query" ng-model-onblur></input>
</div>
<div class="gf-form" ng-if="current.useTags">
<li class="gf-form-label width-10">Tag values query</li>
<input type="text" class="gf-form-input" ng-model='current.tagValuesQuery' placeholder="apps.$tag.*" ng-model-onblur></input>
</div>
</div>
<div class="gf-form-group" ng-if="current.type === 'query'">
<h5>Value groups/tags (Experimental feature)</h5>
<div class="gf-form">
<editor-checkbox text="Enable" model="current.useTags" change="runQuery()"></editor-checkbox>
</div>
<div class="gf-form last" ng-if="current.useTags">
<span class="gf-form-label width-10">Tags query</span>
<input type="text" class="gf-form-input" ng-model='current.tagsQuery' placeholder="metric name or tags query" ng-model-onblur></input>
</div>
<div class="gf-form" ng-if="current.useTags">
<li class="gf-form-label width-10">Tag values query</li>
<input type="text" class="gf-form-input" ng-model='current.tagValuesQuery' placeholder="apps.$tag.*" ng-model-onblur></input>
</div>
</div>
<div class="gf-form-group">
<h5>Preview of values (shows max 20)</h5>
<div class="gf-form-inline">
<div class="gf-form" ng-repeat="option in current.options | limitTo: 20">
<span class="gf-form-label">{{option.text}}</span>
</div>
</div>
</div>
</div>
<div class="gf-form-group">
<h5>Preview of values (shows max 20)</h5>
<div class="gf-form-inline">
<div class="gf-form" ng-repeat="option in current.options | limitTo: 20">
<span class="gf-form-label">{{option.text}}</span>
</div>
</div>
</div>
</div>
<div class="gf-form-button-row p-y-0">
<button type="button" class="btn btn-success" ng-show="mode === 'edit'" ng-click="update();">Update</button>
<div class="gf-form-button-row p-y-0">
<button type="button" class="btn btn-success" ng-show="mode === 'edit'" ng-click="update();">Update</button>
<button type="button" class="btn btn-success" ng-show="mode === 'new'" ng-click="add();">Add</button>
</div>
</div>

View File

@ -37,6 +37,8 @@ export class QueryVariable implements Variable {
current: {text: '', value: ''},
};
supportsMulti = true;
constructor(private model, private datasourceSrv, private templateSrv, private variableSrv, private $q) {
// copy model properties to this instance
assignModelProperties(this, model, this.defaults);
@ -49,7 +51,7 @@ export class QueryVariable implements Variable {
}
setValue(option){
this.variableSrv.setOptionAsCurrent(this, option);
return this.variableSrv.setOptionAsCurrent(this, option);
}
setValueFromUrl(urlValue) {
@ -59,9 +61,7 @@ export class QueryVariable implements Variable {
updateOptions() {
return this.datasourceSrv.get(this.datasource)
.then(this.updateOptionsFromMetricFindQuery.bind(this))
.then(() => {
this.variableSrv.validateVariableSelectionState(this);
});
.then(this.variableSrv.validateVariableSelectionState.bind(this.variableSrv, this));
}
updateOptionsFromMetricFindQuery(datasource) {

View File

@ -15,7 +15,7 @@ export class VariableSrv {
/** @ngInject */
constructor(private $rootScope, private $q, private $location, private $injector, private templateSrv) {
// update time variant variables
// $rootScope.onAppEvent('refresh', this.onDashboardRefresh.bind(this), $rootScope);
$rootScope.$on('refresh', this.onDashboardRefresh.bind(this), $rootScope);
}
init(dashboard) {
@ -41,22 +41,21 @@ export class VariableSrv {
}
onDashboardRefresh() {
// var promises = this.variables
// .filter(variable => variable.refresh === 2)
// .map(variable => {
// var previousOptions = variable.options.slice();
//
// return self.updateOptions(variable).then(function () {
// return self.variableUpdated(variable).then(function () {
// // check if current options changed due to refresh
// if (angular.toJson(previousOptions) !== angular.toJson(variable.options)) {
// $rootScope.appEvent('template-variable-value-updated');
// }
// });
// });
// });
//
// return this.$q.all(promises);
var promises = this.variables
.filter(variable => variable.refresh === 2)
.map(variable => {
var previousOptions = variable.options.slice();
return variable.updateOptions()
.then(this.variableUpdated.bind(this, variable))
.then(() => {
if (angular.toJson(previousOptions) !== angular.toJson(variable.options)) {
this.$rootScope.$emit('template-variable-value-updated');
}
});
});
return this.$q.all(promises);
}
processVariable(variable, queryParams) {

View File

@ -257,6 +257,10 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
esQuery = header + '\n' + esQuery + '\n';
return this._post('_msearch?search_type=count', esQuery).then(function(res) {
if (!res.responses[0].aggregations) {
return [];
}
var buckets = res.responses[0].aggregations["1"].buckets;
return _.map(buckets, function(bucket) {
return {text: bucket.key, value: bucket.key};