From eaaf9246b7284c68aa5bf6e9cca1b75a30ac3359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 2 Feb 2016 09:12:58 +0100 Subject: [PATCH] feat(plugins): more work on refining datasource editors --- public/app/core/core.ts | 2 +- .../app/core/directives/plugin_component.ts | 90 +++++++++++++++++++ .../directives/plugin_directive_loader.ts | 5 +- public/app/features/dashboard/dashboardSrv.js | 36 -------- .../app/features/panel/metrics_panel_ctrl.ts | 24 ++--- public/app/features/panel/panel.ts | 2 + public/app/features/panel/query_editor.ts | 79 ++++++++++++---- public/app/partials/metrics.html | 4 +- .../plugins/datasource/influxdb/datasource.js | 1 - .../prometheus/partials/query.editor.html | 16 ++-- .../datasource/prometheus/query_ctrl.ts | 70 ++++++++------- 11 files changed, 211 insertions(+), 118 deletions(-) create mode 100644 public/app/core/directives/plugin_component.ts diff --git a/public/app/core/core.ts b/public/app/core/core.ts index c216151f2dc..ca608fb35f9 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -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'; diff --git a/public/app/core/directives/plugin_component.ts b/public/app/core/directives/plugin_component.ts new file mode 100644 index 00000000000..1405af3ad3b --- /dev/null +++ b/public/app/core/directives/plugin_component.ts @@ -0,0 +1,90 @@ +/// + +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); diff --git a/public/app/core/directives/plugin_directive_loader.ts b/public/app/core/directives/plugin_directive_loader.ts index 4456afacbe1..4c0d1092a09 100644 --- a/public/app/core/directives/plugin_directive_loader.ts +++ b/public/app/core/directives/plugin_directive_loader.ts @@ -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); diff --git a/public/app/features/dashboard/dashboardSrv.js b/public/app/features/dashboard/dashboardSrv.js index e4d74c985ba..ad45ce64a70 100644 --- a/public/app/features/dashboard/dashboardSrv.js +++ b/public/app/features/dashboard/dashboardSrv.js @@ -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'; diff --git a/public/app/features/panel/metrics_panel_ctrl.ts b/public/app/features/panel/metrics_panel_ctrl.ts index 76b6a7688e4..148d8647f28 100644 --- a/public/app/features/panel/metrics_panel_ctrl.ts +++ b/public/app/features/panel/metrics_panel_ctrl.ts @@ -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}; diff --git a/public/app/features/panel/panel.ts b/public/app/features/panel/panel.ts index 535ccdcf06a..3f98b77ff1b 100644 --- a/public/app/features/panel/panel.ts +++ b/public/app/features/panel/panel.ts @@ -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, } diff --git a/public/app/features/panel/query_editor.ts b/public/app/features/panel/query_editor.ts index 8e43019fdf3..47c201fee5d 100644 --- a/public/app/features/panel/query_editor.ts +++ b/public/app/features/panel/query_editor.ts @@ -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); diff --git a/public/app/partials/metrics.html b/public/app/partials/metrics.html index 6d580e7575f..8ab5c4a1677 100644 --- a/public/app/partials/metrics.html +++ b/public/app/partials/metrics.html @@ -1,8 +1,8 @@
- - + +
diff --git a/public/app/plugins/datasource/influxdb/datasource.js b/public/app/plugins/datasource/influxdb/datasource.js index 8d171deb7f9..984d32ab035 100644 --- a/public/app/plugins/datasource/influxdb/datasource.js +++ b/public/app/plugins/datasource/influxdb/datasource.js @@ -4,7 +4,6 @@ define([ 'app/core/utils/datemath', './influx_series', './influx_query', - './query_ctrl', ], function (angular, _, dateMath, InfluxSeries, InfluxQuery) { 'use strict'; diff --git a/public/app/plugins/datasource/prometheus/partials/query.editor.html b/public/app/plugins/datasource/prometheus/partials/query.editor.html index 4ad94d022eb..ccb67887164 100644 --- a/public/app/plugins/datasource/prometheus/partials/query.editor.html +++ b/public/app/plugins/datasource/prometheus/partials/query.editor.html @@ -1,7 +1,7 @@
  • - {{target.datasource}} + {{ctrl.target.datasource}}
  • - +
  • @@ -24,12 +24,10 @@
    • - {{target.refId}} + {{ctrl.target.refId}}
    • - +
    • diff --git a/public/app/plugins/datasource/prometheus/query_ctrl.ts b/public/app/plugins/datasource/prometheus/query_ctrl.ts index e0fd9aea02d..6535e16c599 100644 --- a/public/app/plugins/datasource/prometheus/query_ctrl.ts +++ b/public/app/plugins/datasource/prometheus/query_ctrl.ts @@ -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};