소스 검색

feat(plugins): last refactoring of how panels are implemented, now the same way as plugin editors

Torkel Ödegaard 10 년 전
부모
커밋
2a8b96b680

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

@@ -3,14 +3,30 @@
 import angular from 'angular';
 import _ from 'lodash';
 
-import coreModule from '../core_module';
+import config from 'app/core/config';
+import coreModule from 'app/core/core_module';
 
-function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q) {
+/** @ngInject */
+function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $templateCache) {
+
+  function getTemplate(component) {
+    if (component.template) {
+      return $q.when(component.template);
+    }
+    var cached = $templateCache.get(component.templateUrl);
+    if (cached) {
+      return $q.when(cached);
+    }
+    return $http.get(component.templateUrl).then(res => {
+      return res.data;
+    });
+  }
 
   function getPluginComponentDirective(options) {
     return function() {
       return {
         templateUrl: options.Component.templateUrl,
+        template: options.Component.template,
         restrict: 'E',
         controller: options.Component,
         controllerAs: 'ctrl',
@@ -20,11 +36,50 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q) {
           if (ctrl.link) {
             ctrl.link(scope, elem, attrs, ctrl);
           }
+          if (ctrl.init) {
+            ctrl.init();
+          }
         }
       };
     };
   }
 
+  function loadPanelComponentInfo(scope, attrs) {
+    var panelElemName = 'panel-' + scope.panel.type;
+    let panelInfo = config.panels[scope.panel.type];
+    if (!panelInfo) {
+      // unknown
+    }
+
+    return System.import(panelInfo.module).then(function(panelModule): any {
+      var PanelCtrl = panelModule.PanelCtrl;
+      var componentInfo = {
+        name: 'panel-plugin-' + panelInfo.id,
+        bindings: {dashboard: "=", panel: "=", row: "="},
+        attrs: {dashboard: "dashboard", panel: "panel", row: "row"},
+        Component: PanelCtrl,
+      };
+
+      if (!PanelCtrl || PanelCtrl.registered) {
+        return componentInfo;
+      };
+
+      if (PanelCtrl.templatePromise) {
+        return PanelCtrl.templatePromise.then(res => {
+          return componentInfo;
+        });
+      }
+
+      PanelCtrl.templatePromise = getTemplate(PanelCtrl).then(template => {
+        PanelCtrl.templateUrl = null;
+        PanelCtrl.template = `<grafana-panel ctrl="ctrl">${template}</grafana-panel>`;
+        return componentInfo;
+      });
+
+      return PanelCtrl.templatePromise;
+    });
+  }
+
   function getModule(scope, attrs) {
     switch (attrs.type) {
       // QueryCtrl
@@ -82,6 +137,10 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q) {
           };
         });
       }
+      // Panel
+      case 'panel': {
+        return loadPanelComponentInfo(scope, attrs);
+      }
       default: {
         return $q.reject({message: "Could not find component type: " + attrs.type });
       }
@@ -127,6 +186,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q) {
         registerPluginComponent(scope, elem, attrs, componentInfo);
       }).catch(err => {
         $rootScope.appEvent('alert-error', ['Plugin Error', err.message || err]);
+        console.log('Plugin componnet error', err);
       });
     }
   };

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

@@ -81,8 +81,8 @@
 
 					<div ng-repeat="panel in row.panels track by panel.id" class="panel" ui-draggable="!dashboard.meta.fullscreen" drag="panel.id"
 						ui-on-drop="onDrop($data, row, panel)" drag-handle-class="drag-handle" panel-width>
-						<panel-loader class="panel-margin" dashboard="dashboard" row="row" panel="panel">
-						</panel-loader>
+						<plugin-component type="panel" class="panel-margin">
+						</plugin-component>
 					</div>
 
 					<div panel-drop-zone class="panel panel-drop-zone" ui-on-drop="onDrop($data, row)" data-drop="true">

+ 4 - 3
public/app/plugins/panel/dashlist/module.ts

