mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tech: rewrite of how the legend is implement, performance increase, and will make future legend enhancements easier
This commit is contained in:
parent
d150bc1e52
commit
e530e4d4bc
@ -46,10 +46,6 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
|
|||||||
scope.get_data();
|
scope.get_data();
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.$on('toggleLegend', function() {
|
|
||||||
render_panel();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Receive render events
|
// Receive render events
|
||||||
scope.$on('render',function(event, renderData) {
|
scope.$on('render',function(event, renderData) {
|
||||||
data = renderData || data;
|
data = renderData || data;
|
||||||
|
@ -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
src/app/panels/graph/legend.js
Normal file
98
src/app/panels/graph/legend.js
Normal file
@ -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
src/app/panels/graph/legend.popover.html
Normal file
27
src/app/panels/graph/legend.popover.html
Normal file
@ -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>
|
||||||
|
|
@ -1,25 +1,22 @@
|
|||||||
<div ng-controller='GraphCtrl'>
|
<div ng-controller='GraphCtrl'>
|
||||||
|
|
||||||
<div class="graph-wrapper" ng-class="{'graph-legend-rightside': panel.legend.rightSide}">
|
<div class="graph-wrapper" ng-class="{'graph-legend-rightside': panel.legend.rightSide}">
|
||||||
<div class="graph-canvas-wrapper">
|
<div class="graph-canvas-wrapper">
|
||||||
|
|
||||||
<div ng-if="datapointsWarning" class="datapoints-warning">
|
<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="!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>
|
<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>
|
||||||
|
|
||||||
<div grafana-graph class="histogram-chart">
|
<div grafana-graph class="histogram-chart">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="graph-legend-wrapper"
|
<div class="graph-legend-wrapper" ng-if="panel.legend.show" graph-legend></div>
|
||||||
ng-if="panel.legend.show"
|
</div>
|
||||||
ng-include="'app/panels/graph/legend.html'">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
<div style="margin-top: 30px" ng-if="editMode">
|
<div style="margin-top: 30px" ng-if="editMode">
|
||||||
<div class="dashboard-editor-header">
|
<div class="dashboard-editor-header">
|
||||||
|
@ -7,6 +7,7 @@ define([
|
|||||||
'moment',
|
'moment',
|
||||||
'components/timeSeries',
|
'components/timeSeries',
|
||||||
'./seriesOverridesCtrl',
|
'./seriesOverridesCtrl',
|
||||||
|
'./legend',
|
||||||
'services/panelSrv',
|
'services/panelSrv',
|
||||||
'services/annotationsSrv',
|
'services/annotationsSrv',
|
||||||
'services/datasourceSrv',
|
'services/datasourceSrv',
|
||||||
@ -23,7 +24,6 @@ function (angular, app, $, _, kbn, moment, TimeSeries) {
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var module = angular.module('grafana.panels.graph');
|
var module = angular.module('grafana.panels.graph');
|
||||||
app.useModule(module);
|
|
||||||
|
|
||||||
module.controller('GraphCtrl', function($scope, $rootScope, panelSrv, annotationsSrv, timeSrv) {
|
module.controller('GraphCtrl', function($scope, $rootScope, panelSrv, annotationsSrv, timeSrv) {
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ function (angular, app, $, _, kbn, moment, TimeSeries) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.render = function(data) {
|
$scope.render = function(data) {
|
||||||
$scope.$emit('render', data);
|
$scope.$broadcast('render', data);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.changeSeriesColor = function(series, color) {
|
$scope.changeSeriesColor = function(series, color) {
|
||||||
@ -291,7 +291,7 @@ function (angular, app, $, _, kbn, moment, TimeSeries) {
|
|||||||
$scope.toggleSeriesExclusiveMode(serie);
|
$scope.toggleSeriesExclusiveMode(serie);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.$emit('toggleLegend', $scope.legend);
|
$scope.render();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.toggleSeriesExclusiveMode = function(serie) {
|
$scope.toggleSeriesExclusiveMode = function(serie) {
|
||||||
|
@ -9,6 +9,7 @@ define([
|
|||||||
'./timer',
|
'./timer',
|
||||||
'./keyboardManager',
|
'./keyboardManager',
|
||||||
'./annotationsSrv',
|
'./annotationsSrv',
|
||||||
|
'./popoverSrv',
|
||||||
'./playlistSrv',
|
'./playlistSrv',
|
||||||
'./unsavedChangesSrv',
|
'./unsavedChangesSrv',
|
||||||
'./dashboard/dashboardKeyBindings',
|
'./dashboard/dashboardKeyBindings',
|
||||||
|
45
src/app/services/popoverSrv.js
Normal file
45
src/app/services/popoverSrv.js
Normal file
@ -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);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -60,9 +60,6 @@
|
|||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
&.pull-right {
|
&.pull-right {
|
||||||
float: none;
|
float: none;
|
||||||
.graph-legend-alias::after {
|
|
||||||
content: 'y\00B2';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user