pagy 8.4.0 → 9.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/apps/calendar.ru +682 -2137
  3. data/apps/demo.ru +17 -13
  4. data/apps/keyset_ar.ru +236 -0
  5. data/apps/keyset_s.ru +238 -0
  6. data/apps/rails.ru +25 -15
  7. data/apps/repro.ru +17 -14
  8. data/bin/pagy +17 -12
  9. data/config/pagy.rb +37 -34
  10. data/javascripts/pagy.min.js +4 -0
  11. data/javascripts/pagy.min.js.map +10 -0
  12. data/javascripts/pagy.mjs +100 -0
  13. data/lib/optimist.rb +1 -1
  14. data/lib/pagy/b64.rb +33 -0
  15. data/lib/pagy/backend.rb +19 -19
  16. data/lib/pagy/calendar/day.rb +4 -3
  17. data/lib/pagy/calendar/month.rb +4 -3
  18. data/lib/pagy/calendar/quarter.rb +4 -3
  19. data/lib/pagy/calendar/unit.rb +103 -0
  20. data/lib/pagy/calendar/week.rb +3 -3
  21. data/lib/pagy/calendar/year.rb +4 -3
  22. data/lib/pagy/calendar.rb +54 -97
  23. data/lib/pagy/countless.rb +15 -16
  24. data/lib/pagy/extras/arel.rb +3 -11
  25. data/lib/pagy/extras/array.rb +5 -10
  26. data/lib/pagy/extras/bootstrap.rb +5 -5
  27. data/lib/pagy/extras/bulma.rb +10 -7
  28. data/lib/pagy/extras/calendar.rb +34 -5
  29. data/lib/pagy/extras/countless.rb +8 -13
  30. data/lib/pagy/extras/elasticsearch_rails.rb +16 -25
  31. data/lib/pagy/extras/gearbox.rb +26 -26
  32. data/lib/pagy/extras/headers.rb +25 -24
  33. data/lib/pagy/extras/i18n.rb +1 -1
  34. data/lib/pagy/extras/js_tools.rb +10 -10
  35. data/lib/pagy/extras/jsonapi.rb +26 -19
  36. data/lib/pagy/extras/keyset.rb +30 -0
  37. data/lib/pagy/extras/limit.rb +63 -0
  38. data/lib/pagy/extras/meilisearch.rb +9 -17
  39. data/lib/pagy/extras/metadata.rb +6 -2
  40. data/lib/pagy/extras/overflow.rb +11 -10
  41. data/lib/pagy/extras/pagy.rb +16 -16
  42. data/lib/pagy/extras/searchkick.rb +9 -17
  43. data/lib/pagy/extras/size.rb +40 -0
  44. data/lib/pagy/extras/standalone.rb +6 -6
  45. data/lib/pagy/extras/trim.rb +3 -3
  46. data/lib/pagy/frontend.rb +37 -35
  47. data/lib/pagy/i18n.rb +2 -2
  48. data/lib/pagy/keyset/active_record.rb +38 -0
  49. data/lib/pagy/keyset/sequel.rb +51 -0
  50. data/lib/pagy/keyset.rb +98 -0
  51. data/lib/pagy/shared_methods.rb +27 -0
  52. data/lib/pagy/url_helpers.rb +5 -5
  53. data/lib/pagy.rb +70 -94
  54. data/locales/ar.yml +9 -10
  55. data/locales/be.yml +2 -2
  56. data/locales/bg.yml +2 -2
  57. data/locales/bs.yml +2 -2
  58. data/locales/ca.yml +5 -7
  59. data/locales/ckb.yml +2 -2
  60. data/locales/cs.yml +2 -2
  61. data/locales/da.yml +2 -2
  62. data/locales/de.yml +2 -2
  63. data/locales/en.yml +2 -2
  64. data/locales/es.yml +2 -2
  65. data/locales/fr.yml +2 -2
  66. data/locales/hr.yml +2 -2
  67. data/locales/id.yml +2 -2
  68. data/locales/it.yml +2 -2
  69. data/locales/ja.yml +2 -2
  70. data/locales/km.yml +2 -2
  71. data/locales/ko.yml +2 -2
  72. data/locales/nb.yml +2 -2
  73. data/locales/nl.yml +2 -2
  74. data/locales/nn.yml +2 -2
  75. data/locales/pl.yml +2 -2
  76. data/locales/pt-BR.yml +2 -2
  77. data/locales/pt.yml +2 -2
  78. data/locales/ru.yml +2 -2
  79. data/locales/sr.yml +2 -2
  80. data/locales/sv-SE.yml +2 -2
  81. data/locales/sv.yml +2 -2
  82. data/locales/sw.yml +2 -2
  83. data/locales/ta.yml +2 -2
  84. data/locales/tr.yml +2 -2
  85. data/locales/uk.yml +2 -2
  86. data/locales/vi.yml +2 -2
  87. data/locales/zh-CN.yml +2 -2
  88. data/locales/zh-HK.yml +2 -2
  89. data/locales/zh-TW.yml +2 -2
  90. metadata +19 -19
  91. data/javascripts/pagy-dev.js +0 -114
  92. data/javascripts/pagy-module.js +0 -113
  93. data/javascripts/pagy.js +0 -1
  94. data/lib/pagy/calendar/helper.rb +0 -65
  95. data/lib/pagy/extras/foundation.rb +0 -95
  96. data/lib/pagy/extras/items.rb +0 -64
  97. data/lib/pagy/extras/materialize.rb +0 -100
  98. data/lib/pagy/extras/semantic.rb +0 -94
  99. data/lib/pagy/extras/uikit.rb +0 -98
  100. /data/javascripts/{pagy-module.d.ts → pagy.d.ts} +0 -0
