mirror of
https://github.com/rancher/norman.git
synced 2025-09-16 07:09:44 +00:00
Subcontext and mapping updates
This commit is contained in:
121
api/handler/query.go
Normal file
121
api/handler/query.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/rancher/norman/types"
|
||||
"github.com/rancher/norman/types/convert"
|
||||
)
|
||||
|
||||
func QueryFilter(opts types.QueryOptions, data []map[string]interface{}) []map[string]interface{} {
|
||||
return ApplyQueryOptions(opts, data)
|
||||
}
|
||||
|
||||
func ApplyQueryOptions(options types.QueryOptions, data []map[string]interface{}) []map[string]interface{} {
|
||||
data = ApplyQueryConditions(options.Conditions, data)
|
||||
data = ApplySort(options.Sort, data)
|
||||
return ApplyPagination(options.Pagination, data)
|
||||
}
|
||||
|
||||
func ApplySort(sortOpts types.Sort, data []map[string]interface{}) []map[string]interface{} {
|
||||
name := sortOpts.Name
|
||||
if name == "" {
|
||||
name = "id"
|
||||
}
|
||||
|
||||
sort.Slice(data, func(i, j int) bool {
|
||||
left, right := i, j
|
||||
if sortOpts.Order == types.DESC {
|
||||
left, right = j, i
|
||||
}
|
||||
|
||||
return convert.ToString(data[left][name]) < convert.ToString(data[right][name])
|
||||
})
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func ApplyQueryConditions(conditions []*types.QueryCondition, data []map[string]interface{}) []map[string]interface{} {
|
||||
var result []map[string]interface{}
|
||||
|
||||
outer:
|
||||
for _, item := range data {
|
||||
for _, condition := range conditions {
|
||||
if !condition.Valid(item) {
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, item)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func ApplyPagination(pagination *types.Pagination, data []map[string]interface{}) []map[string]interface{} {
|
||||
if pagination == nil || pagination.Limit == nil {
|
||||
return data
|
||||
}
|
||||
|
||||
limit := *pagination.Limit
|
||||
if limit < 0 {
|
||||
limit = 0
|
||||
}
|
||||
|
||||
total := int64(len(data))
|
||||
|
||||
// Reset fields
|
||||
pagination.Next = ""
|
||||
pagination.Previous = ""
|
||||
pagination.Partial = false
|
||||
pagination.Total = &total
|
||||
pagination.First = ""
|
||||
|
||||
if len(data) == 0 {
|
||||
return data
|
||||
}
|
||||
|
||||
// startIndex is guaranteed to be a valid index
|
||||
startIndex := int64(0)
|
||||
if pagination.Marker != "" {
|
||||
for i, item := range data {
|
||||
id, _ := item["id"].(string)
|
||||
if id == pagination.Marker {
|
||||
startIndex = int64(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
previousIndex := startIndex - limit
|
||||
if previousIndex <= 0 {
|
||||
previousIndex = 0
|
||||
}
|
||||
nextIndex := startIndex + limit
|
||||
if nextIndex > int64(len(data)) {
|
||||
nextIndex = int64(len(data))
|
||||
}
|
||||
|
||||
if previousIndex < startIndex {
|
||||
pagination.Previous, _ = data[previousIndex]["id"].(string)
|
||||
}
|
||||
|
||||
if nextIndex > startIndex && nextIndex < int64(len(data)) {
|
||||
pagination.Next, _ = data[nextIndex]["id"].(string)
|
||||
}
|
||||
|
||||
if startIndex > 0 || nextIndex < int64(len(data)) {
|
||||
pagination.Partial = true
|
||||
}
|
||||
|
||||
if pagination.Partial {
|
||||
pagination.First, _ = data[0]["id"].(string)
|
||||
|
||||
lastIndex := int64(len(data)) - limit
|
||||
if lastIndex > 0 && lastIndex < int64(len(data)) {
|
||||
pagination.Last, _ = data[lastIndex]["id"].(string)
|
||||
}
|
||||
}
|
||||
|
||||
return data[startIndex:nextIndex]
|
||||
}
|
Reference in New Issue
Block a user