diff --git a/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.test.tsx b/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.test.tsx index eb6d5fb73e5..19878903d7d 100644 --- a/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.test.tsx +++ b/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.test.tsx @@ -1,3 +1,5 @@ +import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks'; +import { setPluginImportUtils } from '@grafana/runtime'; import { SceneCanvasText, SceneGridLayout, @@ -7,16 +9,30 @@ import { SceneVariableSet, TestVariable, VariableValueOption, + VizPanel, + VizPanelMenu, } from '@grafana/scenes'; import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from 'app/features/variables/constants'; import { activateFullSceneTree } from '../utils/test-utils'; -import { RepeatDirection } from './DashboardGridItem'; +import { DashboardGridItem, RepeatDirection } from './DashboardGridItem'; import { DashboardScene } from './DashboardScene'; +import { panelMenuBehavior, repeatPanelMenuBehavior } from './PanelMenuBehavior'; import { RowRepeaterBehavior } from './RowRepeaterBehavior'; import { RowActions } from './row-actions/RowActions'; +jest.mock('@grafana/runtime', () => ({ + ...jest.requireActual('@grafana/runtime'), + setPluginExtensionGetter: jest.fn(), + getPluginLinkExtensions: jest.fn().mockReturnValue({ extensions: [] }), +})); + +setPluginImportUtils({ + importPanelPlugin: (id: string) => Promise.resolve(getPanelPlugin({})), + getPanelPluginFromCache: (id: string) => undefined, +}); + describe('RowRepeaterBehavior', () => { describe('Given scene with variable with 5 values', () => { let scene: DashboardScene, grid: SceneGridLayout, repeatBehavior: RowRepeaterBehavior; @@ -112,6 +128,50 @@ describe('RowRepeaterBehavior', () => { }); }); + describe('Given scene with DashboardGridItem', () => { + let scene: DashboardScene; + let grid: SceneGridLayout; + let rowToRepeat: SceneGridRow; + + beforeEach(async () => { + const menu = new VizPanelMenu({ + $behaviors: [panelMenuBehavior], + }); + + ({ scene, grid, rowToRepeat } = buildScene({ variableQueryTime: 0 })); + const panel = new VizPanel({ pluginId: 'text', menu }); + panel.getPlugin = () => getPanelPlugin({ skipDataQuery: false }); + + rowToRepeat.setState({ + children: [ + new DashboardGridItem({ + body: panel, + }), + ], + }); + + activateFullSceneTree(scene); + await new Promise((r) => setTimeout(r, 1)); + }); + + it('Should set repeat specific panel menu for repeated rows but not original one', () => { + const row1 = grid.state.children[1] as SceneGridRow; + const row2 = grid.state.children[2] as SceneGridRow; + const panelMenuBehaviorOriginal = ( + ((row1.state.children[0] as DashboardGridItem).state.body as VizPanel).state.menu as VizPanelMenu + ).state.$behaviors; + const panelMenuBehaviorClone = ( + ((row2.state.children[0] as DashboardGridItem).state.body as VizPanel).state.menu as VizPanelMenu + ).state.$behaviors; + + expect(panelMenuBehaviorOriginal).toBeDefined(); + expect(panelMenuBehaviorOriginal![0]).toBe(panelMenuBehavior); + + expect(panelMenuBehaviorClone).toBeDefined(); + expect(panelMenuBehaviorClone![0]).toBe(repeatPanelMenuBehavior); + }); + }); + describe('Given scene empty row', () => { let scene: DashboardScene; let grid: SceneGridLayout; diff --git a/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.ts b/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.ts index 9b96f31c1d6..09b590a9a47 100644 --- a/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.ts +++ b/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.ts @@ -12,10 +12,13 @@ import { SceneVariableSet, VariableDependencyConfig, VariableValueSingle, + VizPanelMenu, } from '@grafana/scenes'; import { getMultiVariableValues } from '../utils/utils'; +import { DashboardGridItem } from './DashboardGridItem'; +import { repeatPanelMenuBehavior } from './PanelMenuBehavior'; import { DashboardRepeatsProcessedEvent } from './types'; interface RowRepeaterBehaviorState extends SceneObjectState { @@ -124,9 +127,18 @@ export class RowRepeaterBehavior extends SceneObjectBase 0 ? `${source.state.key}-clone-${localValue}` : source.state.key; const itemClone = source.clone({ key: itemKey, y: itemY }); - //Make sure all the child scene objects have unique keys + // Make sure all the child scene objects have unique keys + // and add proper menu to the repeated panel if (index > 0) { ensureUniqueKeys(itemClone, localValue); + + if (itemClone instanceof DashboardGridItem) { + itemClone.state.body.setState({ + menu: new VizPanelMenu({ + $behaviors: [repeatPanelMenuBehavior], + }), + }); + } } children.push(itemClone);