pagy 9.4.0 → 43.5.5

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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +566 -562
  4. data/apps/demo.ru +246 -182
  5. data/apps/enable_rails_page_segment.rb +56 -0
  6. data/apps/index.rb +4 -2
  7. data/apps/keynav+root_key.ru +316 -0
  8. data/apps/keynav.ru +255 -0
  9. data/apps/{keyset_ar.ru → keyset.ru} +33 -42
  10. data/apps/{keyset_s.ru → keyset_sequel.ru} +32 -40
  11. data/apps/rails.ru +57 -58
  12. data/apps/repro.ru +54 -51
  13. data/bin/pagy +2 -95
  14. data/config/pagy.rb +33 -207
  15. data/javascripts/ai_widget.js +90 -0
  16. data/javascripts/pagy.js +166 -0
  17. data/javascripts/pagy.min.js +2 -4
  18. data/javascripts/pagy.mjs +126 -67
  19. data/javascripts/wand.js +1172 -0
  20. data/lib/pagy/classes/calendar/calendar.rb +101 -0
  21. data/lib/pagy/{calendar → classes/calendar}/day.rb +7 -11
  22. data/lib/pagy/{calendar → classes/calendar}/month.rb +5 -10
  23. data/lib/pagy/{calendar → classes/calendar}/quarter.rb +10 -15
  24. data/lib/pagy/classes/calendar/unit.rb +93 -0
  25. data/lib/pagy/{calendar → classes/calendar}/week.rb +5 -9
  26. data/lib/pagy/{calendar → classes/calendar}/year.rb +5 -6
  27. data/lib/pagy/classes/exceptions.rb +26 -0
  28. data/lib/pagy/classes/keyset/adapters/active_record.rb +50 -0
  29. data/lib/pagy/classes/keyset/adapters/sequel.rb +62 -0
  30. data/lib/pagy/classes/keyset/keynav.rb +85 -0
  31. data/lib/pagy/classes/keyset/keyset.rb +155 -0
  32. data/lib/pagy/classes/offset/countish.rb +17 -0
  33. data/lib/pagy/classes/offset/countless.rb +63 -0
  34. data/lib/pagy/classes/offset/offset.rb +63 -0
  35. data/lib/pagy/classes/offset/search.rb +34 -0
  36. data/lib/pagy/classes/request.rb +48 -0
  37. data/lib/pagy/cli.rb +122 -0
  38. data/lib/pagy/console.rb +5 -20
  39. data/lib/pagy/deprecated.rb +84 -0
  40. data/lib/pagy/modules/abilities/configurable.rb +37 -0
  41. data/lib/pagy/modules/abilities/countable.rb +23 -0
  42. data/lib/pagy/modules/abilities/linkable.rb +72 -0
  43. data/lib/pagy/modules/abilities/rangeable.rb +14 -0
  44. data/lib/pagy/modules/abilities/shiftable.rb +12 -0
  45. data/lib/pagy/{b64.rb → modules/b64.rb} +4 -2
  46. data/lib/pagy/modules/console.rb +33 -0
  47. data/lib/pagy/modules/i18n/i18n.rb +72 -0
  48. data/lib/pagy/modules/i18n/p11n/arabic.rb +30 -0
  49. data/lib/pagy/modules/i18n/p11n/east_slavic.rb +27 -0
  50. data/lib/pagy/modules/i18n/p11n/one_other.rb +15 -0
  51. data/lib/pagy/modules/i18n/p11n/one_upto_two_other.rb +15 -0
  52. data/lib/pagy/modules/i18n/p11n/other.rb +13 -0
  53. data/lib/pagy/modules/i18n/p11n/polish.rb +27 -0
  54. data/lib/pagy/modules/i18n/p11n/west_slavic.rb +22 -0
  55. data/lib/pagy/modules/i18n/p11n.rb +16 -0
  56. data/lib/pagy/modules/searcher.rb +20 -0
  57. data/lib/pagy/next.rb +25 -0
  58. data/lib/pagy/tasks/sync.rb +20 -0
  59. data/lib/pagy/toolbox/helpers/anchor_tags.rb +19 -0
  60. data/lib/pagy/toolbox/helpers/bootstrap/input_nav_js.rb +28 -0
  61. data/lib/pagy/toolbox/helpers/bootstrap/previous_next_html.rb +19 -0
  62. data/lib/pagy/toolbox/helpers/bootstrap/series_nav.rb +32 -0
  63. data/lib/pagy/toolbox/helpers/bootstrap/series_nav_js.rb +24 -0
  64. data/lib/pagy/toolbox/helpers/bulma/input_nav_js.rb +25 -0
  65. data/lib/pagy/toolbox/helpers/bulma/previous_next_html.rb +20 -0
  66. data/lib/pagy/toolbox/helpers/bulma/series_nav.rb +31 -0
  67. data/lib/pagy/toolbox/helpers/bulma/series_nav_js.rb +23 -0
  68. data/lib/pagy/toolbox/helpers/data_hash.rb +29 -0
  69. data/lib/pagy/toolbox/helpers/headers_hash.rb +30 -0
  70. data/lib/pagy/toolbox/helpers/info_tag.rb +30 -0
  71. data/lib/pagy/toolbox/helpers/input_nav_js.rb +22 -0
  72. data/lib/pagy/toolbox/helpers/limit_tag_js.rb +25 -0
  73. data/lib/pagy/toolbox/helpers/loaders.rb +58 -0
  74. data/lib/pagy/toolbox/helpers/page_url.rb +16 -0
  75. data/lib/pagy/toolbox/helpers/series_nav.rb +30 -0
  76. data/lib/pagy/toolbox/helpers/series_nav_js.rb +20 -0
  77. data/lib/pagy/toolbox/helpers/support/a_lambda.rb +36 -0
  78. data/lib/pagy/toolbox/helpers/support/data_pagy_attribute.rb +19 -0
  79. data/lib/pagy/toolbox/helpers/support/nav_aria_label_attribute.rb +10 -0
  80. data/lib/pagy/toolbox/helpers/support/series.rb +37 -0
  81. data/lib/pagy/toolbox/helpers/support/wrap_input_nav_js.rb +18 -0
  82. data/lib/pagy/toolbox/helpers/support/wrap_series_nav.rb +15 -0
  83. data/lib/pagy/toolbox/helpers/support/wrap_series_nav_js.rb +38 -0
  84. data/lib/pagy/toolbox/helpers/urls_hash.rb +12 -0
  85. data/lib/pagy/toolbox/paginators/calendar.rb +34 -0
  86. data/lib/pagy/toolbox/paginators/countish.rb +38 -0
  87. data/lib/pagy/toolbox/paginators/countless.rb +22 -0
  88. data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +56 -0
  89. data/lib/pagy/toolbox/paginators/keynav_js.rb +26 -0
  90. data/lib/pagy/toolbox/paginators/keyset.rb +15 -0
  91. data/lib/pagy/toolbox/paginators/meilisearch.rb +34 -0
  92. data/lib/pagy/toolbox/paginators/method.rb +38 -0
  93. data/lib/pagy/toolbox/paginators/offset.rb +24 -0
  94. data/lib/pagy/toolbox/paginators/searchkick.rb +34 -0
  95. data/lib/pagy/toolbox/paginators/typesense_rails.rb +34 -0
  96. data/lib/pagy.rb +79 -89
  97. data/locales/ar.yml +9 -6
  98. data/locales/be.yml +9 -6
  99. data/locales/bg.yml +9 -6
  100. data/locales/bs.yml +9 -6
  101. data/locales/ca.yml +9 -6
  102. data/locales/ckb.yml +8 -6
  103. data/locales/cs.yml +9 -6
  104. data/locales/da.yml +9 -6
  105. data/locales/de.yml +9 -6
  106. data/locales/dz.yml +9 -6
  107. data/locales/en.yml +9 -6
  108. data/locales/es.yml +9 -6
  109. data/locales/fr.yml +9 -6
  110. data/locales/hr.yml +9 -6
  111. data/locales/hu.yml +24 -0
  112. data/locales/id.yml +10 -9
  113. data/locales/it.yml +9 -6
  114. data/locales/ja.yml +10 -9
  115. data/locales/km.yml +10 -9
  116. data/locales/ko.yml +9 -6
  117. data/locales/nb.yml +9 -6
  118. data/locales/nl.yml +9 -6
  119. data/locales/nn.yml +9 -6
  120. data/locales/pl.yml +9 -6
  121. data/locales/pt-BR.yml +10 -7
  122. data/locales/pt.yml +10 -7
  123. data/locales/ru.yml +9 -6
  124. data/locales/sk.yml +9 -6
  125. data/locales/sr.yml +9 -6
  126. data/locales/sv-SE.yml +9 -6
  127. data/locales/sv.yml +9 -6
  128. data/locales/sw.yml +12 -9
  129. data/locales/ta.yml +9 -6
  130. data/locales/tr.yml +17 -12
  131. data/locales/uk.yml +9 -6
  132. data/locales/vi.yml +9 -6
  133. data/locales/zh-CN.yml +9 -6
  134. data/locales/zh-HK.yml +9 -6
  135. data/locales/zh-TW.yml +9 -6
  136. data/stylesheets/pagy-tailwind.css +68 -0
  137. data/stylesheets/pagy.css +64 -27
  138. metadata +134 -53
  139. data/javascripts/pagy.min.js.map +0 -10
  140. data/lib/optimist.rb +0 -1022
  141. data/lib/pagy/backend.rb +0 -44
  142. data/lib/pagy/calendar/unit.rb +0 -103
  143. data/lib/pagy/calendar.rb +0 -84
  144. data/lib/pagy/countless.rb +0 -38
  145. data/lib/pagy/exceptions.rb +0 -25
  146. data/lib/pagy/extras/arel.rb +0 -28
  147. data/lib/pagy/extras/array.rb +0 -19
  148. data/lib/pagy/extras/bootstrap.rb +0 -97
  149. data/lib/pagy/extras/bulma.rb +0 -93
  150. data/lib/pagy/extras/calendar.rb +0 -79
  151. data/lib/pagy/extras/countless.rb +0 -32
  152. data/lib/pagy/extras/elasticsearch_rails.rb +0 -71
  153. data/lib/pagy/extras/gearbox.rb +0 -55
  154. data/lib/pagy/extras/headers.rb +0 -54
  155. data/lib/pagy/extras/i18n.rb +0 -26
  156. data/lib/pagy/extras/js_tools.rb +0 -70
  157. data/lib/pagy/extras/jsonapi.rb +0 -88
  158. data/lib/pagy/extras/keyset.rb +0 -30
  159. data/lib/pagy/extras/limit.rb +0 -63
  160. data/lib/pagy/extras/meilisearch.rb +0 -57
  161. data/lib/pagy/extras/metadata.rb +0 -42
  162. data/lib/pagy/extras/overflow.rb +0 -81
  163. data/lib/pagy/extras/pagy.rb +0 -82
  164. data/lib/pagy/extras/searchkick.rb +0 -59
  165. data/lib/pagy/extras/size.rb +0 -40
  166. data/lib/pagy/extras/standalone.rb +0 -60
  167. data/lib/pagy/extras/trim.rb +0 -29
  168. data/lib/pagy/frontend.rb +0 -99
  169. data/lib/pagy/i18n.rb +0 -167
  170. data/lib/pagy/keyset/active_record.rb +0 -44
  171. data/lib/pagy/keyset/sequel.rb +0 -57
  172. data/lib/pagy/keyset.rb +0 -118
  173. data/lib/pagy/shared_methods.rb +0 -26
  174. data/lib/pagy/url_helpers.rb +0 -26
  175. data/stylesheets/pagy.scss +0 -48
  176. data/stylesheets/pagy.tailwind.css +0 -21
