From 34e8cfef52285d93b6183930108672d9eeace66f Mon Sep 17 00:00:00 2001 From: Kristina Demeshchik Date: Tue, 13 Jan 2026 11:10:39 -0500 Subject: [PATCH] fix frontend logic --- .../dashboard/state/DashboardModel.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index 097ae6453c4..57c2efa86a9 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -525,6 +525,14 @@ export class DashboardModel implements TimeModel { } } + // Also check panels in legacy rows (pre-v16 dashboard format) + // This ensures unique IDs are assigned before the row upgrade migration runs + for (const panel of this.rawPanelIterator()) { + if (panel.id > max) { + max = panel.id; + } + } + return max + 1; } @@ -539,6 +547,26 @@ export class DashboardModel implements TimeModel { } } + /** + * Iterates over panels from the original raw dashboard data, including legacy rows. + * This is needed to find panel IDs before row upgrade migration runs. + */ + private *rawPanelIterator() { + // @ts-expect-error - rows is a legacy property not included in the modern Dashboard schema + const rows = this.originalDashboard?.rows; + + if (Array.isArray(rows)) { + for (const row of rows) { + const rowPanels = row?.panels; + if (Array.isArray(rowPanels)) { + for (const panel of rowPanels) { + yield panel; + } + } + } + } + } + forEachPanel(callback: (panel: PanelModel, index: number) => void) { for (let i = 0; i < this.panels.length; i++) { callback(this.panels[i], i);