mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(plugins): more work on refining datasource editors
This commit is contained in:
parent
0583ec0f93
commit
eaaf9246b7
@ -16,7 +16,7 @@ import "./directives/password_strenght";
|
||||
import "./directives/spectrum_picker";
|
||||
import "./directives/tags";
|
||||
import "./directives/value_select_dropdown";
|
||||
import "./directives/plugin_directive_loader";
|
||||
import "./directives/plugin_component";
|
||||
import "./directives/rebuild_on_change";
|
||||
import "./directives/give_focus";
|
||||
import './jquery_extended';
|
||||
|
90
public/app/core/directives/plugin_component.ts
Normal file
90
public/app/core/directives/plugin_component.ts
Normal file
@ -0,0 +1,90 @@
|
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
|
||||
import coreModule from '../core_module';
|
||||
|
||||
function pluginDirectiveLoader($compile, datasourceSrv) {
|
||||
|
||||
function getPluginComponentDirective(options) {
|
||||
return function() {
|
||||
return {
|
||||
templateUrl: options.Component.templateUrl,
|
||||
restrict: 'E',
|
||||
controller: options.Component,
|
||||
controllerAs: 'ctrl',
|
||||
bindToController: true,
|
||||
scope: options.bindings,
|
||||
link: (scope, elem, attrs, ctrl) => {
|
||||
if (ctrl.link) {
|
||||
ctrl.link(scope, elem, attrs, ctrl);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function getModule(scope, attrs) {
|
||||
switch (attrs.type) {
|
||||
case "metrics-query-editor":
|
||||
let datasource = scope.target.datasource || scope.ctrl.panel.datasource;
|
||||
return datasourceSrv.get(datasource).then(ds => {
|
||||
scope.datasource = ds;
|
||||
|
||||
return System.import(ds.meta.module).then(dsModule => {
|
||||
return {
|
||||
name: 'metrics-query-editor-' + ds.meta.id,
|
||||
bindings: {target: "=", panelCtrl: "="},
|
||||
attrs: {"target": "target", "panel-ctrl": "ctrl"},
|
||||
Component: dsModule.MetricsQueryEditor
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
case 'datasource-config-view':
|
||||
return System.import(scope.datasourceMeta.module).then(function(dsModule) {
|
||||
return {
|
||||
name: 'ds-config-' + scope.datasourceMeta.id,
|
||||
bindings: {meta: "=", current: "="},
|
||||
attrs: {meta: "datasourceMeta", current: "current"},
|
||||
Component: dsModule.ConfigView,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function appendAndCompile(scope, elem, componentInfo) {
|
||||
var child = angular.element(document.createElement(componentInfo.name));
|
||||
_.each(componentInfo.attrs, (value, key) => {
|
||||
child.attr(key, value);
|
||||
});
|
||||
|
||||
$compile(child)(scope);
|
||||
|
||||
elem.empty();
|
||||
elem.append(child);
|
||||
}
|
||||
|
||||
function registerPluginComponent(scope, elem, attrs, componentInfo) {
|
||||
if (!componentInfo.Component.registered) {
|
||||
var directiveName = attrs.$normalize(componentInfo.name);
|
||||
var directiveFn = getPluginComponentDirective(componentInfo);
|
||||
coreModule.directive(directiveName, directiveFn);
|
||||
componentInfo.Component.registered = true;
|
||||
}
|
||||
|
||||
appendAndCompile(scope, elem, componentInfo);
|
||||
}
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: function(scope, elem, attrs) {
|
||||
getModule(scope, attrs).then(function (componentInfo) {
|
||||
registerPluginComponent(scope, elem, attrs, componentInfo);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
coreModule.directive('pluginComponent', pluginDirectiveLoader);
|
@ -5,7 +5,8 @@ import _ from 'lodash';
|
||||
|
||||
import coreModule from '../core_module';
|
||||
|
||||
function pluginDirectiveLoader($compile, datasourceSrv) {
|
||||
/** @ngInject */
|
||||
function pluginComponentLoader($compile, datasourceSrv) {
|
||||
|
||||
function getPluginComponentDirective(options) {
|
||||
return function() {
|
||||
@ -88,4 +89,4 @@ function pluginDirectiveLoader($compile, datasourceSrv) {
|
||||
};
|
||||
}
|
||||
|
||||
coreModule.directive('pluginDirectiveLoader', pluginDirectiveLoader);
|
||||
coreModule.directive('pluginComponent', pluginComponentLoader);
|
||||
|
@ -177,42 +177,6 @@ function (angular, $, _, moment) {
|
||||
return newPanel;
|
||||
};
|
||||
|
||||
p.getNextQueryLetter = function(panel) {
|
||||
var letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
return _.find(letters, function(refId) {
|
||||
return _.every(panel.targets, function(other) {
|
||||
return other.refId !== refId;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
p.addDataQueryTo = function(panel, datasource) {
|
||||
var target = {
|
||||
refId: this.getNextQueryLetter(panel)
|
||||
};
|
||||
|
||||
if (datasource) {
|
||||
target.datasource = datasource.name;
|
||||
}
|
||||
|
||||
panel.targets.push(target);
|
||||
};
|
||||
|
||||
p.removeDataQuery = function (panel, query) {
|
||||
panel.targets = _.without(panel.targets, query);
|
||||
};
|
||||
|
||||
p.duplicateDataQuery = function(panel, query) {
|
||||
var clone = angular.copy(query);
|
||||
clone.refId = this.getNextQueryLetter(panel);
|
||||
panel.targets.push(clone);
|
||||
};
|
||||
|
||||
p.moveDataQuery = function(panel, fromIndex, toIndex) {
|
||||
_.move(panel.targets, fromIndex, toIndex);
|
||||
};
|
||||
|
||||
p.formatDate = function(date, format) {
|
||||
date = moment.isMoment(date) ? date : moment(date);
|
||||
format = format || 'YYYY-MM-DD HH:mm:ss';
|
||||
|
@ -193,23 +193,6 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
});
|
||||
}
|
||||
|
||||
addDataQuery(datasource) {
|
||||
this.dashboard.addDataQueryTo(this.panel, datasource);
|
||||
}
|
||||
|
||||
removeDataQuery(query) {
|
||||
this.dashboard.removeDataQuery(this.panel, query);
|
||||
this.refresh();
|
||||
};
|
||||
|
||||
duplicateDataQuery(query) {
|
||||
this.dashboard.duplicateDataQuery(this.panel, query);
|
||||
}
|
||||
|
||||
moveDataQuery(fromIndex, toIndex) {
|
||||
this.dashboard.moveDataQuery(this.panel, fromIndex, toIndex);
|
||||
}
|
||||
|
||||
setDatasource(datasource) {
|
||||
// switching to mixed
|
||||
if (datasource.meta.mixed) {
|
||||
@ -229,6 +212,13 @@ class MetricsPanelCtrl extends PanelCtrl {
|
||||
this.datasource = null;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
addDataQuery(datasource) {
|
||||
var target = {
|
||||
datasource: datasource ? datasource.name : undefined
|
||||
};
|
||||
this.panel.targets.push(target);
|
||||
}
|
||||
}
|
||||
|
||||
export {MetricsPanelCtrl};
|
||||
|
@ -5,9 +5,11 @@ import config from 'app/core/config';
|
||||
import {PanelCtrl} from './panel_ctrl';
|
||||
import {MetricsPanelCtrl} from './metrics_panel_ctrl';
|
||||
import {PanelDirective} from './panel_directive';
|
||||
import {QueryEditorCtrl} from './query_editor';
|
||||
|
||||
export {
|
||||
PanelCtrl,
|
||||
MetricsPanelCtrl,
|
||||
PanelDirective,
|
||||
QueryEditorCtrl,
|
||||
}
|
||||
|
@ -3,23 +3,70 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
|
||||
var directivesModule = angular.module('grafana.directives');
|
||||
export class QueryEditorCtrl {
|
||||
target: any;
|
||||
datasource: any;
|
||||
panelCtrl: any;
|
||||
panel: any;
|
||||
|
||||
/** @ngInject */
|
||||
function metricsQueryOptions(dynamicDirectiveSrv, datasourceSrv) {
|
||||
return dynamicDirectiveSrv.create({
|
||||
watchPath: "ctrl.panel.datasource",
|
||||
directive: scope => {
|
||||
return datasourceSrv.get(scope.ctrl.panel.datasource).then(ds => {
|
||||
return System.import(ds.meta.module).then(dsModule => {
|
||||
return {
|
||||
name: 'metrics-query-options-' + ds.meta.id,
|
||||
fn: dsModule.metricsQueryOptions
|
||||
};
|
||||
});
|
||||
});
|
||||
constructor(private $scope, private $injector) {
|
||||
this.panel = this.panelCtrl.panel;
|
||||
this.datasource = $scope.datasource;
|
||||
|
||||
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;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
removeDataQuery(query) {
|
||||
this.panel.targets = _.without(this.panel.targets, query);
|
||||
this.panelCtrl.refresh();
|
||||
};
|
||||
|
||||
duplicateDataQuery(query) {
|
||||
var clone = angular.copy(query);
|
||||
clone.refId = this.getNextQueryLetter();
|
||||
this.panel.targets.push(clone);
|
||||
}
|
||||
|
||||
moveDataQuery(direction) {
|
||||
var index = _.indexOf(this.panel.targets, this.target);
|
||||
_.move(this.panel.targets, index, index + direction);
|
||||
}
|
||||
|
||||
toggleHideQuery(target) {
|
||||
target.hide = !target.hide;
|
||||
this.panelCtrl.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
directivesModule.directive('metricsQueryOptions', metricsQueryOptions);
|
||||
// var directivesModule = angular.module('grafana.directives');
|
||||
//
|
||||
// /** @ngInject */
|
||||
// function metricsQueryOptions(dynamicDirectiveSrv, datasourceSrv) {
|
||||
// return dynamicDirectiveSrv.create({
|
||||
// watchPath: "ctrl.panel.datasource",
|
||||
// directive: scope => {
|
||||
// return datasourceSrv.get(scope.ctrl.panel.datasource).then(ds => {
|
||||
// return System.import(ds.meta.module).then(dsModule => {
|
||||
// return {
|
||||
// name: 'metrics-query-options-' + ds.meta.id,
|
||||
// fn: dsModule.metricsQueryOptions
|
||||
// };
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// directivesModule.directive('metricsQueryOptions', metricsQueryOptions);
|
||||
|
@ -1,8 +1,8 @@
|
||||
<div class="editor-row">
|
||||
|
||||
<div class="tight-form-container">
|
||||
<plugin-directive-loader type="metrics-query-editor" ng-repeat="target in ctrl.panel.targets" ng-class="{'tight-form-disabled': target.hide}">
|
||||
</plugin-directive-loader>
|
||||
<plugin-component type="metrics-query-editor" ng-repeat="target in ctrl.panel.targets" ng-class="{'tight-form-disabled': target.hide}">
|
||||
</plugin-component>
|
||||
</div>
|
||||
|
||||
<div style="margin: 20px 0 0 0">
|
||||
|
@ -4,7 +4,6 @@ define([
|
||||
'app/core/utils/datemath',
|
||||
'./influx_series',
|
||||
'./influx_query',
|
||||
'./query_ctrl',
|
||||
],
|
||||
function (angular, _, dateMath, InfluxSeries, InfluxQuery) {
|
||||
'use strict';
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="tight-form">
|
||||
<ul class="tight-form-list pull-right">
|
||||
<li class="tight-form-item small" ng-show="target.datasource">
|
||||
<em>{{target.datasource}}</em>
|
||||
<em>{{ctrl.target.datasource}}</em>
|
||||
</li>
|
||||
<li class="tight-form-item">
|
||||
<div class="dropdown">
|
||||
@ -9,14 +9,14 @@
|
||||
<i class="fa fa-bars"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu pull-right" role="menu">
|
||||
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.duplicateDataQuery(target)">Duplicate</a></li>
|
||||
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index-1)">Move up</a></li>
|
||||
<li role="menuitem"><a tabindex="1" ng-click="panelCtrl.moveDataQuery($index, $index+1)">Move down</a></li>
|
||||
<li role="menuitem"><a tabindex="1" ng-click="ctrl.duplicateDataQuery(target)">Duplicate</a></li>
|
||||
<li role="menuitem"><a tabindex="1" ng-click="ctrl.moveDataQuery(-1)">Move up</a></li>
|
||||
<li role="menuitem"><a tabindex="1" ng-click="ctrl.moveDataQuery(1)">Move down</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="tight-form-item last">
|
||||
<a class="pointer" tabindex="1" ng-click="panelCtr.removeDataQuery(target)">
|
||||
<a class="pointer" tabindex="1" ng-click="ctrl.removeDataQuery(ctrl.target)">
|
||||
<i class="fa fa-remove"></i>
|
||||
</a>
|
||||
</li>
|
||||
@ -24,12 +24,10 @@
|
||||
|
||||
<ul class="tight-form-list">
|
||||
<li class="tight-form-item" style="min-width: 15px; text-align: center">
|
||||
{{target.refId}}
|
||||
{{ctrl.target.refId}}
|
||||
</li>
|
||||
<li>
|
||||
<a class="tight-form-item"
|
||||
ng-click="target.hide = !target.hide; panelCtrl.refresh();"
|
||||
role="menuitem">
|
||||
<a class="tight-form-item" ng-click="ctrl.toggleHideQuery(ctrl.target);" role="menuitem">
|
||||
<i class="fa fa-eye"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
@ -5,62 +5,64 @@ import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
import * as dateMath from 'app/core/utils/datemath';
|
||||
import {QueryEditorCtrl} from 'app/features/panel/panel';
|
||||
|
||||
function PrometheusQueryCtrl($scope, templateSrv) {
|
||||
$scope.panelCtrl = $scope.ctrl;
|
||||
$scope.panel = $scope.panelCtrl.panel;
|
||||
/** @ngInject */
|
||||
class PrometheusQueryCtrl extends QueryEditorCtrl {
|
||||
static templateUrl = 'public/app/plugins/datasource/prometheus/partials/query.editor.html';
|
||||
metric: any;
|
||||
resolutions: any;
|
||||
oldTarget: any;
|
||||
|
||||
$scope.init = function() {
|
||||
var target = $scope.target;
|
||||
constructor($scope, $injector, private templateSrv) {
|
||||
super($scope, $injector);
|
||||
|
||||
var target = this.target;
|
||||
target.expr = target.expr || '';
|
||||
target.intervalFactor = target.intervalFactor || 2;
|
||||
|
||||
$scope.metric = '';
|
||||
$scope.resolutions = _.map([1,2,3,4,5,10], function(f) {
|
||||
this.metric = '';
|
||||
this.resolutions = _.map([1,2,3,4,5,10], function(f) {
|
||||
return {factor: f, label: '1/' + f};
|
||||
});
|
||||
|
||||
$scope.$on('typeahead-updated', function() {
|
||||
$scope.$apply($scope.inputMetric);
|
||||
$scope.refreshMetricData();
|
||||
$scope.$on('typeahead-updated', () => {
|
||||
$scope.$apply(this.inputMetric);
|
||||
this.refreshMetricData();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
$scope.refreshMetricData = function() {
|
||||
if (!_.isEqual($scope.oldTarget, $scope.target)) {
|
||||
$scope.oldTarget = angular.copy($scope.target);
|
||||
$scope.paneCtrl.refresh();
|
||||
refreshMetricData() {
|
||||
if (!_.isEqual(this.oldTarget, this.target)) {
|
||||
this.oldTarget = angular.copy(this.target);
|
||||
this.panelCtrl.refresh();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$scope.inputMetric = function() {
|
||||
$scope.target.expr += $scope.target.metric;
|
||||
$scope.metric = '';
|
||||
};
|
||||
inputMetric() {
|
||||
this.target.expr += this.target.metric;
|
||||
this.metric = '';
|
||||
}
|
||||
|
||||
$scope.suggestMetrics = function(query, callback) {
|
||||
$scope.datasource
|
||||
.performSuggestQuery(query)
|
||||
.then(callback);
|
||||
};
|
||||
suggestMetrics(query, callback) {
|
||||
this.datasource.performSuggestQuery(query).then(callback);
|
||||
}
|
||||
|
||||
$scope.linkToPrometheus = function() {
|
||||
var range = Math.ceil(($scope.range.to.valueOf() - $scope.range.from.valueOf()) / 1000);
|
||||
var endTime = $scope.range.to.utc().format('YYYY-MM-DD HH:mm');
|
||||
linkToPrometheus() {
|
||||
var range = this.panelCtrl.range;
|
||||
var rangeDiff = Math.ceil((range.to.valueOf() - range.from.valueOf()) / 1000);
|
||||
var endTime = range.to.utc().format('YYYY-MM-DD HH:mm');
|
||||
var expr = {
|
||||
expr: templateSrv.replace($scope.target.expr, $scope.panel.scopedVars),
|
||||
range_input: range + 's',
|
||||
expr: this.templateSrv.replace(this.target.expr, this.panelCtrl.panel.scopedVars),
|
||||
range_input: rangeDiff + 's',
|
||||
end_input: endTime,
|
||||
step_input: '',
|
||||
stacked: $scope.panel.stack,
|
||||
stacked: this.panelCtrl.panel.stack,
|
||||
tab: 0
|
||||
};
|
||||
var hash = encodeURIComponent(JSON.stringify([expr]));
|
||||
return $scope.datasource.directUrl + '/graph#' + hash;
|
||||
return this.datasource.directUrl + '/graph#' + hash;
|
||||
};
|
||||
|
||||
$scope.init();
|
||||
}
|
||||
|
||||
export {PrometheusQueryCtrl};
|
||||
|
Loading…
Reference in New Issue
Block a user