data/lib/pagy/backend.rb DELETED
@@ -1,44 +0,0 @@
1
- # See Pagy::Backend API documentation: https://ddnexus.github.io/pagy/docs/api/backend
2
- # frozen_string_literal: true
3
-
4
- class Pagy
5
- # Define a few generic methods to paginate a collection out of the box,
6
- # or any collection by overriding any of the `pagy_*` methods in your controller.
7
- # See also the extras if you need specialized methods to paginate Arrays or other collections
8
- module Backend
9
- private
10
-
11
- # Return Pagy object and paginated results
12
- def pagy(collection, **vars)
13
- vars[:count] ||= pagy_get_count(collection, vars)
14
- vars[:limit] ||= pagy_get_limit(vars)
15
- vars[:page] ||= pagy_get_page(vars)
16
- pagy = Pagy.new(**vars)
17
- [pagy, pagy_get_items(collection, pagy)]
18
- end
19
-
20
- # Get the count from the collection
21
- def pagy_get_count(collection, vars)
22
- count_args = vars[:count_args] || DEFAULT[:count_args]
23
- (count = collection.count(*count_args)).is_a?(Hash) ? count.size : count
24
- end
25
-
26
- # Sub-method called only by #pagy: here for easy customization of fetching by overriding
27
- # You may need to override this method for collections without offset|limit
28
- def pagy_get_items(collection, pagy)
29
- collection.offset(pagy.offset).limit(pagy.limit)
30
- end
31
-
32
- # Override for limit extra
33
- def pagy_get_limit(_vars)
34
- DEFAULT[:limit]
35
- end
36
-
37
- # Get the page integer from the params
38
- # Overridable by the jsonapi extra
39
- def pagy_get_page(vars, force_integer: true)
40
- page = params[vars[:page_param] || DEFAULT[:page_param]]
41
- force_integer ? (page || 1).to_i : page
42
- end
43
- end
44
- end
@@ -1,103 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support'
4
- require 'active_support/core_ext/time'
5
- require 'active_support/core_ext/date_and_time/calculations'
6
- require 'active_support/core_ext/numeric/time'
7
- require 'active_support/core_ext/integer/time'
8
-
9
- class Pagy # :nodoc:
10
- class Calendar < Hash # :nodoc:
11
- # Base class for time units subclasses (Year, Quarter, Month, Week, Day)
12
- class Unit < Pagy
13
- attr_reader :order, :from, :to
14
-
15
- # Merge and validate the options, do some simple arithmetic and set a few instance variables
16
- def initialize(**vars) # rubocop:disable Lint/MissingSuper
17
- raise InternalError, 'Pagy::Calendar::Unit is a base class; use one of its subclasses' \
18
- if instance_of?(Pagy::Calendar::Unit)
19
-
20
- assign_vars({ **Pagy::DEFAULT, **self.class::DEFAULT }, vars)
21
- assign_and_check(page: 1)
22
- assign_unit_vars
23
- check_overflow
24
- assign_prev_and_next
25
- end
26
-
27
- # The label for the current page (it can pass along the I18n gem opts when it's used with the i18n extra)
28
- def label(opts = {})
29
- label_for(@page, opts)
30
- end
31
-
32
- # The label for any page (it can pass along the I18n gem opts when it's used with the i18n extra)
33
- def label_for(page, opts = {})
34
- opts[:format] ||= @vars[:format]
35
- localize(starting_time_for(page.to_i), opts) # page could be a string
36
- end
37
-
38
- protected
39
-
40
- # The page that includes time
41
- # In case of out of range time, the :fit_time option avoids the outOfRangeError
42
- # and returns the closest page to the passed time argument (first or last page)
43
- def page_at(time, **opts)
44
- fit_time = time
45
- fit_final = @final - 1
46
- unless time.between?(@initial, fit_final)
47
- raise OutOfRangeError.new(self, :time, "between #{@initial} and #{fit_final}", time) unless opts[:fit_time]
48
-
49
- if time < @final
50
- fit_time = @initial
51
- ordinal = 'first'
52
- else
53
- fit_time = fit_final
54
- ordinal = 'last'
55
- end
56
- warn "Pagy::Calendar#page_at: Rescued #{time} out of range by returning the #{ordinal} page."
57
- end
58
- offset = page_offset_at(fit_time) # offset starts from 0
59
- @order == :asc ? offset + 1 : @last - offset
60
- end
61
-
62
- # Base class method for the setup of the unit variables (subclasses must implement it and call super)
63
- def assign_unit_vars
64
- raise VariableError.new(self, :format, 'to be a strftime format', @vars[:format]) unless @vars[:format].is_a?(String)
65
- raise VariableError.new(self, :order, 'to be in [:asc, :desc]', @order) \
66
- unless %i[asc desc].include?(@order = @vars[:order])
67
-
68
- @starting, @ending = @vars[:period]
69
- raise VariableError.new(self, :period, 'to be a an Array of min and max TimeWithZone instances', @vars[:period]) \
70
- unless @starting.is_a?(ActiveSupport::TimeWithZone) \
71
- && @ending.is_a?(ActiveSupport::TimeWithZone) && @starting <= @ending
72
- end
73
-
74
- # Apply the strftime format to the time (overridden by the i18n extra when localization is required)
75
- def localize(time, opts)
76
- time.strftime(opts[:format])
77
- end
78
-
79
- # Number of time units to offset from the @initial time, in order to get the ordered starting time for the page.
80
- # Used in starting_time_for(page) where page starts from 1 (e.g. page to starting_time means subtracting 1)
81
- def time_offset_for(page)
82
- @order == :asc ? page - 1 : @last - page
83
- end
84
-
85
- # Period of the active page (used internally for nested units)
86
- def active_period
87
- [[@starting, @from].max, [@to - 1, @ending].min] # -1 sec: include only last unit day
88
- end
89
-
90
- # :nocov:
91
- # This method must be implemented by the unit subclass
92
- def starting_time_for(*)
93
- raise NoMethodError, 'the starting_time_for method must be implemented by the unit subclass'
94
- end
95
-
96
- # This method must be implemented by the unit subclass
97
- def page_offset_at(*)
98
- raise NoMethodError, 'the page_offset_at method must be implemented by the unit subclass'
99
- end
100
- # :nocov:
101
- end
102
- end
103
- end
data/lib/pagy/calendar.rb DELETED
@@ -1,84 +0,0 @@
1
- # See Pagy::Countless API documentation: https://ddnexus.github.io/pagy/docs/api/calendar
2
- # frozen_string_literal: true
3
-
4
- require_relative '../pagy'
5
- require_relative 'calendar/unit'
6
-
7
- class Pagy # :nodoc:
8
- # Calendar class
9
- class Calendar < Hash
10
- # Specific out of range error
11
- class OutOfRangeError < VariableError; end
12
-
13
- # List of units in desc order of duration. It can be used for custom units.
14
- UNITS = %i[year quarter month week day] # rubocop:disable Style/MutableConstant
15
-
16
- class << self
17
- private
18
-
19
- # Create a unit subclass instance by using the unit name (internal use)
20
- def create(unit, **vars)
21
- raise InternalError, "unit must be in #{UNITS.inspect}; got #{unit}" unless UNITS.include?(unit)
22
-
23
- name = unit.to_s
24
- name[0] = name[0].capitalize
25
- Object.const_get("Pagy::Calendar::#{name}").new(**vars)
26
- end
27
-
28
- # Return calendar, from, to
29
- def init(...)
30
- new.send(:init, ...)
31
- end
32
- end
33
-
34
- # Return the current time of the smallest time unit shown
35
- def showtime
36
- self[@units.last].from
37
- end
38
-
39
- private
40
-
41
- # Create the calendar
42
- def init(conf, period, params)
43
- @conf = Marshal.load(Marshal.dump(conf)) # store a copy
44
- @units = Calendar::UNITS & @conf.keys # get the units in time length desc order
45
- raise ArgumentError, 'no calendar unit found in pagy_calendar @configuration' if @units.empty?
46
-
47
- @period = period
48
- @params = params
49
- @page_param = conf[:pagy][:page_param] || DEFAULT[:page_param]
50
- # set all the :page_param vars for later deletion
51
- @units.each { |unit| conf[unit][:page_param] = :"#{unit}_#{@page_param}" }
52
- calendar = {}
53
- object = nil
54
- @units.each_with_index do |unit, index|
55
- params_to_delete = @units[(index + 1), @units.size].map { |sub| conf[sub][:page_param] } + [@page_param]
56
- conf[unit][:params] = ->(up) { up.except(*params_to_delete.map(&:to_s)) }
57
- conf[unit][:period] = object&.send(:active_period) || @period
58
- conf[unit][:page] = @params[:"#{unit}_#{@page_param}"] # requested page
59
- # :nocov:
60
- conf[unit][:counts] = yield(unit, conf[unit][:period]) if block_given? # nocov doesn't need to fail block_given?
61
- # :nocov:
62
- calendar[unit] = object \
63
- = Calendar.send(:create, unit, **conf[unit])
64
- end
65
- [replace(calendar), object.from, object.to]
66
- end
67
-
68
- # Return the calendar object at time
69
- def calendar_at(time, **opts)
70
- conf = Marshal.load(Marshal.dump(@conf))
71
- page_params = {}
72
- @units.inject(nil) do |object, unit|
73
- conf[unit][:period] = object&.send(:active_period) || @period
74
- conf[unit][:page] = page_params[:"#{unit}_#{@page_param}"] \
75
- = Calendar.send(:create, unit, **conf[unit]).send(:page_at, time, **opts)
76
- conf[unit][:params] ||= {}
77
- conf[unit][:params].merge!(page_params)
78
- Calendar.send(:create, unit, **conf[unit])
79
- end
80
- end
81
- end
82
- # Require the subclass files in UNITS (no custom unit at this point yet)
83
- Calendar::UNITS.each { |unit| require "pagy/calendar/#{unit}" }
84
- end
@@ -1,38 +0,0 @@
1
- # See Pagy::Countless API documentation: https://ddnexus.github.io/pagy/docs/api/countless
2
- # frozen_string_literal: true
3
-
4
- class Pagy # :nodoc:
5
- # No need to know the count to paginate
6
- class Countless < Pagy
7
- # Merge and validate the options, do some simple arithmetic and set a few instance variables
8
- def initialize(**vars) # rubocop:disable Lint/MissingSuper
9
- assign_vars(DEFAULT, vars)
10
- assign_and_check(page: 1, outset: 0)
11
- assign_limit
12
- assign_offset
13
- end
14
-
15
- # Finalize the instance variables based on the fetched size
16
- def finalize(fetched_size)
17
- raise OverflowError.new(self, :page, "to be < #{@page}", @page) if fetched_size.zero? && @page > 1
18
-
19
- @last = fetched_size > @limit ? @page + 1 : @page
20
- @last = @vars[:max_pages] if @vars[:max_pages] && @last > @vars[:max_pages]
21
- check_overflow
22
- @in = [fetched_size, @limit].min
23
- @from = @in.zero? ? 0 : @offset - @outset + 1
24
- @to = @offset - @outset + @in
25
- assign_prev_and_next
26
- self
27
- end
28
- end
29
-
30
- module SeriesOverride # :nodoc:
31
- # Override the original series.
32
- # Return nil if :countless_minimal is enabled
33
- def series(**)
34
- super unless @vars[:countless_minimal]
35
- end
36
- end
37
- prepend SeriesOverride
38
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Pagy
4
- # Generic variable error
5
- class VariableError < ArgumentError
6
- attr_reader :pagy, :variable, :value
7
-
8
- # Set the variables and prepare the message
9
- def initialize(pagy, variable, description, value)
10
- @pagy = pagy
11
- @variable = variable
12
- @value = value
13
- super("expected :#{@variable} #{description}; got #{@value.inspect}")
14
- end
15
- end
16
-
17
- # Specific overflow error
18
- class OverflowError < VariableError; end
19
-
20
- # I18n configuration error
21
- class I18nError < StandardError; end
22
-
23
- # Generic internal error
24
- class InternalError < StandardError; end
25
- end
@@ -1,28 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/arel
2
- # frozen_string_literal: true
3
-
4
- class Pagy # :nodoc:
5
- # Better performance of grouped ActiveRecord collections
6
- module ArelExtra
7
- private
8
-
9
- # Return Pagy object and paginated collection/results
10
- def pagy_arel(collection, **vars)
11
- vars[:count] ||= pagy_arel_count(collection)
12
- pagy(collection, **vars)
13
- end
14
-
15
- # Count using Arel when grouping
16
- def pagy_arel_count(collection)
17
- if collection.group_values.empty?
18
- # COUNT(*)
19
- collection.count(:all)
20
- else
21
- # COUNT(*) OVER ()
22
- sql = Arel.star.count.over(Arel::Nodes::Grouping.new([]))
23
- collection.unscope(:order).pick(sql).to_i
24
- end
25
- end
26
- end
27
- Backend.prepend ArelExtra
28
- end
@@ -1,19 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/array
2
- # frozen_string_literal: true
3
-
4
- class Pagy # :nodoc:
5
- # Paginate arrays efficiently, avoiding expensive array-wrapping and without overriding
6
- module ArrayExtra
7
- private
8
-
9
- # Return Pagy object and paginated items
10
- def pagy_array(array, **vars)
11
- vars[:limit] ||= pagy_get_limit(vars)
12
- vars[:page] ||= pagy_get_page(vars)
13
- vars[:count] ||= array.size
14
- pagy = Pagy.new(**vars)
15
- [pagy, array[pagy.offset, pagy.limit]]
16
- end
17
- end
18
- Backend.prepend ArrayExtra
19
- end
@@ -1,97 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/bootstrap
2
- # frozen_string_literal: true
3
-
4
- require_relative 'js_tools'
5
-
6
- class Pagy # :nodoc:
7
- # Frontend modules are specially optimized for performance.
8
- # The resulting code may not look very elegant, but produces the best benchmarks
9
- module BootstrapExtra
10
- # Pagination for bootstrap: it returns the html with the series of links to the pages
11
- def pagy_bootstrap_nav(pagy, id: nil, classes: 'pagination', aria_label: nil, **vars)
12
- id = %( id="#{id}") if id
13
- a = pagy_anchor(pagy, **vars)
14
-
15
- html = %(<nav#{id} class="pagy-bootstrap nav" #{nav_aria_label(pagy, aria_label:)}><ul class="#{classes}">#{
16
- bootstrap_prev_html(pagy, a)})
17
- pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
- html << case item
19
- when Integer
20
- %(<li class="page-item">#{a.(item, classes: 'page-link')}</li>)
21
- when String
22
- %(<li class="page-item active"><a role="link" class="page-link" aria-current="page" aria-disabled="true">#{
23
- pagy.label_for(item)}</a></li>)
24
- when :gap
25
- %(<li class="page-item gap disabled"><a role="link" class="page-link" aria-disabled="true">#{
26
- pagy_t('pagy.gap')}</a></li>)
27
- else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
28
- end
29
- end
30
- html << %(#{bootstrap_next_html(pagy, a)}</ul></nav>)
31
- end
32
-
33
- # Javascript pagination for bootstrap: it returns a nav with a data-pagy attribute used by the pagy.js file
34
- def pagy_bootstrap_nav_js(pagy, id: nil, classes: 'pagination', aria_label: nil, **vars)
35
- sequels = pagy.sequels(**vars)
36
- id = %( id="#{id}") if id
37
- a = pagy_anchor(pagy, **vars)
38
- tokens = { 'before' => %(<ul class="#{classes}">#{bootstrap_prev_html(pagy, a)}),
39
- 'a' => %(<li class="page-item">#{a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'page-link')}</li>),
40
- 'current' => %(<li class="page-item active"><a role="link" class="page-link" ) +
41
- %(aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a></li>),
42
- 'gap' => %(<li class="page-item gap disabled"><a role="link" class="page-link" aria-disabled="true">#{
43
- pagy_t('pagy.gap')}</a></li>),
44
- 'after' => %(#{bootstrap_next_html pagy, a}</ul>) }
45
-
46
- %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-bootstrap nav-js" #{
47
- nav_aria_label(pagy, aria_label:)} #{
48
- pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
49
- }></nav>)
50
- end
51
-
52
- # Javascript combo pagination for bootstrap: it returns a nav with a data-pagy attribute used by the pagy.js file
53
- def pagy_bootstrap_combo_nav_js(pagy, id: nil, classes: 'pagination', aria_label: nil, **vars)
54
- id = %( id="#{id}") if id
55
- a = pagy_anchor(pagy, **vars)
56
- pages = pagy.pages
57
-
58
- page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
59
- %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0; ) <<
60
- %(border: none; display: inline-block;" class="page-link active">#{JSTools::A_TAG})
61
-
62
- %(<nav#{id} class="pagy-bootstrap combo-nav-js" #{
63
- nav_aria_label(pagy, aria_label:)} #{
64
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN, **vars))
65
- }><ul class="#{classes}">#{
66
- bootstrap_prev_html(pagy, a)
67
- }<li class="page-item pagy-bootstrap"><label class="page-link">#{
68
- pagy_t('pagy.combo_nav_js', page_input:, pages:)
69
- }</label></li>#{
70
- bootstrap_next_html(pagy, a)
71
- }</ul></nav>)
72
- end
73
-
74
- private
75
-
76
- def bootstrap_prev_html(pagy, a)
77
- if (p_prev = pagy.prev)
78
- %(<li class="page-item prev">#{
79
- a.(p_prev, pagy_t('pagy.prev'), classes: 'page-link', aria_label: pagy_t('pagy.aria_label.prev'))}</li>)
80
- else
81
- %(<li class="page-item prev disabled"><a role="link" class="page-link" aria-disabled="true" aria-label="#{
82
- pagy_t('pagy.aria_label.prev')}">#{pagy_t('pagy.prev')}</a></li>)
83
- end
84
- end
85
-
86
- def bootstrap_next_html(pagy, a)
87
- if (p_next = pagy.next)
88
- %(<li class="page-item next">#{
89
- a.(p_next, pagy_t('pagy.next'), classes: 'page-link', aria_label: pagy_t('pagy.aria_label.next'))}</li>)
90
- else
91
- %(<li class="page-item next disabled"><a role="link" class="page-link" aria-disabled="true" aria-label="#{
92
- pagy_t('pagy.aria_label.next')}">#{pagy_t('pagy.next')}</a></li>)
93
- end
94
- end
95
- end
96
- Frontend.prepend BootstrapExtra
97
- end
@@ -1,93 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/bulma
2
- # frozen_string_literal: true
3
-
4
- require_relative 'js_tools'
5
-
6
- class Pagy # :nodoc:
7
- # Frontend modules are specially optimized for performance.
8
- # The resulting code may not look very elegant, but produces the best benchmarks
9
- module BulmaExtra
10
- # Pagination for bulma: it returns the html with the series of links to the pages
11
- def pagy_bulma_nav(pagy, id: nil, classes: 'pagy-bulma nav pagination is-centered',
12
- aria_label: nil, **vars)
13
- id = %( id="#{id}") if id
14
- a = pagy_anchor(pagy, **vars)
15
-
16
- html = %(<nav#{id} class="#{classes}" #{nav_aria_label(pagy, aria_label:)}>)
17
- html << bulma_prev_next_html(pagy, a)
18
- html << %(<ul class="pagination-list">)
19
- pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
20
- html << case item
21
- when Integer
22
- %(<li>#{a.(item, pagy.label_for(item), classes: 'pagination-link')}</li>)
23
- when String
24
- %(<li><a role="link" class="pagination-link is-current" aria-current="page" aria-disabled="true">#{
25
- pagy.label_for(item)}</a></li>)
26
- when :gap
27
- %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.gap'}</span></li>)
28
- else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
29
- end
30
- end
31
- html << %(</ul></nav>)
32
- end
33
-
34
- # Javascript pagination for bulma: it returns a nav with a data-pagy attribute used by the Pagy.nav javascript
35
- def pagy_bulma_nav_js(pagy, id: nil, classes: 'pagy-bulma nav-js pagination is-centered',
36
- aria_label: nil, **vars)
37
- sequels = pagy.sequels(**vars)
38
- id = %( id="#{id}") if id
39
- a = pagy_anchor(pagy, **vars)
40
- tokens = { 'before' => %(#{bulma_prev_next_html(pagy, a)}<ul class="pagination-list">),
41
- 'a' => %(<li>#{a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'pagination-link')}</li>),
42
- 'current' => %(<li><a role="link" class="pagination-link is-current" aria-current="page" aria-disabled="true">#{
43
- LABEL_TOKEN}</a></li>),
44
- 'gap' => %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.gap'}</span></li>),
45
- 'after' => '</ul>' }
46
-
47
- %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}#{classes}" #{
48
- nav_aria_label(pagy, aria_label:)} #{
49
- pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
50
- }></nav>)
51
- end
52
-
53
- # Javascript combo pagination for bulma: it returns a nav with a data-pagy attribute used by the pagy.js file
54
- def pagy_bulma_combo_nav_js(pagy, id: nil, classes: 'pagy-bulma combo-nav-js pagination is-centered',
55
- aria_label: nil, **vars)
56
- id = %( id="#{id}") if id
57
- a = pagy_anchor(pagy, **vars)
58
- pages = pagy.pages
59
-
60
- page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page") <<
61
- %(style="text-align: center; width: #{pages.to_s.length + 1}rem; height: 1.7rem; margin:0 0.3rem; ) <<
62
- %(border: none; border-radius: 4px; padding: 0; font-size: 1.1rem; color: white; ) <<
63
- %(background-color: #485fc7;">#{JSTools::A_TAG})
64
-
65
- %(<nav#{id} class="#{classes}" #{
66
- nav_aria_label(pagy, aria_label:)} #{
67
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN, **vars))
68
- }>#{
69
- bulma_prev_next_html(pagy, a)
70
- }<ul class="pagination-list"><li class="pagination-link"><label>#{
71
- pagy_t('pagy.combo_nav_js', page_input:, pages:)
72
- }</label></li></ul></nav>)
73
- end
74
-
75
- private
76
-
77
- def bulma_prev_next_html(pagy, a)
78
- html = if (p_prev = pagy.prev)
79
- a.(p_prev, pagy_t('pagy.prev'), classes: 'pagination-previous', aria_label: pagy_t('pagy.aria_label.prev'))
80
- else
81
- %(<a role="link" class="pagination-previous" disabled aria-disabled="true" aria-label="#{
82
- pagy_t('pagy.aria_label.prev')}">#{pagy_t 'pagy.prev'}</a>)
83
- end
84
- html << if (p_next = pagy.next)
85
- a.(p_next, pagy_t('pagy.next'), classes: 'pagination-next', aria_label: pagy_t('pagy.aria_label.next'))
86
- else
87
- %(<a role="link" class="pagination-next" disabled aria-disabled="true" aria-label="#{
88
- pagy_t('pagy.aria_label.next')}">#{pagy_t('pagy.next')}</a>)
89
- end
90
- end
91
- end
92
- Frontend.prepend BulmaExtra
93
- end
@@ -1,79 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/calendar
2
- # frozen_string_literal: true
3
-
4
- require_relative '../calendar'
5
-
6
- class Pagy # :nodoc:
7
- # Add pagination filtering by calendar unit (:year, :quarter, :month, :week, :day) to the regular pagination
8
- module CalendarExtra
9
- # Additions for the Backend module
10
- module BackendAddOn
11
- CONF_KEYS = (Calendar::UNITS + %i[pagy active]).freeze
12
-
13
- private
14
-
15
- # Take a collection and a conf Hash with keys in CONF_KEYS and return an array with 3 items: [calendar, pagy, results]
16
- def pagy_calendar(collection, conf)
17
- raise ArgumentError, "keys must be in #{CONF_KEYS.inspect}" \
18
- unless conf.is_a?(Hash) && (conf.keys - CONF_KEYS).empty?
19
-
20
- conf[:pagy] ||= {}
21
- unless conf.key?(:active) && !conf[:active]
22
- calendar, from, to = Calendar.send(:init, conf, pagy_calendar_period(collection), params) do |unit, period|
23
- pagy_calendar_counts(collection, unit, *period) if respond_to?(:pagy_calendar_counts)
24
- end
25
- collection = pagy_calendar_filter(collection, from, to)
26
- end
27
- pagy, results = send(conf[:pagy][:backend] || :pagy, collection, **conf[:pagy]) # use backend: :pagy when omitted
28
- [calendar, pagy, results]
29
- end
30
-
31
- # This method must be implemented by the application
32
- def pagy_calendar_period(*)
33
- raise NoMethodError, 'the pagy_calendar_period method must be implemented by the application ' \
34
- '(see https://ddnexus.github.io/pagy/docs/extras/calendar/#pagy-calendar-period-collection)'
35
- end
36
-
37
- # This method must be implemented by the application
38
- def pagy_calendar_filter(*)
39
- raise NoMethodError, 'the pagy_calendar_filter method must be implemented by the application ' \
40
- '(see https://ddnexus.github.io/pagy/docs/extras/calendar/#pagy-calendar-filter-collection-from-to)'
41
- end
42
- end
43
-
44
- # Override the pagy_anchor
45
- module FrontendOverride
46
- # Consider the vars[:counts]
47
- def pagy_anchor(pagy, anchor_string: nil)
48
- return super unless (counts = pagy.vars[:counts])
49
-
50
- anchor_string &&= %( #{anchor_string})
51
- left, right = %(<a#{anchor_string} href="#{pagy_url_for(pagy, PAGE_TOKEN)}").split(PAGE_TOKEN, 2)
52
- # lambda used by all the helpers
53
- lambda do |page, text = pagy.label_for(page), classes: nil, aria_label: nil|
54
- count = counts[page - 1]
55
- if count.zero?
56
- classes = "#{classes && (classes + ' ')}empty-page"
57
- info_key = 'pagy.info.no_items'
58
- else
59
- info_key = 'pagy.info.single_page'
60
- end
61
- title = %( title="#{pagy_t(info_key, item_name: pagy_t('pagy.item_name', count:), count:)}")
62
- classes = %( class="#{classes}") if classes
63
- aria_label = %( aria-label="#{aria_label}") if aria_label
64
- %(#{left}#{page}#{right}#{title}#{classes}#{aria_label}>#{text}</a>)
65
- end
66
- end
67
- end
68
-
69
- # Additions for the Frontend module
70
- module UrlHelperAddOn
71
- # Return the url for the calendar page at time
72
- def pagy_calendar_url_at(calendar, time, **opts)
73
- pagy_url_for(calendar.send(:calendar_at, time, **opts), 1, **opts)
74
- end
75
- end
76
- end
77
- Backend.prepend CalendarExtra::BackendAddOn, CalendarExtra::UrlHelperAddOn
78
- Frontend.prepend CalendarExtra::UrlHelperAddOn, CalendarExtra::FrontendOverride
79
- end
@@ -1,32 +0,0 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/countless
2
- # frozen_string_literal: true
3
-
4
- require_relative '../countless'
5
-
6
- class Pagy # :nodoc:
7
- DEFAULT[:countless_minimal] = false
8
-
9
- # Paginate without the need of any count, saving one query per rendering
10
- module CountlessExtra
11
- private
12
-
13
- # Return Pagy object and records
14
- def pagy_countless(collection, **vars)
15
- vars[:limit] ||= pagy_get_limit(vars)
16
- vars[:page] ||= pagy_get_page(vars)
17
- pagy = Countless.new(**vars)
18
- [pagy, pagy_countless_get_items(collection, pagy)]
19
- end
20
-
21
- # Sub-method called only by #pagy_countless: here for easy customization of record-extraction by overriding
22
- # You may need to override this method for collections without offset|limit
23
- def pagy_countless_get_items(collection, pagy)
24
- return collection.offset(pagy.offset).limit(pagy.limit) if pagy.vars[:countless_minimal]
25
-
26
- fetched = collection.offset(pagy.offset).limit(pagy.limit + 1).to_a # eager load limit + 1
27
- pagy.finalize(fetched.size) # finalize the pagy object
28
- fetched[0, pagy.limit] # ignore eventual extra item
29
- end
30
- end
31
- Backend.prepend CountlessExtra
32
- end