فهرست منبع

feat(panels): more panel refactoring, using events instead of overriding base class methods

Torkel Ödegaard 9 سال پیش
والد
کامیت
b3c073ab6c

+ 1 - 1
public/app/core/utils/emitter.ts

@@ -14,7 +14,7 @@ export class Emitter {
     this.subjects = {};
   }
 
-  emit(name, data) {
+  emit(name, data?) {
     var fnName = createName(name);
     this.subjects[fnName] || (this.subjects[fnName] = new Subject());
     this.subjects[fnName].next(data);

+ 2 - 2
public/app/features/dashboard/viewStateSrv.js

@@ -139,7 +139,7 @@ function (angular, _, $) {
           self.$scope.broadcastRefresh();
         }
         else {
-          self.fullscreenPanel.$broadcast('render');
+          ctrl.render();
         }
         delete self.fullscreenPanel;
       });
@@ -159,7 +159,7 @@ function (angular, _, $) {
       this.$scope.appEvent('panel-fullscreen-enter', {panelId: ctrl.panel.id});
 
       $timeout(function() {
-        panelScope.$broadcast('render');
+        ctrl.render();
       });
     };
 

+ 5 - 3
public/app/features/panel/metrics_panel_ctrl.ts

@@ -44,16 +44,18 @@ class MetricsPanelCtrl extends PanelCtrl {
     if (!this.panel.targets) {
       this.panel.targets = [{}];
     }
+
+    this.events.on('refresh', this.onMetricsPanelRefresh.bind(this));
+    this.events.on('init-edit-mode', this.onInitMetricsPanelEditMode.bind(this));
   }
 
