pagy 8.0.0 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/apps/calendar.ru +745 -0
  3. data/{lib/apps → apps}/demo.ru +35 -52
  4. data/apps/keyset_ar.ru +236 -0
  5. data/apps/keyset_s.ru +238 -0
  6. data/{lib/apps → apps}/rails.ru +40 -33
  7. data/{lib/apps → apps}/repro.ru +33 -24
  8. data/apps/tmp/calendar.sqlite3 +0 -0
  9. data/apps/tmp/calendar.sqlite3-shm +0 -0
  10. data/apps/tmp/calendar.sqlite3-wal +0 -0
  11. data/apps/tmp/local_secret.txt +1 -0
  12. data/apps/tmp/pagy-keyset-ar.sqlite3 +0 -0
  13. data/apps/tmp/pagy-keyset-ar.sqlite3-shm +0 -0
  14. data/apps/tmp/pagy-keyset-ar.sqlite3-wal +0 -0
  15. data/apps/tmp/pagy-keyset-s.sqlite3 +0 -0
  16. data/{lib/bin → bin}/pagy +36 -17
  17. data/{lib/config → config}/pagy.rb +37 -68
  18. data/javascripts/pagy-module.js +100 -0
  19. data/javascripts/pagy.js +4 -0
  20. data/javascripts/pagy.min.js +4 -0
  21. data/javascripts/pagy.min.js.map +10 -0
  22. data/javascripts/pagy.mjs +100 -0
  23. data/lib/optimist.rb +1 -1
  24. data/lib/pagy/b64.rb +33 -0
  25. data/lib/pagy/backend.rb +24 -15
  26. data/lib/pagy/calendar/day.rb +5 -4
  27. data/lib/pagy/calendar/month.rb +5 -4
  28. data/lib/pagy/calendar/quarter.rb +5 -4
  29. data/lib/pagy/calendar/unit.rb +103 -0
  30. data/lib/pagy/calendar/week.rb +4 -4
  31. data/lib/pagy/calendar/year.rb +5 -4
  32. data/lib/pagy/calendar.rb +55 -99
  33. data/lib/pagy/console.rb +2 -2
  34. data/lib/pagy/countless.rb +17 -16
  35. data/lib/pagy/extras/arel.rb +8 -10
  36. data/lib/pagy/extras/array.rb +4 -6
  37. data/lib/pagy/extras/bootstrap.rb +7 -7
  38. data/lib/pagy/extras/bulma.rb +13 -9
  39. data/lib/pagy/extras/calendar.rb +35 -6
  40. data/lib/pagy/extras/countless.rb +7 -14
  41. data/lib/pagy/extras/elasticsearch_rails.rb +15 -15
  42. data/lib/pagy/extras/gearbox.rb +36 -35
  43. data/lib/pagy/extras/headers.rb +26 -25
  44. data/lib/pagy/extras/i18n.rb +1 -1
  45. data/lib/pagy/extras/js_tools.rb +12 -9
  46. data/lib/pagy/extras/jsonapi.rb +27 -17
  47. data/lib/pagy/extras/keyset.rb +26 -0
  48. data/lib/pagy/extras/limit.rb +63 -0
  49. data/lib/pagy/extras/meilisearch.rb +11 -11
  50. data/lib/pagy/extras/metadata.rb +7 -3
  51. data/lib/pagy/extras/overflow.rb +9 -8
  52. data/lib/pagy/extras/pagy.rb +18 -18
  53. data/lib/pagy/extras/searchkick.rb +11 -11
  54. data/lib/pagy/extras/size.rb +40 -0
  55. data/lib/pagy/extras/standalone.rb +8 -8
  56. data/lib/pagy/extras/trim.rb +3 -3
  57. data/lib/pagy/frontend.rb +39 -37
  58. data/lib/pagy/i18n.rb +1 -1
  59. data/lib/pagy/keyset/active_record.rb +38 -0
  60. data/lib/pagy/keyset/sequel.rb +51 -0
  61. data/lib/pagy/keyset.rb +99 -0
  62. data/lib/pagy/url_helpers.rb +11 -11
  63. data/lib/pagy.rb +96 -120
  64. data/{lib/locales → locales}/ar.yml +9 -10
  65. data/{lib/locales → locales}/be.yml +2 -2
  66. data/{lib/locales → locales}/bg.yml +2 -2
  67. data/{lib/locales → locales}/bs.yml +2 -2
  68. data/{lib/locales → locales}/ca.yml +5 -7
  69. data/{lib/locales → locales}/ckb.yml +2 -2
  70. data/{lib/locales → locales}/cs.yml +2 -2
  71. data/{lib/locales → locales}/da.yml +5 -7
  72. data/{lib/locales → locales}/de.yml +2 -2
  73. data/{lib/locales → locales}/en.yml +2 -2
  74. data/{lib/locales → locales}/es.yml +2 -2
  75. data/{lib/locales → locales}/fr.yml +2 -2
  76. data/{lib/locales → locales}/hr.yml +2 -2
  77. data/{lib/locales → locales}/id.yml +2 -2
  78. data/{lib/locales → locales}/it.yml +2 -2
  79. data/{lib/locales → locales}/ja.yml +2 -2
  80. data/{lib/locales → locales}/km.yml +2 -2
  81. data/{lib/locales → locales}/ko.yml +3 -5
  82. data/{lib/locales → locales}/nb.yml +2 -2
  83. data/{lib/locales → locales}/nl.yml +2 -2
  84. data/{lib/locales → locales}/nn.yml +2 -2
  85. data/{lib/locales → locales}/pl.yml +2 -2
  86. data/{lib/locales → locales}/pt-BR.yml +2 -2
  87. data/{lib/locales → locales}/pt.yml +2 -2
  88. data/{lib/locales → locales}/ru.yml +7 -9
  89. data/{lib/locales → locales}/sr.yml +2 -2
  90. data/{lib/locales → locales}/sv-SE.yml +2 -2
  91. data/{lib/locales → locales}/sv.yml +2 -2
  92. data/{lib/locales → locales}/sw.yml +2 -2
  93. data/{lib/locales → locales}/ta.yml +2 -2
  94. data/{lib/locales → locales}/tr.yml +2 -2
  95. data/{lib/locales → locales}/uk.yml +2 -2
  96. data/{lib/locales → locales}/vi.yml +2 -2
  97. data/{lib/locales → locales}/zh-CN.yml +2 -2
  98. data/{lib/locales → locales}/zh-HK.yml +2 -2
  99. data/{lib/locales → locales}/zh-TW.yml +2 -2
  100. data/pkg/pagy-9.0.0.gem +0 -0
  101. metadata +75 -70
  102. data/lib/apps/calendar.ru +0 -2196
  103. data/lib/javascripts/pagy-dev.js +0 -112
  104. data/lib/javascripts/pagy-module.js +0 -111
  105. data/lib/javascripts/pagy.js +0 -1
  106. data/lib/pagy/calendar/helper.rb +0 -65
  107. data/lib/pagy/extras/foundation.rb +0 -93
  108. data/lib/pagy/extras/items.rb +0 -64
  109. data/lib/pagy/extras/materialize.rb +0 -97
  110. data/lib/pagy/extras/semantic.rb +0 -91
  111. data/lib/pagy/extras/uikit.rb +0 -96
  112. /data/{lib/javascripts/pagy-module.d.ts → javascripts/pagy.d.ts} +0 -0
  113. /data/{lib/stylesheets → stylesheets}/pagy.css +0 -0
  114. /data/{lib/stylesheets → stylesheets}/pagy.scss +0 -0
  115. /data/{lib/stylesheets → stylesheets}/pagy.tailwind.css +0 -0