@@ -0,0 +1,103 @@
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
@@ -3,15 +3,15 @@
3
3
 
4
4
  class Pagy # :nodoc:
5
5
  class Calendar # :nodoc:
6
- # Calendar week subclass
7
- class Week < Calendar
6
+ # Week unit subclass
7
+ class Week < Unit
8
8
  DEFAULT = { order: :asc, # rubocop:disable Style/MutableConstant
9
9
  format: '%Y-%W' }
10
10
 
11
11
  protected
12
12
 
13
13
  # Setup the calendar variables
14
- def setup_unit_vars
14
+ def assign_unit_vars
15
15
  super
16
16
  @initial = @starting.beginning_of_week
17
17
  @final = @ending.next_week.beginning_of_week
@@ -3,16 +3,17 @@
3
3
 
4
4
  class Pagy # :nodoc:
5
5
  class Calendar # :nodoc:
6
- # Calendar year subclass
7
- class Year < Calendar
6
+ # Year unit subclass
7
+ class Year < Unit
8
8
  DEFAULT = { size: 10, # rubocop:disable Style/MutableConstant
9
+ ends: false,
9
10
  order: :asc,
10
11
  format: '%Y' }
11
12
 
12
13
  protected
13
14
 
14
15
  # Setup the calendar variables
15
- def setup_unit_vars
16
+ def assign_unit_vars
16
17
  super
17
18
  @initial = @starting.beginning_of_year
18
19
  @final = @ending.next_year.beginning_of_year
data/lib/pagy/calendar.rb CHANGED
@@ -1,122 +1,79 @@
1
1
  # See Pagy::Countless API documentation: https://ddnexus.github.io/pagy/docs/api/calendar
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'active_support'
5
- require 'active_support/core_ext/time'
6
- require 'active_support/core_ext/date_and_time/calculations'
7
- require 'active_support/core_ext/numeric/time'
8
- require 'active_support/core_ext/integer/time'
9
-
10
4
  require_relative '../pagy'
5
+ require_relative 'calendar/unit'
11
6
 
12
7
  class Pagy # :nodoc:
13
- # Base class for time units subclasses (Year, Quarter, Month, Week, Day)
14
- class Calendar < Pagy
8
+ # Calendar class
9
+ class Calendar < Hash
15
10
  # Specific out of range error
16
11
  class OutOfRangeError < VariableError; end
17
12
 
18
13
  # List of units in desc order of duration. It can be used for custom units.
19
14
  UNITS = %i[year quarter month week day] # rubocop:disable Style/MutableConstant
20
15
 
