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:
Hugo Häggmark
2021-09-20 10:58:24 +02:00
committed by GitHub
parent d5b885f958
commit 2696be49b9
18 changed files with 897 additions and 97 deletions

View File

@@ -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)

View File

@@ -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{

View File

@@ -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)

View File

@@ -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.