From d65569f5d92d1e75cbec682b5a90673550bd71f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 1 Jul 2020 11:06:21 +0200 Subject: [PATCH] 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> --- .../panel-stat/panel-stat-tests.json | 762 ++++++++++++------ .../panels/visualizations/stat-panel.md | 21 + .../grafana-data/src/field/fieldDisplay.ts | 5 +- .../components/BigValue/BigValue.story.tsx | 12 +- .../src/components/BigValue/BigValue.tsx | 21 +- .../components/BigValue/BigValueLayout.tsx | 72 +- .../__snapshots__/BigValue.test.tsx.snap | 2 + .../components/VizRepeater/VizRepeater.tsx | 14 +- packages/grafana-ui/src/components/index.ts | 1 + .../plugins/panel/bargauge/BarGaugePanel.tsx | 17 +- public/app/plugins/panel/gauge/GaugePanel.tsx | 5 +- .../plugins/panel/stat/StatMigrations.test.ts | 13 + .../app/plugins/panel/stat/StatMigrations.ts | 5 + public/app/plugins/panel/stat/StatPanel.tsx | 1 + public/app/plugins/panel/stat/module.tsx | 18 +- public/app/plugins/panel/stat/types.ts | 27 +- 16 files changed, 709 insertions(+), 287 deletions(-) diff --git a/devenv/dev-dashboards/panel-stat/panel-stat-tests.json b/devenv/dev-dashboards/panel-stat/panel-stat-tests.json index 4f1c019de43..c431f93fdbe 100644 --- a/devenv/dev-dashboards/panel-stat/panel-stat-tests.json +++ b/devenv/dev-dashboards/panel-stat/panel-stat-tests.json @@ -19,6 +19,42 @@ "panels": [ { "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": { "h": 3, "w": 24, @@ -29,51 +65,20 @@ "interval": "6m", "options": { "colorMode": "background", - "fieldOptions": { - "calcs": ["mean"], - "defaults": { - "color": { - "mode": "thresholds" - }, - "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": [], - "values": false - }, "graphMode": "area", "justifyMode": "auto", "orientation": "auto", + "reduceOptions": { + "calcs": ["mean"], + "fields": "", + "values": false + }, "sparkline": { "show": true - } + }, + "textMode": "auto" }, - "pluginVersion": "6.6.0-pre", + "pluginVersion": "7.1.0-pre", "targets": [ { "alias": "__house_locations", @@ -93,6 +98,42 @@ }, { "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": { "h": 6, "w": 24, @@ -103,51 +144,20 @@ "interval": "7m", "options": { "colorMode": "background", - "fieldOptions": { - "calcs": ["mean"], - "defaults": { - "color": { - "mode": "thresholds" - }, - "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": [], - "values": false - }, "graphMode": "area", "justifyMode": "auto", "orientation": "auto", + "reduceOptions": { + "calcs": ["mean"], + "fields": "", + "values": false + }, "sparkline": { "show": true - } + }, + "textMode": "auto" }, - "pluginVersion": "6.6.0-pre", + "pluginVersion": "7.1.0-pre", "targets": [ { "alias": "__house_locations", @@ -166,6 +176,42 @@ }, { "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": { "h": 6, "w": 24, @@ -176,51 +222,20 @@ "interval": "7m", "options": { "colorMode": "value", - "fieldOptions": { - "calcs": ["mean"], - "defaults": { - "color": { - "mode": "thresholds" - }, - "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": [], - "values": false - }, "graphMode": "area", "justifyMode": "auto", "orientation": "auto", + "reduceOptions": { + "calcs": ["mean"], + "fields": "", + "values": false + }, "sparkline": { "show": true - } + }, + "textMode": "auto" }, - "pluginVersion": "6.6.0-pre", + "pluginVersion": "7.1.0-pre", "targets": [ { "alias": "__house_locations", @@ -239,8 +254,44 @@ }, { "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": { - "h": 14, + "h": 18, "w": 6, "x": 0, "y": 15 @@ -249,51 +300,20 @@ "interval": "5m", "options": { "colorMode": "background", - "fieldOptions": { - "calcs": ["mean"], - "defaults": { - "color": { - "mode": "thresholds" - }, - "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": [], - "values": false - }, "graphMode": "area", "justifyMode": "auto", "orientation": "horizontal", + "reduceOptions": { + "calcs": ["mean"], + "fields": "", + "values": false + }, "sparkline": { "show": true - } + }, + "textMode": "auto" }, - "pluginVersion": "6.6.0-pre", + "pluginVersion": "7.1.0-pre", "targets": [ { "alias": "__server_names", @@ -306,13 +326,49 @@ ], "timeFrom": null, "timeShift": null, - "title": "Panel Title", + "title": "Horizontal with graph", "type": "stat" }, { "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": { - "h": 11, + "h": 9, "w": 4, "x": 6, "y": 15 @@ -321,51 +377,20 @@ "interval": "10m", "options": { "colorMode": "background", - "fieldOptions": { - "calcs": ["mean"], - "defaults": { - "color": { - "mode": "thresholds" - }, - "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": [], - "values": false - }, "graphMode": "line", "justifyMode": "auto", "orientation": "auto", + "reduceOptions": { + "calcs": ["mean"], + "fields": "", + "values": false + }, "sparkline": { "show": true - } + }, + "textMode": "auto" }, - "pluginVersion": "6.6.0-pre", + "pluginVersion": "7.1.0-pre", "targets": [ { "refId": "A", @@ -398,14 +423,50 @@ ], "timeFrom": null, "timeShift": null, - "title": "Panel Title", + "title": "Auto grid", "type": "stat" }, { "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": { "h": 9, - "w": 8, + "w": 6, "x": 10, "y": 15 }, @@ -413,51 +474,20 @@ "interval": "10m", "options": { "colorMode": "background", - "fieldOptions": { - "calcs": ["mean"], - "defaults": { - "color": { - "mode": "thresholds" - }, - "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": [], - "values": false - }, "graphMode": "line", "justifyMode": "auto", "orientation": "horizontal", + "reduceOptions": { + "calcs": ["mean"], + "fields": "", + "values": false + }, "sparkline": { "show": true - } + }, + "textMode": "auto" }, - "pluginVersion": "6.6.0-pre", + "pluginVersion": "7.1.0-pre", "targets": [ { "refId": "A", @@ -490,11 +520,257 @@ ], "timeFrom": null, "timeShift": null, - "title": "Panel Title", + "title": "Horizontal", + "type": "stat" + }, + { + "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": { + "h": 9, + "w": 8, + "x": 16, + "y": 15 + }, + "id": 15, + "interval": "5m", + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "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": { + "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": { + "h": 9, + "w": 18, + "x": 6, + "y": 24 + }, + "id": 16, + "interval": "5m", + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["mean"], + "fields": "", + "values": false + }, + "sparkline": { + "show": true + }, + "textMode": "value" + }, + "pluginVersion": "7.1.0-pre", + "targets": [ + { + "alias": "__server_names", + "max": 200, + "min": 0, + "noise": 15, + "refId": "A", + "scenarioId": "random_walk", + "seriesCount": 45, + "spread": 1, + "startValue": 0 + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Value only", + "type": "stat" + }, + { + "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": { + "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, + "timeShift": null, + "title": "No text", "type": "stat" } ], - "schemaVersion": 22, + "schemaVersion": 26, "style": "dark", "tags": ["gdev", "panel-tests"], "templating": { @@ -508,5 +784,7 @@ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] }, "timezone": "", - "title": "Panel Tests - Stat" + "title": "Panel Tests - Stat", + "uid": "EJ8_d9jZk", + "version": 1 } diff --git a/docs/sources/panels/visualizations/stat-panel.md b/docs/sources/panels/visualizations/stat-panel.md index 654415ca2cc..590b079ad6a 100644 --- a/docs/sources/panels/visualizations/stat-panel.md +++ b/docs/sources/panels/visualizations/stat-panel.md @@ -48,3 +48,24 @@ Use the following options to refine your visualization: - **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. - **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" >}} diff --git a/packages/grafana-data/src/field/fieldDisplay.ts b/packages/grafana-data/src/field/fieldDisplay.ts index 8ed6dcccbbe..53efac23894 100644 --- a/packages/grafana-data/src/field/fieldDisplay.ts +++ b/packages/grafana-data/src/field/fieldDisplay.ts @@ -84,7 +84,7 @@ export interface GetFieldDisplayValuesOptions { export const DEFAULT_FIELD_DISPLAY_VALUES_LIMIT = 25; 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 values: FieldDisplay[] = []; @@ -223,9 +223,6 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi if (values.length === 0) { 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; diff --git a/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx b/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx index e4dc97ff66a..943a7026e27 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx @@ -1,5 +1,5 @@ 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 { renderComponentWithTheme } from '../../utils/storybook/withTheme'; @@ -8,10 +8,15 @@ const getKnobs = () => { value: text('value', '$5022'), title: text('title', 'Total Earnings'), 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 }), height: number('Height', 300, { range: true, max: 800, min: 200 }), 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 { }; 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, { width: width, height: height, colorMode: colorMode, graphMode: graphMode, + textMode, value: { text: value, numeric: 5022, diff --git a/packages/grafana-ui/src/components/BigValue/BigValue.tsx b/packages/grafana-ui/src/components/BigValue/BigValue.tsx index d2cb5bfddaa..bfeb9ed17fe 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValue.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValue.tsx @@ -32,6 +32,17 @@ export enum BigValueJustifyMode { 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 { height: number; width: number; @@ -43,6 +54,7 @@ export interface Props extends Themeable { graphMode: BigValueGraphMode; justifyMode?: BigValueJustifyMode; alignmentFactors?: DisplayValueAlignmentFactors; + textMode?: BigValueTextMode; } export class BigValue extends PureComponent { @@ -51,19 +63,20 @@ export class BigValue extends PureComponent { }; render() { - const { value, onClick, className } = this.props; + const { onClick, className } = this.props; const layout = buildLayout(this.props); const panelStyles = layout.getPanelStyles(); const valueAndTitleContainerStyles = layout.getValueAndTitleContainerStyles(); const valueStyles = layout.getValueStyles(); const titleStyles = layout.getTitleStyles(); + const textValues = layout.textValues; return ( -
+
- {value.title &&
{value.title}
} - + {textValues.title &&
{textValues.title}
} +
{layout.renderChart()}
diff --git a/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx b/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx index 59f4d48cd0c..3b8c70f6a48 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx @@ -4,11 +4,11 @@ import tinycolor from 'tinycolor2'; import { Chart, Geom } from 'bizcharts'; // Utils -import { getColorFromHexRgbOrName, formattedValueToString } from '@grafana/data'; +import { getColorFromHexRgbOrName, formattedValueToString, DisplayValue } from '@grafana/data'; import { calculateFontSize } from '../../utils/measureText'; // Types -import { BigValueColorMode, Props, BigValueJustifyMode } from './BigValue'; +import { BigValueColorMode, Props, BigValueJustifyMode, BigValueTextMode } from './BigValue'; const LINE_HEIGHT = 1.2; const MAX_TITLE_SIZE = 30; @@ -25,16 +25,17 @@ export abstract class BigValueLayout { valueToAlignTo: string; maxTextWidth: number; maxTextHeight: number; + textValues: BigValueTextValues; 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.justifyCenter = shouldJustifyCenter(props); this.panelPadding = height > 100 ? 12 : 8; - this.titleToAlignTo = alignmentFactors ? alignmentFactors.title : value.title; - this.valueToAlignTo = formattedValueToString(alignmentFactors ? alignmentFactors : value); - + this.textValues = getTextValues(props); + this.justifyCenter = shouldJustifyCenter(props.justifyMode, this.textValues.title); + this.valueToAlignTo = this.textValues.valueToAlignTo; + this.titleToAlignTo = this.textValues.titleToAlignTo; this.titleFontSize = 14; this.valueFontSize = 14; this.chartHeight = 0; @@ -447,10 +448,61 @@ export function buildLayout(props: Props): BigValueLayout { } } -export function shouldJustifyCenter(props: Props) { - const { value, justifyMode } = props; +export function shouldJustifyCenter(justifyMode?: BigValueJustifyMode, title?: string) { if (justifyMode === BigValueJustifyMode.Center) { 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, + }; + } } diff --git a/packages/grafana-ui/src/components/BigValue/__snapshots__/BigValue.test.tsx.snap b/packages/grafana-ui/src/components/BigValue/__snapshots__/BigValue.test.tsx.snap index b423c521838..63e3654e0f1 100644 --- a/packages/grafana-ui/src/components/BigValue/__snapshots__/BigValue.test.tsx.snap +++ b/packages/grafana-ui/src/components/BigValue/__snapshots__/BigValue.test.tsx.snap @@ -40,6 +40,8 @@ exports[`BigValue Render with basic options should render 1`] = ` Object { "numeric": 25, "text": "25", + "titleToAlignTo": undefined, + "valueToAlignTo": "25", } } /> diff --git a/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx b/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx index b18680ba77c..e76d44f23d5 100644 --- a/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx +++ b/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx @@ -32,6 +32,10 @@ export interface VizRepeaterRenderValueProps { height: number; orientation: VizOrientation; alignmentFactors: D; + /** + * Total number of values being shown in repeater + */ + count: number; } interface DefaultProps { @@ -110,7 +114,14 @@ export class VizRepeater extends PureComponent, State> items.push(
- {renderValue({ value, width: itemWidth, height: itemHeight, alignmentFactors, orientation })} + {renderValue({ + value, + width: itemWidth, + height: itemHeight, + alignmentFactors, + orientation, + count: values.length, + })}
); @@ -178,6 +189,7 @@ export class VizRepeater extends PureComponent, State> height: vizHeight, alignmentFactors, orientation: resolvedOrientation, + count: values.length, })}
); diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index a7c1ae4b58d..7774b855f8b 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -65,6 +65,7 @@ export { BigValueSparkline, BigValueGraphMode, BigValueJustifyMode, + BigValueTextMode, } from './BigValue/BigValue'; export { Gauge } from './Gauge/Gauge'; diff --git a/public/app/plugins/panel/bargauge/BarGaugePanel.tsx b/public/app/plugins/panel/bargauge/BarGaugePanel.tsx index 504acd97be6..4768c3ba40a 100644 --- a/public/app/plugins/panel/bargauge/BarGaugePanel.tsx +++ b/public/app/plugins/panel/bargauge/BarGaugePanel.tsx @@ -5,6 +5,8 @@ import { getDisplayValueAlignmentFactors, getFieldDisplayValues, PanelProps, + FieldConfig, + DisplayValue, } from '@grafana/data'; import { BarGauge, DataLinksContextMenu, VizRepeater, VizRepeaterRenderValueProps } from '@grafana/ui'; @@ -18,13 +20,13 @@ export class BarGaugePanel extends PureComponent> { menuProps: DataLinksContextMenuApi ): JSX.Element => { 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 { openMenu, targetClassName } = menuProps; return ( > { ); } } + +export function clearNameForSingleSeries(count: number, field: FieldConfig, display: DisplayValue): DisplayValue { + if (count === 1 && !field.displayName) { + return { + ...display, + title: undefined, + }; + } + + return display; +} diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index 3f2556d8340..81f53fdf675 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -5,6 +5,7 @@ import { DataLinksContextMenuApi } from '@grafana/ui/src/components/DataLinks/Da import { config } from 'app/core/config'; import { GaugeOptions } from './types'; +import { clearNameForSingleSeries } from '../bargauge/BarGaugePanel'; export class GaugePanel extends PureComponent> { renderComponent = ( @@ -12,13 +13,13 @@ export class GaugePanel extends PureComponent> { menuProps: DataLinksContextMenuApi ): JSX.Element => { const { options } = this.props; - const { value, width, height } = valueProps; + const { width, height, count, value } = valueProps; const { field, display } = value; const { openMenu, targetClassName } = menuProps; return ( { it('change from angular singlestat sparkline disabled', () => { @@ -48,4 +49,16 @@ describe('Stat Panel Migrations', () => { const options = statPanelChangedHandler(panel, 'singlestat', old); 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); + }); }); diff --git a/public/app/plugins/panel/stat/StatMigrations.ts b/public/app/plugins/panel/stat/StatMigrations.ts index 84f39318d51..ccc68ddde5c 100644 --- a/public/app/plugins/panel/stat/StatMigrations.ts +++ b/public/app/plugins/panel/stat/StatMigrations.ts @@ -1,6 +1,7 @@ import { sharedSingleStatPanelChangedHandler, BigValueGraphMode, BigValueColorMode } from '@grafana/ui'; import { PanelModel } from '@grafana/data'; import { StatPanelOptions } from './types'; +import { BigValueTextMode } from '@grafana/ui/src/components/BigValue/BigValue'; // This is called when the panel changes from another panel export const statPanelChangedHandler = ( @@ -23,6 +24,10 @@ export const statPanelChangedHandler = ( } else { options.colorMode = BigValueColorMode.Value; } + + if (oldOptions.valueName === 'name') { + options.textMode = BigValueTextMode.Name; + } } return options; diff --git a/public/app/plugins/panel/stat/StatPanel.tsx b/public/app/plugins/panel/stat/StatPanel.tsx index 6d5ab11793b..85885d0483c 100644 --- a/public/app/plugins/panel/stat/StatPanel.tsx +++ b/public/app/plugins/panel/stat/StatPanel.tsx @@ -52,6 +52,7 @@ export class StatPanel extends PureComponent> { colorMode={options.colorMode} graphMode={options.graphMode} justifyMode={options.justifyMode} + textMode={options.textMode} alignmentFactors={alignmentFactors} width={width} height={height} diff --git a/public/app/plugins/panel/stat/module.tsx b/public/app/plugins/panel/stat/module.tsx index fa1fdcfb867..873af89a110 100644 --- a/public/app/plugins/panel/stat/module.tsx +++ b/public/app/plugins/panel/stat/module.tsx @@ -1,4 +1,4 @@ -import { sharedSingleStatMigrationHandler } from '@grafana/ui'; +import { sharedSingleStatMigrationHandler, BigValueTextMode } from '@grafana/ui'; import { PanelPlugin } from '@grafana/data'; import { StatPanelOptions, addStandardDataReduceOptions } from './types'; import { StatPanel } from './StatPanel'; @@ -9,6 +9,22 @@ export const plugin = new PanelPlugin(StatPanel) .setPanelOptions(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 .addRadio({ path: 'colorMode', diff --git a/public/app/plugins/panel/stat/types.ts b/public/app/plugins/panel/stat/types.ts index b192e2f1dda..533189c2b98 100644 --- a/public/app/plugins/panel/stat/types.ts +++ b/public/app/plugins/panel/stat/types.ts @@ -1,7 +1,12 @@ -import { SingleStatBaseOptions, BigValueColorMode, BigValueGraphMode, BigValueJustifyMode } from '@grafana/ui'; +import { + SingleStatBaseOptions, + BigValueColorMode, + BigValueGraphMode, + BigValueJustifyMode, + BigValueTextMode, +} from '@grafana/ui'; import { ReducerID, - SelectableValue, standardEditorsRegistry, FieldOverrideContext, getFieldDisplayName, @@ -14,23 +19,9 @@ export interface StatPanelOptions extends SingleStatBaseOptions { graphMode: BigValueGraphMode; colorMode: BigValueColorMode; justifyMode: BigValueJustifyMode; + textMode: BigValueTextMode; } -export const colorModes: Array> = [ - { value: BigValueColorMode.Value, label: 'Value' }, - { value: BigValueColorMode.Background, label: 'Background' }, -]; - -export const graphModes: Array> = [ - { value: BigValueGraphMode.None, label: 'None' }, - { value: BigValueGraphMode.Area, label: 'Area graph' }, -]; - -export const justifyModes: Array> = [ - { value: BigValueJustifyMode.Auto, label: 'Auto' }, - { value: BigValueJustifyMode.Center, label: 'Center' }, -]; - export function addStandardDataReduceOptions( builder: PanelOptionsEditorBuilder, includeOrientation = true, @@ -65,7 +56,7 @@ export function addStandardDataReduceOptions( builder.addCustomEditor({ id: 'reduceOptions.calcs', path: 'reduceOptions.calcs', - name: 'Value', + name: 'Calculation', description: 'Choose a reducer function / calculation', editor: standardEditorsRegistry.get('stats-picker').editor as any, defaultValue: [ReducerID.mean],