21
- attr_reader :order, :from, :to
22
-
23
- # Merge and validate the options, do some simple arithmetic and set a few instance variables
24
- def initialize(vars) # rubocop:disable Lint/MissingSuper
25
- raise InternalError, 'Pagy::Calendar is a base class; use one of its subclasses' if instance_of?(Pagy::Calendar)
26
-
27
- vars = self.class::DEFAULT.merge(vars) # subclass specific default
28
- normalize_vars(vars) # general default
29
- setup_vars(page: 1)
30
- setup_unit_vars
31
- raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
32
-
33
- @prev = (@page - 1 unless @page == 1)
34
- @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
35
- end
36
-
37
- # The label for the current page (it can pass along the I18n gem opts when it's used with the i18n extra)
38
- def label(opts = {})
39
- label_for(@page, opts)
40
- end
41
-
42
- # The label for any page (it can pass along the I18n gem opts when it's used with the i18n extra)
43
- def label_for(page, opts = {})
44
- opts[:format] ||= @vars[:format]
45
- localize(starting_time_for(page.to_i), opts) # page could be a string
46
- end
47
-
48
- protected
16
+ class << self
17
+ private
49
18
 
50
- # The page that includes time
51
- # In case of out of range time, the :fit_time option avoids the outOfRangeError
52
- # and returns the closest page to the passed time argument (first or last page)
53
- def page_at(time, **opts)
54
- fit_time = time
55
- fit_final = @final - 1
56
- unless time.between?(@initial, fit_final)
57
- raise OutOfRangeError.new(self, :time, "between #{@initial} and #{fit_final}", time) unless opts[:fit_time]
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)
58
22
 
59
- if time < @final
60
- fit_time = @initial
61
- ordinal = 'first'
62
- else
63
- fit_time = fit_final
64
- ordinal = 'last'
65
- end
66
- Warning.warn "Pagy::Calendar#page_at: Rescued #{time} out of range by returning the #{ordinal} page."
23
+ name = unit.to_s
24
+ name[0] = name[0].capitalize
25
+ Object.const_get("Pagy::Calendar::#{name}").new(**vars)
67
26
  end
68
- offset = page_offset_at(fit_time) # offset starts from 0
69
- @order == :asc ? offset + 1 : @last - offset
70
- end
71
27
 
72
- # Base class method for the setup of the unit variables (subclasses must implement it and call super)
73
- def setup_unit_vars
74
- raise VariableError.new(self, :format, 'to be a strftime format', @vars[:format]) unless @vars[:format].is_a?(String)
75
- raise VariableError.new(self, :order, 'to be in [:asc, :desc]', @order) \
76
- unless %i[asc desc].include?(@order = @vars[:order])
77
-
78
- @starting, @ending = @vars[:period]
79
- raise VariableError.new(self, :period, 'to be a an Array of min and max TimeWithZone instances', @vars[:period]) \
80
- unless @starting.is_a?(ActiveSupport::TimeWithZone) \
81
- && @ending.is_a?(ActiveSupport::TimeWithZone) && @starting <= @ending
82
- end
83
-
84
- # Apply the strftime format to the time (overridden by the i18n extra when localization is required)
85
- def localize(time, opts)
86
- time.strftime(opts[:format])
87
- end
88
-
89
- # Number of time units to offset from the @initial time, in order to get the ordered starting time for the page.
90
- # Used in starting_time_for(page) where page starts from 1 (e.g. page to starting_time means subtracting 1)
91
- def time_offset_for(page)
92
- @order == :asc ? page - 1 : @last - page
93
- end
94
-
95
- # Period of the active page (used internally for nested units)
96
- def active_period
97
- [[@starting, @from].max, [@to - 1, @ending].min] # -1 sec: include only last unit day
28
+ # Return calendar, from, to
29
+ def init(conf, period, params)
30
+ new.send(:init, conf, period, params)
31
+ end
98
32
  end
99
33
 
100
- # :nocov:
101
- # This method must be implemented by the unit subclass
102
- def starting_time_for(*)
103
- raise NoMethodError, 'the starting_time_for method must be implemented by the unit subclass'
34
+ # Return the current time of the smallest time unit shown
35
+ def showtime
36
+ self[@units.last].from
104
37
  end
105
38
 
