diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index e1874dfb15d..48424ea2b1a 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -935,7 +935,9 @@ export class DashboardVariableDependency implements SceneVariableDependencyConfi for (const behavior of child.state.$behaviors) { if (behavior instanceof RowRepeaterBehavior) { if (behavior.isWaitingForVariables || (behavior.state.variableName === variable.state.name && hasChanged)) { - behavior.performRepeat(); + behavior.performRepeat(true); + } else if (!behavior.isWaitingForVariables && behavior.state.variableName === variable.state.name) { + behavior.notifyRepeatedPanelsWaitingForVariables(variable); } } } diff --git a/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.test.tsx b/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.test.tsx index bddb841cc14..67701dfeacd 100644 --- a/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.test.tsx +++ b/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.test.tsx @@ -1,3 +1,4 @@ +import { VariableRefresh } from '@grafana/data'; import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks'; import { setPluginImportUtils } from '@grafana/runtime'; import { @@ -144,6 +145,26 @@ describe('RowRepeaterBehavior', () => { expect(gridStateUpdates.length).toBe(1); }); + + it('Should update panels on refresh if variables load on time range change', async () => { + const { scene, repeatBehavior } = buildScene({ + variableQueryTime: 0, + variableRefresh: VariableRefresh.onTimeRangeChanged, + }); + + const notifyPanelsSpy = jest.spyOn(repeatBehavior, 'notifyRepeatedPanelsWaitingForVariables'); + + activateFullSceneTree(scene); + + expect(notifyPanelsSpy).toHaveBeenCalledTimes(0); + + scene.state.$timeRange?.onRefresh(); + + //make sure notifier is called + expect(notifyPanelsSpy).toHaveBeenCalledTimes(1); + + notifyPanelsSpy.mockRestore(); + }); }); describe('Should not repeat row', () => { @@ -251,6 +272,7 @@ interface SceneOptions { maxPerRow?: number; itemHeight?: number; repeatDirection?: RepeatDirection; + variableRefresh?: VariableRefresh; } function buildScene( @@ -334,6 +356,7 @@ function buildScene( isMulti: true, includeAll: true, delayMs: options.variableQueryTime, + refresh: options.variableRefresh, optionsToReturn: variableOptions ?? [ { label: 'A', value: 'A1' }, { label: 'B', value: 'B1' }, diff --git a/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.ts b/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.ts index 663315e5d04..ae1aefee9f6 100644 --- a/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.ts +++ b/public/app/features/dashboard-scene/scene/RowRepeaterBehavior.ts @@ -9,13 +9,14 @@ import { SceneGridRow, SceneObjectBase, SceneObjectState, + SceneVariable, SceneVariableSet, VariableDependencyConfig, VariableValueSingle, VizPanelMenu, } from '@grafana/scenes'; -import { getMultiVariableValues } from '../utils/utils'; +import { getMultiVariableValues, getQueryRunnerFor } from '../utils/utils'; import { DashboardGridItem } from './DashboardGridItem'; import { repeatPanelMenuBehavior } from './PanelMenuBehavior'; @@ -37,6 +38,7 @@ export class RowRepeaterBehavior extends SceneObjectBase this._activationHandler()); } + public notifyRepeatedPanelsWaitingForVariables(variable: SceneVariable) { + const allRows = [this._getRow(), ...(this._clonedRows ?? [])]; + + for (const row of allRows) { + for (const gridItem of row.state.children) { + if (!(gridItem instanceof DashboardGridItem)) { + continue; + } + + const queryRunner = getQueryRunnerFor(gridItem.state.body); + if (queryRunner) { + queryRunner.variableDependency?.variableUpdateCompleted(variable, false); + } + } + } + } + private _activationHandler() { this.performRepeat(); @@ -143,7 +162,7 @@ export class RowRepeaterBehavior extends SceneObjectBase