Просмотр исходного кода

refacoring: more work on metric segment replacement

Torkel Ödegaard 8 лет назад
Родитель
Сommit
6a95df403a

+ 0 - 13
public/app/core/components/form_dropdown/form_dropdown.html

@@ -1,13 +0,0 @@
-<input type="text"
-			 data-provide="typeahead"
-			 class="gf-form-input"
-			 spellcheck="false"
-			 style="display:none"></input>
-
-<a class="gf-form-label"
-	 ng-class="ctrl.cssClass"
-	 tabindex="1"
-	 ng-click="ctrl.open()"
-	 give-focus="ctrl.focus"
-	 ng-bind-html="ctrl.display"></a>
-

+ 69 - 21
public/app/core/components/form_dropdown/form_dropdown.ts

@@ -15,15 +15,17 @@ function typeaheadMatcher(item) {
 export class FormDropdownCtrl {
   inputElement: any;
   linkElement: any;
-  value: any;
-  text: any;
+  model: any;
   display: any;
+  text: any;
   options: any;
   cssClass: any;
   allowCustom: any;
   linkMode: boolean;
   cancelBlur: any;
   onChange: any;
+  getOptions: any;
+  optionCache: any;
 
   constructor(private $scope, $element, private $sce, private templateSrv) {
     this.inputElement = $element.find('input').first();
@@ -31,11 +33,15 @@ export class FormDropdownCtrl {
     this.linkMode = true;
     this.cancelBlur = null;
 
-    if (this.options) {
-      var item = _.find(this.options, {value: this.value});
-      this.updateDisplay(item ? item.text : this.value);
+    if (!this.getOptions) {
+      this.getOptions = () => {
+        return Promise.resolve(this.options);
+      };
     }
 
+    // listen to model changes
+    $scope.$watch("ctrl.model", this.modelChanged.bind(this));
+
     this.inputElement.attr('data-provide', 'typeahead');
     this.inputElement.typeahead({
       source: this.typeaheadSource.bind(this),
@@ -64,19 +70,40 @@ export class FormDropdownCtrl {
     this.inputElement.blur(this.inputBlur.bind(this));
   }
 
+  modelChanged(newVal) {
+    if (_.isObject(this.model)) {
+      this.updateDisplay(this.model.text);
+    } else {
+
+      // if we have text use it
+      if (this.text) {
+        this.updateDisplay(this.text);
+      } else {
+        // otherwise we need to do initial lookup, usually happens first time
+        this.getOptions().then(options => {
+          var item = _.find(options, {value: this.model});
+          this.updateDisplay(item ? item.text : this.model);
+        });
+      }
+    }
+  }
+
   typeaheadSource(query, callback) {
-    if (this.options) {
-      var typeaheadOptions = _.map(this.options, 'text');
+    this.getOptions({$query: query}).then(options => {
+      this.optionCache = options;
+
+      // extract texts
+      let optionTexts = _.map(options, 'text');
 
-      // add current custom value
+      // add custom values
       if (this.allowCustom) {
-        if (_.indexOf(typeaheadOptions, this.text) === -1) {
-          typeaheadOptions.unshift(this.text);
+        if (_.indexOf(optionTexts, this.text) === -1) {
+          options.unshift(this.text);
         }
       }
 
-      callback(typeaheadOptions);
-    }
+      callback(optionTexts);
+    });
   }
 
   typeaheadUpdater(text) {
@@ -114,21 +141,29 @@ export class FormDropdownCtrl {
     }
 
     this.$scope.$apply(() => {
-      var option = _.find(this.options, {text: text});
+      var option = _.find(this.optionCache, {text: text});
 
       if (option) {
-        this.value = option.value;
-        this.updateDisplay(option.text);
+        if (_.isObject(this.model)) {
+          this.model = option;
+        } else {
+          this.model = option.value;
+        }
+        this.text = option.text;
       } else if (this.allowCustom) {
-        this.value = text;
-        this.updateDisplay(text);
+        if (_.isObject(this.model)) {
+          this.model.text = this.model.value = text;
+        } else {
+          this.model = text;
+        }
+        this.text = text;
       }
 
       // needs to call this after digest so
       // property is synced with outerscope
       this.$scope.$$postDigest(() => {
         this.$scope.$apply(() => {
-          this.onChange();
+          this.onChange({$option: option});
         });
       });
 
@@ -157,17 +192,30 @@ export class FormDropdownCtrl {
   }
 }
 
-
+const template =  `
+<input type="text"
+data-provide="typeahead"
+class="gf-form-input"
+spellcheck="false"
+style="display:none"></input>
+
+<a class="gf-form-label"
+	 ng-class="ctrl.cssClass"
+	 tabindex="1"
+	 ng-click="ctrl.open()"
+	 give-focus="ctrl.focus"
+	 ng-bind-html="ctrl.display"></a>
+`;
 
 export function formDropdownDirective() {
   return {
     restrict: 'E',
-    templateUrl: 'public/app/core/components/form_dropdown/form_dropdown.html',
+    template: template,
     controller: FormDropdownCtrl,
     bindToController: true,
     controllerAs: 'ctrl',
     scope: {
-      value: "=",
+      model: "=",
       options: "=",
       getOptions: "&",
       onChange: "&",

+ 1 - 1
public/app/core/directives/dash_edit_link.js

@@ -35,7 +35,7 @@ function ($, angular, coreModule) {
             options.html = editViewMap[options.editview].html;
           }
 
-          if (lastEditView === options.editview) {
+          if (lastEditView && lastEditView === options.editview) {
             hideEditorPane(false);
             return;
           }

+ 2 - 0
public/app/core/directives/metric_segment.js

@@ -143,6 +143,7 @@ function (_, $, coreModule) {
           $input.focus();
 
           linkMode = false;
+
           var typeahead = $input.data('typeahead');
           if (typeahead) {
             $input.val('');
@@ -151,6 +152,7 @@ function (_, $, coreModule) {
         });
 
         $input.blur($scope.inputBlur);
+
         $compile(elem.contents())($scope);
       }
     };

+ 20 - 31
public/app/features/panel/metrics_tab.ts

@@ -5,8 +5,6 @@ import _ from 'lodash';
 import {DashboardModel} from '../dashboard/model';
 
 export class MetricsTabCtrl {
-  dsSegment: any;
-  mixedDsSegment: any;
   dsName: string;
   panel: any;
   panelCtrl: any;
@@ -14,30 +12,26 @@ export class MetricsTabCtrl {
   current: any;
   nextRefId: string;
   dashboard: DashboardModel;
+  panelDsValue: any;
+  addQueryDropdown: any;
 
   /** @ngInject */
-  constructor($scope, private uiSegmentSrv, datasourceSrv) {
+  constructor($scope, private uiSegmentSrv, private datasourceSrv) {
     this.panelCtrl = $scope.ctrl;
     $scope.ctrl = this;
 
     this.panel = this.panelCtrl.panel;
     this.dashboard = this.panelCtrl.dashboard;
     this.datasources = datasourceSrv.getMetricSources();
-
-    var dsValue = this.panelCtrl.panel.datasource || null;
+    this.panelDsValue = this.panelCtrl.panel.datasource || null;
 
     for (let ds of this.datasources) {
-      if (ds.value === dsValue) {
+      if (ds.value === this.panelDsValue) {
         this.current = ds;
       }
     }
 
-    if (!this.current) {
-      this.current = {name: dsValue + ' not found', value: null};
-    }
-
-    this.dsSegment = uiSegmentSrv.newSegment({value: this.current.name, selectMode: true});
-    this.mixedDsSegment = uiSegmentSrv.newSegment({value: 'Add Query', selectMode: true, fake: true});
+    this.addQueryDropdown = {text: 'Add Query', value: null, fake: true};
 
     // update next ref id
     this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel);
@@ -46,33 +40,28 @@ export class MetricsTabCtrl {
   getOptions(includeBuiltin) {
     return Promise.resolve(this.datasources.filter(value => {
       return includeBuiltin || !value.meta.builtIn;
-    }).map(value => {
-      return this.uiSegmentSrv.newSegment(value.name);
+    }).map(ds => {
+      return {value: ds.value, text: ds.name, datasource: ds};
     }));
   }
 
-  datasourceChanged() {
-    var ds = _.find(this.datasources, {name: this.dsSegment.value});
-    if (ds) {
-      this.current = ds;
-      this.panelCtrl.setDatasource(ds);
+  datasourceChanged(option) {
+    if (!option) {
+      return;
     }
-  }
 
-  mixedDatasourceChanged() {
-    var target: any = {isNew: true};
-    var ds = _.find(this.datasources, {name: this.mixedDsSegment.value});
+    this.current = option.datasource;
+    this.panelCtrl.setDatasource(option.datasource);
+  }
 
-    if (ds) {
-      target.datasource = ds.name;
-      this.panelCtrl.addQuery(target);
+  addMixedQuery(option) {
+    if (!option) {
+      return;
     }
 
-    // metric segments are really bad, requires hacks to update
-    const segment = this.uiSegmentSrv.newSegment({value: 'Add Query', selectMode: true, fake: true});
-    this.mixedDsSegment.value = segment.value;
-    this.mixedDsSegment.html = segment.html;
-    this.mixedDsSegment.text = segment.text;
+    var target: any = {isNew: true};
+    this.panelCtrl.addQuery({isNew: true, datasource: option.datasource.name});
+    this.addQueryDropdown = {text: 'Add Query', value: null, fake: true};
   }
 
   addQuery() {

+ 10 - 5
public/app/features/panel/partials/metrics_tab.html

@@ -19,7 +19,10 @@
       </button>
 
       <div class="dropdown" ng-if="ctrl.current.meta.mixed">
-        <metric-segment segment="ctrl.mixedDsSegment" get-options="ctrl.getOptions(false)" on-change="ctrl.mixedDatasourceChanged()"></metric-segment>
+        <gf-form-dropdown model="ctrl.addQueryDropdown"
+                          get-options="ctrl.getOptions(false)"
+                          on-change="ctrl.addMixedQuery($option)">
+        </gf-form-dropdown>
       </div>
     </div>
   </div>
@@ -30,10 +33,12 @@
 <div class="gf-form-group">
   <div class="gf-form-inline">
     <div class="gf-form">
-      <label class="gf-form-label">
-        Panel Data Source
-      </label>
-      <metric-segment segment="ctrl.dsSegment" get-options="ctrl.getOptions(true)" on-change="ctrl.datasourceChanged()"></metric-segment>
+      <label class="gf-form-label">Panel Data Source</label>
+      <gf-form-dropdown model="ctrl.panelDsValue"
+                        get-options="ctrl.getOptions(true)"
+                        on-change="ctrl.datasourceChanged($option)"
+                        css-class="width-10">
+      </gf-form-dropdown>
     </div>
   </div>
 </div>