Commit 575fe7ad by Torkel Ödegaard Committed by GitHub

Gauge: Better handling of gauge repeat title (#16886)

* Gauge: began looking at gauge title

* Gauge: title improvements

* Minor progres

* Gauge: title improvements, still needs more tweaking

* Gauge: title is starting to work ok

* Use selectThemeVariant

* Remove unused type
parent d881976c
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import $ from 'jquery'; import $ from 'jquery';
import { css } from 'emotion';
import { getColorFromHexRgbOrName } from '../../utils'; import { getColorFromHexRgbOrName } from '../../utils';
import { DisplayValue, Threshold, GrafanaThemeType, Themeable } from '../../types'; import { DisplayValue, Threshold, Themeable } from '../../types';
import { selectThemeVariant } from '../../themes';
export interface Props extends Themeable { export interface Props extends Themeable {
height: number; height: number;
...@@ -64,13 +64,21 @@ export class Gauge extends PureComponent<Props> { ...@@ -64,13 +64,21 @@ export class Gauge extends PureComponent<Props> {
draw() { draw() {
const { maxValue, minValue, showThresholdLabels, showThresholdMarkers, width, height, theme, value } = this.props; const { maxValue, minValue, showThresholdLabels, showThresholdMarkers, width, height, theme, value } = this.props;
const dimension = Math.min(width, height * 1.3); const autoProps = calculateGaugeAutoProps(width, height, value.title);
const backgroundColor = theme.type === GrafanaThemeType.Light ? 'rgb(230,230,230)' : theme.colors.dark3; const dimension = Math.min(width, autoProps.gaugeHeight);
const backgroundColor = selectThemeVariant(
{
dark: theme.colors.dark3,
light: '#e6e6e6',
},
theme.type
);
const gaugeWidthReduceRatio = showThresholdLabels ? 1.5 : 1; const gaugeWidthReduceRatio = showThresholdLabels ? 1.5 : 1;
const gaugeWidth = Math.min(dimension / 6, 60) / gaugeWidthReduceRatio; const gaugeWidth = Math.min(dimension / 6, 40) / gaugeWidthReduceRatio;
const thresholdMarkersWidth = gaugeWidth / 5; const thresholdMarkersWidth = gaugeWidth / 5;
const fontSize = Math.min(dimension / 5, 100) * (value.text !== null ? this.getFontScale(value.text.length) : 1); const fontSize = Math.min(dimension / 5.5, 100) * (value.text !== null ? this.getFontScale(value.text.length) : 1);
const thresholdLabelFontSize = fontSize / 2.5; const thresholdLabelFontSize = fontSize / 2.5;
const options: any = { const options: any = {
...@@ -86,7 +94,7 @@ export class Gauge extends PureComponent<Props> { ...@@ -86,7 +94,7 @@ export class Gauge extends PureComponent<Props> {
}, },
frame: { show: false }, frame: { show: false },
label: { show: false }, label: { show: false },
layout: { margin: 0, thresholdWidth: 0 }, layout: { margin: 0, thresholdWidth: 0, vMargin: 0 },
cell: { border: { width: 0 } }, cell: { border: { width: 0 } },
threshold: { threshold: {
values: this.getFormattedThresholds(), values: this.getFormattedThresholds(),
...@@ -103,14 +111,17 @@ export class Gauge extends PureComponent<Props> { ...@@ -103,14 +111,17 @@ export class Gauge extends PureComponent<Props> {
formatter: () => { formatter: () => {
return value.text; return value.text;
}, },
font: { size: fontSize, family: '"Helvetica Neue", Helvetica, Arial, sans-serif' }, font: { size: fontSize, family: theme.typography.fontFamily.sansSerif },
}, },
show: true, show: true,
}, },
}, },
}; };
const plotSeries = { data: [[0, value.numeric]] }; const plotSeries = {
data: [[0, value.numeric]],
label: value.title,
};
try { try {
$.plot(this.canvasElement, [plotSeries], options); $.plot(this.canvasElement, [plotSeries], options);
...@@ -120,26 +131,36 @@ export class Gauge extends PureComponent<Props> { ...@@ -120,26 +131,36 @@ export class Gauge extends PureComponent<Props> {
} }
render() { render() {
const { height, width, value } = this.props; const { width, value, height } = this.props;
const autoProps = calculateGaugeAutoProps(width, height, value.title);
return ( return (
<div <div
style={{ style={{
height: `${Math.min(height, width * 1.3)}px`, width: '100%',
width: `${Math.min(width, height * 1.3)}px`, height: '100%',
margin: 'auto', display: 'flex',
marginTop: '-8px', flexDirection: 'column',
justifyContent: 'center',
overflow: 'hidden',
}} }}
ref={element => (this.canvasElement = element)}
> >
{value.title && ( <div
style={{ height: `${autoProps.gaugeHeight}px`, width: '100%' }}
ref={element => (this.canvasElement = element)}
/>
{autoProps.showLabel && (
<div <div
className={css({ style={{
textAlign: 'center', textAlign: 'center',
bottom: -8, fontSize: autoProps.titleFontSize,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
position: 'relative',
width: '100%', width: '100%',
position: 'absolute', top: '-4px',
})} }}
> >
{value.title} {value.title}
</div> </div>
...@@ -148,3 +169,23 @@ export class Gauge extends PureComponent<Props> { ...@@ -148,3 +169,23 @@ export class Gauge extends PureComponent<Props> {
); );
} }
} }
interface GaugeAutoProps {
titleFontSize: number;
gaugeHeight: number;
showLabel: boolean;
}
function calculateGaugeAutoProps(width: number, height: number, title: string | undefined): GaugeAutoProps {
const showLabel = title !== null && title !== undefined;
const titleFontSize = Math.min((width * 0.15) / 1.5, 20); // 20% of height * line-height, max 40px
const titleHeight = titleFontSize * 1.5;
const availableHeight = showLabel ? height - titleHeight : height;
const gaugeHeight = Math.min(availableHeight * 0.7, width);
return {
showLabel,
gaugeHeight,
titleFontSize,
};
}
...@@ -594,6 +594,8 @@ ...@@ -594,6 +594,8 @@
span.css("position", "absolute"); span.css("position", "absolute");
span.css("top", y + "px"); span.css("top", y + "px");
span.css("white-space", "nowrap");
if (textOptions.font.size) { if (textOptions.font.size) {
span.css("font-size", textOptions.font.size + "px"); span.css("font-size", textOptions.font.size + "px");
} }
...@@ -935,7 +937,7 @@ ...@@ -935,7 +937,7 @@
} }
}, },
values: [ values: [
] ]
} }
} }
...@@ -951,3 +953,4 @@ ...@@ -951,3 +953,4 @@
}); });
})(jQuery); })(jQuery);
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