From 0a0f92e85ea6d319c8e7501e435672608e3e3884 Mon Sep 17 00:00:00 2001 From: Sergej-Vlasov <37613182+Sergej-Vlasov@users.noreply.github.com> Date: Tue, 23 Dec 2025 15:52:50 +0000 Subject: [PATCH] InspectJsonTab: Force render the layout after change to reflect new gridPos (#115688) force render the layout after inspect panel change to account for gridPos change --- .../inspect/InspectJsonTab.test.tsx | 47 ++++++++++++++++++- .../inspect/InspectJsonTab.tsx | 7 +++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard-scene/inspect/InspectJsonTab.test.tsx b/public/app/features/dashboard-scene/inspect/InspectJsonTab.test.tsx index 36337a6ddef..786ff98e236 100644 --- a/public/app/features/dashboard-scene/inspect/InspectJsonTab.test.tsx +++ b/public/app/features/dashboard-scene/inspect/InspectJsonTab.test.tsx @@ -12,7 +12,7 @@ import { } from '@grafana/data'; import { getPanelPlugin } from '@grafana/data/test'; import { setPluginImportUtils, setRunRequest } from '@grafana/runtime'; -import { SceneCanvasText, SceneDataTransformer, SceneQueryRunner, VizPanel } from '@grafana/scenes'; +import { SceneCanvasText, SceneDataTransformer, SceneGridLayout, SceneQueryRunner, VizPanel } from '@grafana/scenes'; import * as libpanels from 'app/features/library-panels/state/api'; import { getStandardTransformers } from 'app/features/transformers/standardTransformers'; @@ -183,6 +183,51 @@ describe('InspectJsonTab', () => { expect(tab.state.onClose).toHaveBeenCalled(); }); + it('Can update gridPos and forces layout re-render', async () => { + const { tab, panel, scene } = await buildTestScene(); + + // Get the layout manager and spy on the grid's forceRender + const layoutManager = scene.state.body as DefaultGridLayoutManager; + const grid = layoutManager.state.grid as SceneGridLayout; + const forceRenderSpy = jest.spyOn(grid, 'forceRender'); + + const originalGridItem = panel.parent as DashboardGridItem; + expect(originalGridItem.state.x).toBe(0); + expect(originalGridItem.state.y).toBe(0); + expect(originalGridItem.state.width).toBe(8); + expect(originalGridItem.state.height).toBe(10); + + tab.onCodeEditorBlur(`{ + "id": 12, + "type": "table", + "title": "Panel A", + "gridPos": { + "x": 5, + "y": 10, + "w": 12, + "h": 8 + }, + "options": {}, + "fieldConfig": {}, + "transformations": [], + "transparent": false + }`); + + tab.onApplyChange(); + + const panel2 = findVizPanelByKey(scene, panel.state.key)!; + const gridItem = panel2.parent as DashboardGridItem; + + // Verify all gridPos properties are updated + expect(gridItem.state.x).toBe(5); + expect(gridItem.state.y).toBe(10); + expect(gridItem.state.width).toBe(12); + expect(gridItem.state.height).toBe(8); + + // Verify forceRender was called on the layout to apply position changes + expect(forceRenderSpy).toHaveBeenCalled(); + }); + it('Can show panel json for V2 dashboard specification', async () => { const { tab } = await buildTestSceneWithV2Spec(); diff --git a/public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx b/public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx index 4fd9bc8b9a6..60f3073dea1 100644 --- a/public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx +++ b/public/app/features/dashboard-scene/inspect/InspectJsonTab.tsx @@ -9,6 +9,7 @@ import { SceneDataTransformer, sceneGraph, SceneGridItemStateLike, + SceneGridLayout, SceneObjectBase, SceneObjectRef, SceneObjectState, @@ -168,6 +169,12 @@ export class InspectJsonTab extends SceneObjectBase { panel.parent.setState(newState); + // Force the grid layout to re-render with the new positions + const layout = sceneGraph.getLayout(panel); + if (layout instanceof SceneGridLayout) { + layout.forceRender(); + } + //Report relevant updates reportPanelInspectInteraction(InspectTab.JSON, 'apply', { panel_type_changed: panel.state.pluginId !== panelModel.type,