Commit 260c731f by Torkel Ödegaard

fix(panel): fixes for panel height and alignment management and scrollable legends, closes #4266

parent e73e7aea
......@@ -129,7 +129,6 @@ function (angular, _, $) {
ctrl.editMode = false;
ctrl.fullscreen = false;
delete ctrl.height;
this.$scope.appEvent('panel-fullscreen-exit', {panelId: ctrl.panel.id});
......@@ -147,13 +146,9 @@ function (angular, _, $) {
};
DashboardViewState.prototype.enterFullscreen = function(panelScope) {
var docHeight = $(window).height();
var editHeight = Math.floor(docHeight * 0.3);
var fullscreenHeight = Math.floor(docHeight * 0.7);
var ctrl = panelScope.ctrl;
ctrl.editMode = this.state.edit && this.$scope.dashboardMeta.canEdit;
ctrl.height = ctrl.editMode ? editHeight : fullscreenHeight;
ctrl.fullscreen = true;
this.oldTimeRange = ctrl.range;
......
......@@ -3,6 +3,11 @@
import config from 'app/core/config';
import _ from 'lodash';
import angular from 'angular';
import $ from 'jquery';
const TITLE_HEIGHT = 25;
const EMPTY_TITLE_HEIGHT = 9;
const PANEL_PADDING = 5;
export class PanelCtrl {
panel: any;
......@@ -20,6 +25,9 @@ export class PanelCtrl {
inspector: any;
editModeInitiated: boolean;
editorHelpIndex: number;
editMode: any;
height: any;
containerHeight: any;
constructor($scope, $injector) {
this.$injector = $injector;
......@@ -34,6 +42,7 @@ export class PanelCtrl {
}
$scope.$on("refresh", () => this.refresh());
$scope.$on("render", () => this.calculatePanelHeight());
}
init() {
......@@ -111,6 +120,23 @@ export class PanelCtrl {
return this.dashboard.meta.fullscreen && !this.fullscreen;
}
calculatePanelHeight() {
if (this.fullscreen) {
var docHeight = $(window).height();
var editHeight = Math.floor(docHeight * 0.3);
var fullscreenHeight = Math.floor(docHeight * 0.7);
this.containerHeight = this.editMode ? editHeight : fullscreenHeight;
} else {
this.containerHeight = this.panel.height || this.row.height;
if (_.isString(this.containerHeight)) {
this.containerHeight = parseInt(this.containerHeight.replace('px', ''), 10);
}
}
this.height = this.containerHeight - (PANEL_PADDING + (this.panel.title ? TITLE_HEIGHT : EMPTY_TITLE_HEIGHT));
}
broadcastRender(arg1?, arg2?) {
this.$scope.$broadcast('render', arg1, arg2);
}
......
......@@ -65,8 +65,8 @@ module.directive('grafanaPanel', function() {
link: function(scope, elem) {
var panelContainer = elem.find('.panel-container');
var ctrl = scope.ctrl;
scope.$watchGroup(['ctrl.fullscreen', 'ctrl.height', 'ctrl.panel.height', 'ctrl.row.height'], function() {
panelContainer.css({ minHeight: ctrl.height || ctrl.panel.height || ctrl.row.height, display: 'block' });
scope.$watchGroup(['ctrl.fullscreen', 'ctrl.containerHeight'], function() {
panelContainer.css({minHeight: ctrl.containerHeight});
elem.toggleClass('panel-fullscreen', ctrl.fullscreen ? true : false);
});
}
......
define([
'angular',
'lodash',
'jquery',
'app/core/utils/kbn',
'app/core/utils/datemath',
'app/core/utils/rangeutil',
],
function (angular, _, $, kbn, dateMath, rangeUtil) {
'use strict';
var module = angular.module('grafana.services');
module.service('panelHelper', function(timeSrv, $rootScope, $q) {
var self = this;
this.setTimeQueryStart = function(scope) {
scope.timing = {};
scope.timing.queryStart = new Date().getTime();
};
this.setTimeQueryEnd = function(scope) {
scope.timing.queryEnd = new Date().getTime();
};
this.setTimeRenderStart = function(scope) {
scope.timing = scope.timing || {};
scope.timing.renderStart = new Date().getTime();
};
this.setTimeRenderEnd = function(scope) {
scope.timing.renderEnd = new Date().getTime();
};
this.broadcastRender = function(scope, arg1, arg2) {
this.setTimeRenderStart(scope);
scope.$broadcast('render', arg1, arg2);
this.setTimeRenderEnd(scope);
if ($rootScope.profilingEnabled) {
$rootScope.performance.panels.push({
panelId: scope.panel.id,
query: scope.timing.queryEnd - scope.timing.queryStart,
render: scope.timing.renderEnd - scope.timing.renderStart,
});
}
};
this.updateTimeRange = function(scope) {
scope.range = timeSrv.timeRange();
scope.rangeRaw = timeSrv.timeRange(false);
this.applyPanelTimeOverrides(scope);
if (scope.panel.maxDataPoints) {
scope.resolution = scope.panel.maxDataPoints;
}
else {
scope.resolution = Math.ceil($(window).width() * (scope.panel.span / 12));
}
var panelInterval = scope.panel.interval;
var datasourceInterval = (scope.datasource || {}).interval;
scope.interval = kbn.calculateInterval(scope.range, scope.resolution, panelInterval || datasourceInterval);
};
this.applyPanelTimeOverrides = function(scope) {
scope.panelMeta.timeInfo = '';
// check panel time overrrides
if (scope.panel.timeFrom) {
var timeFromInfo = rangeUtil.describeTextRange(scope.panel.timeFrom);
if (timeFromInfo.invalid) {
scope.panelMeta.timeFromInfo = 'invalid time override';
return;
}
if (_.isString(scope.rangeRaw.from)) {
var timeFromDate = dateMath.parse(timeFromInfo.from);
scope.panelMeta.timeInfo = timeFromInfo.display;
scope.rangeRaw.from = timeFromInfo.from;
scope.rangeRaw.to = timeFromInfo.to;
scope.range.from = timeFromDate;
}
}
if (scope.panel.timeShift) {
var timeShiftInfo = rangeUtil.describeTextRange(scope.panel.timeShift);
if (timeShiftInfo.invalid) {
scope.panelMeta.timeInfo = 'invalid timeshift';
return;
}
var timeShift = '-' + scope.panel.timeShift;
scope.panelMeta.timeInfo += ' timeshift ' + timeShift;
scope.range.from = dateMath.parseDateMath(timeShift, scope.range.from, false);
scope.range.to = dateMath.parseDateMath(timeShift, scope.range.to, true);
scope.rangeRaw = scope.range;
}
if (scope.panel.hideTimeOverride) {
scope.panelMeta.timeInfo = '';
}
};
this.issueMetricQuery = function(scope, datasource) {
if (!scope.panel.targets || scope.panel.targets.length === 0) {
return $q.when([]);
}
var metricsQuery = {
range: scope.range,
rangeRaw: scope.rangeRaw,
interval: scope.interval,
targets: scope.panel.targets,
format: scope.panel.renderer === 'png' ? 'png' : 'json',
maxDataPoints: scope.resolution,
scopedVars: scope.panel.scopedVars,
cacheTimeout: scope.panel.cacheTimeout
};
this.setTimeQueryStart(scope);
return datasource.query(metricsQuery).then(function(results) {
self.setTimeQueryEnd(scope);
if (scope.dashboard.snapshot) {
scope.panel.snapshotData = results;
}
return results;
});
};
});
});
......@@ -29,7 +29,6 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
var panel = ctrl.panel;
var data, annotations;
var sortedSeries;
var graphHeight;
var legendSideLastValue = null;
var rootScope = scope.$root;
......@@ -67,14 +66,13 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
function getLegendHeight(panelHeight) {
if (!panel.legend.show || panel.legend.rightSide) {
return 0;
return 2;
}
if (panel.legend.alignAsTable) {
var legendSeries = _.filter(data, function(series) {
return series.hideFromLegend(panel.legend) === false;
});
console.log(legendSeries.length);
var total = 23 + (22 * legendSeries.length);
return Math.min(total, Math.floor(panelHeight/2));
} else {
......@@ -84,16 +82,8 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
function setElementHeight() {
try {
graphHeight = ctrl.height || panel.height || ctrl.row.height;
if (_.isString(graphHeight)) {
graphHeight = parseInt(graphHeight.replace('px', ''), 10);
}
graphHeight -= 5; // padding
graphHeight -= panel.title ? 25 : 5; // subtract panel title bar
graphHeight = graphHeight - getLegendHeight(graphHeight); // subtract one line legend
elem.css('height', graphHeight + 'px');
var height = ctrl.height - getLegendHeight(ctrl.height);
elem.css('height', height + 'px');
return true;
} catch(e) { // IE throws errors sometimes
......
......@@ -142,6 +142,7 @@ function (angular, _, $) {
}
}
var seriesShown = 0;
for (i = 0; i < seriesList.length; i++) {
var series = seriesList[i];
......@@ -175,17 +176,19 @@ function (angular, _, $) {
html += '</div>';
$container.append($(html));
seriesShown++;
}
var legendContainerHeight = $container.parent().height();
var legendHeight = $container.height();
if (panel.legend.alignAsTable) {
var maxHeight = ctrl.height;
if (panel.legend.rightSide && legendHeight >= legendContainerHeight) {
$container.toggleClass('graph-legend-fixed-height', true);
if (!panel.legend.rightSide) {
maxHeight = maxHeight/2;
}
if (panel.legend.rightSide) {
$container.css("height", scope.ctrl.height || scope.ctrl.panel.height || scope.ctrl.row.height);
var topPadding = 6;
$container.css("height", maxHeight - topPadding);
} else {
$container.css("height", "");
}
......
......@@ -241,7 +241,6 @@ class SingleStatCtrl extends MetricsPanelCtrl {
var panel = ctrl.panel;
var templateSrv = this.templateSrv;
var data, linkInfo;
var elemHeight;
var $panelContainer = elem.find('.panel-container');
// change elem to singlestat panel
elem = elem.find('.singlestat-panel');
......@@ -253,21 +252,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
});
function setElementHeight() {
try {
elemHeight = ctrl.height || panel.height || ctrl.row.height;
if (_.isString(elemHeight)) {
elemHeight = parseInt(elemHeight.replace('px', ''), 10);
}
elemHeight -= 5; // padding
elemHeight -= panel.title ? 24 : 9; // subtract panel title bar
elem.css('height', elemHeight + 'px');
return true;
} catch (e) { // IE throws errors sometimes
return false;
}
elem.css('height', ctrl.height + 'px');
}
function applyColoringThresholds(value, valueString) {
......@@ -306,7 +291,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
function addSparkline() {
var width = elem.width() + 20;
var height = elemHeight;
var height = ctrl.height;
var plotCanvas = $('<div></div>');
var plotCss: any = {};
......
......@@ -22,8 +22,11 @@
}
.graph-legend {
@include clearfix();
margin: 0 $spacer;
text-align: center;
width: calc(100% - $spacer);
padding-top: 6px;
.popover-content {
padding: 0;
......@@ -71,7 +74,6 @@
float: left;
white-space: nowrap;
padding-left: 10px;
padding-top: 6px;
}
.graph-legend-value {
......@@ -79,11 +81,9 @@
}
.graph-legend-table {
width: 100%;
margin-top: 4px;
overflow-y: scroll;
.graph-legend-series {
display: table-row;
.graph-legend-series { display: table-row;
float: none;
padding-left: 0;
&.pull-right {
......@@ -314,6 +314,3 @@
font-size: 12px;
}
.graph-legend-fixed-height {
overflow-y: scroll;
}
......@@ -179,7 +179,7 @@
top: 38%;
right: 6px;
font-size: 14px;
color: $link-color;
color: $text-color-weak;
}
.sidemenu-org-avatar,
......
......@@ -142,7 +142,7 @@ div.flot-text {
}
.panel-title-container {
min-height: 5px;
min-height: 9px;
padding-top: 4px;
cursor: pointer;
}
......
......@@ -54,7 +54,7 @@ define([
config.panels['test'] = {info: {}};
self.ctrl = $controller(Ctrl, {$scope: self.scope}, {
panel: self.panel, dashboard: self.dashboard
panel: self.panel, dashboard: self.dashboard, row: {}
});
});
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment