mirror of
https://github.com/sbondCo/Watcharr.git
synced 2026-08-07 07:14:44 +00:00
watched: Create getWatchedPage for paginated response
This commit is contained in:
@@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -29,3 +31,51 @@ func WhereaboutsRequired() gin.HandlerFunc {
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Pagination middleware
|
||||
// Reusable way to get pagination values.
|
||||
// If force=true then will default to page=1, otherwise
|
||||
// assume pagination is disabled when query params not present.
|
||||
func PaginatedRequest(force bool) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pageStr := c.Query("p")
|
||||
page := 0
|
||||
if pageStr == "" && force {
|
||||
page = 1
|
||||
slog.Debug("PossiblyPaginated: Pagination is forced, but no page was provided. Using default.")
|
||||
} else if pageStr == "" {
|
||||
slog.Debug("PossiblyPaginated: Pagination is disabled. No parameter provided.")
|
||||
c.Set("paginationEnabled", false)
|
||||
c.Next()
|
||||
return
|
||||
} else {
|
||||
num, err := strconv.Atoi(pageStr)
|
||||
if err != nil {
|
||||
slog.Error("PossiblyPaginated: Query paramater 'p' was not parseable as an int", "err", err)
|
||||
c.JSON(http.StatusBadRequest, ErrorResponse{Error: "query param 'p' must be a number"})
|
||||
return
|
||||
}
|
||||
page = num
|
||||
}
|
||||
limitStr := c.Query("l")
|
||||
limit := 40
|
||||
if limitStr != "" {
|
||||
num, err := strconv.Atoi(limitStr)
|
||||
if err != nil {
|
||||
slog.Error("PossiblyPaginated: Query paramater 'l' was not parseable as an int", "err", err)
|
||||
c.JSON(http.StatusBadRequest, ErrorResponse{Error: "query param 'l' must be a number"})
|
||||
return
|
||||
}
|
||||
limit = num
|
||||
} else {
|
||||
slog.Debug("PossiblyPaginated: Using default limit.")
|
||||
}
|
||||
slog.Debug("PossiblyPaginated: middleware hit", "page", page, "page_limit", limit)
|
||||
c.Set("paginationEnabled", true)
|
||||
c.Set("paginationParams", PaginationParams{
|
||||
Page: page,
|
||||
Limit: limit,
|
||||
})
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Parameters that the paginator uses to
|
||||
// know what to return.
|
||||
type PaginationParams struct {
|
||||
Limit int `json:"limit"`
|
||||
Page int `json:"page"`
|
||||
// TODO sorting and filtering to be params?
|
||||
// Have to think about if this is better in a reusable
|
||||
// fashion (eg query params target db cols) or not.
|
||||
Sort string `json:"sort"`
|
||||
}
|
||||
|
||||
// Pagination response struct.
|
||||
type PaginationResponse struct {
|
||||
PaginationParams
|
||||
TotalRows int64 `json:"total_rows"`
|
||||
TotalPages int `json:"total_pages"`
|
||||
Rows interface{} `json:"rows"`
|
||||
}
|
||||
|
||||
// func paginate(value interface{}, pagination *pkg.Pagination, db *gorm.DB) *gorm.DB {
|
||||
// var totalRows int64
|
||||
// db.Model(value).Count(&totalRows)
|
||||
|
||||
// pagination.TotalRows = totalRows
|
||||
// totalPages := int(math.Ceil(float64(totalRows) / float64(pagination.Limit)))
|
||||
// pagination.TotalPages = totalPages
|
||||
|
||||
// offset := (page - 1) * pageSize
|
||||
// return db.Offset(offset).Limit(pageSize)
|
||||
// }
|
||||
|
||||
func Paginate(p PaginationParams) func(db *gorm.DB) *gorm.DB {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
offset := (p.Page - 1) * p.Limit
|
||||
return db.Offset(offset).Limit(p.Limit)
|
||||
}
|
||||
}
|
||||
+8
-1
@@ -482,8 +482,15 @@ func (b *BaseRouter) addGameRoutes() {
|
||||
func (b *BaseRouter) addWatchedRoutes() {
|
||||
watched := b.rg.Group("/watched").Use(AuthRequired(nil))
|
||||
|
||||
watched.GET("", func(c *gin.Context) {
|
||||
watched.GET("", PaginatedRequest(false), func(c *gin.Context) {
|
||||
isPaginated := c.MustGet("paginationEnabled").(bool)
|
||||
userId := c.MustGet("userId").(uint)
|
||||
if isPaginated {
|
||||
pp := c.MustGet("paginationParams").(PaginationParams)
|
||||
c.JSON(http.StatusOK, getWatchedPage(b.db, userId, pp))
|
||||
return
|
||||
}
|
||||
// Non paginated response
|
||||
c.JSON(http.StatusOK, getWatched(b.db, userId))
|
||||
})
|
||||
|
||||
|
||||
@@ -93,6 +93,23 @@ func getWatched(db *gorm.DB, userId uint) []Watched {
|
||||
return *watched
|
||||
}
|
||||
|
||||
func getWatchedPage(db *gorm.DB, userId uint, pp PaginationParams) []Watched {
|
||||
slog.Debug("getWatchedPage: A page was requested.", "user_id", userId, "pagination_params", pp)
|
||||
watched := new([]Watched)
|
||||
res := db.Scopes(Paginate(pp)).
|
||||
Model(&Watched{}).
|
||||
Preload("Content").
|
||||
Preload("Game").
|
||||
Preload("Game.Poster").
|
||||
Preload("Tags").
|
||||
Where("user_id = ?", userId).
|
||||
Find(&watched)
|
||||
if res.Error != nil {
|
||||
panic(res.Error)
|
||||
}
|
||||
return *watched
|
||||
}
|
||||
|
||||
// Get a watched list item by id (must be for `userId`).
|
||||
func getWatchedItemById(db *gorm.DB, userId uint, id uint) (Watched, error) {
|
||||
watched := new(Watched)
|
||||
|
||||
Reference in New Issue
Block a user