add pagination engine to render
This commit is contained in:
+178
-3
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user