@@ -0,0 +1,81 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const defaultCollectionPageSize = 20
|
||||
|
||||
type paginationData struct {
|
||||
Page int
|
||||
TotalPages int
|
||||
PreviousURL string
|
||||
NextURL string
|
||||
}
|
||||
|
||||
func paginateCollection[T any](r *http.Request, values []T) ([]T, *paginationData) {
|
||||
pageSize := collectionPageSize(r)
|
||||
totalPages := (len(values) + pageSize - 1) / pageSize
|
||||
if totalPages <= 1 {
|
||||
return values, nil
|
||||
}
|
||||
|
||||
page, _ := strconv.Atoi(r.URL.Query().Get("page"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if page > totalPages {
|
||||
page = totalPages
|
||||
}
|
||||
start := (page - 1) * pageSize
|
||||
end := min(start+pageSize, len(values))
|
||||
pagination := &paginationData{Page: page, TotalPages: totalPages}
|
||||
if page > 1 {
|
||||
pagination.PreviousURL = collectionPageURL(r.URL, page-1)
|
||||
}
|
||||
if page < totalPages {
|
||||
pagination.NextURL = collectionPageURL(r.URL, page+1)
|
||||
}
|
||||
return values[start:end], pagination
|
||||
}
|
||||
|
||||
func collectionPageSize(r *http.Request) int {
|
||||
userSuffix := ""
|
||||
if user, ok := userFromContext(r.Context()); ok {
|
||||
userSuffix = "." + strconv.Itoa(user.ID)
|
||||
}
|
||||
for _, cookieName := range []string{"gardomatic.entries-per-page" + userSuffix, "gardomatic.tasks-per-page" + userSuffix} {
|
||||
cookie, err := r.Cookie(cookieName)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
pageSize, err := strconv.Atoi(cookie.Value)
|
||||
if err == nil && validCollectionPageSize(pageSize) {
|
||||
return pageSize
|
||||
}
|
||||
}
|
||||
return defaultCollectionPageSize
|
||||
}
|
||||
|
||||
func validCollectionPageSize(pageSize int) bool {
|
||||
switch pageSize {
|
||||
case 10, 20, 50, 100:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func collectionPageURL(current *url.URL, page int) string {
|
||||
query := current.Query()
|
||||
query.Set("page", strconv.Itoa(page))
|
||||
path := current.Path
|
||||
if path == "" {
|
||||
path = "?"
|
||||
} else {
|
||||
path += "?"
|
||||
}
|
||||
return path + query.Encode()
|
||||
}
|
||||
Reference in New Issue
Block a user