106
- # This method must be implemented by the unit subclass
107
- def page_offset_at(*)
108
- raise NoMethodError, 'the page_offset_at method must be implemented by the unit subclass'
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
+ @units.each do |unit| # set all the :page_param vars for later deletion
51
+ unit_page_param = :"#{unit}_#{@page_param}"
52
+ conf[unit][:page_param] = unit_page_param
53
+ conf[unit][:page] = @params[unit_page_param]
54
+ end
55
+ calendar = {}
56
+ object = nil
57
+ @units.each_with_index do |unit, index|
58
+ params_to_delete = @units[(index + 1), @units.size].map { |sub| conf[sub][:page_param] } + [@page_param]
59
+ conf[unit][:params] = lambda { |up| up.except(*params_to_delete.map(&:to_s)) } # rubocop:disable Style/Lambda
60
+ conf[unit][:period] = object&.send(:active_period) || @period
61
+ calendar[unit] = object = Calendar.send(:create, unit, **conf[unit])
62
+ end
63
+ [replace(calendar), object.from, object.to]
109
64
  end
110
- # :nocov:
111
65
 
112
- class << self
113
- # Create a subclass instance by unit name (internal use)
114
- def create(unit, vars)
115
- raise InternalError, "unit must be in #{UNITS.inspect}; got #{unit}" unless UNITS.include?(unit)
116
-
117
- name = unit.to_s
118
- name[0] = name[0].capitalize
119
- Object.const_get("Pagy::Calendar::#{name}").new(vars)
66
+ # Return the calendar object at time
67
+ def calendar_at(time, **opts)
68
+ conf = Marshal.load(Marshal.dump(@conf))
69
+ page_params = {}
70
+ @units.inject(nil) do |object, unit|
71
+ conf[unit][:period] = object&.send(:active_period) || @period
72
+ conf[unit][:page] = page_params[:"#{unit}_#{@page_param}"] \
73
+ = Calendar.send(:create, unit, **conf[unit]).send(:page_at, time, **opts)
74
+ conf[unit][:params] ||= {}
75
+ conf[unit][:params].merge!(page_params)
76
+ Calendar.send(:create, unit, **conf[unit])
120
77
  end
121
78
  end
122
79
  end
@@ -1,39 +1,38 @@
1
1
  # See Pagy::Countless API documentation: https://ddnexus.github.io/pagy/docs/api/countless
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative '../pagy'
5
-
6
- class Pagy
4
+ class Pagy # :nodoc:
7
5
  # No need to know the count to paginate
8
6
  class Countless < Pagy
9
7
  # Merge and validate the options, do some simple arithmetic and set a few instance variables
10
- def initialize(vars = {}) # rubocop:disable Lint/MissingSuper
11
- normalize_vars(vars)
12
- setup_vars(page: 1, outset: 0)
13
- setup_items_var
14
- setup_offset_var
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
15
13
  end
16
14
 
17
15
  # Finalize the instance variables based on the fetched size
18
16
  def finalize(fetched_size)
19
17
  raise OverflowError.new(self, :page, "to be < #{@page}", @page) if fetched_size.zero? && @page > 1
20
18
 
21
- @last = fetched_size > @items ? @page + 1 : @page
22
- @last = vars[:max_pages] if vars[:max_pages] && @last > vars[:max_pages]
23
- raise OverflowError.new(self, :page, "in 1..#{@last}", @page) if @page > @last
24
-
25
- @in = [fetched_size, @items].min
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
26
23
  @from = @in.zero? ? 0 : @offset - @outset + 1
27
24
  @to = @offset - @outset + @in
28
- @prev = (@page - 1 unless @page == 1)
29
- @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
25
+ assign_prev_and_next
30
26
  self
31
27
  end
28
+ end
32
29
 
30
+ module SeriesOverride # :nodoc:
33
31
  # Override the original series.
34
32
  # Return nil if :countless_minimal is enabled
35
- def series(*, **)
33
+ def series(**)
36
34
  super unless @vars[:countless_minimal]
37
35
  end
38
36
  end
37
+ prepend SeriesOverride
39
38
  end
@@ -7,17 +7,9 @@ class Pagy # :nodoc:
7
7
  private
8
8
 
9
9
  # Return Pagy object and paginated collection/results
