82 lines
1.7 KiB
Go
82 lines
1.7 KiB
Go
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()
|
|
}
|