Commit d65569f5 by Torkel Ödegaard Committed by GitHub

StatPanel: Option showing name instead of value and more (#25676)

* StatPanel: Option showing name instead of value and more

* rename option to textMode

* Move the logic of only showing name if more than one value to gauge and bar gauge panels

* Got tooltip working

* Updated devenv test dashboard

* Added docs for text mode

* Added migration logic

* Update docs/sources/panels/visualizations/stat-panel.md

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Update docs/sources/panels/visualizations/stat-panel.md

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Update docs/sources/panels/visualizations/stat-panel.md

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Update docs/sources/panels/visualizations/stat-panel.md

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Update docs/sources/panels/visualizations/stat-panel.md

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Update docs/sources/panels/visualizations/stat-panel.md

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* Update docs/sources/panels/visualizations/stat-panel.md

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>

* docs fix

* Fixed ts issue

* review changes

Co-authored-by: Diana Payton <52059945+oddlittlebird@users.noreply.github.com>
parent 285c22ee
...@@ -19,22 +19,12 @@ ...@@ -19,22 +19,12 @@
"panels": [ "panels": [
{ {
"datasource": null, "datasource": null,
"gridPos": { "fieldConfig": {
"h": 3,
"w": 24,
"x": 0,
"y": 0
},
"id": 6,
"interval": "6m",
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": ["mean"],
"defaults": { "defaults": {
"color": { "color": {
"mode": "thresholds" "mode": "thresholds"
}, },
"custom": {},
"mappings": [], "mappings": [],
"thresholds": { "thresholds": {
"mode": "absolute", "mode": "absolute",
...@@ -63,17 +53,32 @@ ...@@ -63,17 +53,32 @@
}, },
"unit": "areaM2" "unit": "areaM2"
}, },
"overrides": [], "overrides": []
"values": false
}, },
"gridPos": {
"h": 3,
"w": 24,
"x": 0,
"y": 0
},
"id": 6,
"interval": "6m",
"options": {
"colorMode": "background",
"graphMode": "area", "graphMode": "area",
"justifyMode": "auto", "justifyMode": "auto",
"orientation": "auto", "orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": { "sparkline": {
"show": true "show": true
}
}, },
"pluginVersion": "6.6.0-pre", "textMode": "auto"
},
"pluginVersion": "7.1.0-pre",
"targets": [ "targets": [
{ {
"alias": "__house_locations", "alias": "__house_locations",
...@@ -93,22 +98,12 @@ ...@@ -93,22 +98,12 @@
}, },
{ {
"datasource": null, "datasource": null,
"gridPos": { "fieldConfig": {
"h": 6,
"w": 24,
"x": 0,
"y": 3
},
"id": 10,
"interval": "7m",
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": ["mean"],
"defaults": { "defaults": {
"color": { "color": {
"mode": "thresholds" "mode": "thresholds"
}, },
"custom": {},
"mappings": [], "mappings": [],
"thresholds": { "thresholds": {
"mode": "absolute", "mode": "absolute",
...@@ -137,17 +132,32 @@ ...@@ -137,17 +132,32 @@
}, },
"unit": "areaM2" "unit": "areaM2"
}, },
"overrides": [], "overrides": []
"values": false },
"gridPos": {
"h": 6,
"w": 24,
"x": 0,
"y": 3
}, },
"id": 10,
"interval": "7m",
"options": {
"colorMode": "background",
"graphMode": "area", "graphMode": "area",
"justifyMode": "auto", "justifyMode": "auto",
"orientation": "auto", "orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": { "sparkline": {
"show": true "show": true
}
}, },
"pluginVersion": "6.6.0-pre", "textMode": "auto"
},
"pluginVersion": "7.1.0-pre",
"targets": [ "targets": [
{ {
"alias": "__house_locations", "alias": "__house_locations",
...@@ -166,22 +176,12 @@ ...@@ -166,22 +176,12 @@
}, },
{ {
"datasource": null, "datasource": null,
"gridPos": { "fieldConfig": {
"h": 6,
"w": 24,
"x": 0,
"y": 9
},
"id": 14,
"interval": "7m",
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": ["mean"],
"defaults": { "defaults": {
"color": { "color": {
"mode": "thresholds" "mode": "thresholds"
}, },
"custom": {},
"mappings": [], "mappings": [],
"thresholds": { "thresholds": {
"mode": "absolute", "mode": "absolute",
...@@ -210,17 +210,32 @@ ...@@ -210,17 +210,32 @@
}, },
"unit": "areaM2" "unit": "areaM2"
}, },
"overrides": [], "overrides": []
"values": false },
"gridPos": {
"h": 6,
"w": 24,
"x": 0,
"y": 9
}, },
"id": 14,
"interval": "7m",
"options": {
"colorMode": "value",
"graphMode": "area", "graphMode": "area",
"justifyMode": "auto", "justifyMode": "auto",
"orientation": "auto", "orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": { "sparkline": {
"show": true "show": true
}
}, },
"pluginVersion": "6.6.0-pre", "textMode": "auto"
},
"pluginVersion": "7.1.0-pre",
"targets": [ "targets": [
{ {
"alias": "__house_locations", "alias": "__house_locations",
...@@ -239,22 +254,12 @@ ...@@ -239,22 +254,12 @@
}, },
{ {
"datasource": null, "datasource": null,
"gridPos": { "fieldConfig": {
"h": 14,
"w": 6,
"x": 0,
"y": 15
},
"id": 13,
"interval": "5m",
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": ["mean"],
"defaults": { "defaults": {
"color": { "color": {
"mode": "thresholds" "mode": "thresholds"
}, },
"custom": {},
"mappings": [], "mappings": [],
"thresholds": { "thresholds": {
"mode": "absolute", "mode": "absolute",
...@@ -283,17 +288,32 @@ ...@@ -283,17 +288,32 @@
}, },
"unit": "areaM2" "unit": "areaM2"
}, },
"overrides": [], "overrides": []
"values": false
}, },
"gridPos": {
"h": 18,
"w": 6,
"x": 0,
"y": 15
},
"id": 13,
"interval": "5m",
"options": {
"colorMode": "background",
"graphMode": "area", "graphMode": "area",
"justifyMode": "auto", "justifyMode": "auto",
"orientation": "horizontal", "orientation": "horizontal",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": { "sparkline": {
"show": true "show": true
}
}, },
"pluginVersion": "6.6.0-pre", "textMode": "auto"
},
"pluginVersion": "7.1.0-pre",
"targets": [ "targets": [
{ {
"alias": "__server_names", "alias": "__server_names",
...@@ -306,13 +326,49 @@ ...@@ -306,13 +326,49 @@
], ],
"timeFrom": null, "timeFrom": null,
"timeShift": null, "timeShift": null,
"title": "Panel Title", "title": "Horizontal with graph",
"type": "stat" "type": "stat"
}, },
{ {
"datasource": null, "datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": { "gridPos": {
"h": 11, "h": 9,
"w": 4, "w": 4,
"x": 6, "x": 6,
"y": 15 "y": 15
...@@ -321,12 +377,63 @@ ...@@ -321,12 +377,63 @@
"interval": "10m", "interval": "10m",
"options": { "options": {
"colorMode": "background", "colorMode": "background",
"fieldOptions": { "graphMode": "line",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["mean"], "calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "auto"
},
"pluginVersion": "7.1.0-pre",
"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"
},
{
"refId": "F",
"scenarioId": "random_walk"
},
{
"refId": "G",
"scenarioId": "random_walk"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Auto grid",
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": { "defaults": {
"color": { "color": {
"mode": "thresholds" "mode": "thresholds"
}, },
"custom": {},
"mappings": [], "mappings": [],
"thresholds": { "thresholds": {
"mode": "absolute", "mode": "absolute",
...@@ -355,17 +462,32 @@ ...@@ -355,17 +462,32 @@
}, },
"unit": "areaM2" "unit": "areaM2"
}, },
"overrides": [], "overrides": []
"values": false },
"gridPos": {
"h": 9,
"w": 6,
"x": 10,
"y": 15
}, },
"id": 12,
"interval": "10m",
"options": {
"colorMode": "background",
"graphMode": "line", "graphMode": "line",
"justifyMode": "auto", "justifyMode": "auto",
"orientation": "auto", "orientation": "horizontal",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": { "sparkline": {
"show": true "show": true
}
}, },
"pluginVersion": "6.6.0-pre", "textMode": "auto"
},
"pluginVersion": "7.1.0-pre",
"targets": [ "targets": [
{ {
"refId": "A", "refId": "A",
...@@ -398,28 +520,102 @@ ...@@ -398,28 +520,102 @@
], ],
"timeFrom": null, "timeFrom": null,
"timeShift": null, "timeShift": null,
"title": "Panel Title", "title": "Horizontal",
"type": "stat" "type": "stat"
}, },
{ {
"datasource": null, "datasource": null,
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {},
"mappings": [],
"max": 200,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "blue",
"value": null
},
{
"color": "green",
"value": 10
},
{
"color": "purple",
"value": 20
},
{
"color": "orange",
"value": 40
},
{
"color": "red",
"value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": { "gridPos": {
"h": 9, "h": 9,
"w": 8, "w": 8,
"x": 10, "x": 16,
"y": 15 "y": 15
}, },
"id": 12, "id": 15,
"interval": "10m", "interval": "5m",
"options": { "options": {
"colorMode": "background", "colorMode": "background",
"fieldOptions": { "graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": ["mean"], "calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "name"
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"alias": "__server_names",
"max": 200,
"min": 0,
"noise": 5,
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 7,
"spread": 20,
"startValue": 0
}
],
"timeFrom": null,
"timeShift": null,
"title": "Text mode name",
"type": "stat"
},
{
"datasource": null,
"fieldConfig": {
"defaults": { "defaults": {
"color": { "color": {
"mode": "thresholds" "mode": "thresholds"
}, },
"custom": {},
"mappings": [], "mappings": [],
"max": 200,
"min": 0,
"thresholds": { "thresholds": {
"mode": "absolute", "mode": "absolute",
"steps": [ "steps": [
...@@ -447,54 +643,134 @@ ...@@ -447,54 +643,134 @@
}, },
"unit": "areaM2" "unit": "areaM2"
}, },
"overrides": [], "overrides": []
"values": false
}, },
"graphMode": "line", "gridPos": {
"h": 9,
"w": 18,
"x": 6,
"y": 24
},
"id": 16,
"interval": "5m",
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto", "justifyMode": "auto",
"orientation": "horizontal", "orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": { "sparkline": {
"show": true "show": true
}
}, },
"pluginVersion": "6.6.0-pre", "textMode": "value"
},
"pluginVersion": "7.1.0-pre",
"targets": [ "targets": [
{ {
"alias": "__server_names",
"max": 200,
"min": 0,
"noise": 15,
"refId": "A", "refId": "A",
"scenarioId": "random_walk" "scenarioId": "random_walk",
"seriesCount": 45,
"spread": 1,
"startValue": 0
}
],
"timeFrom": null,
"timeShift": null,
"title": "Value only",
"type": "stat"
}, },
{ {
"refId": "B", "datasource": null,
"scenarioId": "random_walk" "fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
}, },
"custom": {},
"mappings": [],
"max": 200,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{ {
"refId": "C", "color": "blue",
"scenarioId": "random_walk" "value": null
}, },
{ {
"refId": "D", "color": "green",
"scenarioId": "random_walk" "value": 10
}, },
{ {
"refId": "E", "color": "purple",
"scenarioId": "random_walk" "value": 20
}, },
{ {
"refId": "F", "color": "orange",
"scenarioId": "random_walk" "value": 40
}, },
{ {
"refId": "G", "color": "red",
"scenarioId": "random_walk" "value": 80
}
]
},
"unit": "areaM2"
},
"overrides": []
},
"gridPos": {
"h": 5,
"w": 24,
"x": 0,
"y": 33
},
"id": 17,
"interval": "5m",
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["mean"],
"fields": "",
"values": false
},
"sparkline": {
"show": true
},
"textMode": "none"
},
"pluginVersion": "7.1.0-pre",
"targets": [
{
"alias": "__server_names",
"max": 200,
"min": 0,
"noise": 15,
"refId": "A",
"scenarioId": "random_walk",
"seriesCount": 200,
"spread": 1,
"startValue": 0
} }
], ],
"timeFrom": null, "timeFrom": null,
"timeShift": null, "timeShift": null,
"title": "Panel Title", "title": "No text",
"type": "stat" "type": "stat"
} }
], ],
"schemaVersion": 22, "schemaVersion": 26,
"style": "dark", "style": "dark",
"tags": ["gdev", "panel-tests"], "tags": ["gdev", "panel-tests"],
"templating": { "templating": {
...@@ -508,5 +784,7 @@ ...@@ -508,5 +784,7 @@
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
}, },
"timezone": "", "timezone": "",
"title": "Panel Tests - Stat" "title": "Panel Tests - Stat",
"uid": "EJ8_d9jZk",
"version": 1
} }
...@@ -48,3 +48,24 @@ Use the following options to refine your visualization: ...@@ -48,3 +48,24 @@ Use the following options to refine your visualization:
- **Alignment mode -** Choose an alignment mode. - **Alignment mode -** Choose an alignment mode.
- **Auto -** If only a single value is shown (no repeat), then the value is centered. If multiple series or rows are shown, then the value is left-aligned. - **Auto -** If only a single value is shown (no repeat), then the value is centered. If multiple series or rows are shown, then the value is left-aligned.
- **Center -** Stat value is centered. - **Center -** Stat value is centered.
- **Text mode** (Only available in Grafana 7.1+.)
- **Auto -** If the data contains multiple series or fields, show both name and value..
- **Value -** Show only value, never name. Name is displayed in the hover tooltip instead.
- **Value and name -** Always show value and name.
- **Name -** Show name instead of value. Value is displayed in the hover tooltip.
- **None -** Show nothing (empty). Name and value are displayed in the hover tooltip.
## Text mode
> Only available in Grafana 7.1+.
By default, the Stat panel displays:
- Just the value for a single series or field.
- Both the value and name for multiple series or fields.
You can use the Text mode option to control what text the panel renders. If the value is not important, only name and color is, then change the `Text mode` to **Name**. The value will still be used to determine color and is displayed in a tooltip.
Example screenshot:
{{< docs-imagebox img="/img/docs/v71/stat-panel-text-modes.png" max-width="1025px" caption="Stat panel" >}}
...@@ -84,7 +84,7 @@ export interface GetFieldDisplayValuesOptions { ...@@ -84,7 +84,7 @@ export interface GetFieldDisplayValuesOptions {
export const DEFAULT_FIELD_DISPLAY_VALUES_LIMIT = 25; export const DEFAULT_FIELD_DISPLAY_VALUES_LIMIT = 25;
export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): FieldDisplay[] => { export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): FieldDisplay[] => {
const { replaceVariables, reduceOptions, fieldConfig, timeZone } = options; const { replaceVariables, reduceOptions, timeZone } = options;
const calcs = reduceOptions.calcs.length ? reduceOptions.calcs : [ReducerID.last]; const calcs = reduceOptions.calcs.length ? reduceOptions.calcs : [ReducerID.last];
const values: FieldDisplay[] = []; const values: FieldDisplay[] = [];
...@@ -223,9 +223,6 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi ...@@ -223,9 +223,6 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi
if (values.length === 0) { if (values.length === 0) {
values.push(createNoValuesFieldDisplay(options)); values.push(createNoValuesFieldDisplay(options));
} else if (values.length === 1 && !fieldConfig.defaults.displayName) {
// Don't show title for single item
values[0].display.title = undefined;
} }
return values; return values;
......
import { text, select, number, color } from '@storybook/addon-knobs'; import { text, select, number, color } from '@storybook/addon-knobs';
import { BigValue, BigValueColorMode, BigValueGraphMode } from './BigValue'; import { BigValue, BigValueColorMode, BigValueGraphMode, BigValueTextMode } from './BigValue';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { renderComponentWithTheme } from '../../utils/storybook/withTheme'; import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
...@@ -8,10 +8,15 @@ const getKnobs = () => { ...@@ -8,10 +8,15 @@ const getKnobs = () => {
value: text('value', '$5022'), value: text('value', '$5022'),
title: text('title', 'Total Earnings'), title: text('title', 'Total Earnings'),
colorMode: select('Color mode', [BigValueColorMode.Value, BigValueColorMode.Background], BigValueColorMode.Value), colorMode: select('Color mode', [BigValueColorMode.Value, BigValueColorMode.Background], BigValueColorMode.Value),
graphMode: select('Graph mode', [BigValueGraphMode.Area, BigValueGraphMode.Line], BigValueGraphMode.Area), graphMode: select('Graph mode', [BigValueGraphMode.Area, BigValueGraphMode.None], BigValueGraphMode.Area),
width: number('Width', 400, { range: true, max: 800, min: 200 }), width: number('Width', 400, { range: true, max: 800, min: 200 }),
height: number('Height', 300, { range: true, max: 800, min: 200 }), height: number('Height', 300, { range: true, max: 800, min: 200 }),
color: color('Value color', 'red'), color: color('Value color', 'red'),
textMode: select(
'Text mode',
[BigValueTextMode.Auto, BigValueTextMode.Name, BigValueTextMode.ValueAndName, BigValueTextMode.None],
BigValueTextMode.Auto
),
}; };
}; };
...@@ -22,13 +27,14 @@ export default { ...@@ -22,13 +27,14 @@ export default {
}; };
export const basic = () => { export const basic = () => {
const { value, title, colorMode, graphMode, height, width, color } = getKnobs(); const { value, title, colorMode, graphMode, height, width, color, textMode } = getKnobs();
return renderComponentWithTheme(BigValue, { return renderComponentWithTheme(BigValue, {
width: width, width: width,
height: height, height: height,
colorMode: colorMode, colorMode: colorMode,
graphMode: graphMode, graphMode: graphMode,
textMode,
value: { value: {
text: value, text: value,
numeric: 5022, numeric: 5022,
......
...@@ -32,6 +32,17 @@ export enum BigValueJustifyMode { ...@@ -32,6 +32,17 @@ export enum BigValueJustifyMode {
Center = 'center', Center = 'center',
} }
/**
* Options for how the value & title are to be displayed
*/
export enum BigValueTextMode {
Auto = 'auto',
Value = 'value',
ValueAndName = 'value_and_name',
Name = 'name',
None = 'none',
}
export interface Props extends Themeable { export interface Props extends Themeable {
height: number; height: number;
width: number; width: number;
...@@ -43,6 +54,7 @@ export interface Props extends Themeable { ...@@ -43,6 +54,7 @@ export interface Props extends Themeable {
graphMode: BigValueGraphMode; graphMode: BigValueGraphMode;
justifyMode?: BigValueJustifyMode; justifyMode?: BigValueJustifyMode;
alignmentFactors?: DisplayValueAlignmentFactors; alignmentFactors?: DisplayValueAlignmentFactors;
textMode?: BigValueTextMode;
} }
export class BigValue extends PureComponent<Props> { export class BigValue extends PureComponent<Props> {
...@@ -51,19 +63,20 @@ export class BigValue extends PureComponent<Props> { ...@@ -51,19 +63,20 @@ export class BigValue extends PureComponent<Props> {
}; };
render() { render() {
const { value, onClick, className } = this.props; const { onClick, className } = this.props;
const layout = buildLayout(this.props); const layout = buildLayout(this.props);
const panelStyles = layout.getPanelStyles(); const panelStyles = layout.getPanelStyles();
const valueAndTitleContainerStyles = layout.getValueAndTitleContainerStyles(); const valueAndTitleContainerStyles = layout.getValueAndTitleContainerStyles();
const valueStyles = layout.getValueStyles(); const valueStyles = layout.getValueStyles();
const titleStyles = layout.getTitleStyles(); const titleStyles = layout.getTitleStyles();
const textValues = layout.textValues;
return ( return (
<div className={className} style={panelStyles} onClick={onClick}> <div className={className} style={panelStyles} onClick={onClick} title={textValues.tooltip}>
<div style={valueAndTitleContainerStyles}> <div style={valueAndTitleContainerStyles}>
{value.title && <div style={titleStyles}>{value.title}</div>} {textValues.title && <div style={titleStyles}>{textValues.title}</div>}
<FormattedValueDisplay value={value} style={valueStyles} /> <FormattedValueDisplay value={textValues} style={valueStyles} />
</div> </div>
{layout.renderChart()} {layout.renderChart()}
</div> </div>
......
...@@ -4,11 +4,11 @@ import tinycolor from 'tinycolor2'; ...@@ -4,11 +4,11 @@ import tinycolor from 'tinycolor2';
import { Chart, Geom } from 'bizcharts'; import { Chart, Geom } from 'bizcharts';
// Utils // Utils
import { getColorFromHexRgbOrName, formattedValueToString } from '@grafana/data'; import { getColorFromHexRgbOrName, formattedValueToString, DisplayValue } from '@grafana/data';
import { calculateFontSize } from '../../utils/measureText'; import { calculateFontSize } from '../../utils/measureText';
// Types // Types
import { BigValueColorMode, Props, BigValueJustifyMode } from './BigValue'; import { BigValueColorMode, Props, BigValueJustifyMode, BigValueTextMode } from './BigValue';
const LINE_HEIGHT = 1.2; const LINE_HEIGHT = 1.2;
const MAX_TITLE_SIZE = 30; const MAX_TITLE_SIZE = 30;
...@@ -25,16 +25,17 @@ export abstract class BigValueLayout { ...@@ -25,16 +25,17 @@ export abstract class BigValueLayout {
valueToAlignTo: string; valueToAlignTo: string;
maxTextWidth: number; maxTextWidth: number;
maxTextHeight: number; maxTextHeight: number;
textValues: BigValueTextValues;
constructor(private props: Props) { constructor(private props: Props) {
const { width, height, value, alignmentFactors, theme } = props; const { width, height, value, theme } = props;
this.valueColor = getColorFromHexRgbOrName(value.color || 'green', theme.type); this.valueColor = getColorFromHexRgbOrName(value.color || 'green', theme.type);
this.justifyCenter = shouldJustifyCenter(props);
this.panelPadding = height > 100 ? 12 : 8; this.panelPadding = height > 100 ? 12 : 8;
this.titleToAlignTo = alignmentFactors ? alignmentFactors.title : value.title; this.textValues = getTextValues(props);
this.valueToAlignTo = formattedValueToString(alignmentFactors ? alignmentFactors : value); this.justifyCenter = shouldJustifyCenter(props.justifyMode, this.textValues.title);
this.valueToAlignTo = this.textValues.valueToAlignTo;
this.titleToAlignTo = this.textValues.titleToAlignTo;
this.titleFontSize = 14; this.titleFontSize = 14;
this.valueFontSize = 14; this.valueFontSize = 14;
this.chartHeight = 0; this.chartHeight = 0;
...@@ -447,10 +448,61 @@ export function buildLayout(props: Props): BigValueLayout { ...@@ -447,10 +448,61 @@ export function buildLayout(props: Props): BigValueLayout {
} }
} }
export function shouldJustifyCenter(props: Props) { export function shouldJustifyCenter(justifyMode?: BigValueJustifyMode, title?: string) {
const { value, justifyMode } = props;
if (justifyMode === BigValueJustifyMode.Center) { if (justifyMode === BigValueJustifyMode.Center) {
return true; return true;
} }
return (value.title ?? '').length === 0;
return (title ?? '').length === 0;
}
export interface BigValueTextValues extends DisplayValue {
valueToAlignTo: string;
titleToAlignTo?: string;
tooltip?: string;
}
function getTextValues(props: Props): BigValueTextValues {
const { textMode: nameAndValue, value, alignmentFactors } = props;
const titleToAlignTo = alignmentFactors ? alignmentFactors.title : value.title;
const valueToAlignTo = formattedValueToString(alignmentFactors ? alignmentFactors : value);
switch (nameAndValue) {
case BigValueTextMode.Name:
return {
...value,
title: undefined,
prefix: undefined,
suffix: undefined,
text: value.title || '',
titleToAlignTo: undefined,
valueToAlignTo: titleToAlignTo ?? '',
tooltip: formattedValueToString(value),
};
case BigValueTextMode.Value:
return {
...value,
title: undefined,
titleToAlignTo: undefined,
valueToAlignTo,
tooltip: value.title,
};
case BigValueTextMode.None:
return {
numeric: value.numeric,
color: value.color,
title: undefined,
text: '',
titleToAlignTo: undefined,
valueToAlignTo: '1',
tooltip: `Name: ${value.title}\nValue: ${formattedValueToString(value)}`,
};
default:
return {
...value,
titleToAlignTo,
valueToAlignTo,
};
}
} }
...@@ -40,6 +40,8 @@ exports[`BigValue Render with basic options should render 1`] = ` ...@@ -40,6 +40,8 @@ exports[`BigValue Render with basic options should render 1`] = `
Object { Object {
"numeric": 25, "numeric": 25,
"text": "25", "text": "25",
"titleToAlignTo": undefined,
"valueToAlignTo": "25",
} }
} }
/> />
......
...@@ -32,6 +32,10 @@ export interface VizRepeaterRenderValueProps<V, D = {}> { ...@@ -32,6 +32,10 @@ export interface VizRepeaterRenderValueProps<V, D = {}> {
height: number; height: number;
orientation: VizOrientation; orientation: VizOrientation;
alignmentFactors: D; alignmentFactors: D;
/**
* Total number of values being shown in repeater
*/
count: number;
} }
interface DefaultProps { interface DefaultProps {
...@@ -110,7 +114,14 @@ export class VizRepeater<V, D = {}> extends PureComponent<Props<V, D>, State<V>> ...@@ -110,7 +114,14 @@ export class VizRepeater<V, D = {}> extends PureComponent<Props<V, D>, State<V>>
items.push( items.push(
<div key={i} style={itemStyles}> <div key={i} style={itemStyles}>
{renderValue({ value, width: itemWidth, height: itemHeight, alignmentFactors, orientation })} {renderValue({
value,
width: itemWidth,
height: itemHeight,
alignmentFactors,
orientation,
count: values.length,
})}
</div> </div>
); );
...@@ -178,6 +189,7 @@ export class VizRepeater<V, D = {}> extends PureComponent<Props<V, D>, State<V>> ...@@ -178,6 +189,7 @@ export class VizRepeater<V, D = {}> extends PureComponent<Props<V, D>, State<V>>
height: vizHeight, height: vizHeight,
alignmentFactors, alignmentFactors,
orientation: resolvedOrientation, orientation: resolvedOrientation,
count: values.length,
})} })}
</div> </div>
); );
......
...@@ -65,6 +65,7 @@ export { ...@@ -65,6 +65,7 @@ export {
BigValueSparkline, BigValueSparkline,
BigValueGraphMode, BigValueGraphMode,
BigValueJustifyMode, BigValueJustifyMode,
BigValueTextMode,
} from './BigValue/BigValue'; } from './BigValue/BigValue';
export { Gauge } from './Gauge/Gauge'; export { Gauge } from './Gauge/Gauge';
......
...@@ -5,6 +5,8 @@ import { ...@@ -5,6 +5,8 @@ import {
getDisplayValueAlignmentFactors, getDisplayValueAlignmentFactors,
getFieldDisplayValues, getFieldDisplayValues,
PanelProps, PanelProps,
FieldConfig,
DisplayValue,
} from '@grafana/data'; } from '@grafana/data';
import { BarGauge, DataLinksContextMenu, VizRepeater, VizRepeaterRenderValueProps } from '@grafana/ui'; import { BarGauge, DataLinksContextMenu, VizRepeater, VizRepeaterRenderValueProps } from '@grafana/ui';
...@@ -18,13 +20,13 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> { ...@@ -18,13 +20,13 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
menuProps: DataLinksContextMenuApi menuProps: DataLinksContextMenuApi
): JSX.Element => { ): JSX.Element => {
const { options } = this.props; const { options } = this.props;
const { value, alignmentFactors, orientation, width, height } = valueProps; const { value, alignmentFactors, orientation, width, height, count } = valueProps;
const { field, display, view, colIndex } = value; const { field, display, view, colIndex } = value;
const { openMenu, targetClassName } = menuProps; const { openMenu, targetClassName } = menuProps;
return ( return (
<BarGauge <BarGauge
value={display} value={clearNameForSingleSeries(count, field, display)}
width={width} width={width}
height={height} height={height}
orientation={orientation} orientation={orientation}
...@@ -97,3 +99,14 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> { ...@@ -97,3 +99,14 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
); );
} }
} }
export function clearNameForSingleSeries(count: number, field: FieldConfig<any>, display: DisplayValue): DisplayValue {
if (count === 1 && !field.displayName) {
return {
...display,
title: undefined,
};
}
return display;
}
...@@ -5,6 +5,7 @@ import { DataLinksContextMenuApi } from '@grafana/ui/src/components/DataLinks/Da ...@@ -5,6 +5,7 @@ import { DataLinksContextMenuApi } from '@grafana/ui/src/components/DataLinks/Da
import { config } from 'app/core/config'; import { config } from 'app/core/config';
import { GaugeOptions } from './types'; import { GaugeOptions } from './types';
import { clearNameForSingleSeries } from '../bargauge/BarGaugePanel';
export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> { export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
renderComponent = ( renderComponent = (
...@@ -12,13 +13,13 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> { ...@@ -12,13 +13,13 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
menuProps: DataLinksContextMenuApi menuProps: DataLinksContextMenuApi
): JSX.Element => { ): JSX.Element => {
const { options } = this.props; const { options } = this.props;
const { value, width, height } = valueProps; const { width, height, count, value } = valueProps;
const { field, display } = value; const { field, display } = value;
const { openMenu, targetClassName } = menuProps; const { openMenu, targetClassName } = menuProps;
return ( return (
<Gauge <Gauge
value={display} value={clearNameForSingleSeries(count, field, display)}
width={width} width={width}
height={height} height={height}
field={field} field={field}
......
import { PanelModel } from '@grafana/data'; import { PanelModel } from '@grafana/data';
import { statPanelChangedHandler } from './StatMigrations'; import { statPanelChangedHandler } from './StatMigrations';
import { BigValueGraphMode, BigValueColorMode } from '@grafana/ui'; import { BigValueGraphMode, BigValueColorMode } from '@grafana/ui';
import { BigValueTextMode } from '@grafana/ui/src/components/BigValue/BigValue';
describe('Stat Panel Migrations', () => { describe('Stat Panel Migrations', () => {
it('change from angular singlestat sparkline disabled', () => { it('change from angular singlestat sparkline disabled', () => {
...@@ -48,4 +49,16 @@ describe('Stat Panel Migrations', () => { ...@@ -48,4 +49,16 @@ describe('Stat Panel Migrations', () => {
const options = statPanelChangedHandler(panel, 'singlestat', old); const options = statPanelChangedHandler(panel, 'singlestat', old);
expect(options.colorMode).toBe(BigValueColorMode.Background); expect(options.colorMode).toBe(BigValueColorMode.Background);
}); });
it('change from angular singlestat with name stat', () => {
const old: any = {
angular: {
valueName: 'name',
},
};
const panel = {} as PanelModel;
const options = statPanelChangedHandler(panel, 'singlestat', old);
expect(options.textMode).toBe(BigValueTextMode.Name);
});
}); });
import { sharedSingleStatPanelChangedHandler, BigValueGraphMode, BigValueColorMode } from '@grafana/ui'; import { sharedSingleStatPanelChangedHandler, BigValueGraphMode, BigValueColorMode } from '@grafana/ui';
import { PanelModel } from '@grafana/data'; import { PanelModel } from '@grafana/data';
import { StatPanelOptions } from './types'; import { StatPanelOptions } from './types';
import { BigValueTextMode } from '@grafana/ui/src/components/BigValue/BigValue';
// This is called when the panel changes from another panel // This is called when the panel changes from another panel
export const statPanelChangedHandler = ( export const statPanelChangedHandler = (
...@@ -23,6 +24,10 @@ export const statPanelChangedHandler = ( ...@@ -23,6 +24,10 @@ export const statPanelChangedHandler = (
} else { } else {
options.colorMode = BigValueColorMode.Value; options.colorMode = BigValueColorMode.Value;
} }
if (oldOptions.valueName === 'name') {
options.textMode = BigValueTextMode.Name;
}
} }
return options; return options;
......
...@@ -52,6 +52,7 @@ export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> { ...@@ -52,6 +52,7 @@ export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
colorMode={options.colorMode} colorMode={options.colorMode}
graphMode={options.graphMode} graphMode={options.graphMode}
justifyMode={options.justifyMode} justifyMode={options.justifyMode}
textMode={options.textMode}
alignmentFactors={alignmentFactors} alignmentFactors={alignmentFactors}
width={width} width={width}
height={height} height={height}
......
import { sharedSingleStatMigrationHandler } from '@grafana/ui'; import { sharedSingleStatMigrationHandler, BigValueTextMode } from '@grafana/ui';
import { PanelPlugin } from '@grafana/data'; import { PanelPlugin } from '@grafana/data';
import { StatPanelOptions, addStandardDataReduceOptions } from './types'; import { StatPanelOptions, addStandardDataReduceOptions } from './types';
import { StatPanel } from './StatPanel'; import { StatPanel } from './StatPanel';
...@@ -9,6 +9,22 @@ export const plugin = new PanelPlugin<StatPanelOptions>(StatPanel) ...@@ -9,6 +9,22 @@ export const plugin = new PanelPlugin<StatPanelOptions>(StatPanel)
.setPanelOptions(builder => { .setPanelOptions(builder => {
addStandardDataReduceOptions(builder); addStandardDataReduceOptions(builder);
builder.addSelect({
path: 'textMode',
name: 'Text mode',
description: 'Control if name and value is displayed or just name',
settings: {
options: [
{ value: BigValueTextMode.Auto, label: 'Auto' },
{ value: BigValueTextMode.Value, label: 'Value' },
{ value: BigValueTextMode.ValueAndName, label: 'Value and name' },
{ value: BigValueTextMode.Name, label: 'Name' },
{ value: BigValueTextMode.None, label: 'None' },
],
},
defaultValue: 'auto',
});
builder builder
.addRadio({ .addRadio({
path: 'colorMode', path: 'colorMode',
......
import { SingleStatBaseOptions, BigValueColorMode, BigValueGraphMode, BigValueJustifyMode } from '@grafana/ui'; import {
SingleStatBaseOptions,
BigValueColorMode,
BigValueGraphMode,
BigValueJustifyMode,
BigValueTextMode,
} from '@grafana/ui';
import { import {
ReducerID, ReducerID,
SelectableValue,
standardEditorsRegistry, standardEditorsRegistry,
FieldOverrideContext, FieldOverrideContext,
getFieldDisplayName, getFieldDisplayName,
...@@ -14,23 +19,9 @@ export interface StatPanelOptions extends SingleStatBaseOptions { ...@@ -14,23 +19,9 @@ export interface StatPanelOptions extends SingleStatBaseOptions {
graphMode: BigValueGraphMode; graphMode: BigValueGraphMode;
colorMode: BigValueColorMode; colorMode: BigValueColorMode;
justifyMode: BigValueJustifyMode; justifyMode: BigValueJustifyMode;
textMode: BigValueTextMode;
} }
export const colorModes: Array<SelectableValue<BigValueColorMode>> = [
{ value: BigValueColorMode.Value, label: 'Value' },
{ value: BigValueColorMode.Background, label: 'Background' },
];
export const graphModes: Array<SelectableValue<BigValueGraphMode>> = [
{ value: BigValueGraphMode.None, label: 'None' },
{ value: BigValueGraphMode.Area, label: 'Area graph' },
];
export const justifyModes: Array<SelectableValue<BigValueJustifyMode>> = [
{ value: BigValueJustifyMode.Auto, label: 'Auto' },
{ value: BigValueJustifyMode.Center, label: 'Center' },
];
export function addStandardDataReduceOptions( export function addStandardDataReduceOptions(
builder: PanelOptionsEditorBuilder<SingleStatBaseOptions>, builder: PanelOptionsEditorBuilder<SingleStatBaseOptions>,
includeOrientation = true, includeOrientation = true,
...@@ -65,7 +56,7 @@ export function addStandardDataReduceOptions( ...@@ -65,7 +56,7 @@ export function addStandardDataReduceOptions(
builder.addCustomEditor({ builder.addCustomEditor({
id: 'reduceOptions.calcs', id: 'reduceOptions.calcs',
path: 'reduceOptions.calcs', path: 'reduceOptions.calcs',
name: 'Value', name: 'Calculation',
description: 'Choose a reducer function / calculation', description: 'Choose a reducer function / calculation',
editor: standardEditorsRegistry.get('stats-picker').editor as any, editor: standardEditorsRegistry.get('stats-picker').editor as any,
defaultValue: [ReducerID.mean], defaultValue: [ReducerID.mean],
......
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