DashboardScene: Pass hashed panelId to query runner if a panel is a clone (#78820)

* DashboardScene: Pass hashed panelId  to query runner if a panel is a clone

* Test

* Nit
This commit is contained in:
Dominik Prokop 2023-12-01 10:07:55 +01:00 committed by GitHub
parent 69e1046ed3
commit 303c3ddc24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 4 deletions

View File

@ -12,6 +12,8 @@ import appEvents from 'app/core/app_events';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { VariablesChanged } from 'app/features/variables/types';
import { djb2Hash } from '../utils/djb2Hash';
import { DashboardScene, DashboardSceneState } from './DashboardScene';
describe('DashboardScene', () => {
@ -68,6 +70,12 @@ describe('DashboardScene', () => {
panelId: 1,
});
});
it('Should hash the key of the cloned panels and set it as panelId', () => {
const queryRunner = sceneGraph.findObject(scene, (o) => o.state.key === 'data-query-runner2')!;
const expectedPanelId = djb2Hash('panel-2-clone-1');
expect(scene.enrichDataRequest(queryRunner).panelId).toEqual(expectedPanelId);
});
});
describe('When variables change', () => {
@ -112,6 +120,14 @@ function buildTestScene(overrides?: Partial<DashboardSceneState>) {
pluginId: 'table',
}),
}),
new SceneGridItem({
body: new VizPanel({
title: 'Panel B',
key: 'panel-2-clone-1',
pluginId: 'table',
$data: new SceneQueryRunner({ key: 'data-query-runner2', queries: [{ refId: 'A' }] }),
}),
}),
],
}),
...overrides,

View File

@ -27,8 +27,9 @@ import { DashboardSceneRenderer } from '../scene/DashboardSceneRenderer';
import { SaveDashboardDrawer } from '../serialization/SaveDashboardDrawer';
import { DashboardEditView } from '../settings/utils';
import { DashboardModelCompatibilityWrapper } from '../utils/DashboardModelCompatibilityWrapper';
import { djb2Hash } from '../utils/djb2Hash';
import { getDashboardUrl } from '../utils/urlBuilders';
import { forceRenderChildren, getClosestVizPanel, getPanelIdForVizPanel } from '../utils/utils';
import { forceRenderChildren, getClosestVizPanel, getPanelIdForVizPanel, isPanelClone } from '../utils/utils';
import { DashboardSceneUrlSync } from './DashboardSceneUrlSync';
import { ViewPanelScene } from './ViewPanelScene';
@ -279,11 +280,20 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> {
*/
public enrichDataRequest(sceneObject: SceneObject): Partial<DataQueryRequest> {
const panel = getClosestVizPanel(sceneObject);
let panelId = 0;
if (panel && panel.state.key) {
if (isPanelClone(panel.state.key)) {
panelId = djb2Hash(panel?.state.key);
} else {
panelId = getPanelIdForVizPanel(panel);
}
}
return {
app: CoreApp.Dashboard,
dashboardUID: this.state.uid,
panelId: (panel && getPanelIdForVizPanel(panel)) ?? 0,
panelId,
};
}

View File

@ -7,7 +7,7 @@ import appEvents from 'app/core/app_events';
import { PanelInspectDrawer } from '../inspect/PanelInspectDrawer';
import { createDashboardEditViewFor } from '../settings/utils';
import { findVizPanelByKey } from '../utils/utils';
import { findVizPanelByKey, isPanelClone } from '../utils/utils';
import { DashboardScene, DashboardSceneState } from './DashboardScene';
import { ViewPanelScene } from './ViewPanelScene';
@ -69,7 +69,7 @@ export class DashboardSceneUrlSync implements SceneObjectUrlSyncHandler {
const panel = findVizPanelByKey(this._scene, values.viewPanel);
if (!panel) {
// // If we are trying to view a repeat clone that can't be found it might be that the repeats have not been processed yet
if (values.viewPanel.indexOf('clone')) {
if (isPanelClone(values.viewPanel)) {
this._handleViewRepeatClone(values.viewPanel);
return;
}

View File

@ -0,0 +1,12 @@
/**
* Hashes a string using the DJB2 algorithm.
*/
export function djb2Hash(str: string): number {
let hash = 5381;
for (let i = 0; i < str.length; i++) {
hash = (hash * 33) ^ str.charCodeAt(i);
}
return hash >>> 0; // Ensure the result is an unsigned 32-bit integer
}

View File

@ -182,3 +182,7 @@ export function getClosestVizPanel(sceneObject: SceneObject): VizPanel | null {
return null;
}
export function isPanelClone(key: string) {
return key.includes('clone');
}