React 19: non-breaking type and test changes (#114760)
non-breaking type and test changes needed for react 19
This commit is contained in:
@@ -19,7 +19,7 @@ export interface Props<T = string> extends Omit<FieldProps, 'children'> {
|
||||
/** Custom error message to display on saving */
|
||||
saveErrorMessage?: string;
|
||||
/** Input that will save its value on change */
|
||||
children: (onChange: (newValue: T) => void) => React.ReactElement;
|
||||
children: (onChange: (newValue: T) => void) => React.ReactElement<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,7 @@ type BaseProps = {
|
||||
size?: ComponentSize;
|
||||
variant?: ButtonVariant;
|
||||
fill?: ButtonFill;
|
||||
icon?: IconName | React.ReactElement;
|
||||
icon?: IconName | React.ReactElement<IconElementProps>;
|
||||
className?: string;
|
||||
fullWidth?: boolean;
|
||||
type?: string;
|
||||
@@ -207,8 +207,13 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
||||
|
||||
LinkButton.displayName = 'LinkButton';
|
||||
|
||||
type IconElementProps = {
|
||||
className?: string;
|
||||
size?: IconSize;
|
||||
};
|
||||
|
||||
interface IconRendererProps {
|
||||
icon?: IconName | React.ReactElement<{ className?: string; size?: IconSize }>;
|
||||
icon?: IconName | React.ReactElement<IconElementProps>;
|
||||
size?: IconSize;
|
||||
className?: string;
|
||||
iconType?: IconType;
|
||||
|
||||
@@ -316,7 +316,9 @@ const BaseActions = ({ children, disabled, variant, className }: ActionsProps) =
|
||||
return (
|
||||
<div className={cx(css, className)}>
|
||||
{React.Children.map(children, (child) => {
|
||||
return React.isValidElement(child) ? cloneElement(child, { disabled: isDisabled, ...child.props }) : null;
|
||||
return React.isValidElement<Record<string, unknown>>(child)
|
||||
? cloneElement(child, child.type !== React.Fragment ? { disabled: isDisabled, ...child.props } : undefined)
|
||||
: null;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -530,8 +530,8 @@ describe('Combobox', () => {
|
||||
const input = screen.getByRole('combobox');
|
||||
await user.click(input);
|
||||
|
||||
await user.type(input, 'fir');
|
||||
await act(async () => {
|
||||
await user.type(input, 'fir');
|
||||
jest.advanceTimersByTime(500); // Custom value while typing
|
||||
});
|
||||
|
||||
@@ -604,8 +604,8 @@ describe('Combobox', () => {
|
||||
const input = screen.getByRole('combobox');
|
||||
await user.click(input);
|
||||
|
||||
await user.type(input, 'Opt');
|
||||
await act(async () => {
|
||||
await user.type(input, 'Opt');
|
||||
jest.advanceTimersByTime(500); // Custom value while typing
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Button, ButtonVariant } from '../Button/Button';
|
||||
export interface Props {
|
||||
/** Confirm action callback */
|
||||
onConfirm(): void;
|
||||
children: string | ReactElement;
|
||||
children: string | ReactElement<Record<string, unknown>>;
|
||||
/** Custom button styles */
|
||||
className?: string;
|
||||
/** Button size */
|
||||
|
||||
@@ -24,7 +24,7 @@ import { TooltipPlacement } from '../Tooltip/types';
|
||||
export interface Props {
|
||||
overlay: React.ReactElement | (() => React.ReactElement);
|
||||
placement?: TooltipPlacement;
|
||||
children: React.ReactElement;
|
||||
children: React.ReactElement<Record<string, unknown>>;
|
||||
root?: HTMLElement;
|
||||
/** Amount in pixels to nudge the dropdown vertically and horizontally, respectively. */
|
||||
offset?: [number, number];
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Label } from './Label';
|
||||
|
||||
export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/** Form input element, i.e Input or Switch */
|
||||
children: React.ReactElement;
|
||||
children: React.ReactElement<Record<string, unknown>>;
|
||||
/** Label for the field */
|
||||
label?: React.ReactNode;
|
||||
/** Description of the field */
|
||||
@@ -85,7 +85,7 @@ export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
||||
<div className={cx(styles.field, horizontal && styles.fieldHorizontal, className)} {...otherProps}>
|
||||
{labelElement}
|
||||
<div>
|
||||
<div ref={ref}>{React.cloneElement(children, childProps)}</div>
|
||||
<div ref={ref}>{React.cloneElement(children, children.type !== React.Fragment ? childProps : undefined)}</div>
|
||||
{invalid && error && !horizontal && (
|
||||
<div
|
||||
className={cx(styles.fieldValidationWrapper, {
|
||||
|
||||
@@ -212,14 +212,13 @@ export class UnThemedQueryField extends PureComponent<QueryFieldProps, QueryFiel
|
||||
<div className="slate-query-field" data-testid={selectors.components.QueryField.container}>
|
||||
<Editor
|
||||
ref={(editor) => {
|
||||
this.editor = editor!;
|
||||
this.editor = editor;
|
||||
}}
|
||||
schema={SCHEMA}
|
||||
autoCorrect={false}
|
||||
readOnly={this.props.disabled}
|
||||
onBlur={this.handleBlur}
|
||||
onClick={this.props.onClick}
|
||||
// onKeyDown={this.onKeyDown}
|
||||
onChange={(change: { value: Value }) => {
|
||||
this.onChange(change.value, false);
|
||||
}}
|
||||
|
||||
@@ -197,7 +197,7 @@ export const VirtualizedSelectMenu = ({
|
||||
// check if a child has array children (and is therefore a react-select group)
|
||||
// we need to flatten these so the correct count and elements are passed to the virtualized list
|
||||
const hasArrayChildren = (child: React.ReactNode) => {
|
||||
return React.isValidElement(child) && Array.isArray(child.props.children);
|
||||
return React.isValidElement<Record<string, unknown>>(child) && Array.isArray(child.props.children);
|
||||
};
|
||||
|
||||
VirtualizedSelectMenu.displayName = 'VirtualizedSelectMenu';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { createElement, CSSProperties } from 'react';
|
||||
import { CSSObject } from '@emotion/serialize';
|
||||
import { createElement } from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { GrafanaTheme2, ThemeTypographyVariantTypes } from '@grafana/data';
|
||||
@@ -25,7 +26,7 @@ export interface TextProps extends Omit<React.HTMLAttributes<HTMLElement>, 'clas
|
||||
/** If true, numbers will have fixed width, useful for displaying tabular data. False by default */
|
||||
tabular?: boolean;
|
||||
/** Whether to align the text to left, center or right */
|
||||
textAlignment?: CSSProperties['textAlign'];
|
||||
textAlignment?: CSSObject['textAlign'];
|
||||
children: NonNullable<React.ReactNode>;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { useStyles2 } from '../../themes/ThemeContext';
|
||||
|
||||
type Props = {
|
||||
children: React.ReactElement;
|
||||
children: React.ReactElement<Record<string, unknown>>;
|
||||
visible: boolean;
|
||||
duration?: number;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { useStyles2 } from '../../themes/ThemeContext';
|
||||
|
||||
type Props = {
|
||||
children: React.ReactElement;
|
||||
children: React.ReactElement<Record<string, unknown>>;
|
||||
visible: boolean;
|
||||
size: number;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import { VizLegendOptions } from '@grafana/schema';
|
||||
|
||||
import { PanelContext, PanelContextRoot } from '../../components/PanelChrome/PanelContext';
|
||||
import { VizLayout } from '../../components/VizLayout/VizLayout';
|
||||
import { VizLayout, VizLayoutLegendProps } from '../../components/VizLayout/VizLayout';
|
||||
import { UPlotChart } from '../../components/uPlot/Plot';
|
||||
import { AxisProps } from '../../components/uPlot/config/UPlotAxisBuilder';
|
||||
import { Renderers, UPlotConfigBuilder } from '../../components/uPlot/config/UPlotConfigBuilder';
|
||||
@@ -54,7 +54,7 @@ export interface GraphNGProps extends Themeable2 {
|
||||
prepConfig: (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => UPlotConfigBuilder;
|
||||
propsToDiff?: Array<string | PropDiffFn>;
|
||||
preparePlotFrame?: (frames: DataFrame[], dimFields: XYFieldMatchers) => DataFrame | null;
|
||||
renderLegend: (config: UPlotConfigBuilder) => React.ReactElement | null;
|
||||
renderLegend: (config: UPlotConfigBuilder) => React.ReactElement<VizLayoutLegendProps> | null;
|
||||
|
||||
/**
|
||||
* needed for propsToDiff to re-init the plot & config
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ReactElement } from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
/** Returns the ID value of the first, and only, child element */
|
||||
export function getChildId(children: ReactElement): string | undefined {
|
||||
export function getChildId(children: ReactElement<Record<string, unknown>>): string | undefined {
|
||||
let inputId: unknown;
|
||||
|
||||
// Get the first, and only, child to retrieve form input's id
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { SendResetMailPage } from './SendResetMailPage';
|
||||
@@ -38,7 +38,7 @@ describe('VerifyEmail Page', () => {
|
||||
it('should pass validation checks for email field', async () => {
|
||||
render(<SendResetMailPage />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Send reset email' }));
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Send reset email' }));
|
||||
expect(await screen.findByText('Email or username is required')).toBeInTheDocument();
|
||||
|
||||
await userEvent.type(screen.getByRole('textbox', { name: /User Enter your information/i }), 'test@gmail.com');
|
||||
@@ -49,7 +49,7 @@ describe('VerifyEmail Page', () => {
|
||||
render(<SendResetMailPage />);
|
||||
|
||||
await userEvent.type(screen.getByRole('textbox', { name: /User Enter your information/i }), 'test@gmail.com');
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Send reset email' }));
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Send reset email' }));
|
||||
await waitFor(() =>
|
||||
expect(postMock).toHaveBeenCalledWith('/api/user/password/send-reset-email', {
|
||||
userOrEmail: 'test@gmail.com',
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
TimeZone,
|
||||
} from '@grafana/data';
|
||||
import { DashboardCursorSync, VizLegendOptions } from '@grafana/schema';
|
||||
import { Themeable2, VizLayout } from '@grafana/ui';
|
||||
import { Themeable2, VizLayout, VizLayoutLegendProps } from '@grafana/ui';
|
||||
import { AxisProps, pluginLog, Renderers, ScaleProps, UPlotChart, UPlotConfigBuilder } from '@grafana/ui/internal';
|
||||
|
||||
import { GraphNGLegendEvent, XYFieldMatchers } from './types';
|
||||
@@ -48,7 +48,7 @@ export interface GraphNGProps extends Themeable2 {
|
||||
) => UPlotConfigBuilder;
|
||||
propsToDiff?: Array<string | PropDiffFn>;
|
||||
preparePlotFrame?: (frames: DataFrame[], dimFields: XYFieldMatchers) => DataFrame | null;
|
||||
renderLegend: (config: UPlotConfigBuilder) => React.ReactElement | null;
|
||||
renderLegend: (config: UPlotConfigBuilder) => React.ReactElement<VizLayoutLegendProps> | null;
|
||||
replaceVariables: InterpolateFunction;
|
||||
dataLinkPostProcessor?: DataLinkPostProcessor;
|
||||
cursorSync?: DashboardCursorSync;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Popover as GrafanaPopover, PopoverController, Stack, useStyles2 } from '@grafana/ui';
|
||||
|
||||
export interface PopupCardProps {
|
||||
children: ReactElement;
|
||||
children: ReactElement<Record<string, unknown>>;
|
||||
header?: ReactNode;
|
||||
content: ReactElement;
|
||||
footer?: ReactNode;
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ export const NotificationPreview = ({
|
||||
<div className={styles.firstAlertManagerLine} />
|
||||
<div className={styles.alertManagerName}>
|
||||
<Trans i18nKey="alerting.notification-preview.alertmanager">Alertmanager:</Trans>
|
||||
<img src={alertManagerSource.imgUrl} alt="" className={styles.img} />
|
||||
<img src={alertManagerSource.imgUrl || undefined} alt="" className={styles.img} />
|
||||
{alertManagerSource.name}
|
||||
</div>
|
||||
<div className={styles.secondAlertManagerLine} />
|
||||
|
||||
@@ -19,7 +19,7 @@ interface RenderParams<T = ActionImpl | string> {
|
||||
interface KBarResultsProps {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
items: any[];
|
||||
onRender: (params: RenderParams) => React.ReactElement;
|
||||
onRender: (params: RenderParams) => React.ReactElement<Record<string, unknown>>;
|
||||
maxHeight?: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('ShareDrawer', () => {
|
||||
expect(locationService.getSearch().get('shareView')).toBe('link');
|
||||
expect(await screen.findByText('Share externally')).toBeInTheDocument();
|
||||
const closeButton = await screen.findByTestId(selectors.components.Drawer.General.close);
|
||||
await act(() => userEvent.click(closeButton));
|
||||
await userEvent.click(closeButton);
|
||||
|
||||
expect(locationService.getSearch().get('shareView')).toBe(null);
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface OptionsPaneItemInfo {
|
||||
value?: any;
|
||||
description?: string;
|
||||
popularRank?: number;
|
||||
render: (descriptor: OptionsPaneItemDescriptor) => React.ReactElement;
|
||||
render: (descriptor: OptionsPaneItemDescriptor) => React.ReactElement<Record<string, unknown>>;
|
||||
skipField?: boolean;
|
||||
showIf?: () => boolean;
|
||||
/** Hook for controlling visibility */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { act, screen, waitFor } from '@testing-library/react';
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import { useParams } from 'react-router-dom-v5-compat';
|
||||
import { Props } from 'react-virtualized-auto-sizer';
|
||||
import { render } from 'test/test-utils';
|
||||
@@ -120,10 +120,8 @@ describe('DashboardPageProxy', () => {
|
||||
|
||||
it('home dashboard', async () => {
|
||||
getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, dashMock);
|
||||
act(() => {
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
|
||||
});
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -134,11 +132,9 @@ describe('DashboardPageProxy', () => {
|
||||
it('uid dashboard', async () => {
|
||||
getDashboardScenePageStateManager().setDashboardCache('abc-def', dashMock);
|
||||
|
||||
act(() => {
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
|
||||
uid: 'abc-def',
|
||||
});
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
|
||||
uid: 'abc-def',
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -156,11 +152,9 @@ describe('DashboardPageProxy', () => {
|
||||
describe('when user can edit a dashboard ', () => {
|
||||
it('should not render DashboardScenePage if route is Home', async () => {
|
||||
getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, homeMockEditable);
|
||||
act(() => {
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
|
||||
uid: '',
|
||||
});
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
|
||||
uid: '',
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -170,11 +164,9 @@ describe('DashboardPageProxy', () => {
|
||||
|
||||
it('should not render DashboardScenePage if route is Normal and has uid', async () => {
|
||||
getDashboardScenePageStateManager().setDashboardCache('abc-def', dashMockEditable);
|
||||
act(() => {
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
|
||||
uid: 'abc-def',
|
||||
});
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
|
||||
uid: 'abc-def',
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0);
|
||||
@@ -185,11 +177,9 @@ describe('DashboardPageProxy', () => {
|
||||
describe('when user can only view a dashboard ', () => {
|
||||
it('should render DashboardScenePage if route is Home', async () => {
|
||||
getDashboardScenePageStateManager().setDashboardCache(HOME_DASHBOARD_CACHE_KEY, homeMock);
|
||||
act(() => {
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
|
||||
uid: '',
|
||||
});
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Home, component: () => null, path: '/' },
|
||||
uid: '',
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -199,11 +189,9 @@ describe('DashboardPageProxy', () => {
|
||||
|
||||
it('should render DashboardScenePage if route is Normal and has uid', async () => {
|
||||
getDashboardScenePageStateManager().setDashboardCache('uid', dashMock);
|
||||
act(() => {
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
|
||||
uid: 'uid',
|
||||
});
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
|
||||
uid: 'uid',
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(1);
|
||||
@@ -212,11 +200,9 @@ describe('DashboardPageProxy', () => {
|
||||
|
||||
it('should render not DashboardScenePage if dashboard UID does not match route UID', async () => {
|
||||
getDashboardScenePageStateManager().setDashboardCache('uid', dashMock);
|
||||
act(() => {
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
|
||||
uid: 'wrongUID',
|
||||
});
|
||||
setup({
|
||||
route: { routeName: DashboardRoutes.Normal, component: () => null, path: '/' },
|
||||
uid: 'wrongUID',
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(screen.queryAllByTestId('dashboard-scene-page')).toHaveLength(0);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { render } from 'test/test-utils';
|
||||
import { selectors as e2eSelectors } from '@grafana/e2e-selectors';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import { backendSrv } from 'app/core/services/backend_srv';
|
||||
import { DashboardRoutes } from 'app/types/dashboard';
|
||||
import { DashboardDTO, DashboardRoutes } from 'app/types/dashboard';
|
||||
|
||||
import PublicDashboardPageProxy, { PublicDashboardPageProxyProps } from './PublicDashboardPageProxy';
|
||||
|
||||
@@ -56,8 +56,7 @@ describe('PublicDashboardPageProxy', () => {
|
||||
|
||||
// Mock the dashboard UID response so we don't get any refused connection errors
|
||||
// from this test (as the fetch polyfill means this logic would actually try and call the API)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
jest.spyOn(backendSrv, 'getPublicDashboardByUid').mockResolvedValue({ dashboard: {}, meta: {} } as any);
|
||||
jest.spyOn(backendSrv, 'getPublicDashboardByUid').mockResolvedValue({ dashboard: {}, meta: {} } as DashboardDTO);
|
||||
});
|
||||
|
||||
describe('when scene feature enabled', () => {
|
||||
|
||||
@@ -54,7 +54,7 @@ export function DataSourceCard({
|
||||
</div>
|
||||
</Card.Heading>
|
||||
<Card.Figure className={styles.logo}>
|
||||
<img src={ds.meta.info.logos.small} alt={`${ds.meta.name} Logo`} />
|
||||
<img src={ds.meta.info.logos.small || undefined} alt={`${ds.meta.name} Logo`} />
|
||||
</Card.Figure>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@@ -20,7 +20,7 @@ export function DataSourceLogo(props: DataSourceLogoProps) {
|
||||
<img
|
||||
className={styles.pickerDSLogo}
|
||||
alt={`${dataSource.meta.name} logo`}
|
||||
src={dataSource.meta.info.logos.small}
|
||||
src={dataSource.meta.info.logos.small || undefined}
|
||||
></img>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { cloneElement, ReactElement, useRef } from 'react';
|
||||
import { Popover as GrafanaPopover, PopoverController } from '@grafana/ui';
|
||||
|
||||
export type PopoverProps = {
|
||||
children: ReactElement;
|
||||
children: ReactElement<Record<string, unknown>>;
|
||||
content: ReactElement;
|
||||
overlayClassName?: string;
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ type Props = {
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
|
||||
const SearchBarInput = memo(({ value, onChange }: Props) => {
|
||||
const SearchBarInput = memo(({ value = '', onChange }: Props) => {
|
||||
const clearUiFind = () => {
|
||||
onChange('');
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ const EXPRESSION_ICON_MAP = {
|
||||
} as const satisfies Record<ExpressionQueryType, string>;
|
||||
|
||||
interface ExpressionTypeDropdownProps {
|
||||
children: ReactElement;
|
||||
children: ReactElement<Record<string, unknown>>;
|
||||
handleOnSelect: (value: ExpressionQueryType) => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,11 @@ const PanelTypeCardComponent = ({
|
||||
isCurrent ? t('panel.panel-type-card.title-click-to-close', 'Click again to close this section') : plugin.name
|
||||
}
|
||||
>
|
||||
<img className={cx(styles.img, { [styles.disabled]: isDisabled })} src={plugin.info.logos.small} alt="" />
|
||||
<img
|
||||
className={cx(styles.img, { [styles.disabled]: isDisabled })}
|
||||
src={plugin.info.logos.small || undefined}
|
||||
alt=""
|
||||
/>
|
||||
|
||||
<div className={cx(styles.itemContent, { [styles.disabled]: isDisabled })}>
|
||||
<div className={styles.name}>{title}</div>
|
||||
|
||||
@@ -25,7 +25,6 @@ export const ExtensionErrorBoundary = ({
|
||||
log.error(`Extension "${pluginId}/${extensionTitle}" failed to load.`, {
|
||||
message: error.message,
|
||||
componentStack: errorInfo.componentStack ?? '',
|
||||
digest: errorInfo.digest ?? '',
|
||||
});
|
||||
}}
|
||||
fallback={() => {
|
||||
|
||||
@@ -785,7 +785,6 @@ describe('Plugin Extensions / Utils', () => {
|
||||
expect(log.error).toHaveBeenCalledWith(`Extension "${pluginId}/${extensionTitle}" failed to load.`, {
|
||||
message: 'Test error',
|
||||
componentStack: expect.any(String),
|
||||
digest: expect.any(String),
|
||||
});
|
||||
|
||||
expect(screen.getByText(`Extension failed to load: "${pluginId}/${extensionTitle}"`)).toBeVisible();
|
||||
@@ -818,7 +817,6 @@ describe('Plugin Extensions / Utils', () => {
|
||||
expect(log.error).toHaveBeenCalledWith(`Extension "${pluginId}/${extensionTitle}" failed to load.`, {
|
||||
message: 'Test error',
|
||||
componentStack: expect.any(String),
|
||||
digest: expect.any(String),
|
||||
});
|
||||
|
||||
expect(screen.getByText(`Extension failed to load: "${pluginId}/${extensionTitle}"`)).toBeVisible();
|
||||
@@ -965,7 +963,6 @@ describe('Plugin Extensions / Utils', () => {
|
||||
expect(log.error).toHaveBeenCalledWith(`Extension "${pluginId}/${extensionTitle}" failed to load.`, {
|
||||
message: 'Test error',
|
||||
componentStack: expect.any(String),
|
||||
digest: expect.any(String),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -995,7 +992,6 @@ describe('Plugin Extensions / Utils', () => {
|
||||
expect(log.error).toHaveBeenCalledWith(`Extension "${pluginId}/${extensionTitle}" failed to load.`, {
|
||||
message: 'Test error',
|
||||
componentStack: expect.any(String),
|
||||
digest: expect.any(String),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -120,7 +120,15 @@ export const RegressionTransformerEditor = ({
|
||||
);
|
||||
};
|
||||
|
||||
const RegressionField = ({ label, tooltip, children }: { label: string; tooltip?: string; children: ReactElement }) => (
|
||||
const RegressionField = ({
|
||||
label,
|
||||
tooltip,
|
||||
children,
|
||||
}: {
|
||||
label: string;
|
||||
tooltip?: string;
|
||||
children: ReactElement<Record<string, unknown>>;
|
||||
}) => (
|
||||
<InlineField labelWidth={LABEL_WIDTH} label={label} tooltip={tooltip}>
|
||||
{children}
|
||||
</InlineField>
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ export const DefaultSubscription = (props: Props) => {
|
||||
let canceled = false;
|
||||
getSubscriptions().then((result) => {
|
||||
if (!canceled) {
|
||||
updateSubscriptions(result, loadSubscriptionsClicked);
|
||||
updateSubscriptions(result, Boolean(loadSubscriptionsClicked));
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import { Field, Icon, PopoverContent, ReactUtils, Tooltip, useStyles2 } from '@g
|
||||
|
||||
interface EditorFieldProps extends ComponentProps<typeof Field> {
|
||||
label: string;
|
||||
children: React.ReactElement;
|
||||
children: React.ReactElement<Record<string, unknown>>;
|
||||
width?: number | string;
|
||||
optional?: boolean;
|
||||
tooltip?: PopoverContent;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { InlineFieldRow, InlineField } from '@grafana/ui';
|
||||
interface Props {
|
||||
label: string;
|
||||
tooltip?: string;
|
||||
children: React.ReactElement;
|
||||
children: React.ReactElement<Record<string, unknown>>;
|
||||
}
|
||||
const SearchField = ({ label, tooltip, children }: Props) => {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user