BarGauge: Add legend support (#92449)

This commit is contained in:
Adela Almasan 2024-08-28 14:26:55 -06:00 committed by GitHub
parent 9d173ef579
commit 692280cd32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 120 additions and 24 deletions

View File

@ -141,6 +141,10 @@ Automatically show y-axis scrollbar when there's a large amount of data.
This option only applies when bar size is set to manual.
{{% /admonition %}}
## Legend options
{{< docs/shared lookup="visualizations/legend-options-1.md" source="grafana" version="<GRAFANA_VERSION>" >}}
## Standard options
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}

View File

@ -12,7 +12,7 @@ import * as common from '@grafana/schema';
export const pluginVersion = "11.3.0-pre";
export interface Options extends common.SingleStatBaseOptions {
export interface Options extends common.OptionsWithLegend, common.SingleStatBaseOptions {
displayMode: common.BarGaugeDisplayMode;
maxVizHeight: number;
minVizHeight: number;

View File

@ -6,7 +6,8 @@ import { LegendDisplayMode, OptionsWithLegend } from '@grafana/schema';
*/
export function addLegendOptions<T extends OptionsWithLegend>(
builder: PanelOptionsEditorBuilder<T>,
includeLegendCalcs = true
includeLegendCalcs = true,
showLegend = true
) {
builder
.addBooleanSwitch({
@ -14,7 +15,7 @@ export function addLegendOptions<T extends OptionsWithLegend>(
name: 'Visibility',
category: ['Legend'],
description: '',
defaultValue: true,
defaultValue: showLegend,
})
.addRadio({
path: 'legend.displayMode',

View File

@ -0,0 +1,58 @@
import { memo } from 'react';
import { DataFrame, FieldType, getFieldSeriesColor } from '@grafana/data';
import { Field } from '@grafana/data/';
import { AxisPlacement, VizLegendOptions } from '@grafana/schema';
import { useTheme2, VizLayout, VizLayoutLegendProps, VizLegend, VizLegendItem } from '@grafana/ui';
import { getDisplayValuesForCalcs } from '@grafana/ui/src/components/uPlot/utils';
interface BarGaugeLegendProps extends VizLegendOptions, Omit<VizLayoutLegendProps, 'children'> {
data: DataFrame[];
colorField?: Field | null;
}
export const BarGaugeLegend = memo(
({ data, placement, calcs, displayMode, ...vizLayoutLegendProps }: BarGaugeLegendProps) => {
const theme = useTheme2();
let legendItems: VizLegendItem[] = [];
data.forEach((series, frameIndex) => {
series.fields.forEach((field, i) => {
const fieldIndex = i + 1;
if (field.type === FieldType.time || field.config.custom?.hideFrom?.legend) {
return;
}
const label = field.state?.displayName ?? field.name;
const color = getFieldSeriesColor(field, theme).color;
const item: VizLegendItem = {
label: label.toString(),
color,
yAxis: field.config.custom?.axisPlacement === AxisPlacement.Right ? 2 : 1,
disabled: field.state?.hideFrom?.viz,
getDisplayValues: () => getDisplayValuesForCalcs(calcs, field, theme),
getItemKey: () => `${label}-${frameIndex}-${fieldIndex}`,
};
legendItems.push(item);
});
});
return (
<VizLayout.Legend placement={placement} {...vizLayoutLegendProps}>
<VizLegend
placement={placement}
items={legendItems}
displayMode={displayMode}
sortBy={vizLayoutLegendProps.sortBy}
sortDesc={vizLayoutLegendProps.sortDesc}
isSortable={true}
/>
</VizLayout.Legend>
);
}
);
BarGaugeLegend.displayName = 'BarGaugeLegend';

View File

@ -3,7 +3,7 @@ import { uniqueId } from 'lodash';
import { dateMath, dateTime, EventBus, LoadingState, TimeRange, toDataFrame, VizOrientation } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { BarGaugeDisplayMode, BarGaugeValueMode } from '@grafana/schema';
import { BarGaugeDisplayMode, BarGaugeValueMode, LegendDisplayMode, LegendPlacement } from '@grafana/schema';
import { BarGaugeNamePlacement, BarGaugeSizing } from '@grafana/schema/dist/esm/common/common.gen';
import { BarGaugePanel, BarGaugePanelProps } from './BarGaugePanel';
@ -105,6 +105,12 @@ function buildPanelData(overrideValues?: Partial<BarGaugePanelProps>): BarGaugeP
valueMode: BarGaugeValueMode.Color,
namePlacement: BarGaugeNamePlacement.Auto,
sizing: BarGaugeSizing.Auto,
legend: {
showLegend: false,
placement: 'bottom' as LegendPlacement,
calcs: [],
displayMode: LegendDisplayMode.List,
},
},
transparent: false,
timeRange,

View File

@ -2,22 +2,23 @@ import { isNumber } from 'lodash';
import { PureComponent } from 'react';
import {
DisplayProcessor,
DisplayValue,
DisplayValueAlignmentFactors,
FieldConfig,
FieldDisplay,
getDisplayValueAlignmentFactors,
getFieldDisplayValues,
PanelProps,
FieldConfig,
DisplayProcessor,
DisplayValue,
VizOrientation,
} from '@grafana/data';
import { BarGaugeSizing } from '@grafana/schema';
import { BarGauge, DataLinksContextMenu, VizRepeater, VizRepeaterRenderValueProps } from '@grafana/ui';
import { BarGauge, DataLinksContextMenu, VizLayout, VizRepeater, VizRepeaterRenderValueProps } from '@grafana/ui';
import { DataLinksContextMenuApi } from '@grafana/ui/src/components/DataLinks/DataLinksContextMenu';
import { config } from 'app/core/config';
import { Options, defaultOptions } from './panelcfg.gen';
import { BarGaugeLegend } from './BarGaugeLegend';
import { defaultOptions, Options } from './panelcfg.gen';
export class BarGaugePanel extends PureComponent<BarGaugePanelProps> {
renderComponent = (
@ -123,26 +124,43 @@ export class BarGaugePanel extends PureComponent<BarGaugePanelProps> {
return { minVizWidth, minVizHeight, maxVizHeight };
}
getLegend() {
const { options, data } = this.props;
const { legend } = options;
if (legend.showLegend && data && data.series.length > 0) {
return <BarGaugeLegend data={data.series} {...legend} />;
}
return null;
}
render() {
const { height, width, options, data, renderCounter } = this.props;
const { minVizWidth, minVizHeight, maxVizHeight } = this.calcBarSize();
return (
<VizRepeater
source={data}
getAlignmentFactors={getDisplayValueAlignmentFactors}
getValues={this.getValues}
renderValue={this.renderValue}
renderCounter={renderCounter}
width={width}
height={height}
maxVizHeight={maxVizHeight}
minVizWidth={minVizWidth}
minVizHeight={minVizHeight}
itemSpacing={this.getItemSpacing()}
orientation={options.orientation}
/>
<VizLayout width={width} height={height} legend={this.getLegend()}>
{(vizWidth: number, vizHeight: number) => {
return (
<VizRepeater
source={data}
getAlignmentFactors={getDisplayValueAlignmentFactors}
getValues={this.getValues}
renderValue={this.renderValue}
renderCounter={renderCounter}
width={vizWidth}
height={vizHeight}
maxVizHeight={maxVizHeight}
minVizWidth={minVizWidth}
minVizHeight={minVizHeight}
itemSpacing={this.getItemSpacing()}
orientation={options.orientation}
/>
);
}}
</VizLayout>
);
}
}

View File

@ -14,6 +14,7 @@ export const plugin = new PanelPlugin<Options>(BarGaugePanel)
.setPanelOptions((builder) => {
addStandardDataReduceOptions(builder);
addOrientationOption(builder);
commonOptionsBuilder.addLegendOptions(builder, true, false);
commonOptionsBuilder.addTextSizeOptions(builder);
builder

View File

@ -26,6 +26,14 @@ composableKinds: PanelCfg: {
version: [0, 0]
schema: {
Options: {
common.OptionsWithLegend
//// trying to set nested default, not working
//common.OptionsWithLegend | *{
// legend: common.VizLegendOptions | *{
// showLegend: false
// }
//}
common.SingleStatBaseOptions
displayMode: common.BarGaugeDisplayMode & (*"gradient" | _)
valueMode: common.BarGaugeValueMode & (*"color" | _)

View File

@ -10,7 +10,7 @@
import * as common from '@grafana/schema';
export interface Options extends common.SingleStatBaseOptions {
export interface Options extends common.OptionsWithLegend, common.SingleStatBaseOptions {
displayMode: common.BarGaugeDisplayMode;
maxVizHeight: number;
minVizHeight: number;