Browse Source

feat(plugins): migrated elasticsearch to new plugin editor model, also minor fixes

Torkel Ödegaard 10 years ago
parent
commit
0bea6aba63

+ 8 - 2
public/app/core/directives/plugin_component.ts

@@ -5,7 +5,7 @@ import _ from 'lodash';
 
 import coreModule from '../core_module';
 
-function pluginDirectiveLoader($compile, datasourceSrv, $rootScope) {
+function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q) {
 
   function getPluginComponentDirective(options) {
     return function() {
@@ -83,7 +83,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope) {
         });
       }
       default: {
-        $rootScope.appEvent('alert-error', ['Plugin component error', 'could not find component '+ attrs.type]);
+        return $q.reject({message: "Could not find component type: " + attrs.type });
       }
     }
   }
@@ -106,6 +106,10 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope) {
       return;
     }
 
+    if (!componentInfo.Component) {
+      throw {message: 'Failed to find exported plugin component for ' + componentInfo.name};
+    }
+
     if (!componentInfo.Component.registered) {
       var directiveName = attrs.$normalize(componentInfo.name);
       var directiveFn = getPluginComponentDirective(componentInfo);
@@ -121,6 +125,8 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope) {
     link: function(scope, elem, attrs) {
       getModule(scope, attrs).then(function (componentInfo) {
         registerPluginComponent(scope, elem, attrs, componentInfo);
+      }).catch(err => {
+        $rootScope.appEvent('alert-error', ['Plugin Error', err.message || err]);
       });
     }
   };

+ 2 - 2
public/app/plugins/datasource/elasticsearch/datasource.d.ts

@@ -1,3 +1,3 @@
-declare var Datasource: any;
-export default Datasource;
+declare var ElasticDatasource: any;
+export {ElasticDatasource};
 

+ 3 - 1
public/app/plugins/datasource/elasticsearch/datasource.js

@@ -304,5 +304,7 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
     };
   }
 
-  return ElasticDatasource;
+  return {
+    ElasticDatasource: ElasticDatasource
+  };
 });

+ 0 - 30
public/app/plugins/datasource/elasticsearch/module.js

