mirror of https://github.com/k3s-io/k3s
122 lines
2.7 KiB
Go
122 lines
2.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/rancher/norman/types"
|
|
"github.com/rancher/norman/types/convert"
|
|
)
|
|
|
|
func QueryFilter(opts *types.QueryOptions, schema *types.Schema, data []map[string]interface{}) []map[string]interface{} {
|
|
return ApplyQueryOptions(opts, schema, data)
|
|
}
|
|
|
|
func ApplyQueryOptions(options *types.QueryOptions, schema *types.Schema, data []map[string]interface{}) []map[string]interface{} {
|
|
data = ApplyQueryConditions(options.Conditions, schema, 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, schema *types.Schema, data []map[string]interface{}) []map[string]interface{} {
|
|
var result []map[string]interface{}
|
|
|
|
outer:
|
|
for _, item := range data {
|
|
for _, condition := range conditions {
|
|
if !condition.Valid(schema, 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]
|
|
}
|