diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx index c8293801ae6..6ca683bbefb 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx @@ -1,4 +1,5 @@ -import { sceneGraph, SceneGridItem, SceneGridLayout, VizPanel } from '@grafana/scenes'; +import { CoreApp } from '@grafana/data'; +import { sceneGraph, SceneGridItem, SceneGridLayout, SceneQueryRunner, VizPanel } from '@grafana/scenes'; import { DashboardScene } from './DashboardScene'; @@ -50,6 +51,24 @@ describe('DashboardScene', () => { }); }); }); + + describe('Enriching data requests', () => { + let scene: DashboardScene; + + beforeEach(() => { + scene = buildTestScene(); + scene.onEnterEditMode(); + }); + + it('Should add app, uid, and panelId', () => { + const queryRunner = sceneGraph.findObject(scene, (o) => o.state.key === 'data-query-runner')!; + expect(scene.enrichDataRequest(queryRunner)).toEqual({ + app: CoreApp.Dashboard, + dashboardUID: 'dash-1', + panelId: 1, + }); + }); + }); }); function buildTestScene() { @@ -65,6 +84,7 @@ function buildTestScene() { title: 'Panel A', key: 'panel-1', pluginId: 'table', + $data: new SceneQueryRunner({ key: 'data-query-runner', queries: [{ refId: 'A' }] }), }), }), new SceneGridItem({ diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 3f18deb083f..a25fe340ff1 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -1,7 +1,7 @@ import * as H from 'history'; import { Unsubscribable } from 'rxjs'; -import { NavModelItem, UrlQueryMap } from '@grafana/data'; +import { CoreApp, DataQueryRequest, NavModelItem, UrlQueryMap } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { getUrlSyncManager, @@ -18,7 +18,13 @@ import { DashboardMeta } from 'app/types'; import { DashboardSceneRenderer } from '../scene/DashboardSceneRenderer'; import { SaveDashboardDrawer } from '../serialization/SaveDashboardDrawer'; -import { findVizPanelByKey, forceRenderChildren, getDashboardUrl } from '../utils/utils'; +import { + findVizPanelByKey, + forceRenderChildren, + getClosestVizPanel, + getDashboardUrl, + getPanelIdForVizPanel, +} from '../utils/utils'; import { DashboardSceneUrlSync } from './DashboardSceneUrlSync'; @@ -191,4 +197,17 @@ export class DashboardScene extends SceneObjectBase { public closeModal() { this.setState({ overlay: undefined }); } + + /** + * Called by the SceneQueryRunner to privide contextural parameters (tracking) props for the request + */ + public enrichDataRequest(sceneObject: SceneObject): Partial { + const panel = getClosestVizPanel(sceneObject); + + return { + app: CoreApp.Dashboard, + dashboardUID: this.state.uid, + panelId: (panel && getPanelIdForVizPanel(panel)) ?? 0, + }; + } } diff --git a/public/app/features/dashboard-scene/utils/utils.ts b/public/app/features/dashboard-scene/utils/utils.ts index 68f94780821..604f7d354b5 100644 --- a/public/app/features/dashboard-scene/utils/utils.ts +++ b/public/app/features/dashboard-scene/utils/utils.ts @@ -174,3 +174,15 @@ export function getDashboardSceneFor(sceneObject: SceneObject): DashboardScene { throw new Error('SceneObject root is not a DashboardScene'); } + +export function getClosestVizPanel(sceneObject: SceneObject): VizPanel | null { + if (sceneObject instanceof VizPanel) { + return sceneObject; + } + + if (sceneObject.parent) { + return getClosestVizPanel(sceneObject.parent); + } + + return null; +}