From 179f35a537726f17df34582b8fdf5a96555cf787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Tue, 2 Feb 2021 06:25:35 +0100 Subject: [PATCH] PanelLibrary: Adds library panel meta information to dashboard json (#30770) --- pkg/services/librarypanels/database.go | 110 ++++--- pkg/services/librarypanels/librarypanels.go | 16 + .../librarypanels/librarypanels_test.go | 294 +++++++++++++++++- pkg/services/librarypanels/models.go | 18 +- 4 files changed, 368 insertions(+), 70 deletions(-) diff --git a/pkg/services/librarypanels/database.go b/pkg/services/librarypanels/database.go index b53a2b59c08..9a94abc32a3 100644 --- a/pkg/services/librarypanels/database.go +++ b/pkg/services/librarypanels/database.go @@ -12,6 +12,21 @@ import ( "github.com/grafana/grafana/pkg/util" ) +var ( + sqlStatmentLibrayPanelDTOWithMeta = ` +SELECT lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by + , 0 AS can_edit + , u1.login AS created_by_name + , u1.email AS created_by_email + , u2.login AS updated_by_name + , u2.email AS updated_by_email + , (SELECT COUNT(dashboard_id) FROM library_panel_dashboard WHERE librarypanel_id = lp.id) AS connected_dashboards +FROM library_panel AS lp + LEFT JOIN user AS u1 ON lp.created_by = u1.id + LEFT JOIN user AS u2 ON lp.updated_by = u2.id +` +) + // createLibraryPanel adds a Library Panel. func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd createLibraryPanelCommand) (LibraryPanelDTO, error) { libraryPanel := LibraryPanel{ @@ -45,9 +60,10 @@ func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd cre Name: libraryPanel.Name, Model: libraryPanel.Model, Meta: LibraryPanelDTOMeta{ - CanEdit: true, - Created: libraryPanel.Created, - Updated: libraryPanel.Updated, + CanEdit: true, + ConnectedDashboards: 0, + Created: libraryPanel.Created, + Updated: libraryPanel.Updated, CreatedBy: LibraryPanelDTOMetaUser{ ID: libraryPanel.CreatedBy, Name: c.SignedInUser.Login, @@ -179,18 +195,7 @@ func (lps *LibraryPanelService) disconnectLibraryPanelsForDashboard(dashboardID func getLibraryPanel(session *sqlstore.DBSession, uid string, orgID int64) (LibraryPanelWithMeta, error) { libraryPanels := make([]LibraryPanelWithMeta, 0) - sql := `SELECT - lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by - , 0 AS can_edit - , u1.login AS created_by_name - , u1.email AS created_by_email - , u2.login AS updated_by_name - , u2.email AS updated_by_email - FROM library_panel AS lp - LEFT JOIN user AS u1 ON lp.created_by = u1.id - LEFT JOIN user AS u2 ON lp.updated_by = u2.id - WHERE lp.uid=? AND lp.org_id=?` - + sql := sqlStatmentLibrayPanelDTOWithMeta + "WHERE lp.uid=? AND lp.org_id=?" sess := session.SQL(sql, uid, orgID) err := sess.Find(&libraryPanels) if err != nil { @@ -223,9 +228,10 @@ func (lps *LibraryPanelService) getLibraryPanel(c *models.ReqContext, uid string Name: libraryPanel.Name, Model: libraryPanel.Model, Meta: LibraryPanelDTOMeta{ - CanEdit: true, - Created: libraryPanel.Created, - Updated: libraryPanel.Updated, + CanEdit: true, + ConnectedDashboards: libraryPanel.ConnectedDashboards, + Created: libraryPanel.Created, + Updated: libraryPanel.Updated, CreatedBy: LibraryPanelDTOMetaUser{ ID: libraryPanel.CreatedBy, Name: libraryPanel.CreatedByName, @@ -247,18 +253,7 @@ func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]Lib orgID := c.SignedInUser.OrgId libraryPanels := make([]LibraryPanelWithMeta, 0) err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error { - sql := `SELECT - lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by - , 0 AS can_edit - , u1.login AS created_by_name - , u1.email AS created_by_email - , u2.login AS updated_by_name - , u2.email AS updated_by_email - FROM library_panel AS lp - LEFT JOIN user AS u1 ON lp.created_by = u1.id - LEFT JOIN user AS u2 ON lp.updated_by = u2.id - WHERE lp.org_id=?` - + sql := sqlStatmentLibrayPanelDTOWithMeta + "WHERE lp.org_id=?" sess := session.SQL(sql, orgID) err := sess.Find(&libraryPanels) if err != nil { @@ -278,9 +273,10 @@ func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]Lib Name: panel.Name, Model: panel.Model, Meta: LibraryPanelDTOMeta{ - CanEdit: true, - Created: panel.Created, - Updated: panel.Updated, + CanEdit: true, + ConnectedDashboards: panel.ConnectedDashboards, + Created: panel.Created, + Updated: panel.Updated, CreatedBy: LibraryPanelDTOMetaUser{ ID: panel.CreatedBy, Name: panel.CreatedByName, @@ -325,17 +321,11 @@ func (lps *LibraryPanelService) getConnectedDashboards(c *models.ReqContext, uid return connectedDashboardIDs, err } -func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64) (map[string]LibraryPanel, error) { - libraryPanelMap := make(map[string]LibraryPanel) +func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64) (map[string]LibraryPanelDTO, error) { + libraryPanelMap := make(map[string]LibraryPanelDTO) err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error { - sql := `SELECT - lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by - FROM - library_panel_dashboard AS lpd - INNER JOIN - library_panel AS lp ON lpd.librarypanel_id = lp.id AND lpd.dashboard_id=?` - - var libraryPanels []LibraryPanel + var libraryPanels []LibraryPanelWithMeta + sql := sqlStatmentLibrayPanelDTOWithMeta + "INNER JOIN library_panel_dashboard AS lpd ON lpd.librarypanel_id = lp.id AND lpd.dashboard_id=?" sess := session.SQL(sql, dashboardID) err := sess.Find(&libraryPanels) if err != nil { @@ -343,7 +333,30 @@ func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64 } for _, panel := range libraryPanels { - libraryPanelMap[panel.UID] = panel + libraryPanelMap[panel.UID] = LibraryPanelDTO{ + ID: panel.ID, + OrgID: panel.OrgID, + FolderID: panel.FolderID, + UID: panel.UID, + Name: panel.Name, + Model: panel.Model, + Meta: LibraryPanelDTOMeta{ + CanEdit: panel.CanEdit, + ConnectedDashboards: panel.ConnectedDashboards, + Created: panel.Created, + Updated: panel.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: panel.CreatedBy, + Name: panel.CreatedByName, + AvatarUrl: dtos.GetGravatarUrl(panel.CreatedByEmail), + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: panel.UpdatedBy, + Name: panel.UpdatedByName, + AvatarUrl: dtos.GetGravatarUrl(panel.UpdatedByEmail), + }, + }, + } } return nil @@ -401,11 +414,12 @@ func (lps *LibraryPanelService) patchLibraryPanel(c *models.ReqContext, cmd patc Name: libraryPanel.Name, Model: libraryPanel.Model, Meta: LibraryPanelDTOMeta{ - CanEdit: true, - Created: libraryPanel.Created, - Updated: libraryPanel.Updated, + CanEdit: true, + ConnectedDashboards: panelInDB.ConnectedDashboards, + Created: libraryPanel.Created, + Updated: libraryPanel.Updated, CreatedBy: LibraryPanelDTOMetaUser{ - ID: libraryPanel.CreatedBy, + ID: panelInDB.CreatedBy, Name: panelInDB.CreatedByName, AvatarUrl: dtos.GetGravatarUrl(panelInDB.CreatedByEmail), }, diff --git a/pkg/services/librarypanels/librarypanels.go b/pkg/services/librarypanels/librarypanels.go index de6340b7099..02b89206345 100644 --- a/pkg/services/librarypanels/librarypanels.go +++ b/pkg/services/librarypanels/librarypanels.go @@ -104,6 +104,22 @@ func (lps *LibraryPanelService) LoadLibraryPanelsForDashboard(dash *models.Dashb elem.Set("libraryPanel", map[string]interface{}{ "uid": libraryPanelInDB.UID, "name": libraryPanelInDB.Name, + "meta": map[string]interface{}{ + "canEdit": libraryPanelInDB.Meta.CanEdit, + "connectedDashboards": libraryPanelInDB.Meta.ConnectedDashboards, + "created": libraryPanelInDB.Meta.Created, + "updated": libraryPanelInDB.Meta.Updated, + "createdBy": map[string]interface{}{ + "id": libraryPanelInDB.Meta.CreatedBy.ID, + "name": libraryPanelInDB.Meta.CreatedBy.Name, + "avatarUrl": libraryPanelInDB.Meta.CreatedBy.AvatarUrl, + }, + "updatedBy": map[string]interface{}{ + "id": libraryPanelInDB.Meta.UpdatedBy.ID, + "name": libraryPanelInDB.Meta.UpdatedBy.Name, + "avatarUrl": libraryPanelInDB.Meta.UpdatedBy.AvatarUrl, + }, + }, }) } diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index 4b398ea096e..e49f9526b7b 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -1,17 +1,17 @@ package librarypanels import ( + "context" "encoding/json" "fmt" "testing" "time" - "github.com/grafana/grafana/pkg/components/simplejson" - "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" "gopkg.in/macaron.v1" + "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/registry" "github.com/grafana/grafana/pkg/services/sqlstore" @@ -28,6 +28,51 @@ func TestCreateLibraryPanel(t *testing.T) { response = sc.service.createHandler(sc.reqContext, command) require.Equal(t, 400, response.Status()) }) + + testScenario(t, "When an admin tries to create a library panel that does not exists, it should succeed", + func(t *testing.T, sc scenarioContext) { + command := getCreateCommand(1, "Text - Library Panel") + response := sc.service.createHandler(sc.reqContext, command) + require.Equal(t, 200, response.Status()) + + var result libraryPanelResult + err := json.Unmarshal(response.Body(), &result) + require.NoError(t, err) + var expected = libraryPanelResult{ + Result: libraryPanel{ + ID: 1, + OrgID: 1, + FolderID: 1, + UID: result.Result.UID, + Name: "Text - Library Panel", + Model: map[string]interface{}{ + "datasource": "${DS_GDEV-TESTDATA}", + "id": float64(1), + "title": "Text - Library Panel", + "type": "text", + }, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + ConnectedDashboards: 0, + Created: result.Result.Meta.Created, + Updated: result.Result.Meta.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "signed_in_user", + AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "signed_in_user", + AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", + }, + }, + }, + } + if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" { + t.Fatalf("Result mismatch (-want +got):\n%s", diff) + } + }) } func TestConnectLibraryPanel(t *testing.T) { @@ -161,8 +206,40 @@ func TestGetLibraryPanel(t *testing.T) { require.Equal(t, 200, response.Status()) err = json.Unmarshal(response.Body(), &result) require.NoError(t, err) - require.Equal(t, int64(1), result.Result.FolderID) - require.Equal(t, "Text - Library Panel", result.Result.Name) + var expected = libraryPanelResult{ + Result: libraryPanel{ + ID: 1, + OrgID: 1, + FolderID: 1, + UID: result.Result.UID, + Name: "Text - Library Panel", + Model: map[string]interface{}{ + "datasource": "${DS_GDEV-TESTDATA}", + "id": float64(1), + "title": "Text - Library Panel", + "type": "text", + }, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + ConnectedDashboards: 0, + Created: result.Result.Meta.Created, + Updated: result.Result.Meta.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "user_in_db", + AvatarUrl: "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "user_in_db", + AvatarUrl: "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + }, + }, + } + if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" { + t.Fatalf("Result mismatch (-want +got):\n%s", diff) + } }) testScenario(t, "When an admin tries to get a library panel that exists in an other org, it should fail", @@ -181,6 +258,31 @@ func TestGetLibraryPanel(t *testing.T) { response = sc.service.getHandler(sc.reqContext) require.Equal(t, 404, response.Status()) }) + + testScenario(t, "When an admin tries to get a library panel with 2 connected dashboards, it should succeed and return correct connected dashboards", + func(t *testing.T, sc scenarioContext) { + command := getCreateCommand(1, "Text - Library Panel") + response := sc.service.createHandler(sc.reqContext, command) + require.Equal(t, 200, response.Status()) + + var result libraryPanelResult + err := json.Unmarshal(response.Body(), &result) + require.NoError(t, err) + + sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID, ":dashboardId": "1"}) + response = sc.service.connectHandler(sc.reqContext) + require.Equal(t, 200, response.Status()) + sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID, ":dashboardId": "2"}) + response = sc.service.connectHandler(sc.reqContext) + require.Equal(t, 200, response.Status()) + + sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID}) + response = sc.service.getHandler(sc.reqContext) + require.Equal(t, 200, response.Status()) + err = json.Unmarshal(response.Body(), &result) + require.NoError(t, err) + require.Equal(t, int64(2), result.Result.Meta.ConnectedDashboards) + }) } func TestGetAllLibraryPanels(t *testing.T) { @@ -196,7 +298,7 @@ func TestGetAllLibraryPanels(t *testing.T) { require.Equal(t, 0, len(result.Result)) }) - testScenario(t, "When an admin tries to get all library panels and two exist, it should work", + testScenario(t, "When an admin tries to get all library panels and two exist, it should succeed", func(t *testing.T, sc scenarioContext) { command := getCreateCommand(1, "Text - Library Panel") response := sc.service.createHandler(sc.reqContext, command) @@ -212,11 +314,102 @@ func TestGetAllLibraryPanels(t *testing.T) { var result libraryPanelsResult err := json.Unmarshal(response.Body(), &result) require.NoError(t, err) - require.Equal(t, 2, len(result.Result)) - require.Equal(t, int64(1), result.Result[0].FolderID) - require.Equal(t, "Text - Library Panel", result.Result[0].Name) - require.Equal(t, int64(1), result.Result[1].FolderID) - require.Equal(t, "Text - Library Panel2", result.Result[1].Name) + var expected = libraryPanelsResult{ + Result: []libraryPanel{ + { + ID: 1, + OrgID: 1, + FolderID: 1, + UID: result.Result[0].UID, + Name: "Text - Library Panel", + Model: map[string]interface{}{ + "datasource": "${DS_GDEV-TESTDATA}", + "id": float64(1), + "title": "Text - Library Panel", + "type": "text", + }, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + ConnectedDashboards: 0, + Created: result.Result[0].Meta.Created, + Updated: result.Result[0].Meta.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "user_in_db", + AvatarUrl: "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "user_in_db", + AvatarUrl: "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + }, + }, + { + ID: 2, + OrgID: 1, + FolderID: 1, + UID: result.Result[1].UID, + Name: "Text - Library Panel2", + Model: map[string]interface{}{ + "datasource": "${DS_GDEV-TESTDATA}", + "id": float64(1), + "title": "Text - Library Panel", + "type": "text", + }, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + ConnectedDashboards: 0, + Created: result.Result[1].Meta.Created, + Updated: result.Result[1].Meta.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "user_in_db", + AvatarUrl: "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "user_in_db", + AvatarUrl: "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + }, + }, + }, + } + if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" { + t.Fatalf("Result mismatch (-want +got):\n%s", diff) + } + }) + + testScenario(t, "When an admin tries to get all library panels and two exist but only one is connected, it should succeed and return correct connected dashboards", + func(t *testing.T, sc scenarioContext) { + command := getCreateCommand(1, "Text - Library Panel") + response := sc.service.createHandler(sc.reqContext, command) + require.Equal(t, 200, response.Status()) + + command = getCreateCommand(1, "Text - Library Panel2") + response = sc.service.createHandler(sc.reqContext, command) + require.Equal(t, 200, response.Status()) + + var result libraryPanelResult + err := json.Unmarshal(response.Body(), &result) + require.NoError(t, err) + + sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID, ":dashboardId": "1"}) + response = sc.service.connectHandler(sc.reqContext) + require.Equal(t, 200, response.Status()) + sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID, ":dashboardId": "2"}) + response = sc.service.connectHandler(sc.reqContext) + require.Equal(t, 200, response.Status()) + + response = sc.service.getAllHandler(sc.reqContext) + require.Equal(t, 200, response.Status()) + + var results libraryPanelsResult + err = json.Unmarshal(response.Body(), &results) + require.NoError(t, err) + require.Equal(t, int64(0), results.Result[0].Meta.ConnectedDashboards) + require.Equal(t, int64(2), results.Result[1].Meta.ConnectedDashboards) }) testScenario(t, "When an admin tries to get all library panels in a different org, none should be returned", @@ -326,6 +519,13 @@ func TestPatchLibraryPanel(t *testing.T) { err := json.Unmarshal(response.Body(), &existing) require.NoError(t, err) + sc.reqContext.ReplaceAllParams(map[string]string{":uid": existing.Result.UID, ":dashboardId": "1"}) + response = sc.service.connectHandler(sc.reqContext) + require.Equal(t, 200, response.Status()) + sc.reqContext.ReplaceAllParams(map[string]string{":uid": existing.Result.UID, ":dashboardId": "2"}) + response = sc.service.connectHandler(sc.reqContext) + require.Equal(t, 200, response.Status()) + cmd := patchLibraryPanelCommand{ FolderID: 2, Name: "Panel - New name", @@ -345,10 +545,38 @@ func TestPatchLibraryPanel(t *testing.T) { var result libraryPanelResult err = json.Unmarshal(response.Body(), &result) require.NoError(t, err) - existing.Result.FolderID = int64(2) - existing.Result.Name = "Panel - New name" - existing.Result.Model["title"] = "Model - New name" - if diff := cmp.Diff(existing.Result, result.Result, getCompareOptions()...); diff != "" { + var expected = libraryPanelResult{ + Result: libraryPanel{ + ID: 1, + OrgID: 1, + FolderID: 2, + UID: existing.Result.UID, + Name: "Panel - New name", + Model: map[string]interface{}{ + "datasource": "${DS_GDEV-TESTDATA}", + "id": float64(1), + "title": "Model - New name", + "type": "text", + }, + Meta: LibraryPanelDTOMeta{ + CanEdit: true, + ConnectedDashboards: 2, + Created: existing.Result.Meta.Created, + Updated: result.Result.Meta.Updated, + CreatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "user_in_db", + AvatarUrl: "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + UpdatedBy: LibraryPanelDTOMetaUser{ + ID: 1, + Name: "signed_in_user", + AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", + }, + }, + }, + } + if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" { t.Fatalf("Result mismatch (-want +got):\n%s", diff) } }) @@ -374,6 +602,8 @@ func TestPatchLibraryPanel(t *testing.T) { err = json.Unmarshal(response.Body(), &result) require.NoError(t, err) existing.Result.FolderID = int64(100) + existing.Result.Meta.CreatedBy.Name = "user_in_db" + existing.Result.Meta.CreatedBy.AvatarUrl = "/avatar/402d08de060496d6b6874495fe20f5ad" if diff := cmp.Diff(existing.Result, result.Result, getCompareOptions()...); diff != "" { t.Fatalf("Result mismatch (-want +got):\n%s", diff) } @@ -399,6 +629,8 @@ func TestPatchLibraryPanel(t *testing.T) { err = json.Unmarshal(response.Body(), &result) require.NoError(t, err) existing.Result.Name = "New Name" + existing.Result.Meta.CreatedBy.Name = "user_in_db" + existing.Result.Meta.CreatedBy.AvatarUrl = "/avatar/402d08de060496d6b6874495fe20f5ad" if diff := cmp.Diff(existing.Result, result.Result, getCompareOptions()...); diff != "" { t.Fatalf("Result mismatch (-want +got):\n%s", diff) } @@ -426,6 +658,8 @@ func TestPatchLibraryPanel(t *testing.T) { existing.Result.Model = map[string]interface{}{ "name": "New Model Name", } + existing.Result.Meta.CreatedBy.Name = "user_in_db" + existing.Result.Meta.CreatedBy.AvatarUrl = "/avatar/402d08de060496d6b6874495fe20f5ad" if diff := cmp.Diff(existing.Result, result.Result, getCompareOptions()...); diff != "" { t.Fatalf("Result mismatch (-want +got):\n%s", diff) } @@ -450,6 +684,8 @@ func TestPatchLibraryPanel(t *testing.T) { err = json.Unmarshal(response.Body(), &result) require.NoError(t, err) existing.Result.Meta.UpdatedBy.ID = int64(2) + existing.Result.Meta.CreatedBy.Name = "user_in_db" + existing.Result.Meta.CreatedBy.AvatarUrl = "/avatar/402d08de060496d6b6874495fe20f5ad" if diff := cmp.Diff(existing.Result, result.Result, getCompareOptions()...); diff != "" { t.Fatalf("Result mismatch (-want +got):\n%s", diff) } @@ -590,6 +826,22 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) { "libraryPanel": map[string]interface{}{ "uid": existing.Result.UID, "name": existing.Result.Name, + "meta": map[string]interface{}{ + "canEdit": false, + "connectedDashboards": int64(1), + "created": existing.Result.Meta.Created, + "updated": existing.Result.Meta.Updated, + "createdBy": map[string]interface{}{ + "id": existing.Result.Meta.CreatedBy.ID, + "name": "user_in_db", + "avatarUrl": "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + "updatedBy": map[string]interface{}{ + "id": existing.Result.Meta.UpdatedBy.ID, + "name": "user_in_db", + "avatarUrl": "/avatar/402d08de060496d6b6874495fe20f5ad", + }, + }, }, "title": "Text - Library Panel", "type": "text", @@ -1214,10 +1466,24 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo user := models.SignedInUser{ UserId: 1, + Name: "Signed In User", + Login: "signed_in_user", + Email: "signed.in.user@test.com", OrgId: orgID, OrgRole: role, LastSeenAt: time.Now(), } + // deliberate difference between signed in user and user in db to make it crystal clear + // what to expect in the tests + // In the real world these are identical + cmd := &models.CreateUserCommand{ + Email: "user.in.db@test.com", + Name: "User In DB", + Login: "user_in_db", + } + err := sqlstore.CreateUser(context.Background(), cmd) + require.NoError(t, err) + sc := scenarioContext{ user: user, ctx: &ctx, diff --git a/pkg/services/librarypanels/models.go b/pkg/services/librarypanels/models.go index b998b8dc3f7..a0e76c24130 100644 --- a/pkg/services/librarypanels/models.go +++ b/pkg/services/librarypanels/models.go @@ -34,13 +34,14 @@ type LibraryPanelWithMeta struct { Created time.Time Updated time.Time - CanEdit bool - CreatedBy int64 - UpdatedBy int64 - CreatedByName string - CreatedByEmail string - UpdatedByName string - UpdatedByEmail string + CanEdit bool + ConnectedDashboards int64 + CreatedBy int64 + UpdatedBy int64 + CreatedByName string + CreatedByEmail string + UpdatedByName string + UpdatedByEmail string } // LibraryPanelDTO is the frontend DTO for library panels. @@ -56,7 +57,8 @@ type LibraryPanelDTO struct { // LibraryPanelDTOMeta is the meta information for LibraryPanelDTO. type LibraryPanelDTOMeta struct { - CanEdit bool `json:"canEdit"` + CanEdit bool `json:"canEdit"` + ConnectedDashboards int64 `json:"connectedDashboards"` Created time.Time `json:"created"` Updated time.Time `json:"updated"`