-  initEditMode() {
-    super.initEditMode();
+  private onInitMetricsPanelEditMode() {
     this.addEditorTab('Metrics', 'public/app/partials/metrics.html');
     this.addEditorTab('Time range', 'public/app/features/panel/partials/panelTime.html');
     this.datasources = this.datasourceSrv.getMetricSources();
   }
 
-  refresh() {
+  private onMetricsPanelRefresh() {
     // ignore fetching data if another panel is in fullscreen
     if (this.otherPanelInFullscreenMode()) { return; }
 

+ 12 - 6
public/app/features/panel/panel_ctrl.ts

@@ -18,7 +18,6 @@ export class PanelCtrl {
   editorTabIndex: number;
   pluginName: string;
   pluginId: string;
-  icon: string;
   editorTabs: any;
   $scope: any;
   $injector: any;
@@ -60,7 +59,7 @@ export class PanelCtrl {
   }
 
   refresh() {
-    this.render();
+    this.events.emit('refresh', null);
   }
 
   publishAppEvent(evtName, evt) {
@@ -89,6 +88,7 @@ export class PanelCtrl {
     this.editorTabs = [];
     this.addEditorTab('General', 'public/app/partials/panelgeneral.html');
     this.editModeInitiated = true;
+    this.events.emit('init-edit-mode', null);
   }
 
   addEditorTab(title, directiveFn, index?) {
@@ -118,7 +118,9 @@ export class PanelCtrl {
   }
 
   getExtendedMenu() {
-    return [{text: 'Panel JSON', click: 'ctrl.editPanelJson(); dismiss();'}];
+    var actions = [{text: 'Panel JSON', click: 'ctrl.editPanelJson(); dismiss();'}];
+    this.events.emit('init-panel-actions', actions);
+    return actions;
   }
 
   otherPanelInFullscreenMode() {
@@ -126,7 +128,6 @@ export class PanelCtrl {
   }
 
   calculatePanelHeight() {
-
     if (this.fullscreen) {
       var docHeight = $(window).height();
       var editHeight = Math.floor(docHeight * 0.3);
@@ -142,8 +143,13 @@ export class PanelCtrl {
     this.height = this.containerHeight - (PANEL_PADDING + (this.panel.title ? TITLE_HEIGHT : EMPTY_TITLE_HEIGHT));
   }
 
-  render(arg1?, arg2?) {
-    this.$scope.$broadcast('render', arg1, arg2);
+  render(payload?) {
+    // ignore if other panel is in fullscreen mode
+    if (this.otherPanelInFullscreenMode()) {
+      return;
+    }
+
+    this.events.emit('render', payload);
   }
 
   toggleEditorHelp(index) {

+ 7 - 7
public/app/plugins/panel/dashlist/module.ts

@@ -28,18 +28,18 @@ class DashListCtrl extends PanelCtrl {
       this.panel.tags = [$scope.panel.tag];
       delete this.panel.tag;
     }
+
+    this.events.on('refresh', this.onRefresh.bind(this));
+    this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
   }
 
-  initEditMode() {
-    super.initEditMode();
+  onInitEditMode() {
+    this.editorTabIndex = 1;
     this.modes = ['starred', 'search', 'recently viewed'];
-    this.icon = "fa fa-star";
-    this.addEditorTab('Options', () => {
-      return {templateUrl: 'public/app/plugins/panel/dashlist/editor.html'};
-    });
+    this.addEditorTab('Options', 'public/app/plugins/panel/dashlist/editor.html');
   }
 
-  refresh() {
+  onRefresh() {
     var params: any = {limit: this.panel.limit};
 
     if (this.panel.mode === 'recently viewed') {

+ 1 - 5
public/app/plugins/panel/graph/graph.js

@@ -54,7 +54,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
         }, scope);
 
         // Receive render events
-        scope.$on('render',function(event, renderData) {
+        ctrl.events.on('render', function(renderData) {
           data = renderData || data;
           if (!data) {
             ctrl.refresh();
@@ -97,10 +97,6 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
             return true;
           }
 
-          if (ctrl.otherPanelInFullscreenMode()) {
-            return true;
-          }
-
           if (!setElementHeight()) { return true; }
 
           if(_.isString(data)) {

+ 1 - 1
public/app/plugins/panel/graph/legend.js

@@ -22,7 +22,7 @@ function (angular, _, $) {
         var seriesList;
         var i;
 
-        scope.$on('render', function() {
+        ctrl.events.on('render', function() {
           data = ctrl.seriesList;
           if (data) {
             render();

+ 7 - 10
public/app/plugins/panel/graph/module.ts

@@ -110,12 +110,11 @@ class GraphCtrl extends MetricsPanelCtrl {
     this.events.on('data-received', this.onDataReceived.bind(this));
     this.events.on('data-error', this.onDataError.bind(this));
     this.events.on('data-snapshot-load', this.onDataSnapshotLoad.bind(this));
+    this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
+    this.events.on('init-panel-actions', this.onInitPanelActions.bind(this));
   }
 
-  initEditMode() {
-    super.initEditMode();
-
-    this.icon = "fa fa-bar-chart";
+  onInitEditMode() {
     this.addEditorTab('Axes & Grid', 'public/app/plugins/panel/graph/axisEditor.html', 2);
     this.addEditorTab('Display Styles', 'public/app/plugins/panel/graph/styleEditor.html', 3);
 
@@ -129,12 +128,10 @@ class GraphCtrl extends MetricsPanelCtrl {
     this.unitFormats = kbn.getUnitFormats();
   }
 
-  getExtendedMenu() {
-    var menu = super.getExtendedMenu();
-    menu.push({text: 'Export CSV (series as rows)', click: 'ctrl.exportCsv()'});
-    menu.push({text: 'Export CSV (series as columns)', click: 'ctrl.exportCsvColumns()'});
-    menu.push({text: 'Toggle legend', click: 'ctrl.toggleLegend()'});
-    return menu;
+  onInitPanelActions(actions) {
+    actions.push({text: 'Export CSV (series as rows)', click: 'ctrl.exportCsv()'});
+    actions.push({text: 'Export CSV (series as columns)', click: 'ctrl.exportCsvColumns()'});
+    actions.push({text: 'Toggle legend', click: 'ctrl.toggleLegend()'});
   }
 
   setUnitFormat(axis, subItem) {

+ 26 - 22
public/app/plugins/panel/graph/specs/graph_specs.ts

@@ -8,6 +8,7 @@ import $ from 'jquery';
 import helpers from 'test/specs/helpers';
 import TimeSeries from 'app/core/time_series2';
 import moment from 'moment';
+import {Emitter} from 'app/core/core';
 
 describe('grafanaGraph', function() {
 
@@ -24,31 +25,33 @@ describe('grafanaGraph', function() {
         }));
 
         beforeEach(angularMocks.inject(function($rootScope, $compile) {
-          var ctrl: any = {};
+          var ctrl: any = {
+            events: new Emitter(),
+            height: 200,
+            panel: {
+              legend: {},
+              grid: { },
+              y_formats: [],
+              seriesOverrides: [],
+              tooltip: {
+                shared: true
+              }
+            },
+            renderingCompleted: sinon.spy(),
+            hiddenSeries: {},
+            dashboard: {timezone: 'browser'},
+            range: {
+              from: moment([2015, 1, 1, 10]),
+              to: moment([2015, 1, 1, 22]),
+            },
+          };
+
           var scope = $rootScope.$new();
           scope.ctrl = ctrl;
-          var element = angular.element("<div style='width:" + elementWidth + "px' grafana-graph><div>");
 
-          ctrl.height = '200px';
-          ctrl.panel = {
-            legend: {},
-            grid: { },
-            y_formats: [],
-            seriesOverrides: [],
-            tooltip: {
-              shared: true
-            }
-          };
 
           $rootScope.onAppEvent = sinon.spy();
-          ctrl.otherPanelInFullscreenMode = sinon.spy();
-          ctrl.renderingCompleted = sinon.spy();
-          ctrl.hiddenSeries = {};
-          ctrl.dashboard = { timezone: 'browser' };
-          ctrl.range = {
-            from: moment([2015, 1, 1, 10]),
-            to: moment([2015, 1, 1, 22]),
-          };
+
           ctx.data = [];
           ctx.data.push(new TimeSeries({
             datapoints: [[1,1],[2,2]],
@@ -61,11 +64,12 @@ describe('grafanaGraph', function() {
 
           setupFunc(ctrl, ctx.data);
 
+          var element = angular.element("<div style='width:" + elementWidth + "px' grafana-graph><div>");
           $compile(element)(scope);
           scope.$digest();
-          $.plot = ctx.plotSpy = sinon.spy();
 
-          scope.$emit('render', ctx.data);
+          $.plot = ctx.plotSpy = sinon.spy();
+          ctrl.events.emit('render', ctx.data);
           ctx.plotData = ctx.plotSpy.getCall(0).args[1];
           ctx.plotOptions = ctx.plotSpy.getCall(0).args[2];
         }));

+ 7 - 7
public/app/plugins/panel/singlestat/module.ts

@@ -235,14 +235,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
     var templateSrv = this.templateSrv;
     var data, linkInfo;
     var $panelContainer = elem.find('.panel-container');
-    // change elem to singlestat panel
     elem = elem.find('.singlestat-panel');
-    hookupDrilldownLinkTooltip();
-
-    scope.$on('render', function() {
-      render();
-      ctrl.renderingCompleted();
-    });
 
     function setElementHeight() {
       elem.css('height', ctrl.height + 'px');
@@ -417,6 +410,13 @@ class SingleStatCtrl extends MetricsPanelCtrl {
         drilldownTooltip.place_tt(e.pageX+20, e.pageY-15);
       });
     }
+
+    hookupDrilldownLinkTooltip();
+
+    this.events.on('render', function() {
+      render();
+      ctrl.renderingCompleted();
+    });
   }
 }
 

+ 6 - 7
public/app/plugins/panel/table/module.ts

@@ -61,17 +61,16 @@ class TablePanelCtrl extends MetricsPanelCtrl {
     this.events.on('data-received', this.onDataReceived.bind(this));
     this.events.on('data-error', this.onDataError.bind(this));
     this.events.on('data-snapshot-load', this.onDataSnapshotLoad.bind(this));
+    this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
+    this.events.on('init-panel-actions', this.onInitPanelActions.bind(this));
   }
 
-  initEditMode() {
-    super.initEditMode();
+  onInitEditMode() {
     this.addEditorTab('Options', tablePanelEditor, 2);
   }
 
-  getExtendedMenu() {
-    var menu = super.getExtendedMenu();
-    menu.push({text: 'Export CSV', click: 'ctrl.exportCsv()'});
-    return menu;
+  onInitPanelActions(actions) {
+    actions.push({text: 'Export CSV', click: 'ctrl.exportCsv()'});
   }
 
   issueQueries(datasource) {
@@ -211,7 +210,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
       elem.off('click', '.table-panel-page-link');
     });
 
-    scope.$on('render', function(event, renderData) {
+    ctrl.events.on('render', function(renderData) {
       data = renderData || data;
       if (data) {
         renderPanel();

+ 6 - 6
public/app/plugins/panel/text/module.ts

@@ -20,18 +20,18 @@ export class TextPanelCtrl extends PanelCtrl {
     super($scope, $injector);
 
     _.defaults(this.panel, panelDefaults);
+
+    this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
+    this.events.on('refresh', this.onRender.bind(this));
+    this.events.on('render', this.onRender.bind(this));
   }
 
-  initEditMode() {
-    super.initEditMode();
-    this.icon = 'fa fa-text-width';
+  onInitEditMode() {
     this.addEditorTab('Options', 'public/app/plugins/panel/text/editor.html');
     this.editorTabIndex = 1;
   }
 
-  render() {
-    super.render();
-
+  onRender() {
     if (this.panel.mode === 'markdown') {
       this.renderMarkdown(this.panel.content);
     } else if (this.panel.mode === 'html') {

+ 30 - 0
public/test/core/utils/emitter_specs.ts

@@ -0,0 +1,30 @@
+import {describe, beforeEach, it, sinon, expect} from 'test/lib/common'
+
+import {Emitter} from 'app/core/core';
+
+describe("Emitter", () => {
+
+  describe('given 2 subscribers', () => {
+
+    it('should notfiy subscribers', () => {
+      var events = new Emitter();
+      var sub1Called = false;
+      var sub2Called = false;
+
+      events.on('test', () => {
+        sub1Called = true;
+      });
+      events.on('test', () => {
+        sub2Called = true;
+      });
+
+      events.emit('test', null);
+
+      expect(sub1Called).to.be(true);
+      expect(sub2Called).to.be(true);
+    });
+  });
+
+});
+
+