diff --git a/assets/views/tag.jet.html b/assets/views/tag.jet.html
index 575f7fc..db978ad 100644
--- a/assets/views/tag.jet.html
+++ b/assets/views/tag.jet.html
@@ -176,7 +176,7 @@
{{- url := unfinishedQuery(.QueriesC, "page") }}
- {{- paginationData := createPaginator(url, "#checkpoint", .Page, -1) }}
+ {{- paginationData := createPaginator(url, "#checkpoint", .Page, -1, 1, 5) }}
{{- yield pagination(data=paginationData) }}
{{- end }}
diff --git a/server/template/templateFunctions.go b/server/template/templateFunctions.go
index fb117c6..091909c 100644
--- a/server/template/templateFunctions.go
+++ b/server/template/templateFunctions.go
@@ -160,42 +160,81 @@ func ParseTimeCustomFormat(date time.Time, format string) string {
return date.Format(format)
}
-// CreatePaginator generates pagination data based on the current page and maximum number of pages
-func CreatePaginator(base, ending string, current_page, max_page int) PaginationData {
+// CreatePaginator generates pagination data based on the current page and maximum number of pages.
+// It returns a PaginationData struct containing all necessary information for rendering pagination controls.
+//
+// Parameters:
+// - base: The base part of the pagination URL
+// - ending: The ending part of the pagination URL
+// - current_page: The current page being displayed
+// - max_page: Maximum number of pages (-1 if unknown)
+// - page_margin: Number of pages to display before and after the current page
+// - dropdown_offset: Number of pages to include in dropdown before and after current page
+func CreatePaginator(base, ending string, current_page, max_page, page_margin, dropdown_offset int) (PaginationData, error) {
+ // Validate input parameters
+ if current_page < 1 {
+ return PaginationData{}, fmt.Errorf("current_page must be greater than or equal to 1, got %d", current_page)
+ }
+ if max_page != -1 && max_page < current_page {
+ return PaginationData{}, fmt.Errorf("max_page (%d) must be greater than or equal to current_page (%d) when specified", max_page, current_page)
+ }
+ if page_margin < 0 {
+ return PaginationData{}, fmt.Errorf("page_margin must be non-negative, got %d", page_margin)
+ }
+ if dropdown_offset < 0 {
+ return PaginationData{}, fmt.Errorf("dropdown_offset must be non-negative, got %d", dropdown_offset)
+ }
+
+ hasMaxPage := max_page != -1
+
pageUrl := func(page int) string {
return fmt.Sprintf(`%s%d%s`, base, page, ending)
}
- // Number of pages to show on each side of the current page
- //
- // NOTE: values higher than 1 can cause issues on small devices where the pagination element is too wide
- const peek = 1
- hasMaxPage := max_page != -1
+ // Helper function to generate a range of pages
+ generatePageRange := func(start, end int) []PageInfo {
+ if start > end {
+ return []PageInfo{}
+ }
+ pages := make([]PageInfo, 0, end-start+1)
+ for i := start; i <= end; i++ {
+ pages = append(pages, PageInfo{Number: i, URL: pageUrl(i)})
+ }
+ return pages
+ }
// Calculate the range of pages to display
- start := max(1, current_page-peek)
- end := current_page + peek
+ start := max(1, current_page-page_margin)
+ end := current_page + page_margin
if hasMaxPage {
end = min(max_page, end)
}
// Generate page information for the range
- pages := make([]PageInfo, 0, end-start+1)
- for i := start; i <= end; i++ {
- pages = append(pages, PageInfo{Number: i, URL: pageUrl(i)})
+ pages := generatePageRange(start, end)
+
+ var lastPage int
+ if len(pages) > 0 {
+ lastPage = pages[len(pages)-1].Number
+ } else {
+ lastPage = current_page
}
- lastPage := pages[len(pages)-1].Number
-
- // Generate dropdown pages (previous 5, current, next 5)
- dropdownStart := max(1, current_page-5)
- dropdownEnd := current_page + 5
+ // Generate dropdown pages
+ dropdownStart := max(1, current_page-dropdown_offset)
+ dropdownEnd := current_page + dropdown_offset
if hasMaxPage {
dropdownEnd = min(max_page, dropdownEnd)
}
- dropdownPages := make([]PageInfo, 0, dropdownEnd-dropdownStart+1)
- for i := dropdownStart; i <= dropdownEnd; i++ {
- dropdownPages = append(dropdownPages, PageInfo{Number: i, URL: pageUrl(i)})
+ dropdownPages := generatePageRange(dropdownStart, dropdownEnd)
+
+ // Calculate previous and next URLs
+ var previousURL, nextURL string
+ if current_page > 1 {
+ previousURL = pageUrl(current_page - 1)
+ }
+ if !hasMaxPage || current_page < max_page {
+ nextURL = pageUrl(current_page + 1)
}
// Create and return the PaginationData struct
@@ -205,14 +244,14 @@ func CreatePaginator(base, ending string, current_page, max_page int) Pagination
Pages: pages,
HasPrevious: current_page > 1,
HasNext: !hasMaxPage || current_page < max_page,
- PreviousURL: pageUrl(current_page - 1),
- NextURL: pageUrl(current_page + 1),
+ PreviousURL: previousURL,
+ NextURL: nextURL,
FirstURL: pageUrl(1),
LastURL: pageUrl(max_page),
HasMaxPage: hasMaxPage,
LastPage: lastPage,
DropdownPages: dropdownPages,
- }
+ }, nil
}
// GetNovelGenre returns the genre name for a given genre ID
@@ -316,8 +355,14 @@ func GetTemplateFunctions() map[string]any {
"parseTimeCustomFormat": func(date time.Time, format string) string {
return ParseTimeCustomFormat(date, format)
},
- "createPaginator": func(base, ending string, current_page, max_page int) PaginationData {
- return CreatePaginator(base, ending, current_page, max_page)
+ "createPaginator": func(base, ending string, current_page, max_page, page_margin, dropdown_offset int) PaginationData {
+ paginationData, err := CreatePaginator(base, ending, current_page, max_page, page_margin, dropdown_offset)
+ if err != nil {
+ fmt.Printf("Error creating paginator: %v", err)
+ // Return an empty PaginationData in case of error
+ return PaginationData{}
+ }
+ return paginationData
},
"joinArtworkIds": func(artworks []core.ArtworkBrief) string {
ids := []string{}