@@ -3,51 +3,52 @@
3
3
 
4
4
  class Pagy # :nodoc:
5
5
  DEFAULT[:gearbox_extra] = true # extra enabled by default
6
- DEFAULT[:gearbox_items] = [15, 30, 60, 100]
6
+ DEFAULT[:gearbox_limit] = [15, 30, 60, 100]
7
7
 
8
- # Automatically change the number of items per page depending on the page number
9
- # accepts an array as the :gearbox_items variable, that will determine the items for the first pages
8
+ # Automatically change the limit depending on the page number
9
+ # accepts an array as the :gearbox_limit variable, that will determine the limit for the first pages
10
10
  module GearboxExtra
11
- # Setup @items based on the :gearbox_items variable
12
- def setup_items_var
13
- return super if !@vars[:gearbox_extra] || @vars[:items_extra]
11
+ # Assign @limit based on the :gearbox_limit variable
12
+ def assign_limit
13
+ return super if !@vars[:gearbox_extra] || @vars[:limit_extra]
14
14
 
15
- gearbox_items = @vars[:gearbox_items]
16
- raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gearbox_items) \
17
- unless gearbox_items.is_a?(Array) && gearbox_items.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
15
+ gears = @vars[:gearbox_limit]
16
+ raise VariableError.new(self, :gearbox_limit, 'to be an Array of positives', gears) \
17
+ unless gears.is_a?(Array) && gears.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
18
18
 
19
- @items = gearbox_items[@page - 1] || gearbox_items.last
19
+ @limit = gears[@page - 1] || gears.last
20
20
  end
21
21
 
22
- # Setup @pages and @last based on the :gearbox_items variable (not used by Pagy::Countless)
23
- def setup_pages_var
24
- return super if !@vars[:gearbox_extra] || @vars[:items_extra]
22
+ # Asgnsi @offset based on the :gearbox_limit variable
23
+ def assign_offset
24
+ return super if !@vars[:gearbox_extra] || @vars[:limit_extra]
25
25
 
