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

Tech: rewrite of how the legend is implement, performance increase, and will make future legend enhancements easier

Torkel Ödegaard 11 лет назад
Родитель
Сommit
e530e4d4bc

+ 0 - 4
src/app/directives/grafanaGraph.js

@@ -46,10 +46,6 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
           scope.get_data();
         });
 
-        scope.$on('toggleLegend', function() {
-          render_panel();
-        });
-
         // Receive render events
         scope.$on('render',function(event, renderData) {
           data = renderData || data;

+ 0 - 50
src/app/panels/graph/legend.html

@@ -1,50 +0,0 @@
-<section class="graph-legend" ng-class="{'graph-legend-table': panel.legend.alignAsTable}">
-
-  <div class="graph-legend-series" ng-repeat='series in legend'
-       ng-class="{'pull-right': series.yaxis === 2, 'graph-legend-series-hidden': hiddenSeries[series.alias]}">
-    <div class="graph-legend-icon">
-      <i class='icon-minus pointer' ng-style="{color: series.color}" bs-popover="'colorPopup.html'" data-placement="bottom"></i>
-    </div>
-    <div class="graph-legend-alias small">
-      <a ng-click="toggleSeries(series, $event)" data-unique="1" data-placement="{{series.yaxis === 2 ? 'bottomRight' : 'bottomLeft'}}">
-        {{series.alias}}
-      </a>
-    </div>
-    <div class="graph-legend-value current small" ng-show="panel.legend.values && panel.legend.current" ng-bind="series.current"></div>
-    <div class="graph-legend-value min small" ng-show="panel.legend.values && panel.legend.min" ng-bind="series.min"></div>
-    <div class="graph-legend-value max small" ng-show="panel.legend.values && panel.legend.max" ng-bind="series.max"></div>
-    <div class="graph-legend-value total small" ng-show="panel.legend.values && panel.legend.total" ng-bind="series.total"></div>
-    <div class="graph-legend-value avg small" ng-show="panel.legend.values && panel.legend.avg" ng-bind="series.avg"></div>
-  </div>
-
-</section>
-
-
-<script type="text/ng-template" id="colorPopup.html">
-  <div class="graph-legend-popover">
-    <a class="close" ng-click="dismiss();" href="">×</a>
-
-    <div class="editor-row small" style="padding-bottom: 0;">
-      <label>Axis:</label>
-      <button ng-click="toggleYAxis(series);dismiss();"
-              class="btn btn-mini"
-              ng-class="{'btn-success': series.yaxis === 1 }">
-        Left
-      </button>
-      <button ng-click="toggleYAxis(series);dismiss();"
-              class="btn btn-mini"
-              ng-class="{'btn-success': series.yaxis === 2 }">
-        Right
-      </button>
-    </div>
-
-    <div class="editor-row">
-      <i ng-repeat="color in colors"
-        class="pointer"
-        ng-class="{'icon-circle-blank': color === series.color,'icon-circle': color !== series.color}"
-        ng-style="{color:color}"
-        ng-click="changeSeriesColor(series, color);dismiss();">
-      </i>
-    </div>
-  </div>
-</script>

+ 98 - 0
src/app/panels/graph/legend.js

@@ -0,0 +1,98 @@
+define([
+  'angular',
+  'app',
+  'lodash',
+  'kbn',
+  'jquery',
+  'jquery.flot',
+  'jquery.flot.time',
+],
+function (angular, app, _, kbn, $) {
+  'use strict';
+
+  var module = angular.module('grafana.panels.graph');
+
+  module.directive('graphLegend', function(popoverSrv) {
+
+    return {
+      link: function(scope, elem) {
+        var $container = $('<section class="graph-legend"></section>');
+        var firstRender = true;
+        var panel = scope.panel;
+        var data;
+        var i;
+
+        scope.$on('render', function(event, renderData) {
+          data = renderData || data;
+          if (data) {
+            render();
+          }
+        });
+
+        function getSeriesIndexForElement(el) {
+          return el.parents('[data-series-index]').data('series-index');
+        }
+
+        function openColorSelector(e) {
+          var el = $(e.currentTarget);
+          var index = getSeriesIndexForElement(el);
+          var seriesInfo = data[index].info;
+          var popoverScope = scope.$new();
+          popoverScope.series = seriesInfo;
+          popoverSrv.show({
+            element: $(':first-child', el),
+            templateUrl:  'app/panels/graph/legend.popover.html',
+            scope: popoverScope
+          });
+        }
+
+        function toggleSeries(e) {
+          var el = $(e.currentTarget);
+          var index = getSeriesIndexForElement(el);
+          var seriesInfo = data[index].info;
+          scope.toggleSeries(seriesInfo, e);
+        }
+
+        function render() {
+          if (firstRender) {
+            elem.append($container);
+            $container.on('click', '.graph-legend-icon', openColorSelector);
+            $container.on('click', '.graph-legend-alias', toggleSeries);
+            firstRender = false;
+          }
+
+          $container.empty();
+
+          $container.toggleClass('graph-legend-table', panel.legend.alignAsTable);
+
+          for (i = 0; i < data.length; i++) {
+            var series = data[i];
+            var html = '<div class="graph-legend-series';
+            if (series.info.yaxis === 2) { html += ' pull-right'; }
+            if (scope.hiddenSeries[series.label]) { html += ' graph-legend-series-hidden'; }
+            html += '" data-series-index="' + i + '">';
+            html += '<div class="graph-legend-icon">';
+            html += '<i class="icon-minus pointer" style="color:' + series.color + '"></i>';
+            html += '</div>';
+
+            html += '<div class="graph-legend-alias small">';
+            html += '<a>' + series.label + '</a>';
+            html += '</div>';
+
+            if (panel.legend.values) {
+              if (panel.legend.min) { html += '<div class="graph-legend-value min small">' + series.info.min + '</div>'; }
+              if (panel.legend.max) { html += '<div class="graph-legend-value max small">' + series.info.max + '</div>'; }
+              if (panel.legend.avg) { html += '<div class="graph-legend-value avg small">' + series.info.avg + '</div>'; }
+              if (panel.legend.current) { html += '<div class="graph-legend-value current small">' + series.info.current + '</div>'; }
+              if (panel.legend.total) { html += '<div class="graph-legend-value total small">' + series.info.total + '</div>'; }
+            }
+
+            html += '</div>';
+            $container.append($(html));
+          }
+        }
+      }
+    };
+  });
+
+});

+ 27 - 0
src/app/panels/graph/legend.popover.html

@@ -0,0 +1,27 @@
+<div class="graph-legend-popover">
+	<a class="close" ng-click="dismiss();" href="">×</a>
+
+	<div class="editor-row small" style="padding-bottom: 0;">
+		<label>Axis:</label>
+		<button ng-click="toggleYAxis(series);dismiss();"
+			class="btn btn-mini"
+			ng-class="{'btn-success': series.yaxis === 1 }">
+			Left
+		</button>
+		<button ng-click="toggleYAxis(series);dismiss();"
+			class="btn btn-mini"
+			ng-class="{'btn-success': series.yaxis === 2 }">
+			Right
+		</button>
+	</div>
+
+	<div class="editor-row">
+		<i ng-repeat="color in colors"
+			class="pointer"
+			ng-class="{'icon-circle-blank': color === series.color,'icon-circle': color !== series.color}"
+			ng-style="{color:color}"
+			ng-click="changeSeriesColor(series, color);dismiss();">
+		</i>
+	</div>
+</div>
+

+ 12 - 15
src/app/panels/graph/module.html

@@ -1,25 +1,22 @@
 <div ng-controller='GraphCtrl'>
 
-  <div class="graph-wrapper" ng-class="{'graph-legend-rightside': panel.legend.rightSide}">
-      <div class="graph-canvas-wrapper">
+	<div class="graph-wrapper" ng-class="{'graph-legend-rightside': panel.legend.rightSide}">
+		<div class="graph-canvas-wrapper">
 
-        <div ng-if="datapointsWarning" class="datapoints-warning">
-          <span class="small" ng-show="!datapointsCount">No datapoints <tip>Can be caused by timezone mismatch between browser and graphite server</tip></span>
-          <span class="small" ng-show="datapointsOutside">Datapoints outside time range <tip>Can be caused by timezone mismatch between browser and graphite server</tip></span>
-        </div>
+			<div ng-if="datapointsWarning" class="datapoints-warning">
+				<span class="small" ng-show="!datapointsCount">No datapoints <tip>Can be caused by timezone mismatch between browser and graphite server</tip></span>
+				<span class="small" ng-show="datapointsOutside">Datapoints outside time range <tip>Can be caused by timezone mismatch between browser and graphite server</tip></span>
+			</div>
 
-        <div grafana-graph class="histogram-chart">
-        </div>
+			<div grafana-graph class="histogram-chart">
+			</div>
 
-      </div>
+		</div>
 
-      <div class="graph-legend-wrapper"
-           ng-if="panel.legend.show"
-           ng-include="'app/panels/graph/legend.html'">
-      </div>
-  </div>
+		<div class="graph-legend-wrapper" ng-if="panel.legend.show" graph-legend></div>
+	</div>
 
-  <div class="clearfix"></div>
+	<div class="clearfix"></div>
 
 	<div style="margin-top: 30px" ng-if="editMode">
 		<div class="dashboard-editor-header">

+ 3 - 3
src/app/panels/graph/module.js

@@ -7,6 +7,7 @@ define([
   'moment',
   'components/timeSeries',
   './seriesOverridesCtrl',
+  './legend',
   'services/panelSrv',
   'services/annotationsSrv',
   'services/datasourceSrv',
@@ -23,7 +24,6 @@ function (angular, app, $, _, kbn, moment, TimeSeries) {
   'use strict';
 
   var module = angular.module('grafana.panels.graph');
-  app.useModule(module);
 
   module.controller('GraphCtrl', function($scope, $rootScope, panelSrv, annotationsSrv, timeSrv) {
 
@@ -270,7 +270,7 @@ function (angular, app, $, _, kbn, moment, TimeSeries) {
     };
 
     $scope.render = function(data) {
-      $scope.$emit('render', data);
+      $scope.$broadcast('render', data);
     };
 
     $scope.changeSeriesColor = function(series, color) {
@@ -291,7 +291,7 @@ function (angular, app, $, _, kbn, moment, TimeSeries) {
         $scope.toggleSeriesExclusiveMode(serie);
       }
 
-      $scope.$emit('toggleLegend', $scope.legend);
+      $scope.render();
     };
 
     $scope.toggleSeriesExclusiveMode = function(serie) {

+ 1 - 0
src/app/services/all.js

@@ -9,6 +9,7 @@ define([
   './timer',
   './keyboardManager',
   './annotationsSrv',
+  './popoverSrv',
   './playlistSrv',
   './unsavedChangesSrv',
   './dashboard/dashboardKeyBindings',

+ 45 - 0
src/app/services/popoverSrv.js

@@ -0,0 +1,45 @@
+define([
+  'angular',
+],
+function (angular) {
+  'use strict';
+
+  var module = angular.module('grafana.services');
+
+  module.service('popoverSrv', function($templateCache, $timeout, $q, $http, $compile) {
+
+    this.getTemplate = function(url) {
+      return $q.when($templateCache.get(url) || $http.get(url, {cache: true}));
+    };
+
+    this.show = function(options) {
+      var popover = options.element.data('popover');
+      if (popover) {
+        popover.scope.$destroy();
+        popover.destroy();
+        return;
+      }
+
+      this.getTemplate(options.templateUrl).then(function(result) {
+        var template = result.data;
+
+        options.element.popover({
+          content: template,
+          placement: 'bottom',
+          html: true
+        });
+
+        popover = options.element.data('popover');
+        popover.hasContent = function () {
+          return template;
+        };
+
+        popover.toggle();
+        popover.scope = options.scope;
+        $compile(popover.$tip)(popover.scope);
+      });
+    };
+
+  });
+
+});

+ 0 - 3
src/css/less/graph.less

@@ -60,9 +60,6 @@
     padding-left: 0;
     &.pull-right {
       float: none;
-      .graph-legend-alias::after {
-        content: 'y\00B2';
-      }
     }
   }