add pagination engine to render

This commit is contained in:
2024-11-19 15:54:29 +01:00
parent aa16e20958
commit c777ef7056
7 changed files with 509 additions and 30 deletions
+178 -3
View File
@@ -7,6 +7,8 @@ import (
"io/fs"
"net/http"
"path/filepath"
"reflect"
"strconv"
"strings"
)
@@ -14,7 +16,8 @@ type (
templateCache map[string]*template.Template
TemplateData struct {
Data Data
Data Data
Pages Pages
}
RenderOptions func(*Render)
@@ -22,6 +25,7 @@ type (
EnableCache bool
TemplatesPath string
Functions template.FuncMap
TemplateData TemplateData
templateCache templateCache
}
)
@@ -30,8 +34,9 @@ func defaultHTMLRender() *Render {
return &Render{
EnableCache: false,
TemplatesPath: "templates",
Functions: make(template.FuncMap),
templateCache: make(templateCache),
TemplateData: TemplateData{},
Functions: template.FuncMap{},
templateCache: templateCache{},
}
}
@@ -139,3 +144,173 @@ func (re *Render) createTemplateCache() (templateCache, error) {
return cache, nil
}
// Pages contiene la información de paginación.
type Pages struct {
// TotalElements son la cantidad de elementos totales a paginar. Pueden ser
// total de filas o total de páginas de blog.
TotalElements int
// ElementsPerPage muestra la cantidad máxima de elementos a mostrar en una
// página.
ElementsPerPage int
// ActualPage es la página actual, utilizado como ayuda para mostrar la
// página activa.
ActualPage int
}
func (p *Pages) PaginationParams(r *http.Request) {
limit := r.FormValue("limit")
page := r.FormValue("page")
if limit == "" {
if p.ElementsPerPage != 0 {
limit = strconv.Itoa(p.ElementsPerPage)
} else {
limit = "20"
}
}
if page == "" || page == "0" {
if p.ActualPage != 0 {
page = strconv.Itoa(p.ActualPage)
} else {
page = "1"
}
}
limitInt, _ := strconv.Atoi(limit)
pageInt, _ := strconv.Atoi(page)
offset := (pageInt - 1) * limitInt
currentPage := offset/limitInt + 1
p.ElementsPerPage = limitInt
p.ActualPage = currentPage
}
func (p Pages) PaginateArray(elements any) any {
itemsValue := reflect.ValueOf(elements)
if p.ActualPage < 1 {
p.ActualPage = 1
}
if p.ActualPage > p.TotalPages() {
p.ActualPage = p.TotalPages()
}
startIndex := (p.ActualPage - 1) * p.ElementsPerPage
endIndex := startIndex + p.ElementsPerPage
return itemsValue.Slice(startIndex, endIndex).Interface()
}
func (p Pages) CurrentPage() int {
return p.ActualPage
}
// TotalPages devuelve la cantidad total de páginas.
func (p Pages) TotalPages() int {
return (p.TotalElements + p.ElementsPerPage - 1) / p.ElementsPerPage
}
// IsFirst indica si la página actual es la primera.
func (p Pages) IsFirst() bool {
return p.ActualPage == 1
}
// IsLast indica si la página actual es la última.
func (p Pages) IsLast() bool {
return p.ActualPage == p.TotalPages()
}
// HasPrevious indica si hay una página anterior.
func (p Pages) HasPrevious() bool {
return p.ActualPage > 1
}
// HasNext indica si hay una página siguiente.
func (p Pages) HasNext() bool {
return p.ActualPage < p.TotalPages()
}
// Previous devuelve el número de la página anterior.
func (p Pages) Previous() int {
if p.ActualPage > p.TotalPages() {
return p.TotalPages()
}
return p.ActualPage - 1
}
// Next devuelve el número de la página siguiente.
func (p Pages) Next() int {
if p.ActualPage < 1 {
return 1
}
return p.ActualPage + 1
}
func (p Pages) GoToPage(page int) int {
if page < 1 {
page = 1
} else if page > p.TotalPages() {
page = p.TotalPages()
}
return page
}
func (p Pages) First() int {
return p.GoToPage(1)
}
func (p Pages) Last() int {
return p.GoToPage(p.TotalPages())
}
// Page contiene la información de una página. Utilizado para la barra de
// paginación que suelen mostrarse en la parte inferior de una lista o tabla.
type Page struct {
// Number es el número de página.
Number int
// Active es un dato lógico que indica si la página es la actual.
Active bool
}
func (p Page) NumberOfPage() int {
return p.Number
}
// IsActive indica si la página es la actual.
func (p Page) IsActive() bool {
return p.Active
}
// PagesRange muestra un rango de páginas a mostrar en la paginación.
func (p Pages) PageRange(maxPagesToShow int) []Page {
var pages []Page
totalPages := p.TotalPages()
startPage := p.ActualPage - (maxPagesToShow / 2)
endPage := p.ActualPage + (maxPagesToShow / 2)
if startPage < 1 {
startPage = 1
endPage = maxPagesToShow
}
if endPage > totalPages {
endPage = totalPages
startPage = totalPages - maxPagesToShow + 1
if startPage < 1 {
startPage = 1
}
}
for i := startPage; i <= endPage; i++ {
pages = append(pages, Page{
Number: i,
Active: i == p.ActualPage,
})
}
return pages
}