* Refactor the paginator into a ViewComponent.
* Fix inconsistent spacing between paginator items.
* Fix a bug where the sequential paginator generated the wrong next /
previous page links in the <link rel="{next|prev}"> tags in the <head>.
* Always include the final page as a hidden html element, so that it can
be unhidden with custom CSS.
* Make it easier to change the pagination window.
45 lines
1.2 KiB
Ruby
45 lines
1.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class PaginatorComponent < ApplicationComponent
|
|
attr_reader :records, :window, :params
|
|
delegate :current_page, :prev_page, :next_page, :total_pages, :paginator_mode, :paginator_page_limit, to: :records
|
|
delegate :ellipsis_icon, :chevron_left_icon, :chevron_right_icon, to: :helpers
|
|
|
|
def initialize(records:, params:, window: 4)
|
|
@records = records
|
|
@window = window
|
|
@params = params
|
|
end
|
|
|
|
def use_sequential_paginator?
|
|
paginator_mode != :numbered || current_page >= paginator_page_limit
|
|
end
|
|
|
|
def pages
|
|
last_page = total_pages
|
|
left = (current_page - window).clamp(2..)
|
|
right = (current_page + window).clamp(..last_page - 1)
|
|
|
|
[
|
|
1,
|
|
("..." unless left == 2),
|
|
(left..right).to_a,
|
|
("..." unless right == last_page - 1),
|
|
last_page
|
|
].flatten.compact
|
|
end
|
|
|
|
def link_to_page(anchor, page = anchor, **options)
|
|
if page.nil?
|
|
tag.span anchor, **options
|
|
else
|
|
hidden = paginator_mode == :numbered && page > paginator_page_limit
|
|
link_to anchor, url_for_page(page), **options, hidden: hidden
|
|
end
|
|
end
|
|
|
|
def url_for_page(page)
|
|
url_for(**params.merge(page: page).permit!)
|
|
end
|
|
end
|