10
- def pagy_arel(collection, vars = {})
11
- pagy = Pagy.new(pagy_arel_get_vars(collection, vars))
12
- [pagy, pagy_get_items(collection, pagy)]
13
- end
14
-
15
- # Sub-method called only by #pagy_arel: here for easy customization of variables by overriding
16
- def pagy_arel_get_vars(collection, vars)
17
- pagy_set_items_from_params(vars) if defined?(ItemsExtra)
10
+ def pagy_arel(collection, **vars)
18
11
  vars[:count] ||= pagy_arel_count(collection)
19
- vars[:page] ||= pagy_get_page(vars)
20
- vars
12
+ pagy(collection, **vars)
21
13
  end
22
14
 
23
15
  # Count using Arel when grouping
@@ -28,7 +20,7 @@ class Pagy # :nodoc:
28
20
  else
29
21
  # COUNT(*) OVER ()
30
22
  sql = Arel.star.count.over(Arel::Nodes::Grouping.new([]))
31
- collection.unscope(:order).limit(1).pluck(sql).first.to_i
23
+ collection.unscope(:order).pick(sql).to_i
32
24
  end
33
25
  end
34
26
  end
@@ -7,17 +7,12 @@ class Pagy # :nodoc:
7
7
  private
8
8
 
9
9
  # Return Pagy object and paginated items
10
- def pagy_array(array, vars = {})
11
- pagy = Pagy.new(pagy_array_get_vars(array, vars))
12
- [pagy, array[pagy.offset, pagy.items]]
13
- end
14
-
15
- # Sub-method called only by #pagy_array: here for easy customization of variables by overriding
16
- def pagy_array_get_vars(array, vars)
17
- pagy_set_items_from_params(vars) if defined?(ItemsExtra)
18
- vars[:count] ||= array.size
10
+ def pagy_array(array, **vars)
11
+ vars[:limit] ||= pagy_get_limit(vars)
19
12
  vars[:page] ||= pagy_get_page(vars)
20
- vars
13
+ vars[:count] ||= array.size
14
+ pagy = Pagy.new(**vars)
15
+ [pagy, array[pagy.offset, pagy.limit]]
21
16
  end
22
17
  end
23
18
  Backend.prepend ArrayExtra
@@ -10,7 +10,7 @@ class Pagy # :nodoc:
10
10
  # Pagination for bootstrap: it returns the html with the series of links to the pages
11
11
  def pagy_bootstrap_nav(pagy, id: nil, classes: 'pagination', aria_label: nil, **vars)
12
12
  id = %( id="#{id}") if id
13
- a = pagy_anchor(pagy)
13
+ a = pagy_anchor(pagy, **vars)
14
14
 
15
15
  html = %(<nav#{id} class="pagy-bootstrap nav" #{nav_aria_label(pagy, aria_label:)}><ul class="#{classes}">#{
16
16
  bootstrap_prev_html(pagy, a)})
@@ -34,7 +34,7 @@ class Pagy # :nodoc:
34
34
  def pagy_bootstrap_nav_js(pagy, id: nil, classes: 'pagination', aria_label: nil, **vars)
35
35
  sequels = pagy.sequels(**vars)
36
36
  id = %( id="#{id}") if id
37
- a = pagy_anchor(pagy)
37
+ a = pagy_anchor(pagy, **vars)
38
38
  tokens = { 'before' => %(<ul class="#{classes}">#{bootstrap_prev_html(pagy, a)}),
39
39
  'a' => %(<li class="page-item">#{a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'page-link')}</li>),
40
40
  'current' => %(<li class="page-item active"><a role="link" class="page-link" ) +
@@ -50,9 +50,9 @@ class Pagy # :nodoc:
50
50
  end
51
51
 
52
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)
53
+ def pagy_bootstrap_combo_nav_js(pagy, id: nil, classes: 'pagination', aria_label: nil, **vars)
54
54
  id = %( id="#{id}") if id
55
- a = pagy_anchor(pagy)
55
+ a = pagy_anchor(pagy, **vars)
56
56
  pages = pagy.pages
57
57
 
58
58
  page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
@@ -61,7 +61,7 @@ class Pagy # :nodoc:
61
61
 
62
62
  %(<nav#{id} class="pagy-bootstrap combo-nav-js" #{
63
63
  nav_aria_label(pagy, aria_label:)} #{
64
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
64
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN, **vars))
65
65
  }><ul class="#{classes}">#{
