Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: (scenes-react) - VizPanel add missing props and tests #998

Merged
merged 7 commits into from
Dec 12, 2024
Merged
28 changes: 28 additions & 0 deletions packages/scenes-react/src/components/VizPanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,32 @@ describe('VizPanel', () => {

expect(scene.state.children.length).toBe(0);
});

it('Should render with titleItems', () => {
const scene = new SceneContextObject();
const viz = VizConfigBuilders.timeseries().build();
const titleItems = <div>Title Item</div>;

const { getByText } = render(
<TestContextProvider value={scene}>
<VizPanel title="Test" titleItems={titleItems} viz={viz} />

This comment was marked as outdated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore the above, I got this working locally in the browser and everything works as expected, must be something in the test env that is keeping the panel from rendering

</TestContextProvider>
);

expect(getByText('Title Item')).toBeInTheDocument();
});

it('Should render with headerActions', () => {
const scene = new SceneContextObject();
const viz = VizConfigBuilders.timeseries().build();
const headerActions = <button>Action</button>;

const { getByText } = render(
<TestContextProvider value={scene}>
<VizPanel title="Test" headerActions={headerActions} viz={viz} />
</TestContextProvider>
);

expect(getByText('Action')).toBeInTheDocument();
});
});
107 changes: 103 additions & 4 deletions packages/scenes-react/src/components/VizPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { useEffect, useId } from 'react';
import {
SceneObject,
VizPanelMenu,
SceneDataProvider,
VizPanel as VizPanelObject,
VizPanelState,
Expand All @@ -9,18 +11,47 @@ import {
} from '@grafana/scenes';
import { usePrevious } from 'react-use';
import { getPanelOptionsWithDefaults } from '@grafana/data';
import { PanelContext } from '@grafana/ui';
import { writeSceneLog } from '../utils';
import { useSceneContext } from '../hooks/hooks';

export interface VizPanelProps {
title: string;
description?: string;
dataProvider?: SceneDataProvider;
viz: VizConfig;
displayMode?: 'default' | 'transparent';
hoverHeader?: boolean;
hoverHeaderOffset?: number;
menu?: VizPanelMenu;
titleItems?: React.ReactNode | SceneObject | SceneObject[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we restrict this to only react elements?

seriesLimit?: number;
seriesLimitShowAll?: boolean;
headerActions?: React.ReactNode;
extendPanelContext?: (vizPanel: VizPanelObject, context: PanelContext) => void;
collapsible?: boolean;
collapsed?: boolean;
}

export function VizPanel(props: VizPanelProps) {
const { title, viz, dataProvider, headerActions } = props;
const {
title,
description,
viz,
dataProvider,
displayMode,
hoverHeader,
hoverHeaderOffset,
headerActions,
menu,
titleItems,
extendPanelContext,
seriesLimit,
seriesLimitShowAll,
collapsible,
collapsed,
} = props;

const scene = useSceneContext();
const key = useId();
const prevProps = usePrevious(props);
Expand All @@ -30,13 +61,24 @@ export function VizPanel(props: VizPanelProps) {
if (!panel) {
panel = new VizPanelObject({
key: key,
title: title,
pluginId: viz.pluginId,
pluginVersion: viz.pluginVersion,
title: title,
titleItems: titleItems,
description: description,
options: viz.options,
fieldConfig: viz.fieldConfig,
pluginVersion: viz.pluginVersion,
$data: getDataProviderForVizPanel(dataProvider),
displayMode: displayMode,
hoverHeader: hoverHeader,
hoverHeaderOffset: hoverHeaderOffset,
headerActions: headerActions,
menu: menu,
extendPanelContext: extendPanelContext,
collapsible: collapsible,
collapsed: collapsed,
seriesLimit: seriesLimit,
seriesLimitShowAll: seriesLimitShowAll,
});
}

Expand All @@ -54,6 +96,30 @@ export function VizPanel(props: VizPanelProps) {
stateUpdate.title = title;
}

if (description !== prevProps.description) {
stateUpdate.description = description;
}

if (displayMode !== prevProps.displayMode) {
stateUpdate.displayMode = displayMode;
}

if (hoverHeader !== prevProps.hoverHeader) {
stateUpdate.hoverHeader = hoverHeader;
}

if (hoverHeaderOffset !== prevProps.hoverHeaderOffset) {
stateUpdate.hoverHeaderOffset = hoverHeaderOffset;
}

if (menu !== prevProps.menu) {
stateUpdate.menu = menu;
}

if (titleItems !== prevProps.titleItems) {
stateUpdate.titleItems = titleItems;
}

if (headerActions !== prevProps.headerActions) {
stateUpdate.headerActions = headerActions;
}
Expand All @@ -62,6 +128,22 @@ export function VizPanel(props: VizPanelProps) {
stateUpdate.$data = getDataProviderForVizPanel(dataProvider);
}

if (seriesLimit !== prevProps.seriesLimit) {
stateUpdate.seriesLimit = seriesLimit;
}

if (seriesLimitShowAll !== prevProps.seriesLimitShowAll) {
stateUpdate.seriesLimitShowAll = seriesLimitShowAll;
}

if (collapsible !== prevProps.collapsible) {
stateUpdate.collapsible = collapsible;
}

if (collapsed !== prevProps.collapsed) {
stateUpdate.collapsed = collapsed;
}

if (viz !== prevProps.viz) {
if (viz.pluginId === prevProps.viz.pluginId) {
const plugin = panel.getPlugin();
Expand All @@ -84,7 +166,24 @@ export function VizPanel(props: VizPanelProps) {
panel.setState(stateUpdate);
writeSceneLog('VizPanel', 'Updating VizPanel state', stateUpdate);
}
}, [panel, title, headerActions, viz, dataProvider, prevProps]);
}, [
panel,
title,
description,
displayMode,
hoverHeader,
hoverHeaderOffset,
headerActions,
menu,
titleItems,
viz,
dataProvider,
seriesLimit,
seriesLimitShowAll,
collapsible,
collapsed,
prevProps,
]);

return <panel.Component model={panel} />;
}
Expand Down
Loading