Merge branch 'master' into alerting_definitions

This commit is contained in:
bergquist
2016-04-28 11:03:33 +02:00
40 changed files with 1086 additions and 807 deletions
+9
View File
@@ -14,6 +14,15 @@
* **Singlestat**: Fixes prefix an postfix for gauges, fixes [#4812](https://github.com/grafana/grafana/issues/4812)
* **Singlestat**: Fixes auto-refresh on change for some options, fixes [#4809](https://github.com/grafana/grafana/issues/4809)
### Breaking changes
**Data Source Query Editors**: Issue [#3900](https://github.com/grafana/grafana/issues/3900)
Query editors have been updated to use the new form styles. External data source plugins needs to be
updated to work. Sorry to introduce breaking change this late in beta phase. We wanted to get this change
in before 3.0 stable is released so we don't have to break data sources in next release (3.1). If you are
a data source plugin author and want help for how the new form styles work please ask for help in
slack channel (link to slack channel in readme).
# 3.0.0-beta5 (2016-04-15)
### Bug fixes
@@ -11,11 +11,6 @@ export function infoPopover() {
template: '<i class="fa fa-info-circle"></i>',
transclude: true,
link: function(scope, elem, attrs, ctrl, transclude) {
// var inputElem = elem.prev();
// if (inputElem.length === 0) {
// console.log('Failed to find input element for popover');
// return;
// }
var offset = attrs.offset || '0 -10px';
var position = attrs.position || 'right middle';
@@ -9,10 +9,10 @@ function (_, $, coreModule) {
coreModule.default.directive('dropdownTypeahead', function($compile) {
var inputTemplate = '<input type="text"'+
' class="tight-form-input input-medium tight-form-input"' +
' class="gf-form-input input-medium tight-form-input"' +
' spellcheck="false" style="display:none"></input>';
var buttonTemplate = '<a class="tight-form-item tight-form-func dropdown-toggle"' +
var buttonTemplate = '<a class="gf-form-label tight-form-func dropdown-toggle"' +
' tabindex="1" gf-dropdown="menuItems" data-toggle="dropdown"' +
' data-placement="top"><i class="fa fa-plus"></i></a>';
+7 -4
View File
@@ -8,10 +8,13 @@ function (_, $, coreModule) {
coreModule.default.directive('metricSegment', function($compile, $sce) {
var inputTemplate = '<input type="text" data-provide="typeahead" ' +
' class="tight-form-clear-input input-medium"' +
' class="gf-form-input input-medium"' +
' spellcheck="false" style="display:none"></input>';
var buttonTemplate = '<a class="tight-form-item" ng-class="segment.cssClass" ' +
var linkTemplate = '<a class="gf-form-label" ng-class="segment.cssClass" ' +
'tabindex="1" give-focus="segment.focus" ng-bind-html="segment.html"></a>';
var selectTemplate = '<a class="gf-form-input gf-form-input--dropdown" ng-class="segment.cssClass" ' +
'tabindex="1" give-focus="segment.focus" ng-bind-html="segment.html"></a>';
return {
@@ -20,9 +23,9 @@ function (_, $, coreModule) {
getOptions: "&",
onChange: "&",
},
link: function($scope, elem) {
link: function($scope, elem, attrs) {
var $input = $(inputTemplate);
var $button = $(buttonTemplate);
var $button = $(attrs.styleMode === 'select' ? selectTemplate : linkTemplate);
var segment = $scope.segment;
var options = null;
var cancelBlur = null;
-2
View File
@@ -25,7 +25,6 @@ export class ContextSrv {
isGrafanaAdmin: any;
isEditor: any;
sidemenu: any;
lightTheme: any;
constructor() {
this.pinned = store.getBool('grafana.sidemenu.pinned', false);
@@ -41,7 +40,6 @@ export class ContextSrv {
}
this.version = config.buildInfo.version;
this.lightTheme = false;
this.user = new User();
this.isSignedIn = this.user.isSignedIn;
this.isGrafanaAdmin = this.user.isGrafanaAdmin;
+1
View File
@@ -5,4 +5,5 @@ define([
'./query_ctrl',
'./panel_editor_tab',
'./query_editor_row',
'./metrics_ds_selector',
], function () {});
@@ -0,0 +1,106 @@
///<reference path="../../headers/common.d.ts" />
import angular from 'angular';
import _ from 'lodash';
var module = angular.module('grafana.directives');
var template = `
<div class="gf-form-group">
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label">
<i class="icon-gf icon-gf-datasource"></i>
</label>
<label class="gf-form-label">
Panel data source
</label>
<metric-segment segment="ctrl.dsSegment" style-mode="select"
get-options="ctrl.getOptions()"
on-change="ctrl.datasourceChanged()"></metric-segment>
</div>
<div class="gf-form gf-form--offset-1">
<button class="btn btn-inverse gf-form-btn" ng-click="ctrl.addDataQuery()" ng-hide="ctrl.current.meta.mixed">
<i class="fa fa-plus"></i>&nbsp;
Add query
</button>
<div class="dropdown" ng-if="ctrl.current.meta.mixed">
<button class="btn btn-inverse dropdown-toggle gf-form-btn" data-toggle="dropdown">
Add Query&nbsp;<span class="fa fa-caret-down"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li ng-repeat="datasource in ctrl.datasources" role="menuitem" ng-hide="datasource.meta.builtIn">
<a ng-click="ctrl.addDataQuery(datasource);">{{datasource.name}}</a>
</li>
</ul>
</div>
</div>
</div>
</div>
`;
export class MetricsDsSelectorCtrl {
dsSegment: any;
dsName: string;
panelCtrl: any;
datasources: any[];
current: any;
/** @ngInject */
constructor(private uiSegmentSrv, datasourceSrv) {
this.datasources = datasourceSrv.getMetricSources();
var dsValue = this.panelCtrl.panel.datasource || null;
for (let ds of this.datasources) {
if (ds.value === dsValue) {
this.current = ds;
}
}
this.dsSegment = uiSegmentSrv.newSegment(this.current.name);
}
getOptions() {
return Promise.resolve(this.datasources.map(value => {
return this.uiSegmentSrv.newSegment(value.name);
}));
}
datasourceChanged() {
var ds = _.findWhere(this.datasources, {name: this.dsSegment.value});
if (ds) {
this.current = ds;
this.panelCtrl.setDatasource(ds);
}
}
addDataQuery(datasource) {
var target: any = {isNew: true};
if (datasource) {
target.datasource = datasource.name;
}
this.panelCtrl.panel.targets.push(target);
}
}
module.directive('metricsDsSelector', function() {
return {
restrict: 'E',
template: template,
controller: MetricsDsSelectorCtrl,
bindToController: true,
controllerAs: 'ctrl',
transclude: true,
scope: {
panelCtrl: "="
}
};
});
@@ -27,7 +27,6 @@ class MetricsPanelCtrl extends PanelCtrl {
resolution: any;
timeInfo: any;
skipDataOnInit: boolean;
datasources: any[];
dataStream: any;
dataSubscription: any;
@@ -52,7 +51,6 @@ class MetricsPanelCtrl extends PanelCtrl {
private onInitMetricsPanelEditMode() {
this.addEditorTab('Metrics', 'public/app/partials/metrics.html');
this.addEditorTab('Time range', 'public/app/features/panel/partials/panelTime.html');
this.datasources = this.datasourceSrv.getMetricSources();
}
private onMetricsPanelRefresh() {
@@ -249,16 +247,6 @@ class MetricsPanelCtrl extends PanelCtrl {
this.datasource = null;
this.refresh();
}
addDataQuery(datasource) {
var target: any = {};
if (datasource) {
target.datasource = datasource.name;
}
this.panel.targets.push(target);
}
}
export {MetricsPanelCtrl};
@@ -1,4 +1,63 @@
<div class="tight-form">
<div class="gf-form-query">
<div class="gf-form">
<label class="gf-form-label gf-form-query-letter-cell">
<a class="pointer" tabindex="1" ng-click="ctrl.toggleCollapse()">
<span ng-class="{muted: !ctrl.canCollapse}" class="gf-form-query-letter-cell-carret">
<i class="fa fa-caret-down" ng-hide="ctrl.collapsed"></i>
<i class="fa fa-caret-right" ng-show="ctrl.collapsed"></i>
</span>
<span class="gf-form-query-letter-cell-letter">{{ctrl.target.refId}}</span>
<em class="gf-form-query-letter-cell-ds" ng-show="ctrl.target.datasource">({{ctrl.target.datasource}})</em>
</a>
</label>
</div>
<div class="gf-form-query-content gf-form-query-content--collapsed" ng-if="ctrl.collapsed">
<div class="gf-form">
<label class="gf-form-label pointer gf-form-label--grow" ng-click="ctrl.toggleCollapse()">
{{ctrl.collapsedText}}
</label>
</div>
</div>
<div ng-transclude class="gf-form-query-content" ng-if="!ctrl.collapsed">
</div>
<div class="gf-form">
<label class="gf-form-label dropdown">
<a class="pointer dropdown-toggle" data-toggle="dropdown" tabindex="1">
<i class="fa fa-bars"></i>
</a>
<ul class="dropdown-menu pull-right" role="menu">
<li role="menuitem" ng-if="ctrl.hasTextEditMode">
<a tabindex="1" ng-click="ctrl.toggleEditorMode()">Toggle Edit Mode</a>
</li>
<li role="menuitem">
<a tabindex="1" ng-click="ctrl.duplicateQuery()">Duplicate</a>
</li>
<li role="menuitem">
<a tabindex="1" ng-click="ctrl.moveQuery(-1)">Move up</a>
</li>
<li role="menuitem">
<a tabindex="1" ng-click="ctrl.moveQuery(1)">Move down</a>
</li>
</ul>
</label>
<label class="gf-form-label">
<a ng-click="ctrl.toggleHideQuery()" role="menuitem">
<i class="fa fa-eye"></i>
</a>
</label>
<label class="gf-form-label">
<a class="pointer" tabindex="1" ng-click="ctrl.removeQuery(ctrl.target)">
<i class="fa fa-trash"></i>
</a>
</label>
</div>
</div>
<div class="tight-form" ng-if="false">
<ul class="tight-form-list pull-right">
<li ng-show="ctrl.error" class="tight-form-item">
<a bs-tooltip="ctrl.error" style="color: rgb(229, 189, 28)" role="menuitem">
-34
View File
@@ -13,45 +13,11 @@ export class QueryCtrl {
constructor(public $scope, private $injector) {
this.panel = this.panelCtrl.panel;
if (!this.target.refId) {
this.target.refId = this.getNextQueryLetter();
}
}
getNextQueryLetter() {
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
return _.find(letters, refId => {
return _.every(this.panel.targets, function(other) {
return other.refId !== refId;
});
});
}
removeQuery() {
this.panel.targets = _.without(this.panel.targets, this.target);
this.panelCtrl.refresh();
};
duplicateQuery() {
var clone = angular.copy(this.target);
clone.refId = this.getNextQueryLetter();
this.panel.targets.push(clone);
}
moveQuery(direction) {
var index = _.indexOf(this.panel.targets, this.target);
_.move(this.panel.targets, index, index + direction);
}
refresh() {
this.panelCtrl.refresh();
}
toggleHideQuery() {
this.target.hide = !this.target.hide;
this.panelCtrl.refresh();
}
}
+100 -2
View File
@@ -1,17 +1,115 @@
///<reference path="../../headers/common.d.ts" />
import angular from 'angular';
import $ from 'jquery';
import _ from 'lodash';
var module = angular.module('grafana.directives');
export class QueryRowCtrl {
collapsedText: string;
canCollapse: boolean;
getCollapsedText: any;
target: any;
queryCtrl: any;
panelCtrl: any;
panel: any;
collapsed: any;
constructor() {
this.panelCtrl = this.queryCtrl.panelCtrl;
this.target = this.queryCtrl.target;
this.panel = this.panelCtrl.panel;
if (!this.target.refId) {
this.target.refId = this.getNextQueryLetter();
}
this.toggleCollapse(true);
if (this.target.isNew) {
delete this.target.isNew;
this.toggleCollapse(false);
}
}
toggleHideQuery() {
this.target.hide = !this.target.hide;
this.panelCtrl.refresh();
}
getNextQueryLetter() {
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
return _.find(letters, refId => {
return _.every(this.panel.targets, function(other) {
return other.refId !== refId;
});
});
}
toggleCollapse(init) {
if (!this.canCollapse) {
return;
}
if (!this.panelCtrl.__collapsedQueryCache) {
this.panelCtrl.__collapsedQueryCache = {};
}
if (init) {
this.collapsed = this.panelCtrl.__collapsedQueryCache[this.target.refId] !== false;
} else {
this.collapsed = !this.collapsed;
this.panelCtrl.__collapsedQueryCache[this.target.refId] = this.collapsed;
}
try {
this.collapsedText = this.queryCtrl.getCollapsedText();
} catch (e) {
var err = e.message || e.toString();
this.collapsedText = 'Error: ' + err;
}
}
toggleEditorMode() {
if (this.canCollapse && this.collapsed) {
this.collapsed = false;
}
this.queryCtrl.toggleEditorMode();
}
removeQuery() {
delete this.panelCtrl.__collapsedQueryCache[this.target.refId];
this.panel.targets = _.without(this.panel.targets, this.target);
this.panelCtrl.refresh();
}
duplicateQuery() {
var clone = angular.copy(this.target);
clone.refId = this.getNextQueryLetter();
this.panel.targets.push(clone);
}
moveQuery(direction) {
var index = _.indexOf(this.panel.targets, this.target);
_.move(this.panel.targets, index, index + direction);
}
}
/** @ngInject **/
function queryEditorRowDirective() {
return {
restrict: 'E',
controller: QueryRowCtrl,
bindToController: true,
controllerAs: "ctrl",
templateUrl: 'public/app/features/panel/partials/query_editor_row.html',
transclude: true,
scope: {ctrl: "="},
scope: {
queryCtrl: "=",
canCollapse: "=",
hasTextEditMode: "=",
},
};
}
+14 -51
View File
@@ -1,56 +1,19 @@
<div class="editor-row">
<div class="tight-form-container">
<div ng-repeat="target in ctrl.panel.targets" ng-class="{'tight-form-disabled': target.hide}">
<rebuild-on-change property="ctrl.panel.datasource || target.datasource" show-null="true">
<plugin-component type="query-ctrl">
</plugin-component>
</rebuild-on-change>
</div>
</div>
<div style="margin: 20px 0 0 0">
<button class="btn btn-inverse" ng-click="ctrl.addDataQuery()" ng-hide="ctrl.datasource.meta.mixed">
<i class="fa fa-plus"></i>&nbsp;
Query
</button>
<div class="dropdown" ng-if="ctrl.datasource.meta.mixed">
<button class="btn btn-inverse dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-plus"></i>&nbsp;
Query &nbsp; <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li ng-repeat="datasource in ctrl.datasources" role="menuitem" ng-hide="datasource.meta.builtIn">
<a ng-click="ctrl.addDataQuery(datasource);">{{datasource.name}}</a>
</li>
</ul>
</div>
</div>
<rebuild-on-change property="ctrl.panel.datasource" show-null="true">
<plugin-component type="query-options-ctrl">
</plugin-component>
</rebuild-on-change>
<div class="query-editor-rows gf-form-group">
<div ng-repeat="target in ctrl.panel.targets" ng-class="{'gf-form-disabled': target.hide}">
<rebuild-on-change property="ctrl.panel.datasource || target.datasource" show-null="true">
<plugin-component type="query-ctrl">
</plugin-component>
</rebuild-on-change>
</div>
</div>
<div class="editor-row">
<metrics-ds-selector panel-ctrl="ctrl"></metrics-ds-selector>
<div class="pull-right dropdown" style="margin-right: 10px;">
<button class="btn btn-inverse dropdown-toggle" data-toggle="dropdown" bs-tooltip="'Datasource'">
<i class="fa fa-database"></i>&nbsp;
{{ctrl.datasource.name}} &nbsp; <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li ng-repeat="datasource in ctrl.datasources" role="menuitem">
<a ng-click="ctrl.setDatasource(datasource);">{{datasource.name}}</a>
</li>
</ul>
</div>
<div class="clearfix"></div>
<div class="gf-form-group">
<rebuild-on-change property="ctrl.panel.datasource" show-null="true">
<plugin-component type="query-options-ctrl">
</plugin-component>
</rebuild-on-change>
</div>
@@ -1,4 +1,4 @@
<query-editor-row ctrl="ctrl">
<query-editor-row query-ctrl="ctrl" can-collapse="false">
<cloudwatch-query-parameter target="ctrl.target" datasource="ctrl.datasource" on-change="ctrl.refresh()"></cloudwatch-query-parameter>
</query-editor-row>
<cloudwatch-query-parameter target="ctrl.target" datasource="ctrl.datasource" on-change="ctrl.refresh()"></cloudwatch-query-parameter>
@@ -1,58 +1,59 @@
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item query-keyword tight-form-align" style="width: 100px">
Metric
</li>
<li>
<metric-segment segment="regionSegment" get-options="getRegions()" on-change="regionChanged()"></metric-segment>
</li>
<li>
<metric-segment segment="namespaceSegment" get-options="getNamespaces()" on-change="namespaceChanged()"></metric-segment>
</li>
<li>
<metric-segment segment="metricSegment" get-options="getMetrics()" on-change="metricChanged()"></metric-segment>
</li>
<li class="tight-form-item query-keyword">
Stats
</li>
<li ng-repeat="segment in statSegments">
<metric-segment segment="segment" get-options="getStatSegments(segment, $index)" on-change="statSegmentChanged(segment, $index)"></metric-segment>
</li>
</ul>
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Metric</label>
<div class="clearfix"></div>
<metric-segment segment="regionSegment" get-options="getRegions()" on-change="regionChanged()"></metric-segment>
<metric-segment segment="namespaceSegment" get-options="getNamespaces()" on-change="namespaceChanged()"></metric-segment>
<metric-segment segment="metricSegment" get-options="getMetrics()" on-change="metricChanged()"></metric-segment>
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword">Stats</label>
</div>
<div class="gf-form" ng-repeat="segment in statSegments">
<metric-segment segment="segment" get-options="getStatSegments(segment, $index)" on-change="statSegmentChanged(segment, $index)"></metric-segment>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item query-keyword tight-form-align" style="width: 100px">
Dimensions
</li>
<li ng-repeat="segment in dimSegments">
<metric-segment segment="segment" get-options="getDimSegments(segment, $index)" on-change="dimSegmentChanged(segment, $index)"></metric-segment>
</li>
</ul>
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">Dimensions</label>
<metric-segment ng-repeat="segment in dimSegments" segment="segment" get-options="getDimSegments(segment, $index)" on-change="dimSegmentChanged(segment, $index)"></metric-segment>
</div>
<div class="clearfix"></div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item query-keyword tight-form-align" style="width: 100px">
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">
Period
<tip>Interval between points in seconds</tip>
</li>
<li>
<input type="text" class="input-mini tight-form-input" ng-model="target.period" spellcheck='false' placeholder="auto" ng-model-onblur ng-change="onChange()" />
</li>
<li class="tight-form-item query-keyword">
Alias
<tip>{{metric}} {{stat}} {{namespace}} {{region}} {{DIMENSION_NAME}}</tip>
</li>
<li>
<input type="text" class="input-xlarge tight-form-input" ng-model="target.alias" spellcheck='false' ng-model-onblur ng-change="onChange()">
</li>
</ul>
<div class="clearfix"></div>
<info-popover mode="right-normal">Interval between points in seconds</info-popover>
</label>
<input type="text" class="gf-form-input" ng-model="target.period" spellcheck='false' placeholder="auto" ng-model-onblur ng-change="onChange()" />
</div>
<div class="gf-form max-width-30">
<label class="gf-form-label query-keyword width-7">Alias</label>
<input type="text" class="gf-form-input" ng-model="target.alias" spellcheck='false' ng-model-onblur ng-change="onChange()">
<info-popover mode="right-absolute">
Alias replacement variables:
<ul ng-non-bindable>
<li>{{metric}}</li>
<li>{{stat}}</li>
<li>{{namespace}}</li>
<li>{{region}}</li>
<li>{{DIMENSION_NAME}}</li>
</ul>
</info-popover>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
@@ -1,131 +1,89 @@
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item query-keyword tight-form-align" style="width: 75px;">
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">
<span ng-show="isFirst">Group by</span>
<span ng-hide="isFirst">Then by</span>
</li>
<li>
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="tight-form-item-large"></metric-segment-model>
</li>
<li ng-if="agg.field">
<metric-segment-model property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="tight-form-item-xxlarge"></metric-segment>
</li>
<li ng-if="!agg.field">
<span class="tight-form-item tight-form-item-xxlarge">&nbsp;</span>
</li>
<li class="tight-form-item last" ng-if="settingsLinkText">
</label>
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="width-10"></metric-segment-model>
<metric-segment-model ng-if="agg.field" property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></metric-segment>
</div>
<div class="gf-form gf-form--grow">
<label class="gf-form-label gf-form-label--grow">
<a ng-click="toggleOptions()">
<i class="fa fa-caret-down" ng-show="showOptions"></i>
<i class="fa fa-caret-right" ng-hide="showOptions"></i>
{{settingsLinkText}}
</a>
</li>
</ul>
</label>
</div>
<ul class="tight-form-list pull-right">
<li class="tight-form-item last" ng-if="isFirst">
<div class="gf-form">
<label class="gf-form-label" ng-if="isFirst">
<a class="pointer" ng-click="addBucketAgg()"><i class="fa fa-plus"></i></a>
</li>
<li class="tight-form-item last">
</label>
<label class="gf-form-label">
<a class="pointer" ng-click="removeBucketAgg()"><i class="fa fa-minus"></i></a>
</li>
</ul>
<div class="clearfix"></div>
</label>
</div>
</div>
<div class="tight-form" ng-if="showOptions">
<div class="tight-form-inner-box" ng-if="agg.type === 'date_histogram'">
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 170px">
Interval
</li>
<li>
<metric-segment-model property="agg.settings.interval" get-options="getIntervalOptions()" on-change="onChangeInternal()" css-class="last" custom="true"></metric-segment-model>
</li>
</ul>
<div class="clearfix"></div>
<div class="gf-form-group" ng-if="showOptions">
<div ng-if="agg.type === 'date_histogram'">
<div class="gf-form offset-width-7">
<label class="gf-form-label width-10">Interval</label>
<metric-segment-model property="agg.settings.interval" get-options="getIntervalOptions()" on-change="onChangeInternal()" css-class="width-12" custom="true"></metric-segment-model>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 170px">
Min Doc Count
</li>
<li>
<input type="number" class="tight-form-input" ng-model="agg.settings.min_doc_count" ng-blur="onChangeInternal()">
</li>
</ul>
<div class="clearfix"></div>
<div class="gf-form offset-width-7">
<label class="gf-form-label width-10">Min Doc Count</label>
<input type="number" class="gf-form-input max-width-12" ng-model="agg.settings.min_doc_count" ng-blur="onChangeInternal()">
</div>
<div class="tight-form last">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 170px">
Trim edges points
</li>
<li>
<input class="tight-form-input" type="number" ng-model="agg.settings.trimEdges" ng-change="onChangeInternal()">
</li>
<li class="tight-form-item last">
<i class="fa fa-question-circle" bs-tooltip="'Trim the edges on the timeseries x datapoints'" data-placement="right"></i>
</li>
</ul>
<div class="clearfix"></div>
<div class="gf-form offset-width-7">
<label class="gf-form-label width-10">
Trim edges
<info-popover mode="right-normal">
Trim the edges on the timeseries datapoints
</info-popover>
</label>
<input class="gf-form-input max-width-12" type="number" ng-model="agg.settings.trimEdges" ng-change="onChangeInternal()">
</div>
</div>
<div class="tight-form-inner-box" ng-if="agg.type === 'terms'">
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 60px">
Order
</li>
<li>
<metric-segment-model property="agg.settings.order" options="orderOptions" on-change="onChangeInternal()" css-class="last"></metric-segment-model>
</li>
</ul>
<div class="clearfix"></div>
<div ng-if="agg.type === 'terms'">
<div class="gf-form offset-width-7">
<label class="gf-form-label">Order</label>
<metric-segment-model property="agg.settings.order" options="orderOptions" on-change="onChangeInternal()" css-class="width-12"></metric-segment-model>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 60px">
Size
</li>
<li>
<metric-segment-model property="agg.settings.size" options="sizeOptions" on-change="onChangeInternal()" css-class="last"></metric-segment-model>
</li>
</ul>
<div class="clearfix"></div>
<div class="gf-form offset-width-7">
<label class="gf-form-label width-10">Size</label>
<metric-segment-model property="agg.settings.size" options="sizeOptions" on-change="onChangeInternal()" css-class="width-12"></metric-segment-model>
</div>
<div class="tight-form last">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 60px">
Order By
</li>
<li>
<metric-segment-model property="agg.settings.orderBy" options="orderByOptions" on-change="onChangeInternal()" css-class="last"></metric-segment-model>
</li>
</ul>
<div class="clearfix"></div>
<div class="gf-form offset-width-7">
<label class="gf-form-label width-10">Order By</label>
<metric-segment-model property="agg.settings.orderBy" options="orderByOptions" on-change="onChangeInternal()" css-class="width-12"></metric-segment-model>
</div>
</div>
<div class="tight-form-inner-box" ng-if="agg.type === 'filters'">
<div class="tight-form" ng-repeat="filter in agg.settings.filters" ng-class="{last: $last}">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 100px">
Query {{$index + 1}}
</li>
<li>
<input type="text" class="tight-form-input input-large" ng-model="filter.query" spellcheck='false' placeholder="Lucene query" ng-blur="onChangeInternal()">
</li>
<li class="tight-form-item last" ng-if="$first">
<div ng-if="agg.type === 'filters'">
<div class="gf-form-inline" ng-repeat="filter in agg.settings.filters" ng-class="{last: $last}">
<div class="gf-form">
<label class="gf-form-item width-10">Query {{$index + 1}}</label>
<input type="text" class="gf-form-input max-width-12" ng-model="filter.query" spellcheck='false' placeholder="Lucene query" ng-blur="onChangeInternal()">
</div>
<div class="gf-form">
<label class="gf-form-label" ng-if="$first">
<a class="pointer" ng-click="addFiltersQuery()"><i class="fa fa-plus"></i></a>
</li>
<li class="tight-form-item last" ng-if="!$first">
</label>
<label class="gf-form-label" ng-if="!$first">
<a class="pointer" ng-click="removeFiltersQuery(filter)"><i class="fa fa-minus"></i></a>
</li>
</ul>
<div class="clearfix"></div>
</label>
</div>
</div>
</div>
</div>
@@ -1,138 +1,82 @@
<div class="tight-form" ng-class="{'tight-form-disabled': agg.hide}">
<ul class="tight-form-list">
<li class="tight-form-item query-keyword tight-form-align" style="width: 75px;">
<div class="gf-form-inline" ng-class="{'gf-form-disabled': agg.hide}">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">
Metric
&nbsp;
<a ng-click="toggleShowMetric()" bs-tooltip="'Click to toggle show / hide metric'">
<i class="fa fa-eye" ng-hide="agg.hide"></i>
<i class="fa fa-eye-slash" ng-show="agg.hide"></i>
</a>
</li>
<li>
<metric-segment-model property="agg.type" options="metricAggTypes" on-change="onTypeChange()" custom="false" css-class="tight-form-item-large"></metric-segment-model>
</li>
<li ng-if="aggDef.requiresField">
<metric-segment-model property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="tight-form-item-xxlarge"></metric-segment-model>
</li>
<li ng-if="aggDef.isPipelineAgg">
<metric-segment-model property="agg.pipelineAgg" options="pipelineAggOptions" on-change="onChangeInternal()" custom="false" css-class="tight-form-item-xxlarge"></metric-segment-model>
</li>
<li class="tight-form-item last" ng-if="settingsLinkText">
<a ng-click="toggleOptions()">
</label>
</div>
<div class="gf-form">
<metric-segment-model property="agg.type" options="metricAggTypes" on-change="onTypeChange()" custom="false" css-class="width-10"></metric-segment-model>
<metric-segment-model ng-if="aggDef.requiresField" property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></metric-segment-model>
<metric-segment-model ng-if="aggDef.isPipelineAgg" property="agg.pipelineAgg" options="pipelineAggOptions" on-change="onChangeInternal()" custom="false" css-class="width-12"></metric-segment-model>
</div>
<div class="gf-form gf-form--grow">
<label class="gf-form-label gf-form-label--grow">
<a ng-click="toggleOptions()" ng-if="settingsLinkText">
<i class="fa fa-caret-down" ng-show="showOptions"></i>
<i class="fa fa-caret-right" ng-hide="showOptions"></i>
{{settingsLinkText}}
{{settingsLinkText}}
</a>
</li>
</ul>
</label>
</div>
<ul class="tight-form-list pull-right">
<li class="tight-form-item last" ng-if="isFirst">
<div class="gf-form">
<label class="gf-form-label" ng-if="isFirst">
<a class="pointer" ng-click="addMetricAgg()"><i class="fa fa-plus"></i></a>
</li>
<li class="tight-form-item last" ng-if="!isSingle">
</label>
<label class="gf-form-label" ng-if="!isSingle">
<a class="pointer" ng-click="removeMetricAgg()"><i class="fa fa-minus"></i></a>
</li>
</ul>
<div class="clearfix"></div>
</label>
</div>
</div>
<div class="tight-form" ng-if="showOptions">
<div class="tight-form-inner-box tight-form-container">
<div class="tight-form" ng-if="agg.type === 'derivative'">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 75px;">
Unit
</li>
<li>
<input type="text" class="input-medium tight-form-input last" ng-model="agg.settings.unit" ng-blur="onChangeInternal()" spellcheck='false'>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="gf-form-group" ng-if="showOptions">
<div class="gf-form offset-width-7" ng-if="agg.type === 'derivative'">
<label class="gf-form-label width-10">Unit</label>
<input type="text" class="gf-form-input max-width-12" ng-model="agg.settings.unit" ng-blur="onChangeInternal()" spellcheck='false'>
</div>
<div class="gf-form offset-width-7" ng-if="agg.type === 'moving_avg'">
<label class="gf-form-label width-10">Window</label>
<input type="number" class="gf-form-input max-width-12" ng-model="agg.settings.window" ng-blur="onChangeInternal()" spellcheck='false'>
</div>
<div class="gf-form offset-width-7" ng-if="agg.type === 'moving_avg'">
<label class="gf-form-label width-10">Model</label>
<input type="text" class="gf-form-input max-width-12" ng-change="onChangeInternal()" ng-model="agg.settings.model" blur="onChange()" spellcheck='false'>
</div>
<div class="gf-form offset-width-7" ng-if="agg.type === 'percentiles'">
<label class="gf-form-label width-10">Percentiles</label>
<input type="text" class="gf-form-input max-width-12" ng-model="agg.settings.percents" array-join ng-blur="onChange()"></input>
</div>
<div class="tight-form" ng-if="agg.type === 'moving_avg'">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 75px;">
Window
</li>
<li>
<input type="number" class="input-medium tight-form-input last" ng-model="agg.settings.window" ng-blur="onChangeInternal()" spellcheck='false'>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form" ng-if="agg.type === 'moving_avg'">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 75px;">
Model
</li>
<li>
<input type="text" class="input-medium tight-form-input last" ng-change="onChangeInternal()" ng-model="agg.settings.model" blur="onChange()" spellcheck='false'>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form last" ng-if="agg.type === 'percentiles'">
<ul class="tight-form-list">
<li class="tight-form-item">
Percentiles
</li>
<li>
<input type="text" class="input-xlarge tight-form-input last" ng-model="agg.settings.percents" array-join ng-blur="onChange()"></input>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div ng-if="agg.type === 'extended_stats'">
<div class="tight-form" ng-repeat="stat in extendedStats">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 100px">
{{stat.text}}
</li>
<li class="tight-form-item last">
<editor-checkbox text="" model="agg.meta.{{stat.value}}" change="onChange()"></editor-checkbox>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
<div class="tight-form" ng-if="agg.type === 'extended_stats'">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 100px">
Sigma
</li>
<li>
<input type="number" class="input-mini tight-form-input last" placeholder="3" ng-model="agg.settings.sigma" ng-blur="onChange()"></input>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div ng-if="agg.type === 'extended_stats'">
<gf-form-switch ng-repeat="stat in extendedStats" class="gf-form offset-width-7" label="{{stat.text}}" label-class="width-10" checked="agg.meta[stat.value]" on-change="onChangeInternal()"></gf-form-switch>
<div class="tight-form" ng-if="aggDef.supportsInlineScript">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 100px;">
Script
</li>
<li>
<input type="text" class="input-medium tight-form-input last" empty-to-null ng-model="agg.inlineScript" ng-blur="onChangeInternal()" spellcheck='false' placeholder="_value * 1">
</li>
</ul>
<div class="clearfix"></div>
<div class="gf-form offset-width-7">
<label class="gf-form-label width-10">Sigma</label>
<input type="number" class="gf-form-input max-width-12" placeholder="3" ng-model="agg.settings.sigma" ng-blur="onChange()"></input>
</div>
</div>
<div class="tight-form" ng-if="aggDef.supportsMissing">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 100px;">
Missing
<tip>The missing parameter defines how documents that are missing a value should be treated. By default they will be ignored but it is also possible to treat them as if they had a value</tip>
</li>
<li>
<input type="number" class="input-medium tight-form-input last" empty-to-null ng-model="agg.settings.missing" ng-blur="onChangeInternal()" spellcheck='false'>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="gf-form offset-width-7" ng-if="aggDef.supportsInlineScript">
<label class="gf-form-label width-10">Script</label>
<input type="text" class="gf-form-input max-width-12" empty-to-null ng-model="agg.inlineScript" ng-blur="onChangeInternal()" spellcheck='false' placeholder="_value * 1">
</div>
<div class="gf-form offset-width-7" ng-if="aggDef.supportsMissing">
<label class="gf-form-label width-10">
Missing
<tip>The missing parameter defines how documents that are missing a value should be treated. By default they will be ignored but it is also possible to treat them as if they had a value</tip>
</label>
<input type="number" class="gf-form-input max-width-12" empty-to-null ng-model="agg.settings.missing" ng-blur="onChangeInternal()" spellcheck='false'>
</div>
</div>
@@ -1,32 +1,31 @@
<query-editor-row ctrl="ctrl">
<li class="tight-form-item query-keyword" style="width: 75px">
Query
</li>
<li>
<input type="text" class="tight-form-input" style="width: 345px;" ng-model="ctrl.target.query" spellcheck='false' placeholder="Lucene query" ng-blur="ctrl.refresh()">
</li>
<li class="tight-form-item query-keyword">
Alias
</li>
<li>
<input type="text" class="tight-form-input" style="width: 200px;" ng-model="ctrl.target.alias" spellcheck='false' placeholder="alias patterns (empty = auto)" ng-blur="ctrl.refresh()">
</li>
<query-editor-row query-ctrl="ctrl" can-collapse="true">
<div class="gf-form-inline">
<div class="gf-form gf-form--grow">
<label class="gf-form-label query-keyword width-7">Query</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.query" spellcheck='false' placeholder="Lucene query" ng-blur="ctrl.refresh()">
</div>
<div class="gf-form max-width-15">
<label class="gf-form-label query-keyword">Alias</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.alias" spellcheck='false' placeholder="alias patterns" ng-blur="ctrl.refresh()">
</div>
</div>
<div ng-repeat="agg in ctrl.target.metrics">
<elastic-metric-agg
target="ctrl.target" index="$index"
get-fields="ctrl.getFields($fieldType)"
on-change="ctrl.queryUpdated()"
es-version="ctrl.esVersion">
</elastic-metric-agg>
</div>
<div ng-repeat="agg in ctrl.target.bucketAggs">
<elastic-bucket-agg
target="ctrl.target" index="$index"
get-fields="ctrl.getFields($fieldType)"
on-change="ctrl.queryUpdated()">
</elastic-bucket-agg>
</div>
</query-editor-row>
<div ng-repeat="agg in ctrl.target.metrics">
<elastic-metric-agg
target="ctrl.target" index="$index"
get-fields="ctrl.getFields($fieldType)"
on-change="ctrl.queryUpdated()"
es-version="ctrl.esVersion">
</elastic-metric-agg>
</div>
<div ng-repeat="agg in ctrl.target.bucketAggs">
<elastic-bucket-agg
target="ctrl.target" index="$index"
get-fields="ctrl.getFields($fieldType)"
on-change="ctrl.queryUpdated()">
</elastic-bucket-agg>
</div>
@@ -5,6 +5,7 @@ import './metric_agg';
import angular from 'angular';
import _ from 'lodash';
import queryDef from './query_def';
import {QueryCtrl} from 'app/plugins/sdk';
export class ElasticQueryCtrl extends QueryCtrl {
@@ -38,6 +39,48 @@ export class ElasticQueryCtrl extends QueryCtrl {
this.$rootScope.appEvent('elastic-query-updated');
}
getCollapsedText() {
var metricAggs = this.target.metrics;
var bucketAggs = this.target.bucketAggs;
var metricAggTypes = queryDef.getMetricAggTypes(this.esVersion);
var bucketAggTypes = queryDef.bucketAggTypes;
var text = '';
if (this.target.query) {
text += 'Query: ' + this.target.query + ', ';
}
text += 'Metrics: ';
_.each(metricAggs, (metric, index) => {
var aggDef = _.findWhere(metricAggTypes, {value: metric.type});
text += aggDef.text + '(';
if (aggDef.requiresField) {
text += metric.field;
}
text += '), ';
});
_.each(bucketAggs, (bucketAgg, index) => {
if (index === 0) {
text += ' Group by: ';
}
var aggDef = _.findWhere(bucketAggTypes, {value: bucketAgg.type});
text += aggDef.text + '(';
if (aggDef.requiresField) {
text += bucketAgg.field;
}
text += '), ';
});
if (this.target.alias) {
text += 'Alias: ' + this.target.alias;
}
return text;
}
handleQueryError(err) {
this.error = err.message || 'Failed to issue metric query';
return [];
@@ -20,9 +20,9 @@ function (_) {
],
bucketAggTypes: [
{text: "Terms", value: 'terms' },
{text: "Terms", value: 'terms', requiresField: true},
{text: "Filters", value: 'filters' },
{text: "Date Histogram", value: 'date_histogram' },
{text: "Date Histogram", value: 'date_histogram', requiresField: true},
],
orderByOptions: [
@@ -1,5 +1,7 @@
<query-editor-row ctrl="ctrl">
<li class="tight-form-item">
Test metric (fake data source)
</li>
<query-editor-row query-ctrl="ctrl" can-collapse="false">
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label">Test metric (fake data source)</label>
</div>
</div>
</query-editor-row>
@@ -11,10 +11,10 @@ function (angular, _, $, gfunc) {
.module('grafana.directives')
.directive('graphiteAddFunc', function($compile) {
var inputTemplate = '<input type="text"'+
' class="tight-form-input input-medium tight-form-input"' +
' class="gf-form-input"' +
' spellcheck="false" style="display:none"></input>';
var buttonTemplate = '<a class="tight-form-item tight-form-func dropdown-toggle"' +
var buttonTemplate = '<a class="gf-form-label query-part dropdown-toggle"' +
' tabindex="1" gf-dropdown="functionMenu" data-toggle="dropdown">' +
'<i class="fa fa-plus"></i></a>';
@@ -1,21 +1,27 @@
<query-editor-row ctrl="ctrl">
<query-editor-row query-ctrl="ctrl" has-text-edit-mode="true">
<li class="tight-form-flex-wrapper" ng-show="ctrl.target.textEditor">
<input type="text" class="tight-form-clear-input" style="width: 100%;" ng-model="ctrl.target.target" give-focus="ctrl.target.textEditor" spellcheck='false' ng-model-onblur ng-change="ctrl.targetTextChanged()"></input>
</li>
<div class="gf-form" ng-show="ctrl.target.textEditor">
<input type="text" class="gf-form-input" ng-model="ctrl.target.target" spellcheck="false" ng-blur="ctrl.refresh()"></input>
</div>
<li ng-hide-start="ctrl.target.textEditor"></li>
<div ng-hide="ctrl.target.textEditor">
<div class="gf-form-inline">
<div ng-repeat="segment in ctrl.segments" role="menuitem" class="gf-form">
<metric-segment segment="segment" get-options="ctrl.getAltSegments($index)" on-change="ctrl.segmentValueChanged(segment, $index)"></metric-segment>
</div>
<li ng-repeat="segment in ctrl.segments" role="menuitem">
<metric-segment segment="segment" get-options="ctrl.getAltSegments($index)" on-change="ctrl.segmentValueChanged(segment, $index)"></metric-segment>
</li>
<li ng-repeat="func in ctrl.functions">
<span graphite-func-editor class="tight-form-item tight-form-func">
</span>
</li>
<li class="dropdown" graphite-add-func>
</li>
<div ng-repeat="func in ctrl.functions" class="gf-form">
<span graphite-func-editor class="gf-form-label query-part"></span>
</div>
<li ng-hide-end></li>
<div class="gf-form dropdown">
<span graphite-add-func></span>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
</div>
</query-editor-row>
@@ -164,7 +164,7 @@ export default class InfluxQuery {
getMeasurementAndPolicy(interpolate) {
var policy = this.target.policy;
var measurement = this.target.measurement;
var measurement = this.target.measurement || 'measurement';
if (!measurement.match('^/.*/')) {
measurement = '"' + measurement+ '"';
@@ -192,10 +192,6 @@ export default class InfluxQuery {
}
}
if (!target.measurement) {
throw {message: "Metric measurement is missing"};
}
var query = 'SELECT ';
var i, y;
for (i = 0; i < this.selectModels.length; i++) {
@@ -1,73 +1,96 @@
<query-editor-row ctrl="ctrl">
<ul class="tight-form-list" ng-hide="ctrl.target.rawQuery">
<li class="tight-form-item query-keyword" style="width: 75px">
FROM
</li>
<li>
<query-editor-row query-ctrl="ctrl" can-collapse="true" has-text-edit-mode="true">
<div class="gf-form" ng-if="ctrl.target.rawQuery">
<input type="text" class="gf-form-input" ng-model="ctrl.target.query" spellcheck="false" ng-blur="ctrl.refresh()"></input>
</div>
<div ng-if="!ctrl.target.rawQuery">
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">FROM</label>
<metric-segment segment="ctrl.policySegment" get-options="ctrl.getPolicySegments()" on-change="ctrl.policyChanged()"></metric-segment>
</li>
<li>
<metric-segment segment="ctrl.measurementSegment" get-options="ctrl.getMeasurements()" on-change="ctrl.measurementChanged()"></metric-segment>
</li>
<li class="tight-form-item query-keyword" style="padding-left: 15px; padding-right: 15px;">
WHERE
</li>
<li ng-repeat="segment in ctrl.tagSegments">
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword">WHERE</label>
</div>
<div class="gf-form" ng-repeat="segment in ctrl.tagSegments">
<metric-segment segment="segment" get-options="ctrl.getTagsOrValues(segment, $index)" on-change="ctrl.tagSegmentUpdated(segment, $index)"></metric-segment>
</li>
</ul>
</div>
<div class="tight-form-flex-wrapper" ng-show="ctrl.target.rawQuery">
<input type="text" class="tight-form-clear-input" ng-model="ctrl.target.query" spellcheck="false" style="width: 100%;" ng-blur="ctrl.refresh()"></input>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="gf-form-inline" ng-repeat="selectParts in ctrl.queryModel.selectModels">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">
<span ng-show="$index === 0">SELECT</span>
</label>
</div>
<div class="gf-form" ng-repeat="part in selectParts">
<influx-query-part-editor
class="gf-form-label query-part"
part="part"
remove-action="ctrl.removeSelectPart(selectParts, part)"
part-updated="ctrl.selectPartUpdated(selectParts, part)"
get-options="ctrl.getPartOptions(part)">
</influx-query-part-editor>
</div>
<div class="gf-form">
<label class="dropdown"
dropdown-typeahead="ctrl.selectMenu"
dropdown-typeahead-on-select="ctrl.addSelectPart(selectParts, $item, $subItem)">
</label>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">
<span>GROUP BY</span>
</label>
<influx-query-part-editor
ng-repeat="part in ctrl.queryModel.groupByParts"
part="part"
class="gf-form-label query-part"
remove-action="ctrl.removeGroupByPart(part, $index)" part-updated="ctrl.refresh();" get-options="ctrl.getPartOptions(part)">
</influx-query-part-editor>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
</div>
<div class="gf-form-inline">
<div class="gf-form max-width-30">
<label class="gf-form-label query-keyword width-7">ALIAS BY</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.alias" spellcheck='false' placeholder="Naming pattern" ng-blur="ctrl.refresh()">
</div>
<div class="gf-form">
<label class="gf-form-label">Format as</label>
<div class="gf-form-select-wrapper">
<select class="gf-form-input gf-size-auto" ng-model="ctrl.target.resultFormat" ng-options="f.value as f.text for f in ctrl.resultFormats" ng-change="ctrl.refresh()"></select>
</div>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
</query-editor-row>
<div ng-hide="ctrl.target.rawQuery">
<div class="tight-form" ng-repeat="selectParts in ctrl.queryModel.selectModels">
<ul class="tight-form-list">
<li class="tight-form-item query-keyword tight-form-align" style="width: 75px;">
<span ng-show="$index === 0">SELECT</span>
</li>
<li ng-repeat="part in selectParts">
<influx-query-part-editor part="part" class="tight-form-item tight-form-func" remove-action="ctrl.removeSelectPart(selectParts, part)" part-updated="ctrl.selectPartUpdated(selectParts, part)" get-options="ctrl.getPartOptions(part)"></influx-query-part-editor>
</li>
<li class="dropdown" dropdown-typeahead="ctrl.selectMenu" dropdown-typeahead-on-select="ctrl.addSelectPart(selectParts, $item, $subItem)">
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item query-keyword tight-form-align" style="width: 75px;">
<span>GROUP BY</span>
</li>
<li ng-repeat="part in ctrl.queryModel.groupByParts">
<influx-query-part-editor part="part" class="tight-form-item tight-form-func" remove-action="ctrl.removeGroupByPart(part, $index)" part-updated="ctrl.refresh();" get-options="ctrl.getPartOptions(part)"></influx-query-part-editor>
</li>
<li>
<metric-segment segment="ctrl.groupBySegment" get-options="ctrl.getGroupByOptions()" on-change="ctrl.groupByAction(part, $index)"></metric-segment>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item query-keyword tight-form-align" style="width: 75px;">
ALIAS BY
</li>
<li>
<input type="text" class="tight-form-clear-input input-xlarge" ng-model="ctrl.target.alias" spellcheck='false' placeholder="Naming pattern" ng-blur="ctrl.refresh()">
</li>
<li class="tight-form-item">
Format as
</li>
<li>
<select class="input-small tight-form-input" style="width: 104px" ng-model="ctrl.target.resultFormat" ng-options="f.value as f.text for f in ctrl.resultFormats" ng-change="ctrl.refresh()"></select>
</li>
</ul>
<div class="clearfix"></div>
</div>
@@ -38,7 +38,7 @@
</section>
<div class="editor-row">
<div class="pull-left" style="margin-top: 30px;">
<div class="pull-left">
<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 1">
<h5>Alias patterns</h5>
@@ -2,4 +2,4 @@
<span class="pointer fa fa-remove" ng-click="removeActionInternal()" ></span>
</div>
<a ng-click="toggleControls()">{{part.def.type}}</a><span>(</span><span class="query-part-parameters"></span><span>)</span>
<a ng-click="toggleControls()" class="query-part-name">{{part.def.type}}</a><span>(</span><span class="query-part-parameters"></span><span>)</span>
@@ -23,6 +23,7 @@ export class InfluxQueryCtrl extends QueryCtrl {
measurementSegment: any;
removeTagFilterSegment: any;
/** @ngInject **/
constructor($scope, $injector, private templateSrv, private $q, private uiSegmentSrv) {
super($scope, $injector);
@@ -154,7 +155,11 @@ export class InfluxQueryCtrl extends QueryCtrl {
}
toggleEditorMode() {
this.target.query = this.queryModel.render(false);
try {
this.target.query = this.queryModel.render(false);
} catch (err) {
console.log('query render error');
}
this.target.rawQuery = !this.target.rawQuery;
}
@@ -316,5 +321,9 @@ export class InfluxQueryCtrl extends QueryCtrl {
return '=';
}
}
getCollapsedText() {
return this.queryModel.render(false);
}
}
@@ -1,223 +1,253 @@
<query-editor-row ctrl="ctrl">
<li class="tight-form-item query-keyword" style="width: 100px">
Metric
</li>
<li>
<input type="text" class="input-large tight-form-input" ng-model="ctrl.target.metric"
spellcheck='false' bs-typeahead="ctrl.suggestMetrics" placeholder="metric name" data-min-length=0 data-items=100
ng-blur="ctrl.targetBlur()">
</input>
<a bs-tooltip="ctrl.errors.metric" style="color: rgb(229, 189, 28)" ng-show="ctrl.errors.metric">
<i class="fa fa-warning"></i>
</a>
</li>
<li class="tight-form-item query-keyword">
Aggregator
</li>
<li>
<select ng-model="ctrl.target.aggregator" class="tight-form-input input-small"
ng-options="agg for agg in ctrl.aggregators"
ng-change="ctrl.targetBlur()">
</select>
<a bs-tooltip="ctrl.errors.aggregator" style="color: rgb(229, 189, 28)" ng-show="ctrl.errors.aggregator">
<i class="fa fa-warning"></i>
</a>
</li>
<query-editor-row query-ctrl="ctrl" can-collapse="false">
<div class="gf-form-inline">
<div class="gf-form max-width-25">
<label class="gf-form-label query-keyword width-8">
Metric
<label class="gf-form-label" bs-tooltip="ctrl.errors.metric" style="color: rgb(229, 189, 28)" ng-show="ctrl.errors.metric">
<i class="fa fa-warning"></i>
</label>
</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.metric"
spellcheck='false' bs-typeahead="ctrl.suggestMetrics" placeholder="metric name" data-min-length=0 data-items=100
ng-blur="ctrl.targetBlur()">
</input>
</div>
<div class="gf-form">
<label class="gf-form-label query-keyword">
Aggregator
<a bs-tooltip="ctrl.errors.aggregator" style="color: rgb(229, 189, 28)" ng-show="ctrl.errors.aggregator">
<i class="fa fa-warning"></i>
</a>
</label>
<div class="gf-form-select-wrapper max-width-15">
<select ng-model="ctrl.target.aggregator" class="gf-form-input"
ng-options="agg for agg in ctrl.aggregators"
ng-change="ctrl.targetBlur()">
</select>
</div>
</div>
<div class="gf-form max-width-20">
<label class="gf-form-label query-keyword width-6">
Alias:
<info-popover mode="right-normal">
Use patterns like $tag_tagname to replace part of the alias for a tag value
</info-popover>
</label>
<input type="text" class="gf-form-input"
ng-model="ctrl.target.alias"
spellcheck='false'
placeholder="series alias"
data-min-length=0 data-items=100
ng-blur="ctrl.targetBlur()"></input>
</div>
<li class="tight-form-item query-keyword">
Alias:
<tip>Use patterns like $tag_tagname to replace part of the alias for a tag value</tip>
</li>
<li>
<input type="text" class="tight-form-input input-large"
ng-model="ctrl.target.alias"
spellcheck='false'
placeholder="series alias"
data-min-length=0 data-items=100
ng-blur="ctrl.targetBlur()"></input>
</li>
</query-editor-row>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align query-keyword" style="width: 100px">
Down sample
</li>
<div class="gf-form-inline">
<div class="gf-form max-width-25">
<label class="gf-form-label query-keyword width-8">Down sample</label>
<input type="text" class="gf-form-input"
ng-model="ctrl.target.downsampleInterval"
ng-model-onblur
ng-change="ctrl.targetBlur()"
placeholder="interval"></input>
<info-popover mode="right-absolute">
blank for auto, or for example <code>1m</code>
</info-popover>
</div>
<li>
<input type="text" class="input-large tight-form-input"
ng-model="ctrl.target.downsampleInterval"
ng-model-onblur
ng-change="ctrl.targetBlur()"
placeholder="interval (empty = auto)"></input>
</li>
<div class="gf-form">
<label class="gf-form-label query-keyword">Aggregator</label>
<div class="gf-form-select-wrapper">
<select ng-model="ctrl.target.downsampleAggregator" class="gf-form-input"
ng-options="agg for agg in ctrl.aggregators"
ng-change="ctrl.targetBlur()">
</select>
</div>
</div>
<li class="tight-form-item query-keyword">
Aggregator
</li>
<div class="gf-form" ng-if="ctrl.tsdbVersion == 2">
<label class="gf-form-label query-keyword width-6">Fill</label>
<div class="gf-form-select-wrapper">
<select ng-model="ctrl.target.downsampleFillPolicy" class="gf-form-input"
ng-options="agg for agg in ctrl.fillPolicies"
ng-change="ctrl.targetBlur()">
</select>
</div>
</div>
<li>
<select ng-model="ctrl.target.downsampleAggregator" class="tight-form-input input-small"
ng-options="agg for agg in ctrl.aggregators"
ng-change="ctrl.targetBlur()">
</select>
</li>
<gf-form-switch class="gf-form"
label="Disable downsampling"
checked="ctrl.target.disableDownsampling"
on-change="ctrl.targetBlur()">
</gf-form-switch>
<li class="tight-form-item query-keyword" style="width: 59px" ng-if="ctrl.tsdbVersion == 2">
Fill
</li>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<li ng-if="ctrl.tsdbVersion == 2">
<select ng-model="ctrl.target.downsampleFillPolicy" class="tight-form-input input-small"
ng-options="agg for agg in ctrl.fillPolicies"
ng-change="ctrl.targetBlur()">
</select>
</li>
<div class="gf-form-inline" ng-if="ctrl.tsdbVersion == 2">
<div class="gf-form">
<li class="tight-form-item query-keyword">
Disable downsampling <editor-checkbox text="" model="ctrl.target.disableDownsampling" change="ctrl.targetBlur()"></editor-checkbox>
</li>
<label class="gf-form-label query-keyword width-8">
Filters
<info-popover mode="right-normal">
Filters does not work with tags, either of the two will work but not both.
</info-popover>
</label>
</ul>
<div class="clearfix"></div>
</div>
<div ng-repeat="fil in ctrl.target.filters track by $index" class="gf-form-label">
{{fil.tagk}}&nbsp;=&nbsp;{{fil.type}}&#40;{{fil.filter}}&#41;&nbsp;&#44&nbsp;groupBy&nbsp;=&nbsp;{{fil.groupBy}}
<a ng-click="ctrl.editFilter(fil, $index)">
<i class="fa fa-pencil"></i>
</a>
<a ng-click="ctrl.removeFilter($index)">
<i class="fa fa-remove"></i>
</a>
</div>
<label class="gf-form-label query-keyword" ng-hide="ctrl.addFilterMode">
<a ng-click="ctrl.addFilter()">
<i class="fa fa-plus"></i>
</a>
</label>
</div>
<div class="tight-form" ng-if="ctrl.tsdbVersion == 2">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align query-keyword" style="width: 100px">
Filters
<tip ng-if="ctrl.tsdbVersion == 2">Filters does not work with tags, either of the two will work but not both.</tip>
</li>
<li ng-repeat="fil in ctrl.target.filters track by $index" class="tight-form-item">
{{fil.tagk}}&nbsp;=&nbsp;{{fil.type}}&#40;{{fil.filter}}&#41;&nbsp;&#44&nbsp;groupBy&nbsp;=&nbsp;{{fil.groupBy}}
<a ng-click="ctrl.editFilter(fil, $index)">
<i class="fa fa-pencil"></i>
</a>
<a ng-click="ctrl.removeFilter($index)">
<i class="fa fa-remove"></i>
</a>
</li>
<li class="tight-form-item query-keyword" ng-hide="ctrl.addFilterMode">
<a ng-click="ctrl.addFilter()">
<i class="fa fa-plus"></i>
</a>
</li>
<div class="gf-form-inline" ng-show="ctrl.addFilterMode">
<div class="gf-form">
<input type="text" class="gf-form-input" spellcheck='false'
bs-typeahead="ctrl.suggestTagKeys" data-min-length=0 data-items=100
ng-model="ctrl.target.currentFilterKey" placeholder="key">
</input>
</div>
<li class="query-keyword" ng-show="ctrl.addFilterMode">
<input type="text" class="input-small tight-form-input" spellcheck='false'
bs-typeahead="ctrl.suggestTagKeys" data-min-length=0 data-items=100
ng-model="ctrl.target.currentFilterKey" placeholder="key"></input>
<div class="gf-form">
<label class="gf-form-label">Type</label>
<div class="gf-form-select-wrapper">
<select ng-model="ctrl.target.currentFilterType" class="gf-form-input" ng-options="filType for filType in ctrl.filterTypes">
</select>
</div>
</div>
Type <select ng-model="ctrl.target.currentFilterType"
class="tight-form-input input-small"
ng-options="filType for filType in ctrl.filterTypes">
</select>
<input type="text" class="input-small tight-form-input"
spellcheck='false' bs-typeahead="ctrl.suggestTagValues"
data-min-length=0 data-items=100 ng-model="ctrl.target.currentFilterValue" placeholder="filter">
</input>
<div class="gf-form">
<input type="text" class="gf-form-input" spellcheck='false' bs-typeahead="ctrl.suggestTagValues" data-min-length=0 data-items=100 ng-model="ctrl.target.currentFilterValue" placeholder="filter">
</input>
</div>
groupBy <editor-checkbox text="" model="ctrl.target.currentFilterGroupBy"></editor-checkbox>
<gf-form-switch class="gf-form" label="Group by" checked="ctrl.target.currentFilterGroupBy" on-change="ctrl.targetBlur()">
</gf-form-switch>
<a bs-tooltip="ctrl.errors.filters"
style="color: rgb(229, 189, 28)"
ng-show="ctrl.errors.filters">
<i class="fa fa-warning"></i>
</a>
<a ng-click="ctrl.addFilter()" ng-hide="ctrl.errors.filters">
add filter
</a>
<a ng-click="ctrl.closeAddFilterMode()">
<i class="fa fa-remove"></i>
</a>
<div class="gf-form" ng-show="ctrl.addFilterMode">
<label class="gf-form-label" ng-show="ctrl.errors.filters">
<a bs-tooltip="ctrl.errors.filters" style="color: rgb(229, 189, 28)" >
<i class="fa fa-warning"></i>
</a>
</label>
</li>
</ul>
<div class="clearfix"></div>
</div>
<label class="gf-form-label">
<a ng-click="ctrl.addFilter()" ng-hide="ctrl.errors.filters">add filter</a>
<a ng-click="ctrl.closeAddFilterMode()">
<i class="fa fa-remove"></i>
</a>
</label>
</div>
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align query-keyword" style="width: 100px">
Tags
<tip ng-if="ctrl.tsdbVersion == 2">Please use filters, tags are deprecated in opentsdb 2.2</tip>
</li>
<li ng-repeat="(key, value) in ctrl.target.tags track by $index" class="tight-form-item">
{{key}}&nbsp;=&nbsp;{{value}}
<a ng-click="ctrl.editTag(key, value)">
<i class="fa fa-pencil"></i>
</a>
<a ng-click="ctrl.removeTag(key)">
<i class="fa fa-remove"></i>
</a>
</li>
</div>
<li class="tight-form-item query-keyword" ng-hide="ctrl.addTagMode">
<a ng-click="ctrl.addTag()">
<i class="fa fa-plus"></i>
</a>
</li>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<li ng-show="ctrl.addTagMode">
<input type="text" class="input-small tight-form-input" spellcheck='false'
bs-typeahead="ctrl.suggestTagKeys" data-min-length=0 data-items=100
ng-model="ctrl.target.currentTagKey" placeholder="key"></input>
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword width-8">
Tags
<info-popover mode="right-normal" ng-if="ctrl.tsdbVersion == 2">
Please use filters, tags are deprecated in opentsdb 2.2
</info-popover>
</label>
</div>
<input type="text" class="input-small tight-form-input"
spellcheck='false' bs-typeahead="ctrl.suggestTagValues"
data-min-length=0 data-items=100 ng-model="ctrl.target.currentTagValue" placeholder="value">
<div class="gf-form" ng-repeat="(key, value) in ctrl.target.tags track by $index" class="gf-form">
<label class="gf-form-label">
{{key}}&nbsp;=&nbsp;{{value}}
<a ng-click="ctrl.editTag(key, value)">
<i class="fa fa-pencil"></i>
</a>
<a ng-click="ctrl.removeTag(key)">
<i class="fa fa-remove"></i>
</a>
</label>
</div>
<div class="gf-form" ng-hide="ctrl.addTagMode">
<label class="gf-form-label query-keyword">
<a ng-click="ctrl.addTag()"><i class="fa fa-plus"></i></a>
</label>
</div>
<div class="gf-form" ng-show="ctrl.addTagMode">
<input type="text"
class="gf-form-input" spellcheck='false'
bs-typeahead="ctrl.suggestTagKeys" data-min-length=0 data-items=100
ng-model="ctrl.target.currentTagKey" placeholder="key">
</input>
<a bs-tooltip="ctrl.errors.tags"
style="color: rgb(229, 189, 28)"
ng-show="ctrl.errors.tags">
<i class="fa fa-warning"></i>
</a>
<input type="text" class="gf-form-input"
spellcheck='false' bs-typeahead="ctrl.suggestTagValues"
data-min-length=0 data-items=100 ng-model="ctrl.target.currentTagValue" placeholder="value">
</input>
<a ng-click="ctrl.addTag()" ng-hide="ctrl.errors.tags">
add tag
</a>
<a ng-click="ctrl.closeAddTagMode()">
<i class="fa fa-remove"></i>
</a>
</li>
</ul>
<div class="clearfix"></div>
</div>
<label class="gf-form-label" ng-show="ctrl.errors.tags">
<a bs-tooltip="ctrl.errors.tags" style="color: rgb(229, 189, 28)" >
<i class="fa fa-warning"></i>
</a>
</label>
<label class="gf-form-label" >
<a ng-click="ctrl.addTag()" ng-hide="ctrl.errors.tags">add tag</a>
<a ng-click="ctrl.closeAddTagMode()"><i class="fa fa-remove"></i></a>
</label>
</div>
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align query-keyword" style="width: 100px">
Rate <editor-checkbox text="" model="ctrl.target.shouldComputeRate" change="ctrl.targetBlur()"></editor-checkbox>
</li>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<li class="tight-form-item query-keyword" ng-hide="!ctrl.target.shouldComputeRate">
Counter <editor-checkbox text="" model="ctrl.target.isCounter" change="ctrl.targetBlur()"></editor-checkbox>
</li>
<div class="gf-form-inline">
<gf-form-switch class="gf-form" label="Rate" label-class="width-8 query-keyword" checked="ctrl.target.shouldComputeRate" on-change="ctrl.targetBlur()">
</gf-form-switch>
<li class="tight-form-item query-keyword" ng-hide="!ctrl.target.isCounter || !ctrl.target.shouldComputeRate">
Counter Max:
</li>
<gf-form-switch ng-hide="!ctrl.target.shouldComputeRate"
class="gf-form" label="Counter" checked="ctrl.target.isCounter" on-change="ctrl.targetBlur()">
</gf-form-switch>
<li ng-hide="!ctrl.target.isCounter || !ctrl.target.shouldComputeRate">
<input type="text" class="tight-form-input input-small" ng-disabled="!ctrl.target.shouldComputeRate"
ng-model="ctrl.target.counterMax" spellcheck='false'
placeholder="max value" ng-model-onblur
ng-blur="ctrl.targetBlur()"></input>
</li>
<li class="tight-form-item query-keyword" ng-hide="!ctrl.target.isCounter || !ctrl.target.shouldComputeRate">
Reset Value:
</li>
<li ng-hide="!ctrl.target.isCounter || !ctrl.target.shouldComputeRate">
<input type="text" class="tight-form-input input-small" ng-disabled="!ctrl.target.shouldComputeRate"
ng-model="ctrl.target.counterResetValue" spellcheck='false'
placeholder="reset value" ng-model-onblur
ng-blur="ctrl.targetBlur()"></input>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="gf-form" ng-hide="!ctrl.target.isCounter || !ctrl.target.shouldComputeRate">
<label class="gf-form-label">Counter Max</label>
<input type="text" class="gf-form-input"
ng-disabled="!ctrl.target.shouldComputeRate"
ng-model="ctrl.target.counterMax" spellcheck='false'
placeholder="max value" ng-model-onblur
ng-blur="ctrl.targetBlur()">
</input>
<label class="gf-form-label">Reset Value</label>
<input type="text" class="tight-form-input input-small"
ng-disabled="!ctrl.target.shouldComputeRate"
ng-model="ctrl.target.counterResetValue" spellcheck='false'
placeholder="reset value" ng-model-onblur
ng-blur="ctrl.targetBlur()">
</input>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
</query-editor-row>
@@ -1,80 +1,54 @@
<query-editor-row ctrl="ctrl">
<li class="tight-form-item" style="width: 94px">
Query
</li>
<li>
<input type="text"
class="input-xxlarge tight-form-input"
ng-model="ctrl.target.expr"
spellcheck='false'
placeholder="query expression"
data-min-length=0 data-items=100
ng-model-onblur
ng-change="ctrl.refreshMetricData()">
</li>
<li class="tight-form-item">
Metric
</li>
<li>
<input type="text"
class="input-medium tight-form-input"
ng-model="ctrl.target.metric"
spellcheck='false'
bs-typeahead="ctrl.suggestMetrics"
placeholder="metric name"
data-min-length=0 data-items=100>
</li>
</query-editor-row>
<query-editor-row query-ctrl="ctrl" can-collapse="false">
<div class="gf-form-inline">
<div class="gf-form gf-form--grow">
<label class="gf-form-label width-8">Query</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.expr" spellcheck='false' placeholder="query expression" data-min-length=0 data-items=100 ng-model-onblur ng-change="ctrl.refreshMetricData()">
</div>
<div class="gf-form max-width-22">
<label class="gf-form-label">Metric lookup</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.metric" spellcheck='false' bs-typeahead="ctrl.suggestMetrics" placeholder="metric name" data-min-length=0 data-items=100>
</div>
</div>
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align" style="width: 94px">
Legend format
</li>
<li>
<input type="text" class="tight-form-input input-xxlarge" ng-model="ctrl.target.legendFormat"
<div class="gf-form-inline">
<div class="gf-form max-width-26">
<label class="gf-form-label width-8">Legend format</label>
<input type="text" class="gf-form-input" ng-model="ctrl.target.legendFormat"
spellcheck='false' placeholder="legend format" data-min-length=0 data-items=1000
ng-model-onblur ng-change="ctrl.refreshMetricData()">
</input>
</li>
</ul>
</div>
<div class="gf-form">
<label class="gf-form-label width-5">Step</label>
<input type="text" class="gf-form-input max-width-5" ng-model="ctrl.target.interval"
data-placement="right"
spellcheck='false'
placeholder="{{ctrl.panelCtrl.interval}}"
data-min-length=0 data-items=100
ng-model-onblur
ng-change="ctrl.refreshMetricData()"/>
<info-popover mode="right-absolute">
Leave blank for auto handling based on time range and panel width
</info-popover>
</div>
<div class="gf-form">
<label class="gf-form-label">Resolution</label>
<div class="gf-form-select-wrapper max-width-15">
<select ng-model="ctrl.target.intervalFactor" class="gf-form-input"
ng-options="r.factor as r.label for r in ctrl.resolutions"
ng-change="ctrl.refreshMetricData()">
</select>
</div>
<label class="gf-form-label">
<a href="{{ctrl.linkToPrometheus}}" target="_blank" bs-tooltip="'Link to Graph in Prometheus'">
<i class="fa fa-share-square-o"></i>
</a>
</label>
</div>
<div class="clearfix"></div>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
<div class="tight-form">
<ul class="tight-form-list" role="menu">
<li class="tight-form-item tight-form-align" style="width: 94px">
Step
</li>
<li>
<input type="text" class="input-mini tight-form-input" ng-model="ctrl.target.interval"
bs-tooltip="'Leave blank for auto handling based on time range and panel width'"
data-placement="right"
spellcheck='false'
placeholder="{{ctrl.panelCtrl.interval}}"
data-min-length=0 data-items=100
ng-model-onblur
ng-change="ctrl.refreshMetricData()"
/>
</input>
</li>
<li class="tight-form-item">
Resolution
</li>
<li>
<select ng-model="ctrl.target.intervalFactor" class="tight-form-input input-mini"
ng-options="r.factor as r.label for r in ctrl.resolutions"
ng-change="ctrl.refreshMetricData()">
</select>
</li>
<li class="tight-form-item">
<a href="{{ctrl.linkToPrometheus}}" target="_blank" bs-tooltip="'Link to Graph in Prometheus'">
<i class="fa fa-share-square-o"></i>
</a>
</li>
</ul>
<div class="clearfix"></div>
</div>
</query-editor-row>
+1
View File
@@ -70,6 +70,7 @@
@import "components/drop";
@import "components/query_editor";
@import "components/tabbed_view";
@import "components/query_part";
// PAGES
@import "pages/login";
+3 -3
View File
@@ -67,8 +67,8 @@ $page-gradient: linear-gradient(60deg, transparent 70%, darken($page-bg, 4%) 98%
// Links
// -------------------------
$link-color: darken($white,11%);
$link-color-disabled: darken($link-color,30%);
$link-color: darken($white, 11%);
$link-color-disabled: darken($link-color, 30%);
$link-hover-color: $white;
$external-link-color: $blue;
@@ -76,7 +76,7 @@ $external-link-color: $blue;
// -------------------------
$headings-color: darken($white,11%);
$abbr-border-color: $gray-3 !default;
$text-muted: darken($link-color,30%);
$text-muted: $text-color-weak;
$blockquote-small-color: $gray-3 !default;
$blockquote-border-color: $gray-4 !default;
+1 -1
View File
@@ -82,7 +82,7 @@ $external-link-color: $blue;
// -------------------------
$headings-color: $text-color;
$abbr-border-color: $gray-2 !default;
$text-muted: darken($link-color,30%);
$text-muted: $text-color-weak;
$blockquote-small-color: $gray-2 !default;
$blockquote-border-color: $gray-3 !default;
+6 -2
View File
@@ -27,9 +27,9 @@ em { font-style: italic; color: $headings-color; }
cite { font-style: normal; }
// Utility classes
.muted { color: $gray-2; }
.muted { color: $text-muted; }
a.muted:hover,
a.muted:focus { color: darken($gray-2, 10%); }
a.muted:focus { color: darken($text-muted, 10%); }
.text-warning { color: $state-warning-text; }
a.text-warning:hover,
@@ -118,6 +118,10 @@ small,
font-weight: normal;
}
.small-xs {
font-size: $font-size-xs;
}
mark,
.mark {
padding: .2em;
+1 -1
View File
@@ -1,4 +1,4 @@
$popover-arrow-size: 1rem;
$popover-arrow-size: 0.7rem;
$color: inherit;
$backgroundColor: $btn-secondary-bg;
$color: $text-color;
+40 -8
View File
@@ -8,8 +8,22 @@ $gf-form-margin: 0.25rem;
text-align: left;
position: relative;
.cr1 {
margin-left: 8px;
&--offset-1 {
margin-left: $spacer;
}
&--grow {
flex-grow: 1;
}
}
.gf-form-disabled {
color: $text-color-weak;
.query-keyword,
a,
.gf-form-input {
color: $text-color-weak;
}
}
@@ -22,10 +36,6 @@ $gf-form-margin: 0.25rem;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
.gf-form-flex {
flex-grow: 1;
}
}
.gf-form-button-row {
@@ -48,6 +58,12 @@ $gf-form-margin: 0.25rem;
border: $input-btn-border-width solid transparent;
@include border-radius($label-border-radius-sm);
&--grow {
flex-grow: 1;
min-height: 2.70rem;
}
}
.gf-form-checkbox {
@@ -107,6 +123,21 @@ $gf-form-margin: 0.25rem;
}
&.gf-size-auto { width: auto; }
&--dropdown {
padding-right: $input-padding-x*2;
&:after {
position: absolute;
top: 35%;
right: $input-padding-x/2;
background-color: transparent;
color: $input-color;
font: normal normal normal $font-size-sm/1 FontAwesome;
content: '\f0d7';
pointer-events: none;
}
}
}
.gf-form-select-wrapper {
@@ -152,9 +183,11 @@ $gf-form-margin: 0.25rem;
}
.gf-form-btn {
margin-right: $gf-form-margin;
padding: $input-padding-y $input-padding-x;
margin-right: $gf-form-margin;
line-height: $input-line-height;
font-size: $font-size-sm;
flex-shrink: 0;
flex-grow: 0;
}
@@ -209,4 +242,3 @@ $gf-form-margin: 0.25rem;
select.gf-form-input ~ .gf-form-help-icon {
right: 10px;
}
+57 -4
View File
@@ -4,13 +4,66 @@
}
.query-segment-key {
border-right: none;
padding-right: 1px;
//border-right: none;
//padding-right: 1px;
}
.query-segment-operator {
padding-right: 1px;
border-right: none;
//padding-right: 1px;
//border-right: none;
color: $orange;
}
.gf-form-query {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-content: flex-start;
align-items: flex-start;
.gf-form,
.gf-form-filler {
margin-bottom: 2px;
}
.gf-form-switch,
.gf-form-switch label,
.gf-form-input,
.gf-form-select-wrapper,
.gf-form-filler,
.gf-form-label {
margin-right: 2px;
}
}
.gf-form-query-content {
flex-grow: 2;
&--collapsed {
overflow: hidden;
.gf-form-label {
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
white-space: nowrap;
}
}
}
.gf-form-query-letter-cell {
.gf-form-query-letter-cell-carret {
display: inline-block;
width: 0.7rem;
position: relative;
left: -2px;
}
.gf-form-query-letter-cell-letter {
font-weight: bold;
color: $blue;
}
.gf-form-query-letter-cell-ds {
color: $text-color-weak;
}
}
+11
View File
@@ -0,0 +1,11 @@
.query-part {
background-color: $input-bg !important;
&.show-function-controls {
padding-top: 5px;
min-width: 100px;
text-align: center;
}
}
+1 -1
View File
@@ -10,7 +10,7 @@
font-family: inherit;
background: $theme-bg;
color: $theme-color;
padding: $spacer;
padding: 0.65rem;
font-size: $font-size-sm;
max-width: 20rem;
+2 -1
View File
@@ -61,13 +61,14 @@ button.close {
.hide {
display: none;
}
.show {
display: block;
}
// Visibility
.invisible {
visibility: hidden;
visibility: hidden !important;
}
// For Affix plugin
+6
View File
@@ -17,3 +17,9 @@
}
}
@for $i from 1 through 30 {
.offset-width-#{$i} {
margin-left: ($spacer * $i) !important;
}
}