26
- gearbox_items = @vars[:gearbox_items]
27
- # This algorithm is thousands of times faster than the one in the geared_pagination gem
28
- @pages = @last = (if @count > (sum = gearbox_items.sum)
29
- [((@count - sum).to_f / gearbox_items.last).ceil, 1].max + gearbox_items.count
30
- else
31
- pages = 0
32
- remainder = @count
33
- while remainder.positive?
34
- pages += 1
35
- remainder -= gearbox_items[pages - 1]
36
- end
37
- [pages, 1].max
38
- end)
26
+ gears = @vars[:gearbox_limit]
27
+ @offset = if @page <= gears.count
28
+ gears[0, @page - 1].sum
29
+ else
30
+ gears.sum + (gears.last * (@page - gears.count - 1))
31
+ end + @outset
39
32
  end
40
33
 
41
- # Setup @offset based on the :gearbox_items variable
42
- def setup_offset_var
43
- return super if !@vars[:gearbox_extra] || @vars[:items_extra]
34
+ # Assign @last based on the :gearbox_limit variable and @count
35
+ def assign_last
36
+ return super if !@vars[:gearbox_extra] || @vars[:limit_extra]
44
37
 
45
- gearbox_items = @vars[:gearbox_items]
46
- @offset = if @page <= gearbox_items.count
47
- gearbox_items[0, @page - 1].sum
48
- else
49
- gearbox_items.sum + (gearbox_items.last * (@page - gearbox_items.count - 1))
50
- end + @outset
38
+ gears = @vars[:gearbox_limit]
39
+ # This algorithm is thousands of times faster than the one in the geared_pagination gem
40
+ @last = (if count > (sum = gears.sum)
41
+ [((count - sum).to_f / gears.last).ceil, 1].max + gears.count
42
+ else
43
+ pages = 0
44
+ remainder = count
45
+ while remainder.positive?
46
+ pages += 1
47
+ remainder -= gears[pages - 1]
48
+ end
49
+ [pages, 1].max
50
+ end)
51
+ @last = @vars[:max_pages] if @vars[:max_pages] && @last > @vars[:max_pages]
51
52
  end
52
53
  end
53
54
  prepend GearboxExtra
@@ -1,11 +1,11 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/headers
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:headers] = { page: 'current-page',
8
- items: 'page-items',
8
+ limit: 'page-items',
9
9
  count: 'total-count',
10
10
  pages: 'total-pages' }
11
11
  # Add specialized backend methods to add pagination response headers
@@ -21,32 +21,33 @@ class Pagy # :nodoc:
21
21
 
22
22
  # Generate a hash of RFC-8288 compliant http headers
23
23
  def pagy_headers(pagy)
