diff --git a/packages/scenes-react/src/components/VizPanel.test.tsx b/packages/scenes-react/src/components/VizPanel.test.tsx index 7c79a1428..30b308866 100644 --- a/packages/scenes-react/src/components/VizPanel.test.tsx +++ b/packages/scenes-react/src/components/VizPanel.test.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { render } from '@testing-library/react'; import { SceneContextObject } from '../contexts/SceneContextObject'; -import { VizConfigBuilders, VizPanel as VizPanelObject } from '@grafana/scenes'; -import { VizPanel } from './VizPanel'; +import { VizConfigBuilders, VizPanel as VizPanelObject, VizPanelMenu } from '@grafana/scenes'; +import { VizPanel, VizPanelProps } from './VizPanel'; import { PanelPlugin } from '@grafana/data'; import { TestContextProvider } from '../utils/testUtils'; @@ -55,4 +55,113 @@ 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 =
Title Item
; + + const { rerender, unmount } = render( + + + + ); + + const panel = scene.state.children[0] as VizPanelObject; + expect(panel.state.titleItems).toEqual(titleItems); + + rerender( + + + + ); + + expect(panel.state.titleItems).toEqual(undefined); + + unmount(); + + expect(scene.state.children.length).toBe(0); + }); + + it('Should render with headerActions', () => { + const scene = new SceneContextObject(); + const viz = VizConfigBuilders.timeseries().build(); + const headerActions = ; + + const { rerender, unmount } = render( + + + + ); + + const panel = scene.state.children[0] as VizPanelObject; + expect(panel.state.headerActions).toEqual(headerActions); + + rerender( + + + + ); + + unmount(); + + expect(scene.state.children.length).toBe(0); + }); + + it('Should render VizPanelProps', () => { + const scene = new SceneContextObject(); + const viz = VizConfigBuilders.timeseries().build(); + const headerActions = ; + const seriesLimit = 1; + const collapsed = true; + const collapsible = true; + const hoverHeader = true; + const description = 'description'; + const menu = new VizPanelMenu({}); + const title = 'title'; + const props: VizPanelProps = { + title, + viz, + headerActions, + seriesLimit, + collapsed, + collapsible, + hoverHeader, + description, + menu, + }; + + const { rerender, unmount } = render( + + + + ); + + const panel = scene.state.children[0] as VizPanelObject; + expect(panel.state.headerActions).toEqual(headerActions); + expect(panel.state.collapsed).toEqual(collapsed); + expect(panel.state.seriesLimit).toEqual(seriesLimit); + expect(panel.state.collapsible).toEqual(collapsible); + expect(panel.state.hoverHeader).toEqual(hoverHeader); + expect(panel.state.description).toEqual(description); + expect(panel.state.menu).toEqual(menu); + + rerender( + + + + ); + + expect(panel.state.headerActions).toEqual(undefined); + expect(panel.state.collapsed).toEqual(undefined); + expect(panel.state.seriesLimit).toEqual(undefined); + expect(panel.state.collapsible).toEqual(undefined); + expect(panel.state.hoverHeader).toEqual(undefined); + expect(panel.state.description).toEqual(undefined); + expect(panel.state.menu).toEqual(undefined); + + unmount(); + + expect(scene.state.children.length).toBe(0); + }); }); diff --git a/packages/scenes-react/src/components/VizPanel.tsx b/packages/scenes-react/src/components/VizPanel.tsx index 8b74bbbcd..21abf5462 100644 --- a/packages/scenes-react/src/components/VizPanel.tsx +++ b/packages/scenes-react/src/components/VizPanel.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useId } from 'react'; import { + VizPanelMenu, SceneDataProvider, VizPanel as VizPanelObject, VizPanelState, @@ -9,18 +10,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; + 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); @@ -30,13 +60,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, }); } @@ -54,6 +95,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; } @@ -62,6 +127,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(); @@ -84,7 +165,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 ; }