From c8fb66dd4867bb0dfa8a3898e8b0e6884b645f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 23 Apr 2025 16:18:56 +0200 Subject: [PATCH] Dashboard: Fixes issue with row repeats and first row (#104265) * working * Update * Add test * Update --- .../layout-default/RowRepeaterBehavior.test.tsx | 11 ++++++++++- .../scene/layout-default/RowRepeaterBehavior.ts | 17 +++++++++++------ yarn.lock | 16 ++++++++-------- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/public/app/features/dashboard-scene/scene/layout-default/RowRepeaterBehavior.test.tsx b/public/app/features/dashboard-scene/scene/layout-default/RowRepeaterBehavior.test.tsx index 28effcf18b5..c739b3d6520 100644 --- a/public/app/features/dashboard-scene/scene/layout-default/RowRepeaterBehavior.test.tsx +++ b/public/app/features/dashboard-scene/scene/layout-default/RowRepeaterBehavior.test.tsx @@ -61,7 +61,7 @@ describe('RowRepeaterBehavior', () => { const gridItemRow1 = row1.state.children[0] as SceneGridItem; expect(gridItemRow1.state.key!).toBe(joinCloneKeys(row1.state.key!, 'grid-item-1')); - expect(gridItemRow1.state.body?.state.key).toBe(joinCloneKeys(gridItemRow1.state.key!, 'canvas-1')); + expect(gridItemRow1.state.body?.state.key).toBe('canvas-1'); const row2 = grid.state.children[2] as SceneGridRow; expect(row2.state.key).toBe(getCloneKey('row-1', 1)); @@ -140,6 +140,9 @@ describe('RowRepeaterBehavior', () => { }); it('Should handle second repeat cycle and update remove old repeats', async () => { + const sourceRow = grid.state.children[1] as SceneGridRow; + const sourceGridItem = sourceRow.state.children[0] as SceneGridItem; + // trigger another repeat cycle by changing the variable const variable = scene.state.$variables!.state.variables[0] as TestVariable; variable.changeValueTo(['B1', 'C1']); @@ -148,6 +151,12 @@ describe('RowRepeaterBehavior', () => { // should now only have 2 repeated rows (and the panel above + the row at the bottom) expect(grid.state.children.length).toBe(4); + + // Should reuse source row item instances + const sourceRowAfterRepeat = grid.state.children[1] as SceneGridRow; + const sourceItemAfterRepeat = sourceRowAfterRepeat.state.children[0] as SceneGridItem; + expect(sourceRowAfterRepeat).toBe(sourceRow); + expect(sourceItemAfterRepeat).toBe(sourceGridItem); }); it('Should ignore repeat process if variable values are the same', async () => { diff --git a/public/app/features/dashboard-scene/scene/layout-default/RowRepeaterBehavior.ts b/public/app/features/dashboard-scene/scene/layout-default/RowRepeaterBehavior.ts index 5e7b4ef2f0e..975a7221119 100644 --- a/public/app/features/dashboard-scene/scene/layout-default/RowRepeaterBehavior.ts +++ b/public/app/features/dashboard-scene/scene/layout-default/RowRepeaterBehavior.ts @@ -26,8 +26,6 @@ import { import { getMultiVariableValues } from '../../utils/utils'; import { DashboardRepeatsProcessedEvent } from '../types/DashboardRepeatsProcessedEvent'; -import { DashboardGridItem } from './DashboardGridItem'; - interface RowRepeaterBehaviorState extends SceneObjectState { variableName: string; } @@ -196,15 +194,22 @@ export class RowRepeaterBehavior extends SceneObjectBase 0 + ? sourceItem.clone({ + isDraggable: false, + isResizable: false, + }) + : sourceItem; - const cloneItem = sourceItem.clone({ + cloneItem.setState({ key: cloneItemKey, y: cloneItemY, - isDraggable: !isSourceRow && sourceItem instanceof DashboardGridItem ? false : sourceItem.state.isDraggable, - isResizable: !isSourceRow && sourceItem instanceof DashboardGridItem ? false : sourceItem.state.isResizable, }); - ensureUniqueKeys(cloneItem, cloneItemKey); + if (rowIndex > 0) { + ensureUniqueKeys(cloneItem, cloneItemKey); + } children.push(cloneItem); diff --git a/yarn.lock b/yarn.lock index 70d29a1635c..42dd66568b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3475,10 +3475,10 @@ __metadata: linkType: soft "@grafana/scenes-react@npm:^6.8.1": - version: 6.8.1 - resolution: "@grafana/scenes-react@npm:6.8.1" + version: 6.9.0 + resolution: "@grafana/scenes-react@npm:6.9.0" dependencies: - "@grafana/scenes": "npm:6.8.1" + "@grafana/scenes": "npm:6.9.0" lru-cache: "npm:^10.2.2" react-use: "npm:^17.4.0" peerDependencies: @@ -3490,13 +3490,13 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/798595f91971beb5ba34989e7f6aabe8208c28011e36ca2da0f451bc112f760318a14c93d336ef08c99601ef386f25b70568e12c62c6e4a1f258bc93490dc111 + checksum: 10/c7c3759671f4497653a586e9396b5f89ac869dd30c9fb3077734ff80353fd612e2857136edc95d71c06607575930145af8d6811a088c9afda0299925c09ca9c7 languageName: node linkType: hard -"@grafana/scenes@npm:6.8.1, @grafana/scenes@npm:^6.8.1": - version: 6.8.1 - resolution: "@grafana/scenes@npm:6.8.1" +"@grafana/scenes@npm:6.9.0, @grafana/scenes@npm:^6.8.1": + version: 6.9.0 + resolution: "@grafana/scenes@npm:6.9.0" dependencies: "@floating-ui/react": "npm:^0.26.16" "@leeoniya/ufuzzy": "npm:^1.0.16" @@ -3514,7 +3514,7 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/e465eb864ab8a8c4a7dea1a90db1774630ee9d0cdff89799aaae5765c1eac313bd5e96ebb8dac51c41cdcaf5c78f46da6c7eeea18c4a506254990817c05aa840 + checksum: 10/ff02465c53877ce07d11f842696d00b0eb0945ca58d2586664429b66578c7743fb5ac715541649b69d52b2de8eef035340aa2df4cd0e8961c3b782eee9001551 languageName: node linkType: hard