Bar Gauge: Add field name placement option (#75932)

Co-authored-by: Adela Almasan <adela.almasan@grafana.com>
This commit is contained in:
Nathan Marrs 2023-10-05 18:31:03 +02:00 committed by GitHub
parent e902d8fd10
commit b94d06bfa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 92 additions and 12 deletions

View File

@ -31,6 +31,7 @@ It extends [SingleStatBaseOptions](#singlestatbaseoptions).
| `displayMode` | string | **Yes** | | Enum expressing the possible display modes<br/>for the bar gauge component of Grafana UI<br/>Possible values are: `basic`, `lcd`, `gradient`. |
| `minVizHeight` | uint32 | **Yes** | `10` | |
| `minVizWidth` | uint32 | **Yes** | `0` | |
| `namePlacement` | string | **Yes** | | Allows for the bar gauge name to be placed explicitly<br/>Possible values are: `auto`, `top`, `left`. |
| `showUnfilled` | boolean | **Yes** | `true` | |
| `valueMode` | string | **Yes** | | Allows for the table cell gauge display type to set the gauge mode.<br/>Possible values are: `color`, `text`, `hidden`. |
| `orientation` | string | No | | *(Inherited from [SingleStatBaseOptions](#singlestatbaseoptions))*<br/>TODO docs<br/>Possible values are: `auto`, `vertical`, `horizontal`. |

View File

@ -55,7 +55,7 @@ Adjust how the bar gauge is displayed.
Choose a stacking direction.
- **Auto -** Grafana selects what it thinks is the best orientation.
- **Auto -** Grafana determines the best orientation.
- **Horizontal -** Bars stretch horizontally, left to right.
- **Vertical -** Bars stretch vertically, bottom to top.
@ -67,6 +67,26 @@ Choose a display mode.
- **Retro LCD -** The gauge is split into small cells that are lit or unlit.
- **Basic -** Single color based on the matching threshold.
### Value display
Choose a value display mode.
- **Value color -** Value color is determined by value.
- **Text color -** Value color is default text color.
- **Hidden -** Values are hidden.
### Name placement
Choose a name placement mode.
{{% admonition type="note" %}}
This option only applies when the orientation of the bar gauge is horizontal. When the bar gauge is in the vertical orientation, names are always placed at the bottom of each bar gauge.
{{% /admonition %}}
- **Auto -** Grafana determines the best placement.
- **Top -** Names are placed on top of each bar gauge.
- **Left -** Names are placed to the left of each bar gauge.
### Show unfilled area
Select this if you want to render the unfilled region of the bars as dark gray. Not applicable to Retro LCD display mode.

View File

@ -635,6 +635,15 @@ export enum BarGaugeValueMode {
Text = 'text',
}
/**
* Allows for the bar gauge name to be placed explicitly
*/
export enum BarGaugeNamePlacement {
Auto = 'auto',
Left = 'left',
Top = 'top',
}
/**
* TODO docs
*/

View File

@ -246,6 +246,9 @@ BarGaugeDisplayMode: "basic" | "lcd" | "gradient" @cuetsy(kind="enum")
// Allows for the table cell gauge display type to set the gauge mode.
BarGaugeValueMode: "color" | "text" | "hidden" @cuetsy(kind="enum")
// Allows for the bar gauge name to be placed explicitly
BarGaugeNamePlacement: "auto" | "top" | "left" @cuetsy(kind="enum")
// TODO docs
VizTooltipOptions: {
mode: TooltipDisplayMode

View File

@ -17,6 +17,7 @@ export interface Options extends common.SingleStatBaseOptions {
displayMode: common.BarGaugeDisplayMode;
minVizHeight: number;
minVizWidth: number;
namePlacement: common.BarGaugeNamePlacement;
showUnfilled: boolean;
valueMode: common.BarGaugeValueMode;
}
@ -25,6 +26,7 @@ export const defaultOptions: Partial<Options> = {
displayMode: common.BarGaugeDisplayMode.Gradient,
minVizHeight: 10,
minVizWidth: 0,
namePlacement: common.BarGaugeNamePlacement.Auto,
showUnfilled: true,
valueMode: common.BarGaugeValueMode.Color,
};

View File

@ -11,7 +11,7 @@ import {
getDisplayProcessor,
createTheme,
} from '@grafana/data';
import { BarGaugeDisplayMode, BarGaugeValueMode } from '@grafana/schema';
import { BarGaugeDisplayMode, BarGaugeNamePlacement, BarGaugeValueMode } from '@grafana/schema';
import {
BarGauge,
@ -56,6 +56,7 @@ function getProps(propOverrides?: Partial<Props>): Props {
value: field.display(25),
theme,
orientation: VizOrientation.Horizontal,
namePlacement: BarGaugeNamePlacement.Auto,
};
Object.assign(props, propOverrides);
@ -226,6 +227,28 @@ describe('BarGauge', () => {
expect(styles.wrapper.flexDirection).toBe('column');
});
it('should place left even if height > 40 if name placement is set to left', () => {
const props = getProps({
height: 41,
value: getValue(100, 'AA'),
orientation: VizOrientation.Horizontal,
namePlacement: BarGaugeNamePlacement.Left,
});
const styles = getTitleStyles(props);
expect(styles.wrapper.flexDirection).toBe('row');
});
it('should place above even if height < 40 if name placement is set to top', () => {
const props = getProps({
height: 39,
value: getValue(100, 'AA'),
orientation: VizOrientation.Horizontal,
namePlacement: BarGaugeNamePlacement.Top,
});
const styles = getTitleStyles(props);
expect(styles.wrapper.flexDirection).toBe('column');
});
it('should place below if height < 40', () => {
const props = getProps({
height: 30,

View File

@ -20,7 +20,7 @@ import {
VizOrientation,
} from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { BarGaugeDisplayMode, BarGaugeValueMode, VizTextDisplayOptions } from '@grafana/schema';
import { BarGaugeDisplayMode, BarGaugeNamePlacement, BarGaugeValueMode, VizTextDisplayOptions } from '@grafana/schema';
import { Themeable2 } from '../../types';
import { calculateFontSize, measureText } from '../../utils/measureText';
@ -50,6 +50,7 @@ export interface Props extends Themeable2 {
showUnfilled?: boolean;
alignmentFactors?: DisplayValueAlignmentFactors;
valueDisplayMode?: BarGaugeValueMode;
namePlacement?: BarGaugeNamePlacement;
}
export class BarGauge extends PureComponent<Props> {
@ -237,7 +238,7 @@ function isVertical(orientation: VizOrientation) {
}
function calculateTitleDimensions(props: Props): TitleDimensions {
const { height, width, alignmentFactors, orientation, text } = props;
const { height, width, alignmentFactors, orientation, text, namePlacement } = props;
const title = alignmentFactors ? alignmentFactors.title : props.value.title;
if (!title) {
@ -254,8 +255,10 @@ function calculateTitleDimensions(props: Props): TitleDimensions {
};
}
// if height above 40 put text to above bar
if (height > 40) {
const shouldDisplayValueAbove =
(height > 40 && namePlacement === BarGaugeNamePlacement.Auto) || namePlacement === BarGaugeNamePlacement.Top;
if (shouldDisplayValueAbove) {
if (text?.titleSize) {
return {
fontSize: text?.titleSize,

View File

@ -5,6 +5,7 @@ import React from 'react';
import { dateMath, dateTime, EventBus, LoadingState, TimeRange, toDataFrame, VizOrientation } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { BarGaugeDisplayMode, BarGaugeValueMode } from '@grafana/schema';
import { BarGaugeNamePlacement } from '@grafana/schema/dist/esm/common/common.gen';
import { BarGaugePanel, BarGaugePanelProps } from './BarGaugePanel';
@ -102,6 +103,7 @@ function buildPanelData(overrideValues?: Partial<BarGaugePanelProps>): BarGaugeP
minVizHeight: 10,
minVizWidth: 0,
valueMode: BarGaugeValueMode.Color,
namePlacement: BarGaugeNamePlacement.Auto,
},
transparent: false,
timeRange,

View File

@ -50,6 +50,7 @@ export class BarGaugePanel extends PureComponent<BarGaugePanelProps> {
alignmentFactors={count > 1 ? alignmentFactors : undefined}
showUnfilled={options.showUnfilled}
valueDisplayMode={options.valueMode}
namePlacement={options.namePlacement}
/>
);
};

View File

@ -1,5 +1,5 @@
import { PanelPlugin, VizOrientation } from '@grafana/data';
import { BarGaugeDisplayMode, BarGaugeValueMode } from '@grafana/schema';
import { BarGaugeDisplayMode, BarGaugeNamePlacement, BarGaugeValueMode } from '@grafana/schema';
import { commonOptionsBuilder, sharedSingleStatPanelChangedHandler } from '@grafana/ui';
import { addOrientationOption, addStandardDataReduceOptions } from '../stat/common';
@ -41,6 +41,19 @@ export const plugin = new PanelPlugin<Options>(BarGaugePanel)
},
defaultValue: defaultOptions.valueMode,
})
.addRadio({
path: 'namePlacement',
name: 'Name placement',
settings: {
options: [
{ value: BarGaugeNamePlacement.Auto, label: 'Auto' },
{ value: BarGaugeNamePlacement.Top, label: 'Top' },
{ value: BarGaugeNamePlacement.Left, label: 'Left' },
],
},
defaultValue: defaultOptions.namePlacement,
showIf: (options) => options.orientation !== VizOrientation.Vertical,
})
.addBooleanSwitch({
path: 'showUnfilled',
name: 'Show unfilled area',

View File

@ -27,11 +27,12 @@ composableKinds: PanelCfg: {
schema: {
Options: {
common.SingleStatBaseOptions
displayMode: common.BarGaugeDisplayMode & (*"gradient" | _)
valueMode: common.BarGaugeValueMode & (*"color" | _)
showUnfilled: bool | *true
minVizWidth: uint32 | *0
minVizHeight: uint32 | *10
displayMode: common.BarGaugeDisplayMode & (*"gradient" | _)
valueMode: common.BarGaugeValueMode & (*"color" | _)
namePlacement: common.BarGaugeNamePlacement & (*"auto" | _)
showUnfilled: bool | *true
minVizWidth: uint32 | *0
minVizHeight: uint32 | *10
} @cuetsy(kind="interface")
}
}]

View File

@ -14,6 +14,7 @@ export interface Options extends common.SingleStatBaseOptions {
displayMode: common.BarGaugeDisplayMode;
minVizHeight: number;
minVizWidth: number;
namePlacement: common.BarGaugeNamePlacement;
showUnfilled: boolean;
valueMode: common.BarGaugeValueMode;
}
@ -22,6 +23,7 @@ export const defaultOptions: Partial<Options> = {
displayMode: common.BarGaugeDisplayMode.Gradient,
minVizHeight: 10,
minVizWidth: 0,
namePlacement: common.BarGaugeNamePlacement.Auto,
showUnfilled: true,
valueMode: common.BarGaugeValueMode.Color,
};