Files
grafana/public/app/viz/Gauge.tsx

134 lines
3.6 KiB
TypeScript
Raw Normal View History

2018-11-08 16:40:53 +01:00
import React, { PureComponent } from 'react';
import $ from 'jquery';
2018-11-09 16:37:09 +01:00
import { withSize } from 'react-sizeme';
2018-11-08 16:40:53 +01:00
import { TimeSeriesVMs } from 'app/types';
import config from '../core/config';
interface Props {
timeSeries: TimeSeriesVMs;
minValue: number;
maxValue: number;
showThresholdMarkers?: boolean;
thresholds?: number[];
showThresholdLables?: boolean;
2018-11-09 16:37:09 +01:00
size?: { width: number; height: number };
2018-11-08 16:40:53 +01:00
}
2018-11-09 16:37:09 +01:00
const colors = ['rgba(50, 172, 45, 0.97)', 'rgba(237, 129, 40, 0.89)', 'rgba(245, 54, 54, 0.9)'];
2018-11-08 16:40:53 +01:00
export class Gauge extends PureComponent<Props> {
2018-11-09 16:37:09 +01:00
parentElement: any;
canvasElement: any;
2018-11-08 16:40:53 +01:00
static defaultProps = {
minValue: 0,
maxValue: 100,
showThresholdMarkers: true,
showThresholdLables: false,
thresholds: [],
};
componentDidMount() {
this.draw();
}
componentDidUpdate(prevProps: Props) {
2018-11-09 16:37:09 +01:00
this.draw();
2018-11-08 16:40:53 +01:00
}
draw() {
2018-11-09 16:37:09 +01:00
const { maxValue, minValue, showThresholdLables, size, showThresholdMarkers, timeSeries, thresholds } = this.props;
const width = size.width;
const height = size.height;
const dimension = Math.min(width, height * 1.3);
2018-11-08 16:40:53 +01:00
const backgroundColor = config.bootData.user.lightTheme ? 'rgb(230,230,230)' : 'rgb(38,38,38)';
const fontColor = config.bootData.user.lightTheme ? 'rgb(38,38,38)' : 'rgb(230,230,230)';
2018-11-09 16:37:09 +01:00
const fontScale = parseInt('80', 10) / 100;
const fontSize = Math.min(dimension / 5, 100) * fontScale;
const gaugeWidth = Math.min(dimension / 6, 60);
const thresholdMarkersWidth = gaugeWidth / 5;
const thresholdLabelFontSize = fontSize / 2.5;
const formattedThresholds = [];
thresholds.forEach((threshold, index) => {
formattedThresholds.push({
value: threshold,
color: colors[index],
});
});
2018-11-08 16:40:53 +01:00
const options = {
series: {
gauges: {
gauge: {
min: minValue,
max: maxValue,
background: { color: backgroundColor },
border: { color: null },
shadow: { show: false },
2018-11-09 16:37:09 +01:00
width: gaugeWidth,
2018-11-08 16:40:53 +01:00
},
frame: { show: false },
label: { show: false },
layout: { margin: 0, thresholdWidth: 0 },
cell: { border: { width: 0 } },
threshold: {
2018-11-09 16:37:09 +01:00
values: formattedThresholds,
2018-11-08 16:40:53 +01:00
label: {
show: showThresholdLables,
2018-11-09 16:37:09 +01:00
margin: thresholdMarkersWidth + 1,
font: { size: thresholdLabelFontSize },
2018-11-08 16:40:53 +01:00
},
show: showThresholdMarkers,
2018-11-09 16:37:09 +01:00
width: thresholdMarkersWidth,
2018-11-08 16:40:53 +01:00
},
value: {
color: fontColor,
formatter: () => {
return Math.round(timeSeries[0].stats.avg);
},
font: {
2018-11-09 16:37:09 +01:00
size: fontSize,
2018-11-08 16:40:53 +01:00
family: '"Helvetica Neue", Helvetica, Arial, sans-serif',
},
},
show: true,
},
},
};
2018-11-09 16:37:09 +01:00
const plotSeries = {
data: [[0, timeSeries[0].stats.avg]],
};
2018-11-08 16:40:53 +01:00
try {
2018-11-09 16:37:09 +01:00
$.plot(this.canvasElement, [plotSeries], options);
2018-11-08 16:40:53 +01:00
} catch (err) {
console.log('Gauge rendering error', err, options, timeSeries);
}
}
render() {
2018-11-09 16:37:09 +01:00
const { height, width } = this.props.size;
2018-11-08 16:40:53 +01:00
return (
2018-11-09 16:37:09 +01:00
<div className="singlestat-panel" ref={element => (this.parentElement = element)}>
<div
style={{
height: `${height * 0.9}px`,
width: `${Math.min(width, height * 1.3)}px`,
top: '10px',
margin: 'auto',
}}
ref={element => (this.canvasElement = element)}
/>
2018-11-08 16:40:53 +01:00
</div>
);
}
}
2018-11-09 16:37:09 +01:00
export default withSize({ monitorHeight: true })(Gauge);