LibraryPanels: Adds panel type filter and sorting (#33425)
* Wip: inital commit * Chore: updating api * Refactor: adds description search and sorting * Refactor: adds panel filtering * Refactor: limits the height of select * Tests: updates snapshot * Refactor: small UI improvements
This commit is contained in:
@@ -81,7 +81,15 @@ func (lps *LibraryPanelService) getHandler(c *models.ReqContext) response.Respon
|
||||
|
||||
// getAllHandler handles GET /api/library-panels/.
|
||||
func (lps *LibraryPanelService) getAllHandler(c *models.ReqContext) response.Response {
|
||||
libraryPanels, err := lps.getAllLibraryPanels(c, c.QueryInt("perPage"), c.QueryInt("page"), c.Query("name"), c.Query("excludeUid"))
|
||||
query := searchLibraryPanelsQuery{
|
||||
perPage: c.QueryInt("perPage"),
|
||||
page: c.QueryInt("page"),
|
||||
searchString: c.Query("searchString"),
|
||||
sortDirection: c.Query("sortDirection"),
|
||||
panelFilter: c.Query("panelFilter"),
|
||||
excludeUID: c.Query("excludeUid"),
|
||||
}
|
||||
libraryPanels, err := lps.getAllLibraryPanels(c, query)
|
||||
if err != nil {
|
||||
return toLibraryPanelError(err, "Failed to get library panels")
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package librarypanels
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
@@ -15,7 +18,7 @@ import (
|
||||
var (
|
||||
sqlStatmentLibrayPanelDTOWithMeta = `
|
||||
SELECT DISTINCT
|
||||
lp.id, lp.org_id, lp.folder_id, lp.uid, lp.name, lp.type, lp.description, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by, lp.version
|
||||
lp.name, lp.id, lp.org_id, lp.folder_id, lp.uid, lp.type, lp.description, lp.model, lp.created, lp.created_by, lp.updated, lp.updated_by, lp.version
|
||||
, 0 AS can_edit
|
||||
, u1.login AS created_by_name
|
||||
, u1.email AS created_by_email
|
||||
@@ -384,42 +387,71 @@ func (lps *LibraryPanelService) getLibraryPanel(c *models.ReqContext, uid string
|
||||
}
|
||||
|
||||
// getAllLibraryPanels gets all library panels.
|
||||
func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext, perPage int, page int, name string, excludeUID string) (LibraryPanelSearchResult, error) {
|
||||
func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext, query searchLibraryPanelsQuery) (LibraryPanelSearchResult, error) {
|
||||
libraryPanels := make([]LibraryPanelWithMeta, 0)
|
||||
result := LibraryPanelSearchResult{}
|
||||
if perPage <= 0 {
|
||||
perPage = 100
|
||||
if query.perPage <= 0 {
|
||||
query.perPage = 100
|
||||
}
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
if query.page <= 0 {
|
||||
query.page = 1
|
||||
}
|
||||
var panelFilter []string
|
||||
if len(strings.TrimSpace(query.panelFilter)) > 0 {
|
||||
panelFilter = strings.Split(query.panelFilter, ",")
|
||||
}
|
||||
|
||||
err := lps.SQLStore.WithDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error {
|
||||
builder := sqlstore.SQLBuilder{}
|
||||
builder.Write(sqlStatmentLibrayPanelDTOWithMeta)
|
||||
builder.Write(` WHERE lp.org_id=? AND lp.folder_id=0`, c.SignedInUser.OrgId)
|
||||
if len(strings.TrimSpace(name)) > 0 {
|
||||
builder.Write(" AND lp.name "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+name+"%")
|
||||
if len(strings.TrimSpace(query.searchString)) > 0 {
|
||||
builder.Write(" AND lp.name "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+query.searchString+"%")
|
||||
builder.Write(" OR lp.description "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+query.searchString+"%")
|
||||
}
|
||||
if len(strings.TrimSpace(excludeUID)) > 0 {
|
||||
builder.Write(" AND lp.uid <> ?", excludeUID)
|
||||
if len(strings.TrimSpace(query.excludeUID)) > 0 {
|
||||
builder.Write(" AND lp.uid <> ?", query.excludeUID)
|
||||
}
|
||||
if len(panelFilter) > 0 {
|
||||
var sql bytes.Buffer
|
||||
params := make([]interface{}, 0)
|
||||
sql.WriteString(` AND lp.type IN (?` + strings.Repeat(",?", len(panelFilter)-1) + ")")
|
||||
for _, v := range panelFilter {
|
||||
params = append(params, v)
|
||||
}
|
||||
builder.Write(sql.String(), params...)
|
||||
}
|
||||
builder.Write(" UNION ")
|
||||
builder.Write(sqlStatmentLibrayPanelDTOWithMeta)
|
||||
builder.Write(" INNER JOIN dashboard AS dashboard on lp.folder_id = dashboard.id AND lp.folder_id<>0")
|
||||
builder.Write(` WHERE lp.org_id=?`, c.SignedInUser.OrgId)
|
||||
if len(strings.TrimSpace(name)) > 0 {
|
||||
builder.Write(" AND lp.name "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+name+"%")
|
||||
if len(strings.TrimSpace(query.searchString)) > 0 {
|
||||
builder.Write(" AND lp.name "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+query.searchString+"%")
|
||||
builder.Write(" OR lp.description "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+query.searchString+"%")
|
||||
}
|
||||
if len(strings.TrimSpace(excludeUID)) > 0 {
|
||||
builder.Write(" AND lp.uid <> ?", excludeUID)
|
||||
if len(strings.TrimSpace(query.excludeUID)) > 0 {
|
||||
builder.Write(" AND lp.uid <> ?", query.excludeUID)
|
||||
}
|
||||
if len(panelFilter) > 0 {
|
||||
var sql bytes.Buffer
|
||||
params := make([]interface{}, 0)
|
||||
sql.WriteString(` AND lp.type IN (?` + strings.Repeat(",?", len(panelFilter)-1) + ")")
|
||||
for _, v := range panelFilter {
|
||||
params = append(params, v)
|
||||
}
|
||||
builder.Write(sql.String(), params...)
|
||||
}
|
||||
if c.SignedInUser.OrgRole != models.ROLE_ADMIN {
|
||||
builder.WriteDashboardPermissionFilter(c.SignedInUser, models.PERMISSION_VIEW)
|
||||
}
|
||||
if perPage != 0 {
|
||||
offset := perPage * (page - 1)
|
||||
builder.Write(lps.SQLStore.Dialect.LimitOffset(int64(perPage), int64(offset)))
|
||||
if query.sortDirection == search.SortAlphaDesc.Name {
|
||||
builder.Write(" ORDER BY 1 DESC")
|
||||
} else {
|
||||
builder.Write(" ORDER BY 1 ASC")
|
||||
}
|
||||
if query.perPage != 0 {
|
||||
offset := query.perPage * (query.page - 1)
|
||||
builder.Write(lps.SQLStore.Dialect.LimitOffset(int64(query.perPage), int64(offset)))
|
||||
}
|
||||
if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryPanels); err != nil {
|
||||
return err
|
||||
@@ -460,11 +492,21 @@ func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext, perPag
|
||||
countBuilder := sqlstore.SQLBuilder{}
|
||||
countBuilder.Write("SELECT * FROM library_panel")
|
||||
countBuilder.Write(` WHERE org_id=?`, c.SignedInUser.OrgId)
|
||||
if len(strings.TrimSpace(name)) > 0 {
|
||||
countBuilder.Write(" AND name "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+name+"%")
|
||||
if len(strings.TrimSpace(query.searchString)) > 0 {
|
||||
countBuilder.Write(" AND name "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+query.searchString+"%")
|
||||
countBuilder.Write(" OR description "+lps.SQLStore.Dialect.LikeStr()+" ?", "%"+query.searchString+"%")
|
||||
}
|
||||
if len(strings.TrimSpace(excludeUID)) > 0 {
|
||||
countBuilder.Write(" AND uid <> ?", excludeUID)
|
||||
if len(strings.TrimSpace(query.excludeUID)) > 0 {
|
||||
countBuilder.Write(" AND uid <> ?", query.excludeUID)
|
||||
}
|
||||
if len(panelFilter) > 0 {
|
||||
var sql bytes.Buffer
|
||||
params := make([]interface{}, 0)
|
||||
sql.WriteString(` AND type IN (?` + strings.Repeat(",?", len(panelFilter)-1) + ")")
|
||||
for _, v := range panelFilter {
|
||||
params = append(params, v)
|
||||
}
|
||||
countBuilder.Write(sql.String(), params...)
|
||||
}
|
||||
if err := session.SQL(countBuilder.GetSQLString(), countBuilder.GetParams()...).Find(&panels); err != nil {
|
||||
return err
|
||||
@@ -473,8 +515,8 @@ func (lps *LibraryPanelService) getAllLibraryPanels(c *models.ReqContext, perPag
|
||||
result = LibraryPanelSearchResult{
|
||||
TotalCount: int64(len(panels)),
|
||||
LibraryPanels: retDTOs,
|
||||
Page: page,
|
||||
PerPage: perPage,
|
||||
Page: query.page,
|
||||
PerPage: query.perPage,
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -124,6 +126,252 @@ func TestGetAllLibraryPanels(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and sort desc is set, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("sortDirection", search.SortAlphaDesc.Name)
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
var result libraryPanelsSearch
|
||||
err = json.Unmarshal(resp.Body(), &result)
|
||||
require.NoError(t, err)
|
||||
var expected = libraryPanelsSearch{
|
||||
Result: libraryPanelsSearchResult{
|
||||
TotalCount: 2,
|
||||
Page: 1,
|
||||
PerPage: 100,
|
||||
LibraryPanels: []libraryPanel{
|
||||
{
|
||||
ID: 2,
|
||||
OrgID: 1,
|
||||
FolderID: 1,
|
||||
UID: result.Result.LibraryPanels[0].UID,
|
||||
Name: "Text - Library Panel2",
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"description": "A description",
|
||||
"id": float64(1),
|
||||
"title": "Text - Library Panel2",
|
||||
"type": "text",
|
||||
},
|
||||
Version: 1,
|
||||
Meta: LibraryPanelDTOMeta{
|
||||
CanEdit: true,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.LibraryPanels[0].Meta.Created,
|
||||
Updated: result.Result.LibraryPanels[0].Meta.Updated,
|
||||
CreatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
UpdatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: 1,
|
||||
OrgID: 1,
|
||||
FolderID: 1,
|
||||
UID: result.Result.LibraryPanels[1].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"description": "A description",
|
||||
"id": float64(1),
|
||||
"title": "Text - Library Panel",
|
||||
"type": "text",
|
||||
},
|
||||
Version: 1,
|
||||
Meta: LibraryPanelDTOMeta{
|
||||
CanEdit: true,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.LibraryPanels[1].Meta.Created,
|
||||
Updated: result.Result.LibraryPanels[1].Meta.Updated,
|
||||
CreatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
UpdatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" {
|
||||
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and panelFilter is set to existing types, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Gauge - Library Panel", []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
"title": "Gauge - Library Panel",
|
||||
"type": "gauge",
|
||||
"description": "Gauge description"
|
||||
}
|
||||
`))
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
command = getCreateCommandWithModel(sc.folder.Id, "BarGauge - Library Panel", []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
"title": "BarGauge - Library Panel",
|
||||
"type": "bargauge",
|
||||
"description": "BarGauge description"
|
||||
}
|
||||
`))
|
||||
resp = sc.service.createHandler(sc.reqContext, command)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("panelFilter", "bargauge,gauge")
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
var result libraryPanelsSearch
|
||||
err = json.Unmarshal(resp.Body(), &result)
|
||||
require.NoError(t, err)
|
||||
var expected = libraryPanelsSearch{
|
||||
Result: libraryPanelsSearchResult{
|
||||
TotalCount: 2,
|
||||
Page: 1,
|
||||
PerPage: 100,
|
||||
LibraryPanels: []libraryPanel{
|
||||
{
|
||||
ID: 3,
|
||||
OrgID: 1,
|
||||
FolderID: 1,
|
||||
UID: result.Result.LibraryPanels[0].UID,
|
||||
Name: "BarGauge - Library Panel",
|
||||
Type: "bargauge",
|
||||
Description: "BarGauge description",
|
||||
Model: map[string]interface{}{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"description": "BarGauge description",
|
||||
"id": float64(1),
|
||||
"title": "BarGauge - Library Panel",
|
||||
"type": "bargauge",
|
||||
},
|
||||
Version: 1,
|
||||
Meta: LibraryPanelDTOMeta{
|
||||
CanEdit: true,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.LibraryPanels[0].Meta.Created,
|
||||
Updated: result.Result.LibraryPanels[0].Meta.Updated,
|
||||
CreatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
UpdatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
OrgID: 1,
|
||||
FolderID: 1,
|
||||
UID: result.Result.LibraryPanels[1].UID,
|
||||
Name: "Gauge - Library Panel",
|
||||
Type: "gauge",
|
||||
Description: "Gauge description",
|
||||
Model: map[string]interface{}{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": float64(1),
|
||||
"title": "Gauge - Library Panel",
|
||||
"type": "gauge",
|
||||
"description": "Gauge description",
|
||||
},
|
||||
Version: 1,
|
||||
Meta: LibraryPanelDTOMeta{
|
||||
CanEdit: true,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.LibraryPanels[1].Meta.Created,
|
||||
Updated: result.Result.LibraryPanels[1].Meta.Updated,
|
||||
CreatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
UpdatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" {
|
||||
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and panelFilter is set to non existing type, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Gauge - Library Panel", []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
"title": "Gauge - Library Panel",
|
||||
"type": "gauge",
|
||||
"description": "Gauge description"
|
||||
}
|
||||
`))
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("panelFilter", "unknown1,unknown2")
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
var result libraryPanelsSearch
|
||||
err = json.Unmarshal(resp.Body(), &result)
|
||||
require.NoError(t, err)
|
||||
var expected = libraryPanelsSearch{
|
||||
Result: libraryPanelsSearchResult{
|
||||
TotalCount: 0,
|
||||
Page: 1,
|
||||
PerPage: 100,
|
||||
LibraryPanels: []libraryPanel{},
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" {
|
||||
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and excludeUID is set, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
@@ -311,7 +559,182 @@ func TestGetAllLibraryPanels(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 1 and name is panel2, it should succeed and the result should be correct",
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and searchString exists in the description, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Text - Library Panel2", []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
"title": "Text - Library Panel",
|
||||
"type": "text",
|
||||
"description": "Some other d e s c r i p t i o n"
|
||||
}
|
||||
`))
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("perPage", "1")
|
||||
sc.reqContext.Req.Form.Add("page", "1")
|
||||
sc.reqContext.Req.Form.Add("searchString", "description")
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
var result libraryPanelsSearch
|
||||
err = json.Unmarshal(resp.Body(), &result)
|
||||
require.NoError(t, err)
|
||||
var expected = libraryPanelsSearch{
|
||||
Result: libraryPanelsSearchResult{
|
||||
TotalCount: 1,
|
||||
Page: 1,
|
||||
PerPage: 1,
|
||||
LibraryPanels: []libraryPanel{
|
||||
{
|
||||
ID: 1,
|
||||
OrgID: 1,
|
||||
FolderID: 1,
|
||||
UID: result.Result.LibraryPanels[0].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"description": "A description",
|
||||
"id": float64(1),
|
||||
"title": "Text - Library Panel",
|
||||
"type": "text",
|
||||
},
|
||||
Version: 1,
|
||||
Meta: LibraryPanelDTOMeta{
|
||||
CanEdit: true,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.LibraryPanels[0].Meta.Created,
|
||||
Updated: result.Result.LibraryPanels[0].Meta.Updated,
|
||||
CreatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
UpdatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" {
|
||||
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and searchString exists in both name and description, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Some Other", []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
"title": "Text - Library Panel",
|
||||
"type": "text",
|
||||
"description": "A Library Panel"
|
||||
}
|
||||
`))
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("searchString", "Library Panel")
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
var result libraryPanelsSearch
|
||||
err = json.Unmarshal(resp.Body(), &result)
|
||||
require.NoError(t, err)
|
||||
var expected = libraryPanelsSearch{
|
||||
Result: libraryPanelsSearchResult{
|
||||
TotalCount: 2,
|
||||
Page: 1,
|
||||
PerPage: 100,
|
||||
LibraryPanels: []libraryPanel{
|
||||
{
|
||||
ID: 2,
|
||||
OrgID: 1,
|
||||
FolderID: 1,
|
||||
UID: result.Result.LibraryPanels[0].UID,
|
||||
Name: "Some Other",
|
||||
Type: "text",
|
||||
Description: "A Library Panel",
|
||||
Model: map[string]interface{}{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"description": "A Library Panel",
|
||||
"id": float64(1),
|
||||
"title": "Some Other",
|
||||
"type": "text",
|
||||
},
|
||||
Version: 1,
|
||||
Meta: LibraryPanelDTOMeta{
|
||||
CanEdit: true,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.LibraryPanels[0].Meta.Created,
|
||||
Updated: result.Result.LibraryPanels[0].Meta.Updated,
|
||||
CreatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
UpdatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: 1,
|
||||
OrgID: 1,
|
||||
FolderID: 1,
|
||||
UID: result.Result.LibraryPanels[1].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"description": "A description",
|
||||
"id": float64(1),
|
||||
"title": "Text - Library Panel",
|
||||
"type": "text",
|
||||
},
|
||||
Version: 1,
|
||||
Meta: LibraryPanelDTOMeta{
|
||||
CanEdit: true,
|
||||
ConnectedDashboards: 0,
|
||||
Created: result.Result.LibraryPanels[1].Meta.Created,
|
||||
Updated: result.Result.LibraryPanels[1].Meta.Updated,
|
||||
CreatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
UpdatedBy: LibraryPanelDTOMetaUser{
|
||||
ID: 1,
|
||||
Name: UserInDbName,
|
||||
AvatarUrl: UserInDbAvatar,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if diff := cmp.Diff(expected, result, getCompareOptions()...); diff != "" {
|
||||
t.Fatalf("Result mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 1 and searchString is panel2, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
@@ -321,7 +744,7 @@ func TestGetAllLibraryPanels(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("perPage", "1")
|
||||
sc.reqContext.Req.Form.Add("page", "1")
|
||||
sc.reqContext.Req.Form.Add("name", "panel2")
|
||||
sc.reqContext.Req.Form.Add("searchString", "panel2")
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
@@ -375,7 +798,7 @@ func TestGetAllLibraryPanels(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 3 and name is panel, it should succeed and the result should be correct",
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 3 and searchString is panel, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
@@ -385,7 +808,7 @@ func TestGetAllLibraryPanels(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("perPage", "1")
|
||||
sc.reqContext.Req.Form.Add("page", "3")
|
||||
sc.reqContext.Req.Form.Add("name", "panel")
|
||||
sc.reqContext.Req.Form.Add("searchString", "panel")
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
@@ -405,7 +828,7 @@ func TestGetAllLibraryPanels(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 3 and name does not exist, it should succeed and the result should be correct",
|
||||
scenarioWithLibraryPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 3 and searchString does not exist, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
@@ -415,7 +838,7 @@ func TestGetAllLibraryPanels(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("perPage", "1")
|
||||
sc.reqContext.Req.Form.Add("page", "3")
|
||||
sc.reqContext.Req.Form.Add("name", "monkey")
|
||||
sc.reqContext.Req.Form.Add("searchString", "monkey")
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
|
||||
@@ -720,10 +720,7 @@ func overrideLibraryPanelServiceInRegistry(cfg *setting.Cfg) LibraryPanelService
|
||||
}
|
||||
|
||||
func getCreateCommand(folderID int64, name string) createLibraryPanelCommand {
|
||||
command := createLibraryPanelCommand{
|
||||
FolderID: folderID,
|
||||
Name: name,
|
||||
Model: []byte(`
|
||||
command := getCreateCommandWithModel(folderID, name, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@@ -731,7 +728,16 @@ func getCreateCommand(folderID int64, name string) createLibraryPanelCommand {
|
||||
"type": "text",
|
||||
"description": "A description"
|
||||
}
|
||||
`),
|
||||
`))
|
||||
|
||||
return command
|
||||
}
|
||||
|
||||
func getCreateCommandWithModel(folderID int64, name string, model []byte) createLibraryPanelCommand {
|
||||
command := createLibraryPanelCommand{
|
||||
FolderID: folderID,
|
||||
Name: name,
|
||||
Model: model,
|
||||
}
|
||||
|
||||
return command
|
||||
|
||||
@@ -137,3 +137,13 @@ type patchLibraryPanelCommand struct {
|
||||
Model json.RawMessage `json:"model"`
|
||||
Version int64 `json:"version" binding:"Required"`
|
||||
}
|
||||
|
||||
// searchLibraryPanelsQuery is the query used for searching for LibraryPanels
|
||||
type searchLibraryPanelsQuery struct {
|
||||
perPage int
|
||||
page int
|
||||
searchString string
|
||||
sortDirection string
|
||||
panelFilter string
|
||||
excludeUID string
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ type SearchService struct {
|
||||
func (s *SearchService) Init() error {
|
||||
s.Bus.AddHandler(s.searchHandler)
|
||||
s.sortOptions = map[string]SortOption{
|
||||
sortAlphaAsc.Name: sortAlphaAsc,
|
||||
sortAlphaDesc.Name: sortAlphaDesc,
|
||||
SortAlphaAsc.Name: SortAlphaAsc,
|
||||
SortAlphaDesc.Name: SortAlphaDesc,
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
sortAlphaAsc = SortOption{
|
||||
SortAlphaAsc = SortOption{
|
||||
Name: "alpha-asc",
|
||||
DisplayName: "Alphabetically (A–Z)",
|
||||
Description: "Sort results in an alphabetically ascending order",
|
||||
@@ -16,7 +16,7 @@ var (
|
||||
searchstore.TitleSorter{},
|
||||
},
|
||||
}
|
||||
sortAlphaDesc = SortOption{
|
||||
SortAlphaDesc = SortOption{
|
||||
Name: "alpha-desc",
|
||||
DisplayName: "Alphabetically (Z–A)",
|
||||
Description: "Sort results in an alphabetically descending order",
|
||||
|
||||
Reference in New Issue
Block a user