@@ -1,30 +0,0 @@
-define([
-  './datasource',
-  './edit_view',
-  './bucket_agg',
-  './metric_agg',
-],
-function (ElasticDatasource, editView) {
-  'use strict';
-
-  function metricsQueryEditor() {
-    return {controller: 'ElasticQueryCtrl', templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/query.editor.html'};
-  }
-
-  function metricsQueryOptions() {
-    return {templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/query.options.html'};
-  }
-
-  function annotationsQueryEditor() {
-    return {templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html'};
-  }
-
-  return {
-    Datasource: ElasticDatasource,
-    configView: editView.default,
-    annotationsQueryEditor: annotationsQueryEditor,
-    metricsQueryEditor: metricsQueryEditor,
-    metricsQueryOptions: metricsQueryOptions,
-  };
-
-});

+ 22 - 0
public/app/plugins/datasource/elasticsearch/module.ts

@@ -0,0 +1,22 @@
+import {ElasticDatasource} from './datasource';
+import {ElasticQueryCtrl} from './query_ctrl';
+
+class ElasticConfigCtrl {
+  static templateUrl = 'public/app/plugins/datasource/elasticsearch/partials/config.html';
+}
+
+class ElasticQueryOptionsCtrl {
+  static templateUrl = 'public/app/plugins/datasource/elasticsearch/partials/query.options.html';
+}
+
+class ElasticAnnotationsQueryCtrl {
+  static templateUrl = 'public/app/plugins/datasource/elasticsearch/partials/annotations.editor.html';
+}
+
+export {
+  ElasticDatasource as Datasource,
+  ElasticQueryCtrl as QueryCtrl,
+  ElasticConfigCtrl as ConfigCtrl,
+  ElasticQueryOptionsCtrl as QueryOptionsCtrl,
+  ElasticAnnotationsQueryCtrl as AnnotationsQueryCtrl,
+};

+ 28 - 73
public/app/plugins/datasource/elasticsearch/partials/query.editor.html

@@ -1,77 +1,32 @@
-<div  class="tight-form">
-	<ul class="tight-form-list pull-right">
-		<li ng-show="parserError" class="tight-form-item">
-			<a bs-tooltip="parserError" style="color: rgb(229, 189, 28)" role="menuitem">
-				<i class="fa fa-warning"></i>
-			</a>
-		</li>
-		<li class="tight-form-item small" ng-show="target.datasource">
-			<em>{{target.datasource}}</em>
-		</li>
-		<li class="tight-form-item">
-			<div class="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"><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>
-				</ul>
-			</div>
-		</li>
+<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>
 
-		<li class="tight-form-item last">
-			<a class="pointer" tabindex="1" ng-click="panelCtrl.removeDataQuery(target)">
-				<i class="fa fa-remove"></i>
-			</a>
-		</li>
-	</ul>
-
-	<ul class="tight-form-list">
-		<li class="tight-form-item" style="min-width: 15px; text-align: center">
-			{{target.refId}}
-		</li>
-		<li>
-			<a class="tight-form-item" ng-click="target.hide = !target.hide; panelCtrl.refresh();" role="menuitem">
-				<i class="fa fa-eye"></i>
-			</a>
-		</li>
-	</ul>
-
-	<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="target.query" spellcheck='false' placeholder="Lucene query" ng-blur="panelCtrl.refresh()">
-		</li>
-		<li class="tight-form-item query-keyword">
-			Alias
-		</li>
-		<li>
-			<input type="text" class="tight-form-input" style="width: 200px;" ng-model="target.alias" spellcheck='false' placeholder="alias patterns (empty = auto)" ng-blur="panelCtrl.refresh()">
-		</li>
-	</ul>
-	<div class="clearfix"></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-hide="target.rawQuery">
-	<div ng-repeat="agg in target.metrics">
-		<elastic-metric-agg
-			target="target" index="$index"
-			get-fields="getFields($fieldType)"
-			on-change="queryUpdated()"
-			es-version="esVersion">
-		</elastic-metric-agg>
-	</div>
-
-	<div ng-repeat="agg in target.bucketAggs">
-		<elastic-bucket-agg
-			target="target" index="$index"
-			get-fields="getFields($fieldType)"
-			on-change="queryUpdated()">
-		</elastic-bucket-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>
+

+ 3 - 3
public/app/plugins/datasource/elasticsearch/partials/query.options.html

@@ -8,7 +8,7 @@
 				Group by time interval
 			</li>
 			<li>
-				<input type="text" class="input-medium tight-form-input" ng-model="ctrl.panel.interval" ng-blur="ctrl.refresh();"
+				<input type="text" class="input-medium tight-form-input" ng-model="ctrl.panelCtrl.panel.interval" ng-blur="ctrl.panelCtrl.refresh();"
 							 spellcheck='false' placeholder="example: >10s">
 			</li>
 			<li class="tight-form-item">
@@ -23,7 +23,7 @@
 				<i class="fa fa-info-circle"></i>
 			</li>
 			<li class="tight-form-item">
-				<a ng-click="ctrl.toggleEditorHelp(1);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
+				<a ng-click="ctrl.panelCtrl.toggleEditorHelp(1);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
 					alias patterns
 				</a>
 			</li>
@@ -34,7 +34,7 @@
 
 <div class="editor-row">
 	<div class="pull-left" style="margin-top: 30px;">
-		<div class="grafana-info-box span6" ng-if="ctrl.editorHelpIndex === 1">
+		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 1">
 			<h5>Alias patterns</h5>
 			<ul ng-non-bindable>
 				<li>{{term fieldname}} = replaced with value of term group by</li>

+ 0 - 46
public/app/plugins/datasource/elasticsearch/query_ctrl.js

@@ -1,46 +0,0 @@
-define([
-  'angular',
-],
-function (angular) {
-  'use strict';
-
-  var module = angular.module('grafana.controllers');
-
-  module.controller('ElasticQueryCtrl', function($scope, $rootScope, $timeout, uiSegmentSrv) {
-    $scope.esVersion = $scope.datasource.esVersion;
-    $scope.panelCtrl = $scope.ctrl;
-
-    $scope.init = function() {
-      var target = $scope.target;
-      if (!target) { return; }
-
-      $scope.queryUpdated();
-    };
-
-    $scope.getFields = function(type) {
-      var jsonStr = angular.toJson({find: 'fields', type: type});
-      return $scope.datasource.metricFindQuery(jsonStr)
-      .then(uiSegmentSrv.transformToSegments(false))
-      .then(null, $scope.handleQueryError);
-    };
-
-    $scope.queryUpdated = function() {
-      var newJson = angular.toJson($scope.datasource.queryBuilder.build($scope.target), true);
-      if (newJson !== $scope.oldQueryRaw) {
-        $scope.rawQueryOld = newJson;
-        $scope.panelCtrl.refresh();
-      }
-
-      $rootScope.appEvent('elastic-query-updated');
-    };
-
-    $scope.handleQueryError = function(err) {
-      $scope.parserError = err.message || 'Failed to issue metric query';
-      return [];
-    };
-
-    $scope.init();
-
-  });
-
-});

+ 45 - 0
public/app/plugins/datasource/elasticsearch/query_ctrl.ts

@@ -0,0 +1,45 @@
+///<reference path="../../../headers/common.d.ts" />
+
+import './bucket_agg';
+import './metric_agg';
+
+import angular from 'angular';
+import _ from 'lodash';
+import {QueryCtrl} from 'app/features/panel/panel';
+
+export class ElasticQueryCtrl extends QueryCtrl {
+  static templateUrl = 'public/app/plugins/datasource/elasticsearch/partials/query.editor.html';
+
+  esVersion: any;
+  rawQueryOld: string;
+
+  /** @ngInject **/
+  constructor($scope, $injector, private $rootScope, private $timeout, private uiSegmentSrv) {
+    super($scope, $injector);
+
+    this.esVersion = this.datasource.esVersion;
+    this.queryUpdated();
+  }
+
+  getFields(type) {
+    var jsonStr = angular.toJson({find: 'fields', type: type});
+    return this.datasource.metricFindQuery(jsonStr)
+    .then(this.uiSegmentSrv.transformToSegments(false))
+    .catch(this.handleQueryError.bind(this));
+  }
+
+  queryUpdated() {
+    var newJson = angular.toJson(this.datasource.queryBuilder.build(this.target), true);
+    if (newJson !== this.rawQueryOld) {
+      this.rawQueryOld = newJson;
+      this.refresh();
+    }
+
+    this.$rootScope.appEvent('elastic-query-updated');
+  }
+
+  handleQueryError(err) {
+    this.error = err.message || 'Failed to issue metric query';
+    return [];
+  }
+}

+ 2 - 2
public/app/plugins/datasource/elasticsearch/specs/datasource_specs.ts

@@ -3,7 +3,7 @@ import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/co
 import moment from 'moment';
 import angular from 'angular';
 import helpers from 'test/specs/helpers';
-import Datasource from "../datasource";
+import {ElasticDatasource} from "../datasource";
 
 describe('ElasticDatasource', function() {
   var ctx = new helpers.ServiceTestContext();
@@ -21,7 +21,7 @@ describe('ElasticDatasource', function() {
 
   function createDatasource(instanceSettings) {
     instanceSettings.jsonData = instanceSettings.jsonData || {};
-    ctx.ds = ctx.$injector.instantiate(Datasource, {instanceSettings: instanceSettings});
+    ctx.ds = ctx.$injector.instantiate(ElasticDatasource, {instanceSettings: instanceSettings});
   }
 
   describe('When testing datasource with index pattern', function() {

+ 0 - 29
public/app/plugins/datasource/elasticsearch/specs/query_ctrl_specs.ts

@@ -1,29 +0,0 @@
-///<amd-dependency path="../query_ctrl" />
-///<amd-dependency path="app/core/services/segment_srv" />
-///<amd-dependency path="test/specs/helpers" name="helpers" />
-
-import {describe, beforeEach, it, sinon, expect, angularMocks} from 'test/lib/common';
-import helpers from 'test/specs/helpers';
-
-describe('ElasticQueryCtrl', function() {
-  var ctx = new helpers.ControllerTestContext();
-
-  beforeEach(angularMocks.module('grafana.controllers'));
-  beforeEach(angularMocks.module('grafana.services'));
-  beforeEach(ctx.providePhase());
-  beforeEach(ctx.createControllerPhase('ElasticQueryCtrl'));
-
-  beforeEach(function() {
-    ctx.scope.target = {};
-    ctx.scope.$parent = { get_data: sinon.spy() };
-
-    ctx.scope.datasource = ctx.datasource;
-    ctx.scope.datasource.metricFindQuery = sinon.stub().returns(ctx.$q.when([]));
-  });
-
-  describe('init', function() {
-    beforeEach(function() {
-      ctx.scope.init();
-    });
-  });
-});

+ 3 - 2
public/app/plugins/datasource/grafana/module.ts

@@ -2,14 +2,15 @@
 
 import angular from 'angular';
 import {GrafanaDatasource} from './datasource';
+import {QueryCtrl} from 'app/features/panel/panel';
 
-class GrafanaMetricsQueryEditor {
+class GrafanaQueryCtrl extends QueryCtrl {
   static templateUrl = 'public/app/plugins/datasource/grafana/partials/query.editor.html';
 }
 
 export {
   GrafanaDatasource,
   GrafanaDatasource as Datasource,
-  GrafanaMetricsQueryEditor as MetricsQueryEditor,
+  GrafanaQueryCtrl as QueryCtrl,
 };
 

+ 5 - 56
public/app/plugins/datasource/grafana/partials/query.editor.html

@@ -1,56 +1,5 @@
-<div class="tight-form">
-	<ul class="tight-form-list pull-right">
-		<li ng-show="parserError" class="tight-form-item">
-			<a bs-tooltip="parserError" style="color: rgb(229, 189, 28)" role="menuitem">
-				<i class="fa fa-warning"></i>
-			</a>
-		</li>
-		<li class="tight-form-item">
-			<div class="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">
-						<a  tabindex="1"
-							ng-click="duplicate()">
-							Duplicate
-						</a>
-					</li>
-					<li role="menuitem">
-						<a  tabindex="1"
-							ng-click="moveMetricQuery($index, $index-1)">
-							Move up
-						</a>
-					</li>
-					<li role="menuitem">
-						<a  tabindex="1"
-							ng-click="moveMetricQuery($index, $index+1)">
-							Move down
-						</a>
-					</li>
-				</ul>
-			</div>
-		</li>
-		<li class="tight-form-item last">
-			<a class="pointer" tabindex="1" ng-click="removeDataQuery(target)">
-				<i class="fa fa-remove"></i>
-			</a>
-		</li>
-	</ul>
-
-	<ul class="tight-form-list">
-		<li class="tight-form-item" style="min-width: 15px; text-align: center">
-			{{ctrl.target.refId}}
-		</li>
-		<li>
-			<a class="tight-form-item" ng-click="target.hide = !target.hide; get_data();" role="menuitem">
-				<i class="fa fa-eye"></i>
-			</a>
-		</li>
-		<li class="tight-form-item">
-			Test metric (fake data source)
-		</li>
-	</ul>
-	<div class="clearfix"></div>
-</div>
+<query-editor-row ctrl="ctrl">
+	<li class="tight-form-item">
+		Test metric (fake data source)
+	</li>
+</query-editor-row>

+ 1 - 30
public/app/plugins/datasource/influxdb/module.ts

@@ -21,33 +21,4 @@ export {
   InfluxAnnotationsQueryCtrl as AnnotationsQueryCtrl,
 };
 
-// define([
-//   './datasource',
-// ],
-// function (InfluxDatasource) {
-//   'use strict';
-//
-//   function influxMetricsQueryEditor() {
-//     return {controller: 'InfluxQueryCtrl', templateUrl: 'public/app/plugins/datasource/influxdb/partials/query.editor.html'};
-//   }
-//
-//   function influxMetricsQueryOptions() {
-//     return {templateUrl: 'public/app/plugins/datasource/influxdb/partials/query.options.html'};
-//   }
-//
-//   function influxAnnotationsQueryEditor() {
-//     return {templateUrl: 'public/app/plugins/datasource/influxdb/partials/annotations.editor.html'};
-//   }
-//
-//   function influxConfigView() {
-//     return {templateUrl: 'public/app/plugins/datasource/influxdb/partials/config.html'};
-//   }
-//
-//   return {
-//     Datasource:               InfluxDatasource,
-//     metricsQueryEditor:       influxMetricsQueryEditor,
-//     metricsQueryOptions:      influxMetricsQueryOptions,
-//     annotationsQueryEditor:   influxAnnotationsQueryEditor,
-//     configView:               influxConfigView,
-//   };
-// });
+

+ 7 - 7
public/app/plugins/datasource/influxdb/partials/query.options.html

@@ -8,7 +8,7 @@
 				 Group by time interval
 			</li>
 			<li>
-				<input type="text" class="input-medium tight-form-input" ng-model="ctrl.panel.interval" ng-blur="ctrl.refresh();"
+				<input type="text" class="input-medium tight-form-input" ng-model="ctrl.panelCtrl.panel.interval" ng-blur="ctrl.panelCtrl.refresh();"
 				spellcheck='false' placeholder="example: >10s">
 			</li>
 			<li class="tight-form-item">
@@ -24,17 +24,17 @@
 				<i class="fa fa-info-circle"></i>
 			</li>
 			<li class="tight-form-item">
-				<a ng-click="ctrl.toggleEditorHelp(1);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
+				<a ng-click="ctrl.panelCtrl.toggleEditorHelp(1);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
 					alias patterns
 				</a>
 			</li>
 			<li class="tight-form-item">
-				<a ng-click="ctrl.toggleEditorHelp(2)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
+				<a ng-click="ctrl.panelCtrl.toggleEditorHelp(2)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
 					stacking &amp; and fill
 				</a>
 			</li>
 			<li class="tight-form-item">
-				<a ng-click="ctrl.toggleEditorHelp(3)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
+				<a ng-click="ctrl.panelCtrl.toggleEditorHelp(3)" bs-tooltip="'click to show helpful info'" data-placement="bottom">
 					group by time
 				</a>
 			</li>
@@ -46,7 +46,7 @@
 <div class="editor-row">
 	<div class="pull-left" style="margin-top: 30px;">
 
-		<div class="grafana-info-box span6" ng-if="ctrl.editorHelpIndex === 1">
+		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 1">
 			<h5>Alias patterns</h5>
 			<ul>
 				<li>$m = replaced with measurement name</li>
@@ -58,7 +58,7 @@
 			</ul>
 		</div>
 
-		<div class="grafana-info-box span6" ng-if="ctrl.editorHelpIndex === 2">
+		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 2">
 			<h5>Stacking and fill</h5>
 			<ul>
 				<li>When stacking is enabled it important that points align</li>
@@ -69,7 +69,7 @@
 			</ul>
 		</div>
 
-		<div class="grafana-info-box span6" ng-if="ctrl.editorHelpIndex === 3">
+		<div class="grafana-info-box span6" ng-if="ctrl.panelCtrl.editorHelpIndex === 3">
 			<h5>Group by time</h5>
 			<ul>
 				<li>Group by time is important, otherwise the query could return many thousands of datapoints that will slow down Grafana</li>