mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 15:42:13 +08:00
Search: Support multiple order filters (#24230)
This commit is contained in:
@ -3,7 +3,6 @@ package search
|
|||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
|
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
@ -49,7 +48,7 @@ type FindPersistedDashboardsQuery struct {
|
|||||||
Page int64
|
Page int64
|
||||||
Permission models.PermissionType
|
Permission models.PermissionType
|
||||||
|
|
||||||
SortBy searchstore.FilterOrderBy
|
Filters []interface{}
|
||||||
|
|
||||||
Result HitList
|
Result HitList
|
||||||
}
|
}
|
||||||
@ -86,7 +85,9 @@ func (s *SearchService) searchHandler(query *Query) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sortOpt, exists := s.sortOptions[query.Sort]; exists {
|
if sortOpt, exists := s.sortOptions[query.Sort]; exists {
|
||||||
dashboardQuery.SortBy = sortOpt.Filter
|
for _, filter := range sortOpt.Filter {
|
||||||
|
dashboardQuery.Filters = append(dashboardQuery.Filters, filter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bus.Dispatch(&dashboardQuery); err != nil {
|
if err := bus.Dispatch(&dashboardQuery); err != nil {
|
||||||
|
@ -11,13 +11,17 @@ var (
|
|||||||
Name: "alpha-asc",
|
Name: "alpha-asc",
|
||||||
DisplayName: "Alphabetically (A-Z)",
|
DisplayName: "Alphabetically (A-Z)",
|
||||||
Description: "Sort results in an alphabetically ascending order",
|
Description: "Sort results in an alphabetically ascending order",
|
||||||
Filter: searchstore.TitleSorter{},
|
Filter: []SortOptionFilter{
|
||||||
|
searchstore.TitleSorter{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
sortAlphaDesc = SortOption{
|
sortAlphaDesc = SortOption{
|
||||||
Name: "alpha-desc",
|
Name: "alpha-desc",
|
||||||
DisplayName: "Alphabetically (Z-A)",
|
DisplayName: "Alphabetically (Z-A)",
|
||||||
Description: "Sort results in an alphabetically descending order",
|
Description: "Sort results in an alphabetically descending order",
|
||||||
Filter: searchstore.TitleSorter{Descending: true},
|
Filter: []SortOptionFilter{
|
||||||
|
searchstore.TitleSorter{Descending: true},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,7 +29,11 @@ type SortOption struct {
|
|||||||
Name string
|
Name string
|
||||||
DisplayName string
|
DisplayName string
|
||||||
Description string
|
Description string
|
||||||
Filter searchstore.FilterOrderBy
|
Filter []SortOptionFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
type SortOptionFilter interface {
|
||||||
|
searchstore.FilterOrderBy
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterSortOption allows for hooking in more search options from
|
// RegisterSortOption allows for hooking in more search options from
|
||||||
|
@ -216,12 +216,7 @@ type DashboardSearchProjection struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) {
|
func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error) {
|
||||||
if query.SortBy == nil {
|
|
||||||
query.SortBy = searchstore.TitleSorter{}
|
|
||||||
}
|
|
||||||
|
|
||||||
filters := []interface{}{
|
filters := []interface{}{
|
||||||
query.SortBy,
|
|
||||||
permissions.DashboardPermissionFilter{
|
permissions.DashboardPermissionFilter{
|
||||||
OrgRole: query.SignedInUser.OrgRole,
|
OrgRole: query.SignedInUser.OrgRole,
|
||||||
OrgId: query.SignedInUser.OrgId,
|
OrgId: query.SignedInUser.OrgId,
|
||||||
@ -231,6 +226,8 @@ func findDashboards(query *search.FindPersistedDashboardsQuery) ([]DashboardSear
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filters = append(filters, query.Filters...)
|
||||||
|
|
||||||
if query.OrgId != 0 {
|
if query.OrgId != 0 {
|
||||||
filters = append(filters, searchstore.OrgFilter{OrgId: query.OrgId})
|
filters = append(filters, searchstore.OrgFilter{OrgId: query.OrgId})
|
||||||
} else if query.SignedInUser.OrgId != 0 {
|
} else if query.SignedInUser.OrgId != 0 {
|
||||||
|
@ -9,9 +9,13 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/services/search"
|
"github.com/grafana/grafana/pkg/services/search"
|
||||||
|
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDashboardDataAccess(t *testing.T) {
|
func TestDashboardDataAccess(t *testing.T) {
|
||||||
@ -401,6 +405,33 @@ func TestDashboardDataAccess(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDashboard_SortingOptions(t *testing.T) {
|
||||||
|
// insertTestDashboard uses GoConvey's assertions. Workaround.
|
||||||
|
Convey("test with multiple sorting options", t, func() {
|
||||||
|
InitTestDB(t)
|
||||||
|
dashB := insertTestDashboard("Beta", 1, 0, false)
|
||||||
|
dashA := insertTestDashboard("Alfa", 1, 0, false)
|
||||||
|
|
||||||
|
assert.NotZero(t, dashA.Id)
|
||||||
|
assert.Less(t, dashB.Id, dashA.Id)
|
||||||
|
|
||||||
|
q := &search.FindPersistedDashboardsQuery{
|
||||||
|
SignedInUser: &models.SignedInUser{OrgId: 1, UserId: 1, OrgRole: models.ROLE_ADMIN},
|
||||||
|
// adding two sorting options (silly no-op example, but it'll complicate the query)
|
||||||
|
Filters: []interface{}{
|
||||||
|
searchstore.TitleSorter{},
|
||||||
|
searchstore.TitleSorter{Descending: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
dashboards, err := findDashboards(q)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Len(t, dashboards, 2)
|
||||||
|
assert.Equal(t, dashA.Id, dashboards[0].Id)
|
||||||
|
assert.Equal(t, dashB.Id, dashboards[1].Id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func insertTestDashboard(title string, orgId int64, folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
|
func insertTestDashboard(title string, orgId int64, folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
|
||||||
cmd := models.SaveDashboardCommand{
|
cmd := models.SaveDashboardCommand{
|
||||||
OrgId: orgId,
|
OrgId: orgId,
|
||||||
|
@ -113,13 +113,14 @@ func (b *Builder) applyFilters() (ordering string) {
|
|||||||
b.params = append(b.params, groupParams...)
|
b.params = append(b.params, groupParams...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(orders) > 0 {
|
if len(orders) < 1 {
|
||||||
orderBy := fmt.Sprintf(" ORDER BY %s", strings.Join(orders, ", "))
|
orders = append(orders, TitleSorter{}.OrderBy())
|
||||||
b.sql.WriteString(orderBy)
|
|
||||||
|
|
||||||
order := strings.Join(orderJoins, "")
|
|
||||||
order += orderBy
|
|
||||||
return order
|
|
||||||
}
|
}
|
||||||
return " ORDER BY dashboard.id"
|
|
||||||
|
orderBy := fmt.Sprintf(" ORDER BY %s", strings.Join(orders, ", "))
|
||||||
|
b.sql.WriteString(orderBy)
|
||||||
|
|
||||||
|
order := strings.Join(orderJoins, "")
|
||||||
|
order += orderBy
|
||||||
|
return order
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user