mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
fix(panel): fixes for panel height and alignment management and scrollable legends, closes #4266
This commit is contained in:
@@ -129,7 +129,6 @@ function (angular, _, $) {
|
|||||||
|
|
||||||
ctrl.editMode = false;
|
ctrl.editMode = false;
|
||||||
ctrl.fullscreen = false;
|
ctrl.fullscreen = false;
|
||||||
delete ctrl.height;
|
|
||||||
|
|
||||||
this.$scope.appEvent('panel-fullscreen-exit', {panelId: ctrl.panel.id});
|
this.$scope.appEvent('panel-fullscreen-exit', {panelId: ctrl.panel.id});
|
||||||
|
|
||||||
@@ -147,13 +146,9 @@ function (angular, _, $) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DashboardViewState.prototype.enterFullscreen = function(panelScope) {
|
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;
|
var ctrl = panelScope.ctrl;
|
||||||
|
|
||||||
ctrl.editMode = this.state.edit && this.$scope.dashboardMeta.canEdit;
|
ctrl.editMode = this.state.edit && this.$scope.dashboardMeta.canEdit;
|
||||||
ctrl.height = ctrl.editMode ? editHeight : fullscreenHeight;
|
|
||||||
ctrl.fullscreen = true;
|
ctrl.fullscreen = true;
|
||||||
|
|
||||||
this.oldTimeRange = ctrl.range;
|
this.oldTimeRange = ctrl.range;
|
||||||
|
@@ -3,6 +3,11 @@
|
|||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
const TITLE_HEIGHT = 25;
|
||||||
|
const EMPTY_TITLE_HEIGHT = 9;
|
||||||
|
const PANEL_PADDING = 5;
|
||||||
|
|
||||||
export class PanelCtrl {
|
export class PanelCtrl {
|
||||||
panel: any;
|
panel: any;
|
||||||
@@ -20,6 +25,9 @@ export class PanelCtrl {
|
|||||||
inspector: any;
|
inspector: any;
|
||||||
editModeInitiated: boolean;
|
editModeInitiated: boolean;
|
||||||
editorHelpIndex: number;
|
editorHelpIndex: number;
|
||||||
|
editMode: any;
|
||||||
|
height: any;
|
||||||
|
containerHeight: any;
|
||||||
|
|
||||||
constructor($scope, $injector) {
|
constructor($scope, $injector) {
|
||||||
this.$injector = $injector;
|
this.$injector = $injector;
|
||||||
@@ -34,6 +42,7 @@ export class PanelCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$scope.$on("refresh", () => this.refresh());
|
$scope.$on("refresh", () => this.refresh());
|
||||||
|
$scope.$on("render", () => this.calculatePanelHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@@ -111,6 +120,23 @@ export class PanelCtrl {
|
|||||||
return this.dashboard.meta.fullscreen && !this.fullscreen;
|
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?) {
|
broadcastRender(arg1?, arg2?) {
|
||||||
this.$scope.$broadcast('render', arg1, arg2);
|
this.$scope.$broadcast('render', arg1, arg2);
|
||||||
}
|
}
|
||||||
@@ -172,9 +198,9 @@ export class PanelCtrl {
|
|||||||
shareScope.dashboard = this.dashboard;
|
shareScope.dashboard = this.dashboard;
|
||||||
|
|
||||||
this.publishAppEvent('show-modal', {
|
this.publishAppEvent('show-modal', {
|
||||||
src: 'public/app/features/dashboard/partials/shareModal.html',
|
src: 'public/app/features/dashboard/partials/shareModal.html',
|
||||||
scope: shareScope
|
scope: shareScope
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
openInspector() {
|
openInspector() {
|
||||||
|
@@ -65,8 +65,8 @@ module.directive('grafanaPanel', function() {
|
|||||||
link: function(scope, elem) {
|
link: function(scope, elem) {
|
||||||
var panelContainer = elem.find('.panel-container');
|
var panelContainer = elem.find('.panel-container');
|
||||||
var ctrl = scope.ctrl;
|
var ctrl = scope.ctrl;
|
||||||
scope.$watchGroup(['ctrl.fullscreen', 'ctrl.height', 'ctrl.panel.height', 'ctrl.row.height'], function() {
|
scope.$watchGroup(['ctrl.fullscreen', 'ctrl.containerHeight'], function() {
|
||||||
panelContainer.css({ minHeight: ctrl.height || ctrl.panel.height || ctrl.row.height, display: 'block' });
|
panelContainer.css({minHeight: ctrl.containerHeight});
|
||||||
elem.toggleClass('panel-fullscreen', ctrl.fullscreen ? true : false);
|
elem.toggleClass('panel-fullscreen', ctrl.fullscreen ? true : false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,135 +0,0 @@
|
|||||||
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 panel = ctrl.panel;
|
||||||
var data, annotations;
|
var data, annotations;
|
||||||
var sortedSeries;
|
var sortedSeries;
|
||||||
var graphHeight;
|
|
||||||
var legendSideLastValue = null;
|
var legendSideLastValue = null;
|
||||||
var rootScope = scope.$root;
|
var rootScope = scope.$root;
|
||||||
|
|
||||||
@@ -67,14 +66,13 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
|
|||||||
|
|
||||||
function getLegendHeight(panelHeight) {
|
function getLegendHeight(panelHeight) {
|
||||||
if (!panel.legend.show || panel.legend.rightSide) {
|
if (!panel.legend.show || panel.legend.rightSide) {
|
||||||
return 0;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel.legend.alignAsTable) {
|
if (panel.legend.alignAsTable) {
|
||||||
var legendSeries = _.filter(data, function(series) {
|
var legendSeries = _.filter(data, function(series) {
|
||||||
return series.hideFromLegend(panel.legend) === false;
|
return series.hideFromLegend(panel.legend) === false;
|
||||||
});
|
});
|
||||||
console.log(legendSeries.length);
|
|
||||||
var total = 23 + (22 * legendSeries.length);
|
var total = 23 + (22 * legendSeries.length);
|
||||||
return Math.min(total, Math.floor(panelHeight/2));
|
return Math.min(total, Math.floor(panelHeight/2));
|
||||||
} else {
|
} else {
|
||||||
@@ -84,16 +82,8 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
|
|||||||
|
|
||||||
function setElementHeight() {
|
function setElementHeight() {
|
||||||
try {
|
try {
|
||||||
graphHeight = ctrl.height || panel.height || ctrl.row.height;
|
var height = ctrl.height - getLegendHeight(ctrl.height);
|
||||||
if (_.isString(graphHeight)) {
|
elem.css('height', height + 'px');
|
||||||
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');
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch(e) { // IE throws errors sometimes
|
} catch(e) { // IE throws errors sometimes
|
||||||
|
@@ -142,6 +142,7 @@ function (angular, _, $) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var seriesShown = 0;
|
||||||
for (i = 0; i < seriesList.length; i++) {
|
for (i = 0; i < seriesList.length; i++) {
|
||||||
var series = seriesList[i];
|
var series = seriesList[i];
|
||||||
|
|
||||||
@@ -175,17 +176,19 @@ function (angular, _, $) {
|
|||||||
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
$container.append($(html));
|
$container.append($(html));
|
||||||
|
|
||||||
|
seriesShown++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var legendContainerHeight = $container.parent().height();
|
if (panel.legend.alignAsTable) {
|
||||||
var legendHeight = $container.height();
|
var maxHeight = ctrl.height;
|
||||||
|
|
||||||
if (panel.legend.rightSide && legendHeight >= legendContainerHeight) {
|
if (!panel.legend.rightSide) {
|
||||||
$container.toggleClass('graph-legend-fixed-height', true);
|
maxHeight = maxHeight/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel.legend.rightSide) {
|
var topPadding = 6;
|
||||||
$container.css("height", scope.ctrl.height || scope.ctrl.panel.height || scope.ctrl.row.height);
|
$container.css("height", maxHeight - topPadding);
|
||||||
} else {
|
} else {
|
||||||
$container.css("height", "");
|
$container.css("height", "");
|
||||||
}
|
}
|
||||||
|
@@ -241,7 +241,6 @@ class SingleStatCtrl extends MetricsPanelCtrl {
|
|||||||
var panel = ctrl.panel;
|
var panel = ctrl.panel;
|
||||||
var templateSrv = this.templateSrv;
|
var templateSrv = this.templateSrv;
|
||||||
var data, linkInfo;
|
var data, linkInfo;
|
||||||
var elemHeight;
|
|
||||||
var $panelContainer = elem.find('.panel-container');
|
var $panelContainer = elem.find('.panel-container');
|
||||||
// change elem to singlestat panel
|
// change elem to singlestat panel
|
||||||
elem = elem.find('.singlestat-panel');
|
elem = elem.find('.singlestat-panel');
|
||||||
@@ -253,21 +252,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function setElementHeight() {
|
function setElementHeight() {
|
||||||
try {
|
elem.css('height', ctrl.height + 'px');
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyColoringThresholds(value, valueString) {
|
function applyColoringThresholds(value, valueString) {
|
||||||
@@ -306,7 +291,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
|
|||||||
|
|
||||||
function addSparkline() {
|
function addSparkline() {
|
||||||
var width = elem.width() + 20;
|
var width = elem.width() + 20;
|
||||||
var height = elemHeight;
|
var height = ctrl.height;
|
||||||
|
|
||||||
var plotCanvas = $('<div></div>');
|
var plotCanvas = $('<div></div>');
|
||||||
var plotCss: any = {};
|
var plotCss: any = {};
|
||||||
|
@@ -22,8 +22,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.graph-legend {
|
.graph-legend {
|
||||||
|
@include clearfix();
|
||||||
margin: 0 $spacer;
|
margin: 0 $spacer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
width: calc(100% - $spacer);
|
||||||
|
padding-top: 6px;
|
||||||
|
|
||||||
.popover-content {
|
.popover-content {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -71,7 +74,6 @@
|
|||||||
float: left;
|
float: left;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-top: 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph-legend-value {
|
.graph-legend-value {
|
||||||
@@ -79,11 +81,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.graph-legend-table {
|
.graph-legend-table {
|
||||||
width: 100%;
|
overflow-y: scroll;
|
||||||
margin-top: 4px;
|
|
||||||
|
|
||||||
.graph-legend-series {
|
.graph-legend-series { display: table-row;
|
||||||
display: table-row;
|
|
||||||
float: none;
|
float: none;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
&.pull-right {
|
&.pull-right {
|
||||||
@@ -314,6 +314,3 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph-legend-fixed-height {
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
@@ -179,7 +179,7 @@
|
|||||||
top: 38%;
|
top: 38%;
|
||||||
right: 6px;
|
right: 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: $link-color;
|
color: $text-color-weak;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidemenu-org-avatar,
|
.sidemenu-org-avatar,
|
||||||
|
@@ -142,7 +142,7 @@ div.flot-text {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.panel-title-container {
|
.panel-title-container {
|
||||||
min-height: 5px;
|
min-height: 9px;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@@ -54,7 +54,7 @@ define([
|
|||||||
|
|
||||||
config.panels['test'] = {info: {}};
|
config.panels['test'] = {info: {}};
|
||||||
self.ctrl = $controller(Ctrl, {$scope: self.scope}, {
|
self.ctrl = $controller(Ctrl, {$scope: self.scope}, {
|
||||||
panel: self.panel, dashboard: self.dashboard
|
panel: self.panel, dashboard: self.dashboard, row: {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user