Browse Source

feat(plugins): more work on refining datasource editors

Torkel Ödegaard 10 years ago
parent
commit
eaaf9246b7

+ 1 - 1
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';

+ 90 - 0
public/app/core/directives/plugin_component.ts

@@ -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);

+ 3 - 2
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);

+ 0 - 36
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';

+ 7 - 17
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};

+ 2 - 0
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,
 }

+ 64 - 17
public/app/features/panel/query_editor.ts

@@ -3,23 +3,70 @@
 import angular from 'angular';
 import _ from 'lodash';
 
-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
-          };
-        });
-      });
+export class QueryEditorCtrl {
+  target: any;
+  datasource: any;
+  panelCtrl: any;
+  panel: any;
+
+  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);

+ 2 - 2
public/app/partials/metrics.html

@@ -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">

+ 0 - 1
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';

+ 7 - 9
public/app/plugins/datasource/prometheus/partials/query.editor.html

@@ -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>

+ 36 - 34
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};