mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
LibraryPanels: Improves export and import of library panels between orgs (#39214)
* Chore: adds tests to reducer * Refactor: rewrite state * Refactor: adds library panels to export * wip * Refactor: adds import library panels * Refactor: changes UI * Chore: pushing drone * Update public/app/features/manage-dashboards/components/ImportDashboardForm.tsx Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Update public/app/features/manage-dashboards/components/ImportDashboardForm.tsx Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com> * Chore: reverted unknown merge changes Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>
This commit is contained in:
@@ -46,7 +46,7 @@ func (l *LibraryElementService) deleteHandler(c *models.ReqContext) response.Res
|
||||
|
||||
// getHandler handles GET /api/library-elements/:uid.
|
||||
func (l *LibraryElementService) getHandler(c *models.ReqContext) response.Response {
|
||||
element, err := l.getLibraryElementByUid(c)
|
||||
element, err := l.getLibraryElementByUid(c, macaron.Params(c.Req)[":uid"])
|
||||
if err != nil {
|
||||
return toLibraryElementError(err, "Failed to get library element")
|
||||
}
|
||||
@@ -108,8 +108,8 @@ func toLibraryElementError(err error, message string) response.Response {
|
||||
if errors.Is(err, errLibraryElementAlreadyExists) {
|
||||
return response.Error(400, errLibraryElementAlreadyExists.Error(), err)
|
||||
}
|
||||
if errors.Is(err, errLibraryElementNotFound) {
|
||||
return response.Error(404, errLibraryElementNotFound.Error(), err)
|
||||
if errors.Is(err, ErrLibraryElementNotFound) {
|
||||
return response.Error(404, ErrLibraryElementNotFound.Error(), err)
|
||||
}
|
||||
if errors.Is(err, errLibraryElementDashboardNotFound) {
|
||||
return response.Error(404, errLibraryElementDashboardNotFound.Error(), err)
|
||||
|
||||
@@ -81,7 +81,7 @@ func getLibraryElement(dialect migrator.Dialect, session *sqlstore.DBSession, ui
|
||||
return LibraryElementWithMeta{}, err
|
||||
}
|
||||
if len(elements) == 0 {
|
||||
return LibraryElementWithMeta{}, errLibraryElementNotFound
|
||||
return LibraryElementWithMeta{}, ErrLibraryElementNotFound
|
||||
}
|
||||
if len(elements) > 1 {
|
||||
return LibraryElementWithMeta{}, fmt.Errorf("found %d elements, while expecting at most one", len(elements))
|
||||
@@ -196,28 +196,28 @@ func (l *LibraryElementService) deleteLibraryElement(c *models.ReqContext, uid s
|
||||
if rowsAffected, err := result.RowsAffected(); err != nil {
|
||||
return err
|
||||
} else if rowsAffected != 1 {
|
||||
return errLibraryElementNotFound
|
||||
return ErrLibraryElementNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// getLibraryElement gets a Library Element where param == value
|
||||
func (l *LibraryElementService) getLibraryElements(c *models.ReqContext, params []Pair) ([]LibraryElementDTO, error) {
|
||||
// getLibraryElements gets a Library Element where param == value
|
||||
func getLibraryElements(c *models.ReqContext, store *sqlstore.SQLStore, params []Pair) ([]LibraryElementDTO, error) {
|
||||
libraryElements := make([]LibraryElementWithMeta, 0)
|
||||
err := l.SQLStore.WithDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error {
|
||||
err := store.WithDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error {
|
||||
builder := sqlstore.SQLBuilder{}
|
||||
builder.Write(selectLibraryElementDTOWithMeta)
|
||||
builder.Write(", 'General' as folder_name ")
|
||||
builder.Write(", '' as folder_uid ")
|
||||
builder.Write(getFromLibraryElementDTOWithMeta(l.SQLStore.Dialect))
|
||||
builder.Write(getFromLibraryElementDTOWithMeta(store.Dialect))
|
||||
writeParamSelectorSQL(&builder, append(params, Pair{"folder_id", 0})...)
|
||||
builder.Write(" UNION ")
|
||||
builder.Write(selectLibraryElementDTOWithMeta)
|
||||
builder.Write(", dashboard.title as folder_name ")
|
||||
builder.Write(", dashboard.uid as folder_uid ")
|
||||
builder.Write(getFromLibraryElementDTOWithMeta(l.SQLStore.Dialect))
|
||||
builder.Write(getFromLibraryElementDTOWithMeta(store.Dialect))
|
||||
builder.Write(" INNER JOIN dashboard AS dashboard on le.folder_id = dashboard.id AND le.folder_id <> 0")
|
||||
writeParamSelectorSQL(&builder, params...)
|
||||
if c.SignedInUser.OrgRole != models.ROLE_ADMIN {
|
||||
@@ -228,7 +228,7 @@ func (l *LibraryElementService) getLibraryElements(c *models.ReqContext, params
|
||||
return err
|
||||
}
|
||||
if len(libraryElements) == 0 {
|
||||
return errLibraryElementNotFound
|
||||
return ErrLibraryElementNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -274,8 +274,8 @@ func (l *LibraryElementService) getLibraryElements(c *models.ReqContext, params
|
||||
}
|
||||
|
||||
// getLibraryElementByUid gets a Library Element by uid.
|
||||
func (l *LibraryElementService) getLibraryElementByUid(c *models.ReqContext) (LibraryElementDTO, error) {
|
||||
libraryElements, err := l.getLibraryElements(c, []Pair{{key: "org_id", value: c.SignedInUser.OrgId}, {key: "uid", value: macaron.Params(c.Req)[":uid"]}})
|
||||
func (l *LibraryElementService) getLibraryElementByUid(c *models.ReqContext, UID string) (LibraryElementDTO, error) {
|
||||
libraryElements, err := getLibraryElements(c, l.SQLStore, []Pair{{key: "org_id", value: c.SignedInUser.OrgId}, {key: "uid", value: UID}})
|
||||
if err != nil {
|
||||
return LibraryElementDTO{}, err
|
||||
}
|
||||
@@ -288,7 +288,7 @@ func (l *LibraryElementService) getLibraryElementByUid(c *models.ReqContext) (Li
|
||||
|
||||
// getLibraryElementByName gets a Library Element by name.
|
||||
func (l *LibraryElementService) getLibraryElementsByName(c *models.ReqContext) ([]LibraryElementDTO, error) {
|
||||
return l.getLibraryElements(c, []Pair{{"org_id", c.SignedInUser.OrgId}, {"name", macaron.Params(c.Req)[":name"]}})
|
||||
return getLibraryElements(c, l.SQLStore, []Pair{{"org_id", c.SignedInUser.OrgId}, {"name", macaron.Params(c.Req)[":name"]}})
|
||||
}
|
||||
|
||||
// getAllLibraryElements gets all Library Elements.
|
||||
@@ -458,7 +458,7 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa
|
||||
}
|
||||
|
||||
_, err := getLibraryElement(l.SQLStore.Dialect, session, updateUID, c.SignedInUser.OrgId)
|
||||
if !errors.Is(err, errLibraryElementNotFound) {
|
||||
if !errors.Is(err, ErrLibraryElementNotFound) {
|
||||
return errLibraryElementAlreadyExists
|
||||
}
|
||||
}
|
||||
@@ -498,7 +498,7 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa
|
||||
}
|
||||
return err
|
||||
} else if rowsAffected != 1 {
|
||||
return errLibraryElementNotFound
|
||||
return ErrLibraryElementNotFound
|
||||
}
|
||||
|
||||
dto = LibraryElementDTO{
|
||||
|
||||
@@ -22,6 +22,7 @@ func ProvideService(cfg *setting.Cfg, sqlStore *sqlstore.SQLStore, routeRegister
|
||||
// Service is a service for operating on library elements.
|
||||
type Service interface {
|
||||
CreateElement(c *models.ReqContext, cmd CreateLibraryElementCommand) (LibraryElementDTO, error)
|
||||
GetElement(c *models.ReqContext, UID string) (LibraryElementDTO, error)
|
||||
GetElementsForDashboard(c *models.ReqContext, dashboardID int64) (map[string]LibraryElementDTO, error)
|
||||
ConnectElementsToDashboard(c *models.ReqContext, elementUIDs []string, dashboardID int64) error
|
||||
DisconnectElementsFromDashboard(c *models.ReqContext, dashboardID int64) error
|
||||
@@ -41,6 +42,11 @@ func (l *LibraryElementService) CreateElement(c *models.ReqContext, cmd CreateLi
|
||||
return l.createLibraryElement(c, cmd)
|
||||
}
|
||||
|
||||
// GetElement gets an element from a UID.
|
||||
func (l *LibraryElementService) GetElement(c *models.ReqContext, UID string) (LibraryElementDTO, error) {
|
||||
return l.getLibraryElementByUid(c, UID)
|
||||
}
|
||||
|
||||
// GetElementsForDashboard gets all connected elements for a specific dashboard.
|
||||
func (l *LibraryElementService) GetElementsForDashboard(c *models.ReqContext, dashboardID int64) (map[string]LibraryElementDTO, error) {
|
||||
return l.getElementsForDashboardID(c, dashboardID)
|
||||
|
||||
@@ -137,8 +137,8 @@ type LibraryElementConnectionDTO struct {
|
||||
var (
|
||||
// errLibraryElementAlreadyExists is an error for when the user tries to add a library element that already exists.
|
||||
errLibraryElementAlreadyExists = errors.New("library element with that name or UID already exists")
|
||||
// errLibraryElementNotFound is an error for when a library element can't be found.
|
||||
errLibraryElementNotFound = errors.New("library element could not be found")
|
||||
// ErrLibraryElementNotFound is an error for when a library element can't be found.
|
||||
ErrLibraryElementNotFound = errors.New("library element could not be found")
|
||||
// errLibraryElementDashboardNotFound is an error for when a library element connection can't be found.
|
||||
errLibraryElementDashboardNotFound = errors.New("library element connection could not be found")
|
||||
// errLibraryElementHasConnections is an error for when an user deletes a library element that is connected.
|
||||
|
||||
Reference in New Issue
Block a user