66
66
  bootstrap_prev_html(pagy, a)
67
67
  }<li class="page-item pagy-bootstrap"><label class="page-link">#{
@@ -8,9 +8,10 @@ class Pagy # :nodoc:
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module BulmaExtra
10
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', aria_label: nil, **vars)
11
+ def pagy_bulma_nav(pagy, id: nil, classes: 'pagy-bulma nav pagination is-centered',
12
+ aria_label: nil, **vars)
12
13
  id = %( id="#{id}") if id
13
- a = pagy_anchor(pagy)
14
+ a = pagy_anchor(pagy, **vars)
14
15
 
15
16
  html = %(<nav#{id} class="#{classes}" #{nav_aria_label(pagy, aria_label:)}>)
16
17
  html << bulma_prev_next_html(pagy, a)
@@ -31,10 +32,11 @@ class Pagy # :nodoc:
31
32
  end
32
33
 
33
34
  # Javascript pagination for bulma: it returns a nav with a data-pagy attribute used by the Pagy.nav javascript
34
- def pagy_bulma_nav_js(pagy, id: nil, classes: 'pagy-bulma nav-js pagination is-centered', aria_label: nil, **vars)
35
+ def pagy_bulma_nav_js(pagy, id: nil, classes: 'pagy-bulma nav-js pagination is-centered',
36
+ aria_label: nil, **vars)
35
37
  sequels = pagy.sequels(**vars)
36
38
  id = %( id="#{id}") if id
37
- a = pagy_anchor(pagy)
39
+ a = pagy_anchor(pagy, **vars)
38
40
  tokens = { 'before' => %(#{bulma_prev_next_html(pagy, a)}<ul class="pagination-list">),
39
41
  'a' => %(<li>#{a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'pagination-link')}</li>),
40
42
  'current' => %(<li><a role="link" class="pagination-link is-current" aria-current="page" aria-disabled="true">#{
@@ -49,9 +51,10 @@ class Pagy # :nodoc:
49
51
  end
50
52
 
51
53
  # Javascript combo pagination for bulma: it returns a nav with a data-pagy attribute used by the pagy.js file
52
- def pagy_bulma_combo_nav_js(pagy, id: nil, classes: 'pagy-bulma combo-nav-js pagination is-centered', aria_label: nil)
54
+ def pagy_bulma_combo_nav_js(pagy, id: nil, classes: 'pagy-bulma combo-nav-js pagination is-centered',
55
+ aria_label: nil, **vars)
53
56
  id = %( id="#{id}") if id
54
- a = pagy_anchor(pagy)
57
+ a = pagy_anchor(pagy, **vars)
55
58
  pages = pagy.pages
56
59
 
57
60
  page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page") <<
@@ -61,7 +64,7 @@ class Pagy # :nodoc:
61
64
 
62
65
  %(<nav#{id} class="#{classes}" #{
63
66
  nav_aria_label(pagy, aria_label:)} #{
64
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
67
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN, **vars))
65
68
  }>#{
66
69
  bulma_prev_next_html(pagy, a)
67
70
  }<ul class="pagination-list"><li class="pagination-link"><label>#{
@@ -2,7 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require_relative '../calendar'
5
- require_relative '../calendar/helper'
6
5
 
7
6
  class Pagy # :nodoc:
8
7
  # Add pagination filtering by calendar unit (:year, :quarter, :month, :week, :day) to the regular pagination
@@ -20,10 +19,15 @@ class Pagy # :nodoc:
20
19
 
21
20
  conf[:pagy] ||= {}
22
21
  unless conf.key?(:active) && !conf[:active]
23
- calendar, from, to = Calendar::Helper.send(:init, conf, pagy_calendar_period(collection), params)
24
- collection = pagy_calendar_filter(collection, from, to)
22
+ calendar, from, to = Calendar.send(:init, conf, pagy_calendar_period(collection), params)
23
+ if respond_to?(:pagy_calendar_counts)
24
+ calendar.each_key do |unit|
25
+ calendar[unit].vars[:counts] = pagy_calendar_counts(collection, unit, *calendar[unit].vars[:period])
26
+ end
27
+ end
28
+ collection = pagy_calendar_filter(collection, from, to)
25
29
  end
26
- pagy, results = send(conf[:pagy][:backend] || :pagy, collection, conf[:pagy]) # use backend: :pagy when omitted
30
+ pagy, results = send(conf[:pagy][:backend] || :pagy, collection, **conf[:pagy]) # use backend: :pagy when omitted
27
31
  [calendar, pagy, results]
28
32
  end
29
33
 
@@ -40,6 +44,31 @@ class Pagy # :nodoc:
40
44
  end
41
45
  end
42
46
 
47
+ # Override the pagy_anchor
48
+ module FrontendOverride
49
+ # Consider the vars[:count]
50
+ def pagy_anchor(pagy, anchor_string: nil)
51
+ return super unless (counts = pagy.vars[:counts])
52
+
53
+ anchor_string &&= %( #{anchor_string})
54
+ left, right = %(<a#{anchor_string} href="#{pagy_url_for(pagy, PAGE_TOKEN)}").split(PAGE_TOKEN, 2)
55
+ # lambda used by all the helpers
56
+ lambda do |page, text = pagy.label_for(page), classes: nil, aria_label: nil|
57
+ count = counts[page - 1]
58
+ item_name = pagy_t('pagy.item_name', count:)
59
+ if count.zero?
60
+ classes = "#{classes && (classes + ' ')}empty-page"
61
+ title = %( title="#{pagy_t('pagy.info.no_items', item_name:, count:)}")
62
+ else
63
+ title = %( title="#{pagy_t('pagy.info.single_page', item_name:, count:)}")
64
+ end
65
+ classes = %( class="#{classes}") if classes
66
+ aria_label = %( aria-label="#{aria_label}") if aria_label
67
+ %(#{left}#{page}#{right}#{title}#{classes}#{aria_label}>#{text}</a>)
68
+ end
69
+ end
70
+ end
71
+
43
72
  # Additions for the Frontend module
44
73
  module UrlHelperAddOn
45
74
  # Return the url for the calendar page at time
@@ -49,5 +78,5 @@ class Pagy # :nodoc:
49
78
  end
50
79
  end
51
80
  Backend.prepend CalendarExtra::BackendAddOn, CalendarExtra::UrlHelperAddOn
52
- Frontend.prepend CalendarExtra::UrlHelperAddOn
81
+ Frontend.prepend CalendarExtra::UrlHelperAddOn, CalendarExtra::FrontendOverride
53
82
  end
@@ -10,27 +10,22 @@ class Pagy # :nodoc:
10
10
  module CountlessExtra
11
11
  private
12
12
 
13
- # Return Pagy object and items
14
- def pagy_countless(collection, vars = {})
15
- pagy = Countless.new(pagy_countless_get_vars(collection, vars))
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)
16
18
  [pagy, pagy_countless_get_items(collection, pagy)]
17
19
  end
18
20
 
19
- # Sub-method called only by #pagy_countless: here for easy customization of variables by overriding
20
- def pagy_countless_get_vars(_collection, vars)
21
- pagy_set_items_from_params(vars) if defined?(ItemsExtra)
22
- vars[:page] ||= pagy_get_page(vars)
23
- vars
24
- end
25
-
26
21
  # Sub-method called only by #pagy_countless: here for easy customization of record-extraction by overriding
27
22
  # You may need to override this method for collections without offset|limit
28
23
  def pagy_countless_get_items(collection, pagy)
29
- return collection.offset(pagy.offset).limit(pagy.items) if pagy.vars[:countless_minimal]
24
+ return collection.offset(pagy.offset).limit(pagy.limit) if pagy.vars[:countless_minimal]
30
25
 
31
- fetched = collection.offset(pagy.offset).limit(pagy.items + 1).to_a # eager load items + 1
26
+ fetched = collection.offset(pagy.offset).limit(pagy.limit + 1).to_a # eager load limit + 1
32
27
  pagy.finalize(fetched.size) # finalize the pagy object
33
- fetched[0, pagy.items] # ignore eventual extra item
28
+ fetched[0, pagy.limit] # ignore eventual extra item
34
29
  end
35
30
  end
36
31
  Backend.prepend CountlessExtra