Commit 0a8eae2c by Hugo Häggmark Committed by GitHub

PanelLibrary: changes casing of responses and adds meta property (#30668)

* PanelLibrary: changes casing of responses and adds meta property

* Chore: updates comments

* Chore: updates after PR comments

* Chore: changes casing of orgId
parent 1bdd3eb3
...@@ -5,17 +5,15 @@ import ( ...@@ -5,17 +5,15 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"github.com/grafana/grafana/pkg/util"
) )
// createLibraryPanel adds a Library Panel. // createLibraryPanel adds a Library Panel.
func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd createLibraryPanelCommand) (LibraryPanel, error) { func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd createLibraryPanelCommand) (LibraryPanelDTO, error) {
libraryPanel := LibraryPanel{ libraryPanel := LibraryPanel{
OrgID: c.SignedInUser.OrgId, OrgID: c.SignedInUser.OrgId,
FolderID: cmd.FolderID, FolderID: cmd.FolderID,
...@@ -39,7 +37,31 @@ func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd cre ...@@ -39,7 +37,31 @@ func (lps *LibraryPanelService) createLibraryPanel(c *models.ReqContext, cmd cre
return nil return nil
}) })
return libraryPanel, err dto := LibraryPanelDTO{
ID: libraryPanel.ID,
OrgID: libraryPanel.OrgID,
FolderID: libraryPanel.FolderID,
UID: libraryPanel.UID,
Name: libraryPanel.Name,
Model: libraryPanel.Model,
Meta: LibraryPanelDTOMeta{
CanEdit: true,
Created: libraryPanel.Created,
Updated: libraryPanel.Updated,
CreatedBy: LibraryPanelDTOMetaUser{
ID: libraryPanel.CreatedBy,
Name: c.SignedInUser.Login,
AvatarUrl: dtos.GetGravatarUrl(c.SignedInUser.Email),
},
UpdatedBy: LibraryPanelDTOMetaUser{
ID: libraryPanel.UpdatedBy,
Name: c.SignedInUser.Login,
AvatarUrl: dtos.GetGravatarUrl(c.SignedInUser.Email),
},
},
}
return dto, err
} }
func connectDashboard(session *sqlstore.DBSession, dialect migrator.Dialect, user *models.SignedInUser, uid string, dashboardID int64) error { func connectDashboard(session *sqlstore.DBSession, dialect migrator.Dialect, user *models.SignedInUser, uid string, dashboardID int64) error {
...@@ -148,42 +170,90 @@ func (lps *LibraryPanelService) disconnectLibraryPanelsForDashboard(dashboardID ...@@ -148,42 +170,90 @@ func (lps *LibraryPanelService) disconnectLibraryPanelsForDashboard(dashboardID
}) })
} }
func getLibraryPanel(session *sqlstore.DBSession, uid string, orgID int64) (LibraryPanel, error) { func getLibraryPanel(session *sqlstore.DBSession, uid string, orgID int64) (LibraryPanelWithMeta, error) {
libraryPanels := make([]LibraryPanel, 0) libraryPanels := make([]LibraryPanelWithMeta, 0)
session.Table("library_panel") sql := `SELECT
session.Where("uid=? AND org_id=?", uid, orgID) lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by
err := session.Find(&libraryPanels) , 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=?`
sess := session.SQL(sql, uid, orgID)
err := sess.Find(&libraryPanels)
if err != nil { if err != nil {
return LibraryPanel{}, err return LibraryPanelWithMeta{}, err
} }
if len(libraryPanels) == 0 { if len(libraryPanels) == 0 {
return LibraryPanel{}, errLibraryPanelNotFound return LibraryPanelWithMeta{}, errLibraryPanelNotFound
} }
if len(libraryPanels) > 1 { if len(libraryPanels) > 1 {
return LibraryPanel{}, fmt.Errorf("found %d panels, while expecting at most one", len(libraryPanels)) return LibraryPanelWithMeta{}, fmt.Errorf("found %d panels, while expecting at most one", len(libraryPanels))
} }
return libraryPanels[0], nil return libraryPanels[0], nil
} }
// getLibraryPanel gets a Library Panel. // getLibraryPanel gets a Library Panel.
func (lps *LibraryPanelService) getLibraryPanel(c *models.ReqContext, uid string) (LibraryPanel, error) { func (lps *LibraryPanelService) getLibraryPanel(c *models.ReqContext, uid string) (LibraryPanelDTO, error) {
var libraryPanel LibraryPanel var libraryPanel LibraryPanelWithMeta
err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error { err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error {
var err error var err error
libraryPanel, err = getLibraryPanel(session, uid, c.SignedInUser.OrgId) libraryPanel, err = getLibraryPanel(session, uid, c.SignedInUser.OrgId)
return err return err
}) })
return libraryPanel, err dto := LibraryPanelDTO{
ID: libraryPanel.ID,
OrgID: libraryPanel.OrgID,
FolderID: libraryPanel.FolderID,
UID: libraryPanel.UID,
Name: libraryPanel.Name,
Model: libraryPanel.Model,
Meta: LibraryPanelDTOMeta{
CanEdit: true,
Created: libraryPanel.Created,
Updated: libraryPanel.Updated,
CreatedBy: LibraryPanelDTOMetaUser{
ID: libraryPanel.CreatedBy,
Name: libraryPanel.CreatedByName,
AvatarUrl: dtos.GetGravatarUrl(libraryPanel.CreatedByEmail),
},
UpdatedBy: LibraryPanelDTOMetaUser{
ID: libraryPanel.UpdatedBy,
Name: libraryPanel.UpdatedByName,
AvatarUrl: dtos.GetGravatarUrl(libraryPanel.UpdatedByEmail),
},
},
}
return dto, err
} }
// getAllLibraryPanels gets all library panels. // getAllLibraryPanels gets all library panels.
func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]LibraryPanel, error) { func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]LibraryPanelDTO, error) {
orgID := c.SignedInUser.OrgId orgID := c.SignedInUser.OrgId
libraryPanels := make([]LibraryPanel, 0) libraryPanels := make([]LibraryPanelWithMeta, 0)
err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error { err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error {
err := session.SQL("SELECT * FROM library_panel WHERE org_id=?", orgID).Find(&libraryPanels) 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=?`
sess := session.SQL(sql, orgID)
err := sess.Find(&libraryPanels)
if err != nil { if err != nil {
return err return err
} }
...@@ -191,7 +261,34 @@ func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]Lib ...@@ -191,7 +261,34 @@ func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext) ([]Lib
return nil return nil
}) })
return libraryPanels, err retDTOs := make([]LibraryPanelDTO, 0)
for _, panel := range libraryPanels {
retDTOs = append(retDTOs, LibraryPanelDTO{
ID: panel.ID,
OrgID: panel.OrgID,
FolderID: panel.FolderID,
UID: panel.UID,
Name: panel.Name,
Model: panel.Model,
Meta: LibraryPanelDTOMeta{
CanEdit: true,
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 retDTOs, err
} }
// getConnectedDashboards gets all dashboards connected to a Library Panel. // getConnectedDashboards gets all dashboards connected to a Library Panel.
...@@ -225,7 +322,7 @@ func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64 ...@@ -225,7 +322,7 @@ func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64
libraryPanelMap := make(map[string]LibraryPanel) libraryPanelMap := make(map[string]LibraryPanel)
err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error { err := lps.SQLStore.WithDbSession(context.Background(), func(session *sqlstore.DBSession) error {
sql := `SELECT sql := `SELECT
lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.model, lp.created, lp.created_by, lp.updated, updated_by 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 FROM
library_panel_dashboard AS lpd library_panel_dashboard AS lpd
INNER JOIN INNER JOIN
...@@ -249,15 +346,15 @@ func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64 ...@@ -249,15 +346,15 @@ func (lps *LibraryPanelService) getLibraryPanelsForDashboardID(dashboardID int64
} }
// patchLibraryPanel updates a Library Panel. // patchLibraryPanel updates a Library Panel.
func (lps *LibraryPanelService) patchLibraryPanel(c *models.ReqContext, cmd patchLibraryPanelCommand, uid string) (LibraryPanel, error) { func (lps *LibraryPanelService) patchLibraryPanel(c *models.ReqContext, cmd patchLibraryPanelCommand, uid string) (LibraryPanelDTO, error) {
var libraryPanel LibraryPanel var dto LibraryPanelDTO
err := lps.SQLStore.WithTransactionalDbSession(context.Background(), func(session *sqlstore.DBSession) error { err := lps.SQLStore.WithTransactionalDbSession(context.Background(), func(session *sqlstore.DBSession) error {
panelInDB, err := getLibraryPanel(session, uid, c.SignedInUser.OrgId) panelInDB, err := getLibraryPanel(session, uid, c.SignedInUser.OrgId)
if err != nil { if err != nil {
return err return err
} }
libraryPanel = LibraryPanel{ var libraryPanel = LibraryPanel{
ID: panelInDB.ID, ID: panelInDB.ID,
OrgID: c.SignedInUser.OrgId, OrgID: c.SignedInUser.OrgId,
FolderID: cmd.FolderID, FolderID: cmd.FolderID,
...@@ -289,8 +386,32 @@ func (lps *LibraryPanelService) patchLibraryPanel(c *models.ReqContext, cmd patc ...@@ -289,8 +386,32 @@ func (lps *LibraryPanelService) patchLibraryPanel(c *models.ReqContext, cmd patc
return errLibraryPanelNotFound return errLibraryPanelNotFound
} }
dto = LibraryPanelDTO{
ID: libraryPanel.ID,
OrgID: libraryPanel.OrgID,
FolderID: libraryPanel.FolderID,
UID: libraryPanel.UID,
Name: libraryPanel.Name,
Model: libraryPanel.Model,
Meta: LibraryPanelDTOMeta{
CanEdit: true,
Created: libraryPanel.Created,
Updated: libraryPanel.Updated,
CreatedBy: LibraryPanelDTOMetaUser{
ID: libraryPanel.CreatedBy,
Name: panelInDB.CreatedByName,
AvatarUrl: dtos.GetGravatarUrl(panelInDB.CreatedByEmail),
},
UpdatedBy: LibraryPanelDTOMetaUser{
ID: libraryPanel.UpdatedBy,
Name: c.SignedInUser.Login,
AvatarUrl: dtos.GetGravatarUrl(c.SignedInUser.Email),
},
},
}
return nil return nil
}) })
return libraryPanel, err return dto, err
} }
...@@ -449,7 +449,7 @@ func TestPatchLibraryPanel(t *testing.T) { ...@@ -449,7 +449,7 @@ func TestPatchLibraryPanel(t *testing.T) {
var result libraryPanelResult var result libraryPanelResult
err = json.Unmarshal(response.Body(), &result) err = json.Unmarshal(response.Body(), &result)
require.NoError(t, err) require.NoError(t, err)
existing.Result.UpdatedBy = int64(2) existing.Result.Meta.UpdatedBy.ID = int64(2)
if diff := cmp.Diff(existing.Result, result.Result, getCompareOptions()...); diff != "" { if diff := cmp.Diff(existing.Result, result.Result, getCompareOptions()...); diff != "" {
t.Fatalf("Result mismatch (-want +got):\n%s", diff) t.Fatalf("Result mismatch (-want +got):\n%s", diff)
} }
...@@ -1092,16 +1092,13 @@ func TestDisconnectLibraryPanelsForDashboard(t *testing.T) { ...@@ -1092,16 +1092,13 @@ func TestDisconnectLibraryPanelsForDashboard(t *testing.T) {
} }
type libraryPanel struct { type libraryPanel struct {
ID int64 `json:"id"` ID int64 `json:"id"`
OrgID int64 `json:"orgId"` OrgID int64 `json:"orgId"`
FolderID int64 `json:"folderId"` FolderID int64 `json:"folderId"`
UID string `json:"uid"` UID string `json:"uid"`
Name string `json:"name"` Name string `json:"name"`
Model map[string]interface{} `json:"model"` Model map[string]interface{} `json:"model"`
Created time.Time `json:"created"` Meta LibraryPanelDTOMeta `json:"meta"`
Updated time.Time `json:"updated"`
CreatedBy int64 `json:"createdBy"`
UpdatedBy int64 `json:"updatedBy"`
} }
type libraryPanelResult struct { type libraryPanelResult struct {
......
...@@ -22,6 +22,56 @@ type LibraryPanel struct { ...@@ -22,6 +22,56 @@ type LibraryPanel struct {
UpdatedBy int64 UpdatedBy int64
} }
// LibraryPanelWithMeta is the model used to retrieve library panels with additional meta information.
type LibraryPanelWithMeta struct {
ID int64 `xorm:"pk autoincr 'id'"`
OrgID int64 `xorm:"org_id"`
FolderID int64 `xorm:"folder_id"`
UID string `xorm:"uid"`
Name string
Model json.RawMessage
Created time.Time
Updated time.Time
CanEdit bool
CreatedBy int64
UpdatedBy int64
CreatedByName string
CreatedByEmail string
UpdatedByName string
UpdatedByEmail string
}
// LibraryPanelDTO is the frontend DTO for library panels.
type LibraryPanelDTO struct {
ID int64 `json:"id"`
OrgID int64 `json:"orgId"`
FolderID int64 `json:"folderId"`
UID string `json:"uid"`
Name string `json:"name"`
Model json.RawMessage `json:"model"`
Meta LibraryPanelDTOMeta `json:"meta"`
}
// LibraryPanelDTOMeta is the meta information for LibraryPanelDTO.
type LibraryPanelDTOMeta struct {
CanEdit bool `json:"canEdit"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
CreatedBy LibraryPanelDTOMetaUser `json:"createdBy"`
UpdatedBy LibraryPanelDTOMetaUser `json:"updatedBy"`
}
// LibraryPanelDTOMetaUser is the meta information for user that creates/changes the library panel.
type LibraryPanelDTOMetaUser struct {
ID int64 `json:"id"`
Name string `json:"name"`
AvatarUrl string `json:"avatarUrl"`
}
// libraryPanelDashboard is the model for library panel connections. // libraryPanelDashboard is the model for library panel connections.
type libraryPanelDashboard struct { type libraryPanelDashboard struct {
ID int64 `xorm:"pk autoincr 'id'"` ID int64 `xorm:"pk autoincr 'id'"`
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment