Chore: convert some class components to functional (#112661)

* convert BigValue to functional component

* convert AbstractList

* Revert "convert AbstractList"

This reverts commit 673c22a81d.

* ignore and deprecate remaining list components

* convert NotFoundDisplay

* convert rectangle

* fix some test components

* convert thresholds.tsx

* convert SpanGraph to functional component

* convert InviteeRow to functional component

* converted InviteesTable to functional component

* convert PanelPluginError to functional components

* convert UserOrganizations

* convert UserSessions to a functional component

* convert UserTeams to a functional component

* convert CloudMonitoringCheatSheet to a functional component

* convert ConfigEditor a react functional component

* convert TestInfoTab to a functional component

* convert DebugPanel to a functional component

* fix types + BigValue story
This commit is contained in:
Ashley Harrison
2025-10-21 17:33:38 +01:00
committed by GitHub
parent 5d82502535
commit 7678fc9de1
23 changed files with 471 additions and 592 deletions
@@ -29,27 +29,36 @@ const meta: Meta = {
width: { control: { type: 'range', min: 200, max: 800 } },
height: { control: { type: 'range', min: 200, max: 800 } },
colorMode: {
control: { type: 'select', options: [BigValueColorMode.Value, BigValueColorMode.Background] },
control: {
type: 'select',
},
options: [BigValueColorMode.Value, BigValueColorMode.Background],
},
graphMode: {
control: { type: 'select' },
options: [BigValueGraphMode.Area, BigValueGraphMode.None],
},
justifyMode: {
control: { type: 'select' },
options: [BigValueJustifyMode.Auto, BigValueJustifyMode.Center],
},
graphMode: { control: { type: 'select', options: [BigValueGraphMode.Area, BigValueGraphMode.None] } },
justifyMode: { control: { type: 'select', options: [BigValueJustifyMode.Auto, BigValueJustifyMode.Center] } },
textMode: {
control: {
type: 'radio',
options: [
BigValueTextMode.Auto,
BigValueTextMode.Name,
BigValueTextMode.ValueAndName,
BigValueTextMode.None,
BigValueTextMode.Value,
],
},
options: [
BigValueTextMode.Auto,
BigValueTextMode.Name,
BigValueTextMode.ValueAndName,
BigValueTextMode.None,
BigValueTextMode.Value,
],
},
color: { control: 'color' },
},
};
interface StoryProps extends Partial<Props> {
interface StoryProps extends Props {
numeric: number;
title: string;
color: string;
@@ -1,6 +1,5 @@
import { cx } from '@emotion/css';
import { PureComponent } from 'react';
import * as React from 'react';
import { memo, type MouseEventHandler } from 'react';
import { DisplayValue, DisplayValueAlignmentFactors, FieldSparkline } from '@grafana/data';
import { PercentChangeColorMode, VizTextDisplayOptions } from '@grafana/schema';
@@ -51,7 +50,7 @@ export interface Props extends Themeable2 {
/** Sparkline values for showing a graph under/behind the value */
sparkline?: FieldSparkline;
/** onClick handler for the value */
onClick?: React.MouseEventHandler<HTMLElement>;
onClick?: MouseEventHandler<HTMLElement>;
/** Custom styling */
className?: string;
/** Color mode for coloring the value or the background */
@@ -83,58 +82,55 @@ export interface Props extends Themeable2 {
disableWideLayout?: boolean;
}
export class BigValue extends PureComponent<Props> {
static defaultProps: Partial<Props> = {
justifyMode: BigValueJustifyMode.Auto,
};
export const BigValue = memo<Props>((props) => {
const { onClick, className, hasLinks, theme, justifyMode = BigValueJustifyMode.Auto } = props;
render() {
const { onClick, className, hasLinks, theme } = 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;
const percentChange = this.props.value.percentChange;
const percentChangeColorMode = this.props.percentChangeColorMode;
const showPercentChange = percentChange != null && !Number.isNaN(percentChange);
const layout = buildLayout({ ...props, justifyMode });
const panelStyles = layout.getPanelStyles();
const valueAndTitleContainerStyles = layout.getValueAndTitleContainerStyles();
const valueStyles = layout.getValueStyles();
const titleStyles = layout.getTitleStyles();
const textValues = layout.textValues;
const percentChange = props.value.percentChange;
const percentChangeColorMode = props.percentChangeColorMode;
const showPercentChange = percentChange != null && !Number.isNaN(percentChange);
// When there is an outer data link this tooltip will override the outer native tooltip
const tooltip = hasLinks ? undefined : textValues.tooltip;
if (!onClick) {
return (
<div className={className} style={panelStyles} title={tooltip}>
<div style={valueAndTitleContainerStyles}>
{textValues.title && <div style={titleStyles}>{textValues.title}</div>}
<FormattedValueDisplay value={textValues} style={valueStyles} />
{showPercentChange && (
<PercentChange
percentChange={percentChange}
styles={layout.getPercentChangeStyles(percentChange, percentChangeColorMode, valueStyles)}
/>
)}
</div>
{layout.renderChart()}
</div>
);
}
// When there is an outer data link this tooltip will override the outer native tooltip
const tooltip = hasLinks ? undefined : textValues.tooltip;
if (!onClick) {
return (
<button
type="button"
className={cx(clearButtonStyles(theme), className)}
style={panelStyles}
onClick={onClick}
title={tooltip}
>
<div className={className} style={panelStyles} title={tooltip}>
<div style={valueAndTitleContainerStyles}>
{textValues.title && <div style={titleStyles}>{textValues.title}</div>}
<FormattedValueDisplay value={textValues} style={valueStyles} />
{showPercentChange && (
<PercentChange
percentChange={percentChange}
styles={layout.getPercentChangeStyles(percentChange, percentChangeColorMode, valueStyles)}
/>
)}
</div>
{layout.renderChart()}
</button>
</div>
);
}
}
return (
<button
type="button"
className={cx(clearButtonStyles(theme), className)}
style={panelStyles}
onClick={onClick}
title={tooltip}
>
<div style={valueAndTitleContainerStyles}>
{textValues.title && <div style={titleStyles}>{textValues.title}</div>}
<FormattedValueDisplay value={textValues} style={valueStyles} />
</div>
{layout.renderChart()}
</button>
);
});
BigValue.displayName = 'BigValue';
@@ -26,6 +26,9 @@ const getStyles = stylesFactory((inlineList = false) => ({
}),
}));
/** @deprecated Use ul/li/arr.map directly instead */
// no point converting, this is deprecated
// eslint-disable-next-line react-prefer-function-component/react-prefer-function-component
export class AbstractList<T> extends PureComponent<AbstractListProps<T>> {
constructor(props: AbstractListProps<T>) {
super(props);
@@ -3,6 +3,8 @@ import { PureComponent } from 'react';
import { ListProps, AbstractList } from './AbstractList';
/** @deprecated Use ul/li/arr.map directly instead */
// no point converting, this is deprecated
// eslint-disable-next-line react-prefer-function-component/react-prefer-function-component
export class InlineList<T> extends PureComponent<ListProps<T>> {
render() {
return <AbstractList inline {...this.props} />;
@@ -3,6 +3,8 @@ import { PureComponent } from 'react';
import { ListProps, AbstractList } from './AbstractList';
/** @deprecated Use ul/li/arr.map directly instead */
// no point converting, this is deprecated
// eslint-disable-next-line react-prefer-function-component/react-prefer-function-component
export class List<T> extends PureComponent<ListProps<T>> {
render() {
return <AbstractList {...this.props} />;