Commit 0de9c038 by Peter Holmberg

Merge branch 'gauge-multi-series' into bar-gauge-poc

parents 5f56a07a c7bb563c
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"links": [],
"panels": [
{
"datasource": "gdev-testdata",
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 0
},
"id": 6,
"links": [],
"options-gauge": {
"decimals": 0,
"maxValue": 100,
"minValue": 0,
"options": {
"decimals": 0,
"maxValue": 100,
"minValue": 0,
"prefix": "",
"showThresholdLabels": false,
"showThresholdMarkers": true,
"stat": "avg",
"suffix": "",
"thresholds": [],
"unit": "none",
"valueMappings": []
},
"prefix": "",
"showThresholdLabels": false,
"showThresholdMarkers": true,
"stat": "avg",
"suffix": "",
"thresholds": [
{
"color": "#1F78C1",
"index": 5,
"value": 96.875
},
{
"color": "#E24D42",
"index": 4,
"value": 93.75
},
{
"color": "#EF843C",
"index": 3,
"value": 87.5
},
{
"color": "#6ED0E0",
"index": 2,
"value": 75
},
{
"color": "#EAB839",
"index": 1,
"value": 50
},
{
"color": "#7EB26D",
"index": 0,
"value": null
}
],
"unit": "none",
"valueMappings": [
{
"from": "50",
"id": 1,
"operator": "",
"text": "Hello :) ",
"to": "90",
"type": 2,
"value": ""
}
]
},
"targets": [
{
"refId": "A",
"scenarioId": "random_walk"
},
{
"refId": "B",
"scenarioId": "random_walk"
},
{
"refId": "C",
"scenarioId": "random_walk"
},
{
"refId": "D",
"scenarioId": "random_walk"
},
{
"refId": "E",
"scenarioId": "random_walk"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Horizontal with range variable",
"type": "gauge"
},
{
"datasource": "gdev-testdata",
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 8
},
"id": 2,
"links": [],
"options-gauge": {
"decimals": 0,
"maxValue": 100,
"minValue": 0,
"options": {
"decimals": 0,
"maxValue": 100,
"minValue": 0,
"prefix": "",
"showThresholdLabels": false,
"showThresholdMarkers": true,
"stat": "avg",
"suffix": "",
"thresholds": [],
"unit": "none",
"valueMappings": []
},
"prefix": "",
"showThresholdLabels": false,
"showThresholdMarkers": true,
"stat": "avg",
"suffix": "",
"thresholds": [
{
"color": "#EAB839",
"index": 1,
"value": 50
},
{
"color": "#7EB26D",
"index": 0,
"value": null
}
],
"unit": "none",
"valueMappings": []
},
"targets": [
{
"refId": "A",
"scenarioId": "random_walk"
},
{
"refId": "B",
"scenarioId": "random_walk"
},
{
"refId": "C",
"scenarioId": "random_walk"
},
{
"refId": "D",
"scenarioId": "random_walk"
},
{
"refId": "E",
"scenarioId": "random_walk"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Repeat horizontal",
"type": "gauge"
},
{
"datasource": "gdev-testdata",
"gridPos": {
"h": 14,
"w": 5,
"x": 0,
"y": 16
},
"id": 4,
"links": [],
"options-gauge": {
"decimals": 0,
"maxValue": "200",
"minValue": 0,
"options": {
"decimals": 0,
"maxValue": 100,
"minValue": 0,
"prefix": "",
"showThresholdLabels": false,
"showThresholdMarkers": true,
"stat": "avg",
"suffix": "",
"thresholds": [],
"unit": "none",
"valueMappings": []
},
"prefix": "",
"showThresholdLabels": false,
"showThresholdMarkers": true,
"stat": "max",
"suffix": "",
"thresholds": [
{
"color": "#6ED0E0",
"index": 2,
"value": 75
},
{
"color": "#EAB839",
"index": 1,
"value": 50
},
{
"color": "#7EB26D",
"index": 0,
"value": null
}
],
"unit": "none",
"valueMappings": []
},
"targets": [
{
"refId": "A",
"scenarioId": "random_walk"
},
{
"refId": "B",
"scenarioId": "random_walk"
},
{
"refId": "C",
"scenarioId": "random_walk"
},
{
"refId": "D",
"scenarioId": "random_walk"
},
{
"refId": "E",
"scenarioId": "random_walk"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Vertical",
"type": "gauge"
}
],
"schemaVersion": 17,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
"time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
},
"timezone": "",
"title": "Multi series gauges",
"uid": "szkuR1umk",
"version": 7
}
......@@ -173,17 +173,15 @@ export class Gauge extends PureComponent<Props> {
const { height, width } = this.props;
return (
<div className="singlestat-panel">
<div
style={{
height: `${height * 0.9}px`,
width: `${Math.min(width, height * 1.3)}px`,
top: '10px',
margin: 'auto',
}}
ref={element => (this.canvasElement = element)}
/>
</div>
<div
style={{
height: `${height * 0.9}px`,
width: `${Math.min(width, height * 1.3)}px`,
top: '10px',
margin: 'auto',
}}
ref={element => (this.canvasElement = element)}
/>
);
}
}
......@@ -15,6 +15,7 @@ export const provideConfig = (component: React.ComponentType<any>) => {
export const getCurrentThemeName = () =>
config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark;
export const getCurrentTheme = () => getTheme(getCurrentThemeName());
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
......
......@@ -9,6 +9,8 @@ import { FormField, PanelEditorProps } from '@grafana/ui';
import { GaugeOptions } from './types';
export class GaugeOptionsBox extends PureComponent<PanelEditorProps<GaugeOptions>> {
labelWidth = 8;
onToggleThresholdLabels = () =>
this.props.onChange({ ...this.props.options, showThresholdLabels: !this.props.options.showThresholdLabels });
......@@ -25,17 +27,17 @@ export class GaugeOptionsBox extends PureComponent<PanelEditorProps<GaugeOptions
return (
<PanelOptionsGroup title="Gauge">
<FormField label="Min value" labelWidth={8} onChange={this.onMinValueChange} value={minValue} />
<FormField label="Max value" labelWidth={8} onChange={this.onMaxValueChange} value={maxValue} />
<FormField label="Min value" labelWidth={this.labelWidth} onChange={this.onMinValueChange} value={minValue} />
<FormField label="Max value" labelWidth={this.labelWidth} onChange={this.onMaxValueChange} value={maxValue} />
<Switch
label="Show labels"
labelClass="width-8"
labelClass={`width-${this.labelWidth}`}
checked={showThresholdLabels}
onChange={this.onToggleThresholdLabels}
/>
<Switch
label="Show markers"
labelClass="width-8"
labelClass={`width-${this.labelWidth}`}
checked={showThresholdMarkers}
onChange={this.onToggleThresholdMarkers}
/>
......
......@@ -2,62 +2,124 @@
import React, { PureComponent } from 'react';
// Services & Utils
import { processTimeSeries, ThemeContext } from '@grafana/ui';
import { processTimeSeries } from '@grafana/ui';
import { config } from 'app/core/config';
// Components
import { Gauge } from '@grafana/ui';
// Types
import { GaugeOptions } from './types';
import { PanelProps, NullValueMode, TimeSeriesValue } from '@grafana/ui/src/types';
import { PanelProps, NullValueMode } from '@grafana/ui/src/types';
interface Props extends PanelProps<GaugeOptions> {}
export class GaugePanel extends PureComponent<Props> {
render() {
const { panelData, width, height, onInterpolate, options } = this.props;
const { valueOptions } = options;
renderMultipleGauge(timeSeries) {
const { options, height, width } = this.props;
const { stat } = options.valueOptions;
return timeSeries.map((series, index) => {
const singleStatWidth = 1 / timeSeries.length * 100;
const singleStatHeight = 1 / timeSeries.length * 100;
const repeatingGaugeWidth = Math.floor(width / timeSeries.length) - 10; // make Gauge slightly smaller than panel.
const repeatingGaugeHeight = Math.floor(height / timeSeries.length) - 10;
const horizontalPanels = {
display: 'inline-block',
height: height,
width: `${singleStatWidth}%`,
};
const verticalPanels = {
display: 'block',
width: width,
height: `${singleStatHeight}%`,
};
let style = {};
let gaugeWidth = width;
let gaugeHeight = height;
if (width > height) {
style = horizontalPanels;
gaugeWidth = repeatingGaugeWidth;
} else if (height > width) {
style = verticalPanels;
gaugeHeight = repeatingGaugeHeight;
}
const value = stat !== 'name' ? series.stats[stat] : series.label;
return (
<div className="singlestat-panel" key={`${timeSeries.label}-${index}`} style={style}>
{this.renderGauge(value, gaugeWidth, gaugeHeight)}
<div style={{ textAlign: 'center' }}>{series.label}</div>
</div>
);
});
}
renderGauge(value, width, height) {
const { onInterpolate, options } = this.props;
const { valueOptions } = options;
const prefix = onInterpolate(valueOptions.prefix);
const suffix = onInterpolate(valueOptions.suffix);
let value: TimeSeriesValue;
return (
<Gauge
value={value}
width={width}
height={height}
prefix={prefix}
suffix={suffix}
unit={valueOptions.unit}
decimals={valueOptions.decimals}
thresholds={options.thresholds}
valueMappings={options.valueMappings}
showThresholdLabels={options.showThresholdLabels}
showThresholdMarkers={options.showThresholdMarkers}
minValue={options.minValue}
maxValue={options.maxValue}
theme={config.theme}
/>
);
}
renderSingleGauge(timeSeries) {
const { options, width, height } = this.props;
const value = timeSeries[0].stats[options.valueOptions.stat];
return <div className="singlestat-panel">{this.renderGauge(value, width, height)}</div>;
}
renderGaugeWithTableData(panelData) {
const { width, height } = this.props;
const firstTableDataValue = panelData.tableData.rows[0].find(prop => prop > 0);
return <div className="singlestat-panel">{this.renderGauge(firstTableDataValue, width, height)}</div>;
}
render() {
const { panelData } = this.props;
if (panelData.timeSeries) {
const vmSeries = processTimeSeries({
const timeSeries = processTimeSeries({
timeSeries: panelData.timeSeries,
nullValueMode: NullValueMode.Null,
});
if (vmSeries[0]) {
value = vmSeries[0].stats[valueOptions.stat];
if (timeSeries.length > 1) {
return this.renderMultipleGauge(timeSeries);
} else if (timeSeries.length > 0) {
return this.renderSingleGauge(timeSeries);
} else {
value = null;
return null;
}
} else if (panelData.tableData) {
value = panelData.tableData.rows[0].find(prop => prop > 0);
return this.renderGaugeWithTableData(panelData);
} else {
return <div className="singlestat-panel">No time series data available</div>;
}
return (
<ThemeContext.Consumer>
{theme => (
<Gauge
value={value}
width={width}
height={height}
prefix={prefix}
suffix={suffix}
unit={valueOptions.unit}
decimals={valueOptions.decimals}
thresholds={options.thresholds}
valueMappings={options.valueMappings}
showThresholdLabels={options.showThresholdLabels}
showThresholdMarkers={options.showThresholdMarkers}
minValue={options.minValue}
maxValue={options.maxValue}
theme={theme}
/>
)}
</ThemeContext.Consumer>
);
}
}
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