@@ -13,6 +13,8 @@ var panelDefaults = {
 };
 
 class DashListCtrl extends PanelCtrl {
+  static templateUrl = 'public/app/plugins/panel/dashlist/module.html';
+
   dashList: any[];
   modes: any[];
 
@@ -55,10 +57,9 @@ class DashListCtrl extends PanelCtrl {
 
 class DashListPanel extends PanelDirective {
   controller = DashListCtrl;
-  templateUrl = 'public/app/plugins/panel/dashlist/module.html';
 }
 
 export {
-  DashListCtrl,
-  DashListPanel as Panel
+  DashListCtrl as DashListCtrl,
+  DashListCtrl as PanelCtrl,
 }

+ 0 - 295
public/app/plugins/panel/graph/graph_ctrl.ts

@@ -1,295 +0,0 @@
-///<reference path="../../../headers/common.d.ts" />
-
-import moment from 'moment';
-import kbn from 'app/core/utils/kbn';
-import _ from 'lodash';
-import TimeSeries from '../../../core/time_series2';
-import * as fileExport from '../../../core/utils/file_export';
-import {MetricsPanelCtrl} from '../../../features/panel/panel';
-
-var panelDefaults = {
-  // datasource name, null = default datasource
-  datasource: null,
-  // sets client side (flot) or native graphite png renderer (png)
-  renderer: 'flot',
-  // Show/hide the x-axis
-  'x-axis'      : true,
-  // Show/hide y-axis
-  'y-axis'      : true,
-  // y axis formats, [left axis,right axis]
-  y_formats    : ['short', 'short'],
-  // grid options
-  grid          : {
-    leftLogBase: 1,
-    leftMax: null,
-    rightMax: null,
-    leftMin: null,
-    rightMin: null,
-    rightLogBase: 1,
-    threshold1: null,
-    threshold2: null,
-    threshold1Color: 'rgba(216, 200, 27, 0.27)',
-    threshold2Color: 'rgba(234, 112, 112, 0.22)'
-  },
-  // show/hide lines
-  lines         : true,
-  // fill factor
-  fill          : 1,
-  // line width in pixels
-  linewidth     : 2,
-  // show hide points
-  points        : false,
-  // point radius in pixels
-  pointradius   : 5,
-  // show hide bars
-  bars          : false,
-  // enable/disable stacking
-  stack         : false,
-  // stack percentage mode
-  percentage    : false,
-  // legend options
-  legend: {
-    show: true, // disable/enable legend
-    values: false, // disable/enable legend values
-    min: false,
-    max: false,
-    current: false,
-    total: false,
-    avg: false
-  },
-  // how null points should be handled
-  nullPointMode : 'connected',
-  // staircase line mode
-  steppedLine: false,
-  // tooltip options
-  tooltip       : {
-    value_type: 'cumulative',
-    shared: true,
-  },
-  // time overrides
-  timeFrom: null,
-  timeShift: null,
-  // metric queries
-  targets: [{}],
-  // series color overrides
-  aliasColors: {},
-  // other style overrides
-  seriesOverrides: [],
-};
-
-class GraphCtrl extends MetricsPanelCtrl {
-  hiddenSeries: any = {};
-  seriesList: any = [];
-  logScales: any;
-  unitFormats: any;
-  annotationsPromise: any;
-  datapointsCount: number;
-  datapointsOutside: boolean;
-  datapointsWarning: boolean;
-  colors: any = [];
-
-  /** @ngInject */
-  constructor($scope, $injector, private annotationsSrv) {
-    super($scope, $injector);
-
-    _.defaults(this.panel, panelDefaults);
-    _.defaults(this.panel.tooltip, panelDefaults.tooltip);
-    _.defaults(this.panel.grid, panelDefaults.grid);
-    _.defaults(this.panel.legend, panelDefaults.legend);
-
-    this.colors = $scope.$root.colors;
-  }
-
-  initEditMode() {
-    super.initEditMode();
-
-    this.icon = "fa fa-bar-chart";
-    this.addEditorTab('Axes & Grid', 'public/app/plugins/panel/graph/axisEditor.html', 2);
-    this.addEditorTab('Display Styles', 'public/app/plugins/panel/graph/styleEditor.html', 3);
-
-    this.logScales = {
-      'linear': 1,
-      'log (base 2)': 2,
-      'log (base 10)': 10,
-      'log (base 32)': 32,
-      'log (base 1024)': 1024
-    };
-    this.unitFormats = kbn.getUnitFormats();
-  }
-
-  getExtendedMenu() {
-    var menu = super.getExtendedMenu();
-    menu.push({text: 'Export CSV', click: 'ctrl.exportCsv()'});
-    menu.push({text: 'Toggle legend', click: 'ctrl.toggleLegend()'});
-    return menu;
-  }
-
-  setUnitFormat(axis, subItem) {
-    this.panel.y_formats[axis] = subItem.value;
-    this.render();
-  }
-
-  refreshData(datasource) {
-    this.annotationsPromise = this.annotationsSrv.getAnnotations(this.dashboard);
-
-    return this.issueQueries(datasource)
-    .then(res => this.dataHandler(res))
-    .catch(err => {
-      this.seriesList = [];
-      this.render([]);
-      throw err;
-    });
-  }
-
-  zoomOut(evt) {
-    this.publishAppEvent('zoom-out', evt);
-  }
-
-  loadSnapshot(snapshotData) {
-    this.updateTimeRange();
-    this.annotationsPromise = this.annotationsSrv.getAnnotations(this.dashboard);
-    this.dataHandler(snapshotData);
-  }
-
-  dataHandler(results) {
-    // png renderer returns just a url
-    if (_.isString(results)) {
-      this.render(results);
-      return;
-    }
-
-    this.datapointsWarning = false;
-    this.datapointsCount = 0;
-    this.datapointsOutside = false;
-    this.seriesList = _.map(results.data, (series, i) => this.seriesHandler(series, i));
-    this.datapointsWarning = this.datapointsCount === 0 || this.datapointsOutside;
-
-    this.annotationsPromise.then(annotations => {
-      this.loading = false;
-      this.seriesList.annotations = annotations;
-      this.render(this.seriesList);
-    }, () => {
-      this.loading = false;
-      this.render(this.seriesList);
-    });
-  };
-
-  seriesHandler(seriesData, index) {
-    var datapoints = seriesData.datapoints;
-    var alias = seriesData.target;
-    var colorIndex = index % this.colors.length;
-    var color = this.panel.aliasColors[alias] || this.colors[colorIndex];
-
-    var series = new TimeSeries({
-      datapoints: datapoints,
-      alias: alias,
-      color: color,
-    });
-
-    if (datapoints && datapoints.length > 0) {
-      var last = moment.utc(datapoints[datapoints.length - 1][1]);
-      var from = moment.utc(this.range.from);
-      if (last - from < -10000) {
-        this.datapointsOutside = true;
-      }
-
-      this.datapointsCount += datapoints.length;
-    }
-
-    return series;
-  }
-
-  render(data?: any) {
-    this.broadcastRender(data);
-  }
-
-  changeSeriesColor(series, color) {
-    series.color = color;
-    this.panel.aliasColors[series.alias] = series.color;
-    this.render();
-  }
-
-  toggleSeries(serie, event) {
-    if (event.ctrlKey || event.metaKey || event.shiftKey) {
-      if (this.hiddenSeries[serie.alias]) {
-        delete this.hiddenSeries[serie.alias];
-      } else {
-        this.hiddenSeries[serie.alias] = true;
-      }
-    } else {
-      this.toggleSeriesExclusiveMode(serie);
-    }
-
-    this.render();
-  }
-
-  toggleSeriesExclusiveMode (serie) {
-    var hidden = this.hiddenSeries;
-
-    if (hidden[serie.alias]) {
-      delete hidden[serie.alias];
-    }
-
-    // check if every other series is hidden
-    var alreadyExclusive = _.every(this.seriesList, value => {
-      if (value.alias === serie.alias) {
-        return true;
-      }
-
-      return hidden[value.alias];
-    });
-
-    if (alreadyExclusive) {
-      // remove all hidden series
-      _.each(this.seriesList, value => {
-        delete this.hiddenSeries[value.alias];
-      });
-    } else {
-      // hide all but this serie
-      _.each(this.seriesList, value => {
-        if (value.alias === serie.alias) {
-          return;
-        }
-
-        this.hiddenSeries[value.alias] = true;
-      });
-    }
-  }
-
-  toggleYAxis(info) {
-    var override = _.findWhere(this.panel.seriesOverrides, { alias: info.alias });
-    if (!override) {
-      override = { alias: info.alias };
-      this.panel.seriesOverrides.push(override);
-    }
-    override.yaxis = info.yaxis === 2 ? 1 : 2;
-    this.render();
-  };
-
-  addSeriesOverride(override) {
-    this.panel.seriesOverrides.push(override || {});
-  }
-
-  removeSeriesOverride(override) {
-    this.panel.seriesOverrides = _.without(this.panel.seriesOverrides, override);
-    this.render();
-  }
-
-  // Called from panel menu
-  toggleLegend() {
-    this.panel.legend.show = !this.panel.legend.show;
-    this.refresh();
-  }
-
-  legendValuesOptionChanged() {
-    var legend = this.panel.legend;
-    legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
-    this.render();
-  }
-
-  exportCsv() {
-    fileExport.exportSeriesListToCsv(this.seriesList);
-  }
-}
-
-export {GraphCtrl}

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

@@ -1,17 +1,301 @@
-
-import {PanelDirective} from '../../../features/panel/panel';
-import {GraphCtrl} from './graph_ctrl';
+///<reference path="../../../headers/common.d.ts" />
 
 import './graph';
 import './legend';
 import './seriesOverridesCtrl';
 
-class GraphPanel extends PanelDirective {
-  controller = GraphCtrl;
-  templateUrl = 'public/app/plugins/panel/graph/module.html';
-}
+import moment from 'moment';
+import kbn from 'app/core/utils/kbn';
+import _ from 'lodash';
+import TimeSeries from '../../../core/time_series2';
+import * as fileExport from '../../../core/utils/file_export';
+import {MetricsPanelCtrl} from '../../../features/panel/panel';
+
+var panelDefaults = {
+  // datasource name, null = default datasource
+  datasource: null,
+  // sets client side (flot) or native graphite png renderer (png)
+  renderer: 'flot',
+  // Show/hide the x-axis
+  'x-axis'      : true,
+  // Show/hide y-axis
+  'y-axis'      : true,
+  // y axis formats, [left axis,right axis]
+  y_formats    : ['short', 'short'],
+  // grid options
+  grid          : {
+    leftLogBase: 1,
+    leftMax: null,
+    rightMax: null,
+    leftMin: null,
+    rightMin: null,
+    rightLogBase: 1,
+    threshold1: null,
+    threshold2: null,
+    threshold1Color: 'rgba(216, 200, 27, 0.27)',
+    threshold2Color: 'rgba(234, 112, 112, 0.22)'
+  },
+  // show/hide lines
+  lines         : true,
+  // fill factor
+  fill          : 1,
+  // line width in pixels
+  linewidth     : 2,
+  // show hide points
+  points        : false,
+  // point radius in pixels
+  pointradius   : 5,
+  // show hide bars
+  bars          : false,
+  // enable/disable stacking
+  stack         : false,
+  // stack percentage mode
+  percentage    : false,
+  // legend options
+  legend: {
+    show: true, // disable/enable legend
+    values: false, // disable/enable legend values
+    min: false,
+    max: false,
+    current: false,
+    total: false,
+    avg: false
+  },
+  // how null points should be handled
+  nullPointMode : 'connected',
+  // staircase line mode
+  steppedLine: false,
+  // tooltip options
+  tooltip       : {
+    value_type: 'cumulative',
+    shared: true,
+  },
+  // time overrides
+  timeFrom: null,
+  timeShift: null,
+  // metric queries
+  targets: [{}],
+  // series color overrides
+  aliasColors: {},
+  // other style overrides
+  seriesOverrides: [],
+};
+
+class GraphCtrl extends MetricsPanelCtrl {
+  static templateUrl = 'public/app/plugins/panel/graph/module.html';
+
+  hiddenSeries: any = {};
+  seriesList: any = [];
+  logScales: any;
+  unitFormats: any;
+  annotationsPromise: any;
+  datapointsCount: number;
+  datapointsOutside: boolean;
+  datapointsWarning: boolean;
+  colors: any = [];
+
+  /** @ngInject */
+  constructor($scope, $injector, private annotationsSrv) {
+    super($scope, $injector);
+
+    _.defaults(this.panel, panelDefaults);
+    _.defaults(this.panel.tooltip, panelDefaults.tooltip);
+    _.defaults(this.panel.grid, panelDefaults.grid);
+    _.defaults(this.panel.legend, panelDefaults.legend);
+
+    this.colors = $scope.$root.colors;
+  }
+
+  initEditMode() {
+    super.initEditMode();
+
+    this.icon = "fa fa-bar-chart";
+    this.addEditorTab('Axes & Grid', 'public/app/plugins/panel/graph/axisEditor.html', 2);
+    this.addEditorTab('Display Styles', 'public/app/plugins/panel/graph/styleEditor.html', 3);
+
+    this.logScales = {
+      'linear': 1,
+      'log (base 2)': 2,
+      'log (base 10)': 10,
+      'log (base 32)': 32,
+      'log (base 1024)': 1024
+    };
+    this.unitFormats = kbn.getUnitFormats();
+  }
+
+  getExtendedMenu() {
+    var menu = super.getExtendedMenu();
+    menu.push({text: 'Export CSV', click: 'ctrl.exportCsv()'});
+    menu.push({text: 'Toggle legend', click: 'ctrl.toggleLegend()'});
+    return menu;
+  }
+
+  setUnitFormat(axis, subItem) {
+    this.panel.y_formats[axis] = subItem.value;
+    this.render();
+  }
+
+  refreshData(datasource) {
+    this.annotationsPromise = this.annotationsSrv.getAnnotations(this.dashboard);
+
+    return this.issueQueries(datasource)
+    .then(res => this.dataHandler(res))
+    .catch(err => {
+      this.seriesList = [];
+      this.render([]);
+      throw err;
+    });
+  }
+
+  zoomOut(evt) {
+    this.publishAppEvent('zoom-out', evt);
+  }
+
+  loadSnapshot(snapshotData) {
+    this.updateTimeRange();
+    this.annotationsPromise = this.annotationsSrv.getAnnotations(this.dashboard);
+    this.dataHandler(snapshotData);
+  }
+
+  dataHandler(results) {
+    // png renderer returns just a url
+    if (_.isString(results)) {
+      this.render(results);
+      return;
+    }
+
+    this.datapointsWarning = false;
+    this.datapointsCount = 0;
+    this.datapointsOutside = false;
+    this.seriesList = _.map(results.data, (series, i) => this.seriesHandler(series, i));
+    this.datapointsWarning = this.datapointsCount === 0 || this.datapointsOutside;
+
+    this.annotationsPromise.then(annotations => {
+      this.loading = false;
+      this.seriesList.annotations = annotations;
+      this.render(this.seriesList);
+    }, () => {
+      this.loading = false;
+      this.render(this.seriesList);
+    });
+  };
+
+  seriesHandler(seriesData, index) {
+    var datapoints = seriesData.datapoints;
+    var alias = seriesData.target;
+    var colorIndex = index % this.colors.length;
+    var color = this.panel.aliasColors[alias] || this.colors[colorIndex];
 
-export {
-  GraphPanel,
-  GraphPanel as Panel
+    var series = new TimeSeries({
+      datapoints: datapoints,
+      alias: alias,
+      color: color,
+    });
+
+    if (datapoints && datapoints.length > 0) {
+      var last = moment.utc(datapoints[datapoints.length - 1][1]);
+      var from = moment.utc(this.range.from);
+      if (last - from < -10000) {
+        this.datapointsOutside = true;
+      }
+
+      this.datapointsCount += datapoints.length;
+    }
+
+    return series;
+  }
+
+  render(data?: any) {
+    this.broadcastRender(data);
+  }
+
+  changeSeriesColor(series, color) {
+    series.color = color;
+    this.panel.aliasColors[series.alias] = series.color;
+    this.render();
+  }
+
+  toggleSeries(serie, event) {
+    if (event.ctrlKey || event.metaKey || event.shiftKey) {
+      if (this.hiddenSeries[serie.alias]) {
+        delete this.hiddenSeries[serie.alias];
+      } else {
+        this.hiddenSeries[serie.alias] = true;
+      }
+    } else {
+      this.toggleSeriesExclusiveMode(serie);
+    }
+
+    this.render();
+  }
+
+  toggleSeriesExclusiveMode (serie) {
+    var hidden = this.hiddenSeries;
+
+    if (hidden[serie.alias]) {
+      delete hidden[serie.alias];
+    }
+
+    // check if every other series is hidden
+    var alreadyExclusive = _.every(this.seriesList, value => {
+      if (value.alias === serie.alias) {
+        return true;
+      }
+
+      return hidden[value.alias];
+    });
+
+    if (alreadyExclusive) {
+      // remove all hidden series
+      _.each(this.seriesList, value => {
+        delete this.hiddenSeries[value.alias];
+      });
+    } else {
+      // hide all but this serie
+      _.each(this.seriesList, value => {
+        if (value.alias === serie.alias) {
+          return;
+        }
+
+        this.hiddenSeries[value.alias] = true;
+      });
+    }
+  }
+
+  toggleYAxis(info) {
+    var override = _.findWhere(this.panel.seriesOverrides, { alias: info.alias });
+    if (!override) {
+      override = { alias: info.alias };
+      this.panel.seriesOverrides.push(override);
+    }
+    override.yaxis = info.yaxis === 2 ? 1 : 2;
+    this.render();
+  };
+
+  addSeriesOverride(override) {
+    this.panel.seriesOverrides.push(override || {});
+  }
+
+  removeSeriesOverride(override) {
+    this.panel.seriesOverrides = _.without(this.panel.seriesOverrides, override);
+    this.render();
+  }
+
+  // Called from panel menu
+  toggleLegend() {
+    this.panel.legend.show = !this.panel.legend.show;
+    this.refresh();
+  }
+
+  legendValuesOptionChanged() {
+    var legend = this.panel.legend;
+    legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
+    this.render();
+  }
+
+  exportCsv() {
+    fileExport.exportSeriesListToCsv(this.seriesList);
+  }
 }
+
+export {GraphCtrl, GraphCtrl as PanelCtrl}

+ 1 - 1
public/app/plugins/panel/graph/specs/graph_ctrl_specs.ts

@@ -3,7 +3,7 @@
 import {describe, beforeEach, it, sinon, expect, angularMocks} from '../../../../../test/lib/common';
 
 import angular from 'angular';
-import {GraphCtrl} from '../graph_ctrl';
+import {GraphCtrl} from '../module';
 import helpers from '../../../../../test/specs/helpers';
 
 describe('GraphCtrl', function() {

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

@@ -10,6 +10,8 @@ var panelDefaults = {
 };
 
 export class TextPanelCtrl extends PanelCtrl {
+  static templateUrl = `public/app/plugins/panel/text/module.html`;
+
   converter: any;
   content: string;
 
@@ -79,9 +81,4 @@ export class TextPanelCtrl extends PanelCtrl {
   }
 }
 
-class TextPanel extends PanelDirective {
-  templateUrl = `public/app/plugins/panel/text/module.html`;
-  controller = TextPanelCtrl;
-}
-
-export {TextPanel as Panel}
+export {TextPanelCtrl as PanelCtrl}