From e9ad159d41cb247269dab0e107b83201b215bb02 Mon Sep 17 00:00:00 2001 From: Anton Khorev Date: Mon, 23 Jun 2025 21:15:29 +0300 Subject: [PATCH] Limit number of items in version lists --- app/helpers/numbered_pagination_helper.rb | 15 ++- .../numbered_pagination_helper_test.rb | 115 ++++++++++++++++++ 2 files changed, 126 insertions(+), 4 deletions(-) diff --git a/app/helpers/numbered_pagination_helper.rb b/app/helpers/numbered_pagination_helper.rb index fcb985d4d..27e911a53 100644 --- a/app/helpers/numbered_pagination_helper.rb +++ b/app/helpers/numbered_pagination_helper.rb @@ -1,5 +1,5 @@ module NumberedPaginationHelper - def element_versions_pagination(top_version, active_version: 0, &) + def element_versions_pagination(top_version, active_version: top_version + 1, window_half_size: 50, &) lists = [] if top_version <= 5 @@ -11,7 +11,8 @@ module NumberedPaginationHelper else start_list_versions = 1..(active_version < 3 ? active_version + 1 : 1) end_list_versions = (active_version > top_version - 2 ? active_version - 1 : top_version)..top_version - middle_list_versions = (start_list_versions.last + 1)..(end_list_versions.first - 1) + middle_list_versions = Range.new([active_version - window_half_size, start_list_versions.last + 1].max, + [active_version + window_half_size, end_list_versions.first - 1].min) lists << tag.ul(:class => "pagination pagination-sm mt-1") do start_list_versions.each do |v| @@ -25,11 +26,13 @@ module NumberedPaginationHelper "overflow-x-scroll pb-3", # horizontal scrollbar with reserved space below "pt-1 px-1 mx-n1" # space reserved for focus outlines ]) do + concat element_versions_pagination_item("...", :edge => [true, false]) if middle_list_versions.first > start_list_versions.last + 1 middle_list_versions.each do |v| concat element_versions_pagination_item(v, **yield(v), :active => v == active_version, :edge => [v == start_list_versions.last + 1, v == end_list_versions.first - 1]) end + concat element_versions_pagination_item("...", :edge => [false, true]) if middle_list_versions.last < end_list_versions.first - 1 end lists << tag.ul(:class => "pagination pagination-sm mt-1") do end_list_versions.each do |v| @@ -50,7 +53,11 @@ module NumberedPaginationHelper "border-start-0" => edge.first && !edge_border, "rounded-end-0" => edge.last, "border-end-0" => edge.last && !edge_border }] - link = link_to body, href, :class => link_class, :title => title - tag.li link, :class => ["page-item", { "active" => active }] + link = if href + link_to body, href, :class => link_class, :title => title + else + tag.span body, :class => link_class + end + tag.li link, :class => ["page-item", { "disabled" => !href, "active" => active }] end end diff --git a/test/helpers/numbered_pagination_helper_test.rb b/test/helpers/numbered_pagination_helper_test.rb index 6db1608dd..c94c84b53 100644 --- a/test/helpers/numbered_pagination_helper_test.rb +++ b/test/helpers/numbered_pagination_helper_test.rb @@ -165,6 +165,115 @@ class NumberedPaginationHelperTest < ActionView::TestCase end end + def test_element_versions_pagination_window_start_include + pagination = element_versions_pagination(50, :window_half_size => 3, :active_version => 3) { |v| sample_item_data v } + pagination_dom = Rails::Dom::Testing.html_document_fragment.parse(pagination) + assert_dom pagination_dom, "ul", :count => 3 do |lists| + assert_dom lists[0], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(1) + end + assert_dom lists[1], "> li", 6 do |items| + check_version_link items.shift, sample_item_data(2) + check_version_link items.shift, sample_item_data(3), :active => true + check_version_link items.shift, sample_item_data(4) + check_version_link items.shift, sample_item_data(5) + check_version_link items.shift, sample_item_data(6) + check_version_ellipsis items.shift + end + assert_dom lists[2], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(50) + end + end + end + + def test_element_versions_pagination_window_start_touch + pagination = element_versions_pagination(50, :window_half_size => 3, :active_version => 5) { |v| sample_item_data v } + pagination_dom = Rails::Dom::Testing.html_document_fragment.parse(pagination) + assert_dom pagination_dom, "ul", :count => 3 do |lists| + assert_dom lists[0], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(1) + end + assert_dom lists[1], "> li", 8 do |items| + check_version_link items.shift, sample_item_data(2) + check_version_link items.shift, sample_item_data(3) + check_version_link items.shift, sample_item_data(4) + check_version_link items.shift, sample_item_data(5), :active => true + check_version_link items.shift, sample_item_data(6) + check_version_link items.shift, sample_item_data(7) + check_version_link items.shift, sample_item_data(8) + check_version_ellipsis items.shift + end + assert_dom lists[2], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(50) + end + end + end + + def test_element_versions_pagination_window_middle + pagination = element_versions_pagination(50, :window_half_size => 3, :active_version => 43) { |v| sample_item_data v } + pagination_dom = Rails::Dom::Testing.html_document_fragment.parse(pagination) + assert_dom pagination_dom, "ul", :count => 3 do |lists| + assert_dom lists[0], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(1) + end + assert_dom lists[1], "> li", 9 do |items| + check_version_ellipsis items.shift + check_version_link items.shift, sample_item_data(40) + check_version_link items.shift, sample_item_data(41) + check_version_link items.shift, sample_item_data(42) + check_version_link items.shift, sample_item_data(43), :active => true + check_version_link items.shift, sample_item_data(44) + check_version_link items.shift, sample_item_data(45) + check_version_link items.shift, sample_item_data(46) + check_version_ellipsis items.shift + end + assert_dom lists[2], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(50) + end + end + end + + def test_element_versions_pagination_window_end_touch + pagination = element_versions_pagination(50, :window_half_size => 3, :active_version => 46) { |v| sample_item_data v } + pagination_dom = Rails::Dom::Testing.html_document_fragment.parse(pagination) + assert_dom pagination_dom, "ul", :count => 3 do |lists| + assert_dom lists[0], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(1) + end + assert_dom lists[1], "> li", 8 do |items| + check_version_ellipsis items.shift + check_version_link items.shift, sample_item_data(43) + check_version_link items.shift, sample_item_data(44) + check_version_link items.shift, sample_item_data(45) + check_version_link items.shift, sample_item_data(46), :active => true + check_version_link items.shift, sample_item_data(47) + check_version_link items.shift, sample_item_data(48) + check_version_link items.shift, sample_item_data(49) + end + assert_dom lists[2], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(50) + end + end + end + + def test_element_versions_pagination_window_end_beyond + pagination = element_versions_pagination(50, :window_half_size => 3) { |v| sample_item_data v } + pagination_dom = Rails::Dom::Testing.html_document_fragment.parse(pagination) + assert_dom pagination_dom, "ul", :count => 3 do |lists| + assert_dom lists[0], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(1) + end + assert_dom lists[1], "> li", 3 do |items| + check_version_ellipsis items.shift + check_version_link items.shift, sample_item_data(48) + check_version_link items.shift, sample_item_data(49) + end + assert_dom lists[2], "> li", 1 do |items| + check_version_link items.shift, sample_item_data(50) + end + end + end + private def sample_item_data(version) @@ -178,4 +287,10 @@ class NumberedPaginationHelperTest < ActionView::TestCase assert_dom "> @title", data[:title] end end + + def check_version_ellipsis(*elements) + assert_dom(*elements, "> @class", "page-item disabled") + assert_dom(*elements, "> a", 0) + assert_dom(*elements, "> span", 1, "...") + end end -- 2.39.5