mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ux(query editors): progress on new query editor styles
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -5,4 +5,5 @@ define([
|
||||
'./query_ctrl',
|
||||
'./panel_editor_tab',
|
||||
'./query_editor_row',
|
||||
'./metrics_ds_selector',
|
||||
], function () {});
|
||||
|
||||
104
public/app/features/panel/metrics_ds_selector.ts
Normal file
104
public/app/features/panel/metrics_ds_selector.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
///<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">
|
||||
Data source
|
||||
</label>
|
||||
|
||||
<metric-segment segment="ctrl.dsSegment"
|
||||
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>
|
||||
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 <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();
|
||||
|
||||
for (let ds of this.datasources) {
|
||||
if (ds.value === this.panelCtrl.panel.datasource) {
|
||||
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 = {};
|
||||
|
||||
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};
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label">
|
||||
<a class="pointer" tabindex="1" ng-click="ctrl.toggleEditorMode()">
|
||||
<i class="fa fa-pencil"></i>
|
||||
<a class="pointer" tabindex="1" ng-click="ctrl.collapsed = !ctrl.collapsed">
|
||||
<i class="fa fa-chevron-down" ng-hide="ctrl.collapsed"></i>
|
||||
<i class="fa fa-chevron-left" ng-show="ctrl.collapsed"></i>
|
||||
</a>
|
||||
</label>
|
||||
<label class="gf-form-label dropdown">
|
||||
@@ -24,6 +25,9 @@
|
||||
<i class="fa fa-bars"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu pull-right" role="menu">
|
||||
<li role="menuitem">
|
||||
<a tabindex="1" ng-click="ctrl.toggleEditorMode()">Toggle text editor</a>
|
||||
</li>
|
||||
<li role="menuitem">
|
||||
<a tabindex="1" ng-click="ctrl.duplicateQuery()">Duplicate</a>
|
||||
</li>
|
||||
@@ -35,6 +39,11 @@
|
||||
</li>
|
||||
</ul>
|
||||
</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>
|
||||
|
||||
|
||||
@@ -10,9 +10,11 @@ export class QueryCtrl {
|
||||
panel: any;
|
||||
hasRawMode: boolean;
|
||||
error: string;
|
||||
collapsed: boolean;
|
||||
|
||||
constructor(public $scope, private $injector) {
|
||||
this.panel = this.panelCtrl.panel;
|
||||
this.collapsed = true;
|
||||
|
||||
if (!this.target.refId) {
|
||||
this.target.refId = this.getNextQueryLetter();
|
||||
|
||||
@@ -1,56 +1,19 @@
|
||||
<div class="editor-row">
|
||||
|
||||
<div class="query-editor-rows">
|
||||
<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>
|
||||
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>
|
||||
Query <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="{'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 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>
|
||||
{{ctrl.datasource.name}} <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,17 +1,21 @@
|
||||
<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-editor-row ctrl="ctrl"></query-editor-row>
|
||||
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list">
|
||||
<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>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="agg in ctrl.target.metrics">
|
||||
<elastic-metric-agg
|
||||
|
||||
@@ -1,89 +1,98 @@
|
||||
<query-editor-row ctrl="ctrl">
|
||||
|
||||
<div class="gf-form" ng-show="ctrl.target.rawQuery">
|
||||
<input type="text" class="gf-form-input" ng-model="ctrl.target.query" spellcheck="false" ng-blur="ctrl.refresh()"></input>
|
||||
</div>
|
||||
<div class="gf-form" ng-if="ctrl.collapsed">
|
||||
<label class="gf-form-label gf-form-filler pointer" ng-click="ctrl.collapsed = !ctrl.collapsed">
|
||||
{{ctrl.target.query}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div ng-hide="ctrl.target.rawQuery">
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword width-7">FROM</label>
|
||||
<div ng-if="!ctrl.collapsed">
|
||||
|
||||
<metric-segment segment="ctrl.policySegment" get-options="ctrl.getPolicySegments()" on-change="ctrl.policyChanged()"></metric-segment>
|
||||
<metric-segment segment="ctrl.measurementSegment" get-options="ctrl.getMeasurements()" on-change="ctrl.measurementChanged()"></metric-segment>
|
||||
</div>
|
||||
<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 class="gf-form">
|
||||
<label class="gf-form-label query-keyword">WHERE</label>
|
||||
<div ng-if="!ctrl.target.rawQuery">
|
||||
|
||||
<div ng-repeat="segment in ctrl.tagSegments">
|
||||
<metric-segment segment="segment" get-options="ctrl.getTagsOrValues(segment, $index)" on-change="ctrl.tagSegmentUpdated(segment, $index)"></metric-segment>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword width-7">FROM</label>
|
||||
|
||||
<div class="gf-form-filler"></div>
|
||||
</div>
|
||||
<metric-segment segment="ctrl.policySegment" get-options="ctrl.getPolicySegments()" on-change="ctrl.policyChanged()"></metric-segment>
|
||||
<metric-segment segment="ctrl.measurementSegment" get-options="ctrl.getMeasurements()" on-change="ctrl.measurementChanged()"></metric-segment>
|
||||
</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">
|
||||
<label class="gf-form-label query-keyword">WHERE</label>
|
||||
|
||||
<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 ng-repeat="segment in ctrl.tagSegments">
|
||||
<metric-segment segment="segment" get-options="ctrl.getTagsOrValues(segment, $index)" on-change="ctrl.tagSegmentUpdated(segment, $index)"></metric-segment>
|
||||
</div>
|
||||
</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-filler"></div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-filler"></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-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword width-7">
|
||||
<span>GROUP BY</span>
|
||||
</label>
|
||||
<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>
|
||||
|
||||
<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 class="gf-form">
|
||||
<label class="dropdown"
|
||||
dropdown-typeahead="ctrl.selectMenu"
|
||||
dropdown-typeahead-on-select="ctrl.addSelectPart(selectParts, $item, $subItem)">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<metric-segment segment="ctrl.groupBySegment" get-options="ctrl.getGroupByOptions()" on-change="ctrl.groupByAction(part, $index)"></metric-segment>
|
||||
</div>
|
||||
<div class="gf-form-filler"></div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-filler"></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>
|
||||
|
||||
</div>
|
||||
<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 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-filler"></div>
|
||||
</div>
|
||||
<metric-segment segment="ctrl.groupBySegment" get-options="ctrl.getGroupByOptions()" on-change="ctrl.groupByAction(part, $index)"></metric-segment>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-filler"></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-filler"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</query-editor-row>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -8,8 +8,8 @@ $gf-form-margin: 0.25rem;
|
||||
text-align: left;
|
||||
position: relative;
|
||||
|
||||
.cr1 {
|
||||
margin-left: 8px;
|
||||
&--offset-1 {
|
||||
margin-left: $spacer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,9 +162,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;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,3 @@
|
||||
}
|
||||
}
|
||||
|
||||
.query-part-name {
|
||||
}
|
||||
|
||||
.query-part-parameters {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user