|
@@ -1,8 +1,8 @@
|
|
|
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> {
|
|
|
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 backgroundColor = theme.type === GrafanaThemeType.Light ? 'rgb(230,230,230)' : theme.colors.dark3;
|
|
|
|
|
|
|
+ const autoProps = calculateGaugeAutoProps(width, height, value.title);
|
|
|
|
|
+ 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> {
|
|
|
},
|
|
},
|
|
|
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> {
|
|
|
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> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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: `${Math.min(width, height * 1.3)}px`,
|
|
|
|
|
- margin: 'auto',
|
|
|
|
|
- marginTop: '-8px',
|
|
|
|
|
|
|
+ width: '100%',
|
|
|
|
|
+ height: '100%',
|
|
|
|
|
+ display: 'flex',
|
|
|
|
|
+ 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> {
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+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,
|
|
|
|
|
+ };
|
|
|
|
|
+}
|