]> git.openstreetmap.org Git - rails.git/blob - app/helpers/numbered_pagination_helper.rb
Limit number of items in version lists
[rails.git] / app / helpers / numbered_pagination_helper.rb
1 module NumberedPaginationHelper
2   def element_versions_pagination(top_version, active_version: top_version + 1, window_half_size: 50, &)
3     lists = []
4
5     if top_version <= 5
6       lists << tag.ul(:class => "pagination pagination-sm mt-1") do
7         (1..top_version).each do |v|
8           concat element_versions_pagination_item(v, **yield(v), :active => v == active_version)
9         end
10       end
11     else
12       start_list_versions = 1..(active_version < 3 ? active_version + 1 : 1)
13       end_list_versions = (active_version > top_version - 2 ? active_version - 1 : top_version)..top_version
14       middle_list_versions = Range.new([active_version - window_half_size, start_list_versions.last + 1].max,
15                                        [active_version + window_half_size, end_list_versions.first - 1].min)
16
17       lists << tag.ul(:class => "pagination pagination-sm mt-1") do
18         start_list_versions.each do |v|
19           concat element_versions_pagination_item(v, **yield(v), :active => v == active_version,
20                                                                  :edge => [false, v == start_list_versions.last],
21                                                                  :edge_border => true)
22         end
23       end
24       lists << tag.ul(:class => [
25                         "pagination pagination-sm",
26                         "overflow-x-scroll pb-3", # horizontal scrollbar with reserved space below
27                         "pt-1 px-1 mx-n1" # space reserved for focus outlines
28                       ]) do
29         concat element_versions_pagination_item("...", :edge => [true, false]) if middle_list_versions.first > start_list_versions.last + 1
30         middle_list_versions.each do |v|
31           concat element_versions_pagination_item(v, **yield(v), :active => v == active_version,
32                                                                  :edge => [v == start_list_versions.last + 1,
33                                                                            v == end_list_versions.first - 1])
34         end
35         concat element_versions_pagination_item("...", :edge => [false, true]) if middle_list_versions.last < end_list_versions.first - 1
36       end
37       lists << tag.ul(:class => "pagination pagination-sm mt-1") do
38         end_list_versions.each do |v|
39           concat element_versions_pagination_item(v, **yield(v), :active => v == active_version,
40                                                                  :edge => [v == end_list_versions.first, false],
41                                                                  :edge_border => true)
42         end
43       end
44     end
45
46     tag.div safe_join(lists), :class => "d-flex align-items-start"
47   end
48
49   private
50
51   def element_versions_pagination_item(body, href: nil, title: nil, active: false, edge: [false, false], edge_border: false)
52     link_class = ["page-link", { "rounded-start-0" => edge.first,
53                                  "border-start-0" => edge.first && !edge_border,
54                                  "rounded-end-0" => edge.last,
55                                  "border-end-0" => edge.last && !edge_border }]
56     link = if href
57              link_to body, href, :class => link_class, :title => title
58            else
59              tag.span body, :class => link_class
60            end
61     tag.li link, :class => ["page-item", { "disabled" => !href, "active" => active }]
62   end
63 end