24
- pagy_headers_hash(pagy).tap do |hash|
25
- hash['link'] = hash['link'].map { |rel, link| %(<#{link}>; rel="#{rel}") }.join(', ')
26
- end
27
- end
24
+ headers = pagy.vars[:headers]
25
+ { 'link' => link(pagy) }.tap do |hash|
26
+ hash[headers[:page]] = pagy.page.to_s if pagy.page && headers[:page]
27
+ hash[headers[:limit]] = pagy.limit.to_s \
28
+ if headers[:limit] && !(defined?(Calendar) && pagy.is_a?(Calendar::Unit))
29
+ return hash if (defined?(Countless) && pagy.is_a?(Countless)) || \
30
+ (defined?(Keyset) && pagy.is_a?(Keyset))
28
31
 
29
- # Generates a hash structure of the headers
30
- def pagy_headers_hash(pagy)
31
- countless = defined?(Countless) && pagy.is_a?(Countless)
32
- rel = { 'first' => 1, 'prev' => pagy.prev, 'next' => pagy.next }
33
- rel['last'] = pagy.last unless countless
34
- url_str = pagy_url_for(pagy, PAGE_TOKEN, absolute: true)
35
- link = rel.filter_map do |r, num|
36
- next unless num # rubocop:disable Layout/EmptyLineAfterGuardClause
37
- [r, url_str.sub(PAGE_TOKEN, num.to_s)]
38
- end.compact.to_h
39
- hash = { 'link' => link }
40
- headers = pagy.vars[:headers]
41
- hash[headers[:page]] = pagy.page.to_s if headers[:page]
42
- if headers[:items] && !(defined?(Calendar) && pagy.is_a?(Calendar)) # items is not for Calendar
43
- hash[headers[:items]] = pagy.vars[:items].to_s
44
- end
45
- unless countless
46
- hash[headers[:pages]] = pagy.pages.to_s if headers[:pages]
32
+ hash[headers[:pages]] = pagy.last.to_s if headers[:pages]
47
33
  hash[headers[:count]] = pagy.count.to_s if pagy.count && headers[:count] # count may be nil with Calendar
48
34
  end
49
- hash
35
+ end
36
+
37
+ def link(pagy)
38
+ [].tap do |link|
39
+ if defined?(Keyset) && pagy.is_a?(Keyset)
40
+ link << %(<#{pagy_url_for(pagy, nil, absolute: true)}>; rel="first")
41
+ link << %(<#{pagy_url_for(pagy, pagy.next, absolute: true)}>; rel="next") if pagy.next
42
+ else
43
+ url_str = pagy_url_for(pagy, PAGE_TOKEN, absolute: true)
44
+ link << %(<#{url_str.sub(PAGE_TOKEN, '1')}>; rel="first")
45
+ link << %(<#{url_str.sub(PAGE_TOKEN, pagy.prev.to_s)}>; rel="prev") if pagy.prev
46
+ link << %(<#{url_str.sub(PAGE_TOKEN, pagy.next.to_s)}>; rel="next") if pagy.next
47
+ link << %(<#{url_str.sub(PAGE_TOKEN, pagy.last.to_s)}>; rel="last") \
48
+ unless defined?(Countless) && pagy.is_a?(Countless)
49
+ end
50
+ end.join(', ')
50
51
  end
51
52
  end
52
53
  Backend.prepend HeadersExtra
@@ -19,7 +19,7 @@ class Pagy # :nodoc:
19
19
  end
20
20
  end
21
21
  end
22
- Calendar.prepend I18nExtra::CalendarOverride if defined?(Calendar)
22
+ Calendar::Unit.prepend I18nExtra::CalendarOverride if defined?(Calendar::Unit)
23
23
 
24
24
  # Add the pagy locales to the I18n.load_path
25
25
  ::I18n.load_path += Dir[Pagy.root.join('locales', '*.yml')]
@@ -1,20 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../b64'
4
+
3
5
  class Pagy # :nodoc:
4
6
  DEFAULT[:steps] = false # default false will use {0 => @vars[:size]}
5
7
 
6
8
  # Private module documented in the main classes
7
9
  module JSTools
10
+ # Dummy tag for input helpers: needed because Turbo does not intercept window.location changes
11
+ A_TAG = '<a href="#" style="display: none;">#</a>'
12
+
8
13
  # Additions for the Pagy class
9
14
  module PagyAddOn
10
15
  # `Pagy` instance method used by the `pagy*_nav_js` helpers.
11
16
  # It returns the sequels of width/series generated from the :steps hash
12
17
  # Example:
13
- # >> pagy = Pagy.new(count:1000, page: 20, steps: {0 => [1,2,2,1], 350 => [2,3,3,2], 550 => [3,4,4,3]})
18
+ # >> pagy = Pagy.new(count:1000, page: 20, steps: {0 => 5, 350 => 7, 550 => 9})
14
19
  # >> pagy.sequels
15
- # #=> { "0" => [1, :gap, 18, 19, "20", 21, 22, :gap, 50],
16
- # "350" => [1, 2, :gap, 17, 18, 19, "20", 21, 22, 23, :gap, 49, 50],
17
- # "550" => [1, 2, 3, :gap, 16, 17, 18, 19, "20", 21, 22, 23, 24, :gap, 48, 49, 50] }
20
+ # #=> { "0" => [18, 19, "20", 21, 22],
21
+ # "350" => [1, :gap, 19, "20", 21, :gap, 50],
22
+ # "550" => [1 :gap, 18, 19, "20", 21, 22, :gap, 50] }
18
23
  # Notice: if :steps is false it will use the single {0 => @vars[:size]} size
19
24
  def sequels(steps: @vars[:steps] || { 0 => @vars[:size] }, **_)
20
25
  raise VariableError.new(self, :steps, 'to define the 0 width', steps) unless steps.key?(0)
@@ -39,7 +44,7 @@ class Pagy # :nodoc:
39
44
  end
40
45
  end
41
46
  end
42
- Calendar.prepend CalendarOverride if defined?(Calendar)
47
+ Calendar::Unit.prepend CalendarOverride if defined?(Calendar::Unit)
43
48
 
44
49
  # Additions for the Frontend
45
50
  module FrontendAddOn
@@ -48,8 +53,7 @@ class Pagy # :nodoc:
48
53
  # Base64 encoded JSON is smaller than HTML escaped JSON
49
54
  def pagy_data(pagy, *args)
50
55
  args << pagy.vars[:page_param] if pagy.vars[:trim_extra]
51
- strict_base64_encoded = [Oj.dump(args, mode: :strict)].pack('m0')
52
- %(data-pagy="#{strict_base64_encoded}")
56
+ %(data-pagy="#{B64.encode(Oj.dump(args, mode: :strict))}")
53
57
  end
54
58
  else
55
59
  require 'json'
@@ -57,8 +61,7 @@ class Pagy # :nodoc:
57
61
  # Base64 encoded JSON is smaller than HTML escaped JSON
58
62
  def pagy_data(pagy, *args)
59
63
  args << pagy.vars[:page_param] if pagy.vars[:trim_extra]
60
- strict_base64_encoded = [args.to_json].pack('m0')
61
- %(data-pagy="#{strict_base64_encoded}")
64
+ %(data-pagy="#{B64.encode(args.to_json)}")
62
65
  end
63
66
  end
64
67
  end
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/jsonapi
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:jsonapi] = true
@@ -24,10 +24,17 @@ class Pagy # :nodoc:
24
24
 
25
25
  # Return the jsonapi links
26
26
  def pagy_jsonapi_links(pagy, **opts)
27
- { first: pagy_url_for(pagy, 1, **opts),
28
- last: pagy_url_for(pagy, pagy.last, **opts),
29
- prev: pagy.prev ? pagy_url_for(pagy, pagy.prev, **opts) : nil,
30
- next: pagy.next ? pagy_url_for(pagy, pagy.next, **opts) : nil }
27
+ if defined?(Pagy::Keyset) && pagy.is_a?(Pagy::Keyset)
28
+ { first: pagy_url_for(pagy, nil, **opts),
29
+ last: nil,
30
+ prev: nil,
31
+ next: pagy.next ? pagy_url_for(pagy, pagy.next, **opts) : nil }
32
+ else
33
+ { first: pagy_url_for(pagy, 1, **opts),
34
+ last: pagy_url_for(pagy, pagy.last, **opts),
35
+ prev: pagy.prev ? pagy_url_for(pagy, pagy.prev, **opts) : nil,
36
+ next: pagy.next ? pagy_url_for(pagy, pagy.next, **opts) : nil }
37
+ end
31
38
  end
32
39
 
33
40
  # Should skip the jsonapi
@@ -40,38 +47,41 @@ class Pagy # :nodoc:
40
47
  # Override the Backend method
41
48
  def pagy_get_page(vars)
42
49
  return super if pagy_skip_jsonapi?(vars)
43
- return 1 if params[:page].nil?
50
+ return if params[:page].nil?
44
51
 
45
- params[:page][vars[:page_param] || DEFAULT[:page_param]].to_i
52
+ params[:page][vars[:page_param] || DEFAULT[:page_param]]
46
53
  end
47
54
  end
48
55
  Backend.prepend BackendOverride
49
56
 
50
- # Module overriding ItemsExtra
51
- module ItemsExtraOverride
57
+ # Module overriding LimitExtra
58
+ module LimitExtraOverride
52
59
  private
53
60
 
54
- # Override the ItemsExtra::Backend method
55
- def pagy_get_items_size(vars)
61
+ # Override the LimitExtra::Backend method
62
+ def pagy_get_limit_param(vars)
56
63
  return super if pagy_skip_jsonapi?(vars)
57
64
  return if params[:page].nil?
58
65
 
59
- params[:page][vars[:items_param] || DEFAULT[:items_param]]
66
+ params[:page][vars[:limit_param] || DEFAULT[:limit_param]]
60
67
  end
61
68
  end
62
69
  # :nocov:
63
- ItemsExtra::BackendAddOn.prepend ItemsExtraOverride if defined?(ItemsExtra::BackendAddOn)
70
+ LimitExtra::BackendAddOn.prepend LimitExtraOverride if defined?(LimitExtra::BackendAddOn)
64
71
  # :nocov:
65
72
 
66
73
  # Module overriding UrlHelper
67
74
  module UrlHelperOverride
68
75
  # Override UrlHelper method
69
- def pagy_set_query_params(page, vars, params)
76
+ def pagy_set_query_params(page, vars, query_params)
70
77
  return super unless vars[:jsonapi]
71
78
 
72
- params['page'] ||= {}
73
- params['page'][vars[:page_param].to_s] = page
74
- params['page'][vars[:items_param].to_s] = vars[:items] if vars[:items_extra]
79
+ query_params['page'] ||= {}
80
+ query_params['page'][vars[:page_param].to_s] = page if page
81
+ query_params['page'][vars[:limit_param].to_s] = vars[:limit] if vars[:limit_extra]
82
+ # :nocov:
83
+ query_params.delete(:page) if query_params['page'].empty?
84
+ # :nocov:
75
85
  end
76
86
  end
77
87
  UrlHelpers.prepend UrlHelperOverride
@@ -0,0 +1,26 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/keyset
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../keyset'
5
+
6
+ class Pagy # :nodoc:
7
+ # Add keyset pagination
8
+ module KeysetExtra
9
+ private
10
+
11
+ # Return Pagy::Keyset object and paginated records
12
+ def pagy_keyset(set, **vars)
13
+ pagy = Keyset.new(set, **pagy_keyset_get_vars(vars))
14
+ [pagy, pagy.records]
15
+ end
16
+
17
+ # Sub-method called only by #pagy_keyset: here for easy customization of variables by overriding
18
+ def pagy_keyset_get_vars(vars)
19
+ vars.tap do |v|
20
+ v[:page] ||= pagy_get_page(v)
21
+ v[:limit] ||= pagy_get_limit(v)
22
+ end
23
+ end
24
+ end
25
+ Backend.prepend KeysetExtra
26
+ end
@@ -0,0 +1,63 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/limit
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'js_tools'
5
+
6
+ class Pagy # :nodoc:
7
+ DEFAULT[:limit_param] = :limit
8
+ DEFAULT[:limit_max] = 100
9
+ DEFAULT[:limit_extra] = true # extra enabled by default
10
+
11
+ # Allow the client to request a custom limit per page with an optional selector UI
12
+ module LimitExtra
13
+ # Additions for the Backend module
14
+ module BackendAddOn
15
+ private
16
+
17
+ # Set the limit variable considering the params and other pagy variables
18
+ def pagy_get_limit(vars)
19
+ return unless vars.key?(:limit_extra) ? vars[:limit_extra] : DEFAULT[:limit_extra] # :limit_extra is false
20
+ return unless (limit_count = pagy_get_limit_param(vars)) # no limit from request params
21
+
22
+ vars[:limit] = [limit_count.to_i, vars.key?(:limit_max) ? vars[:limit_max] : DEFAULT[:limit_max]].compact.min
23
+ end
24
+
25
+ # Get the limit count from the params
26
+ # Overridable by the jsonapi extra
27
+ def pagy_get_limit_param(vars)
28
+ params[vars[:limit_param] || DEFAULT[:limit_param]]
29
+ end
30
+ end
31
+ Backend.prepend LimitExtra::BackendAddOn
32
+
33
+ # Additions for the Frontend module
34
+ module FrontendAddOn
35
+ LIMIT_TOKEN = '__pagy_limit__'
36
+
37
+ # Return the limit selector HTML. For example "Show [20] items per page"
38
+ def pagy_limit_selector_js(pagy, id: nil, item_name: nil)
39
+ return '' unless pagy.vars[:limit_extra]
40
+
41
+ id = %( id="#{id}") if id
42
+ vars = pagy.vars
43
+ limit = vars[:limit]
44
+ vars[:limit] = LIMIT_TOKEN
45
+ url_token = pagy_url_for(pagy, PAGE_TOKEN)
46
+ vars[:limit] = limit # restore the limit
47
+
48
+ limit_input = %(<input name="limit" type="number" min="1" max="#{vars[:limit_max]}" value="#{
49
+ limit}" style="padding: 0; text-align: center; width: #{limit.to_s.length + 1}rem;">#{JSTools::A_TAG})
50
+
51
+ %(<span#{id} class="pagy limit-selector-js" #{
52
+ pagy_data(pagy, :selector, pagy.from, url_token)
53
+ }><label>#{
54
+ pagy_t('pagy.limit_selector_js',
55
+ item_name: item_name || pagy_t('pagy.item_name', count: limit),
56
+ limit_input:,
57
+ count: limit)
58
+ }</label></span>)
59
+ end
60
+ end
61
+ Frontend.prepend LimitExtra::FrontendAddOn
62
+ end
63
+ end
@@ -20,12 +20,12 @@ class Pagy # :nodoc:
20
20
  # Extension for the Pagy class
21
21
  module PagyExtension
22
22
  # Create a Pagy object from a Meilisearch results
23
- def new_from_meilisearch(results, vars = {})
24
- vars[:items] = results.raw_answer['hitsPerPage']
23
+ def new_from_meilisearch(results, **vars)
24
+ vars[:limit] = results.raw_answer['hitsPerPage']
25
25
  vars[:page] = results.raw_answer['page']
26
26
  vars[:count] = results.raw_answer['totalHits']
27
27
 
28
- new(vars)
28
+ new(**vars)
29
29
  end
30
30
  end
31
31
  Pagy.extend PagyExtension
@@ -35,17 +35,17 @@ class Pagy # :nodoc:
35
35
  private
36
36
 
37
37
  # Return Pagy object and results
38
- def pagy_meilisearch(pagy_search_args, vars = {})
38
+ def pagy_meilisearch(pagy_search_args, **vars)
39
39
  model, term, options = pagy_search_args
40
40
  vars = pagy_meilisearch_get_vars(nil, vars)
41
- options[:hits_per_page] = vars[:items]
41
+ options[:hits_per_page] = vars[:limit]
42
42
  options[:page] = vars[:page]
43
43
  results = model.send(:ms_search, term, options)
44
44
  vars[:count] = results.raw_answer['totalHits']
45
45
 
46
- pagy = ::Pagy.new(vars)
46
+ pagy = ::Pagy.new(**vars)
47
47
  # with :last_page overflow we need to re-run the method in order to get the hits
48
- return pagy_meilisearch(pagy_search_args, vars.merge(page: pagy.page)) \
48
+ return pagy_meilisearch(pagy_search_args, **vars, page: pagy.page) \
49
49
  if defined?(::Pagy::OverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
50
50
 
51
51
  [pagy, results]
@@ -54,10 +54,10 @@ class Pagy # :nodoc:
54
54
  # Sub-method called only by #pagy_meilisearch: here for easy customization of variables by overriding.
55
55
  # The _collection argument is not available when the method is called.
56
56
  def pagy_meilisearch_get_vars(_collection, vars)
57
- pagy_set_items_from_params(vars) if defined?(ItemsExtra)
58
- vars[:items] ||= DEFAULT[:items]
59
- vars[:page] ||= pagy_get_page(vars)
60
- vars
57
+ vars.tap do |v|
58
+ v[:page] ||= pagy_get_page(v)
59
+ v[:limit] ||= pagy_get_limit(v) || DEFAULT[:limit]
60
+ end
61
61
  end
62
62
  end
63
63
  Backend.prepend BackendAddOn
@@ -1,11 +1,11 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/metadata
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:metadata] = %i[ scaffold_url first_url prev_url page_url next_url last_url
8
- count page items vars pages last in from to prev next series ]
8
+ count page limit vars pages last in from to prev next series ]
9
9
 
10
10
  # Add a specialized backend method for pagination metadata
11
11
  module MetadataExtra
@@ -17,7 +17,11 @@ class Pagy # :nodoc:
17
17
  def pagy_metadata(pagy, absolute: nil)
18
18
  scaffold_url = pagy_url_for(pagy, PAGE_TOKEN, absolute:)
19
19
  {}.tap do |metadata|
20
- keys = defined?(Calendar) && pagy.is_a?(Calendar) ? pagy.vars[:metadata] - %i[count items] : pagy.vars[:metadata]
20
+ keys = if defined?(Calendar::Unit) && pagy.is_a?(Calendar::Unit)
21
+ pagy.vars[:metadata] - %i[count limit]
22
+ else
23
+ pagy.vars[:metadata]
24
+ end
21
25
  keys.each do |key|
22
26
  metadata[key] = case key
23
27
  when :scaffold_url then scaffold_url
@@ -14,7 +14,7 @@ class Pagy # :nodoc:
14
14
  end
15
15
 
16
16
  # Add rescue clause for different behaviors
17
- def initialize(vars)
17
+ def initialize(**vars)
18
18
  @overflow ||= false # still true if :last_page re-run the method after an overflow
19
19
  super
20
20
  rescue OverflowError
@@ -24,11 +24,12 @@ class Pagy # :nodoc:
24
24
  raise # same as without the extra
25
25
  when :last_page
26
26
  requested_page = @vars[:page] # save the requested page (even after re-run)
27
- initialize vars.merge!(page: @last) # re-run with the last page
27
+ initialize(**vars, page: @last) # re-run with the last page
28
28
  @vars[:page] = requested_page # restore the requested page
29
29
  when :empty_page
30
- @offset = @items = @from = @to = 0 # vars relative to the actual page
31
- if defined?(Calendar) && is_a?(Calendar) # only for Calendar instances
30
+ @offset = @limit = @in = @from = @to = 0 # vars relative to the actual page
31
+ if defined?(Calendar::Unit) \
32
+ && is_a?(Calendar::Unit) # only for Calendar::Units instances
32
33
  edge = @order == :asc ? @final : @initial # get the edge of the overflow side (neat, but any time would do)
33
34
  @from = @to = edge # set both to the edge utc time (a >=&&< query will get no records)
34
35
  end
@@ -51,12 +52,12 @@ class Pagy # :nodoc:
51
52
  end
52
53
  end
53
54
  Pagy.prepend PagyOverride
54
- Pagy::Calendar.prepend PagyOverride if defined?(Calendar)
55
+ Pagy::Calendar::Unit.prepend PagyOverride if defined?(Calendar::Unit)
55
56
 
56
57
  # Support for Pagy::Countless class
57
58
  module CountlessOverride
58
59
  # Add rescue clause for different behaviors
59
- def finalize(items)
60
+ def finalize(fetched_size)
60
61
  @overflow = false
61
62
  super
62
63
  rescue OverflowError
@@ -65,8 +66,8 @@ class Pagy # :nodoc:
65
66
  when :exception
66
67
  raise # same as without the extra
67
68
  when :empty_page
68
- @offset = @items = @from = @to = 0 # vars relative to the actual page
69
- @vars[:size] = [] # no page in the series
69
+ @offset = @limit = @from = @to = 0 # vars relative to the actual page
70
+ @vars[:size] = 0 # no page in the series
70
71
  self
71
72
  else
72
73
  raise VariableError.new(self, :overflow, 'to be in [:empty_page, :exception]', @vars[:overflow])
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/pagy
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/js_tools'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
@@ -12,7 +12,7 @@ class Pagy # :nodoc:
12
12
  def pagy_nav_js(pagy, id: nil, aria_label: nil, **vars)
13
13
  sequels = pagy.sequels(**vars)
14
14
  id = %( id="#{id}") if id
15
- a = pagy_anchor(pagy)
15
+ a = pagy_anchor(pagy, **vars)
16
16
  tokens = { 'before' => prev_a(pagy, a),
17
17
  'a' => a.(PAGE_TOKEN, LABEL_TOKEN),
18
18
  'current' => %(<a class="current" role="link" aria-current="page" aria-disabled="true">#{
@@ -27,17 +27,17 @@ class Pagy # :nodoc:
27
27
  end
28
28
 
29
29
  # Javascript combo pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
30
- def pagy_combo_nav_js(pagy, id: nil, aria_label: nil)
30
+ def pagy_combo_nav_js(pagy, id: nil, aria_label: nil, **vars)
31
31
  id = %( id="#{id}") if id
32
- a = pagy_anchor(pagy)
32
+ a = pagy_anchor(pagy, **vars)
33
33
  pages = pagy.pages
34
34
 
35
35
  page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
36
- %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0;">)
36
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0;">#{JSTools::A_TAG})
37
37
 
38
38
  %(<nav#{id} class="pagy combo-nav-js" #{
39
39
  nav_aria_label(pagy, aria_label:)} #{
40
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}>#{
40
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN, **vars))}>#{
41
41
  prev_a(pagy, a)
42
42
  }<label>#{
43
43
  pagy_t('pagy.combo_nav_js', page_input:, pages:)
@@ -47,35 +47,35 @@ class Pagy # :nodoc:
47
47
  end
48
48
 
49
49
  # Return the previous page URL string or nil
50
- def pagy_prev_url(pagy, absolute: false)
51
- pagy_url_for(pagy, pagy.prev, absolute:) if pagy.prev
50
+ def pagy_prev_url(pagy, **vars)
51
+ pagy_url_for(pagy, pagy.prev, **vars) if pagy.prev
52
52
  end
53
53
 
54
54
  # Return the next page URL string or nil
55
- def pagy_next_url(pagy, absolute: false)
56
- pagy_url_for(pagy, pagy.next, absolute:) if pagy.next
55
+ def pagy_next_url(pagy, **vars)
56
+ pagy_url_for(pagy, pagy.next, **vars) if pagy.next
57
57
  end
58
58
 
59
59
  # Return the enabled/disabled previous page anchor tag
60
- def pagy_prev_a(pagy, text: pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'))
61
- a = pagy_anchor(pagy)
60
+ def pagy_prev_a(pagy, text: pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'), **vars)
61
+ a = pagy_anchor(pagy, **vars)
62
62
  prev_a(pagy, a, text:, aria_label:)
63
63
  end
64
64
 
65
65
  # Return the enabled/disabled next page anchor tag
66
- def pagy_next_a(pagy, text: pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.prev'))
67
- a = pagy_anchor(pagy)
66
+ def pagy_next_a(pagy, text: pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.next'), **vars)
67
+ a = pagy_anchor(pagy, **vars)
68
68
  next_a(pagy, a, text:, aria_label:)
69
69
  end
70
70
 
71
71
  # Conditionally return the previous page link tag
72
- def pagy_prev_link(pagy, absolute: false)
73
- %(<link href="#{pagy_url_for(pagy, pagy.prev, absolute:)}"/>) if pagy.prev
72
+ def pagy_prev_link(pagy, **vars)
73
+ %(<link href="#{pagy_url_for(pagy, pagy.prev, **vars)}"/>) if pagy.prev
74
74
  end
75
75
 
76
76
  # Conditionally return the next page link tag
77
- def pagy_next_link(pagy, absolute: false)
78
- %(<link href="#{pagy_url_for(pagy, pagy.next, absolute:)}"/>) if pagy.next
77
+ def pagy_next_link(pagy, **vars)
78
+ %(<link href="#{pagy_url_for(pagy, pagy.next, **vars)}"/>) if pagy.next
79
79
  end
80
80
  end
81
81
  Frontend.prepend PagyExtra