From c90677831b8b3c2025936ed12371d68246ba0804 Mon Sep 17 00:00:00 2001 From: Collin Fingar Date: Thu, 4 Dec 2025 12:21:27 -0500 Subject: [PATCH] Library Panels: Update connection generation for V2 (#114504) * Library Panels: Update connection generation for V2 * add test --------- Co-authored-by: Haris Rozajac --- pkg/services/librarypanels/librarypanels.go | 21 +++++++++++++--- .../librarypanels/librarypanels_test.go | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/pkg/services/librarypanels/librarypanels.go b/pkg/services/librarypanels/librarypanels.go index e029925ed25..ca08b57dc0d 100644 --- a/pkg/services/librarypanels/librarypanels.go +++ b/pkg/services/librarypanels/librarypanels.go @@ -64,9 +64,19 @@ var _ Service = (*LibraryPanelService)(nil) // ConnectLibraryPanelsForDashboard loops through all panels in dashboard JSON and connects any library panels to the dashboard. func (lps *LibraryPanelService) ConnectLibraryPanelsForDashboard(c context.Context, signedInUser identity.Requester, dash *dashboards.Dashboard) error { - panels := dash.Data.Get("panels").MustArray() + var panels []any + isV2 := dash.Data.Get("elements").Interface() != nil + if isV2 { + elementsMap := dash.Data.Get("elements").MustMap() + panels = make([]any, 0, len(elementsMap)) + for _, element := range elementsMap { + panels = append(panels, element) + } + } else { + panels = dash.Data.Get("panels").MustArray() + } libraryPanels := make(map[string]string) - err := connectLibraryPanelsRecursively(c, panels, libraryPanels) + err := connectLibraryPanelsRecursively(c, panels, libraryPanels, isV2) if err != nil { return err } @@ -83,10 +93,13 @@ func isLibraryPanelOrRow(panel *simplejson.Json, panelType string) bool { return panel.Interface() != nil || panelType == "row" } -func connectLibraryPanelsRecursively(c context.Context, panels []any, libraryPanels map[string]string) error { +func connectLibraryPanelsRecursively(c context.Context, panels []any, libraryPanels map[string]string, isV2 bool) error { for _, panel := range panels { panelAsJSON := simplejson.NewFromAny(panel) libraryPanel := panelAsJSON.Get("libraryPanel") + if isV2 { + libraryPanel = panelAsJSON.Get("spec").Get("libraryPanel") + } panelType := panelAsJSON.Get("type").MustString() if !isLibraryPanelOrRow(libraryPanel, panelType) { continue @@ -95,7 +108,7 @@ func connectLibraryPanelsRecursively(c context.Context, panels []any, libraryPan // we have a row if panelType == "row" { rowPanels := panelAsJSON.Get("panels").MustArray() - err := connectLibraryPanelsRecursively(c, rowPanels, libraryPanels) + err := connectLibraryPanelsRecursively(c, rowPanels, libraryPanels, isV2) if err != nil { return err } diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index a5ebd74d609..d93fb00bf5e 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -87,6 +87,31 @@ func TestIntegrationConnectLibraryPanelsForDashboard(t *testing.T) { require.Equal(t, sc.initialResult.Result.UID, elements[sc.initialResult.Result.UID].UID) }) + scenarioWithLibraryPanel(t, "When an admin tries to store a V2 dashboard with a library panel, it should connect the two", + func(t *testing.T, sc scenarioContext) { + dashJSON := map[string]any{ + "elements": []any{ + map[string]any{ + "kind": "Panel", + "spec": map[string]any{ + "datasource": "${DS_GDEV-TESTDATA}", + "libraryPanel": map[string]any{ + "uid": sc.initialResult.Result.UID, + }, + }, + }, + }, + } + dash := dashboards.Dashboard{ + Title: "Testing ConnectLibraryPanelsForDashboard for V2 dashboard", + Data: simplejson.NewFromAny(dashJSON), + } + dashInDB := createDashboard(t, sc, &dash) + + err := sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB) + require.NoError(t, err) + }) + scenarioWithLibraryPanel(t, "When an admin tries to store a dashboard with library panels inside and outside of rows, it should connect all", func(t *testing.T, sc scenarioContext) { cmd := model.CreateLibraryElementCommand{