pagy 4.11.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/config/pagy.rb +66 -45
- data/lib/javascripts/pagy.js +15 -6
- data/lib/pagy/backend.rb +6 -10
- data/lib/pagy/console.rb +5 -4
- data/lib/pagy/countless.rb +13 -20
- data/lib/pagy/exceptions.rb +2 -4
- data/lib/pagy/extras/arel.rb +6 -6
- data/lib/pagy/extras/array.rb +6 -6
- data/lib/pagy/extras/bootstrap.rb +32 -29
- data/lib/pagy/extras/bulma.rb +40 -32
- data/lib/pagy/extras/countless.rb +8 -9
- data/lib/pagy/extras/elasticsearch_rails.rb +64 -47
- data/lib/pagy/extras/foundation.rb +26 -26
- data/lib/pagy/extras/gearbox.rb +42 -0
- data/lib/pagy/extras/headers.rb +24 -16
- data/lib/pagy/extras/i18n.rb +7 -16
- data/lib/pagy/extras/items.rb +37 -38
- data/lib/pagy/extras/materialize.rb +28 -30
- data/lib/pagy/extras/meilisearch.rb +50 -45
- data/lib/pagy/extras/metadata.rb +29 -13
- data/lib/pagy/extras/navs.rb +24 -26
- data/lib/pagy/extras/overflow.rb +57 -60
- data/lib/pagy/extras/searchkick.rb +51 -45
- data/lib/pagy/extras/semantic.rb +28 -30
- data/lib/pagy/extras/shared.rb +44 -40
- data/lib/pagy/extras/standalone.rb +37 -42
- data/lib/pagy/extras/support.rb +14 -13
- data/lib/pagy/extras/trim.rb +10 -11
- data/lib/pagy/extras/uikit.rb +27 -28
- data/lib/pagy/frontend.rb +22 -47
- data/lib/pagy/i18n.rb +159 -0
- data/lib/pagy/url_helpers.rb +22 -0
- data/lib/pagy.rb +52 -26
- data/lib/templates/uikit_nav.html.erb +1 -1
- data/lib/templates/uikit_nav.html.slim +1 -1
- metadata +7 -10
- data/lib/locales/utils/i18n.rb +0 -17
- data/lib/locales/utils/loader.rb +0 -31
- data/lib/locales/utils/p11n.rb +0 -112
- data/lib/pagy/deprecation.rb +0 -27
data/lib/pagy/extras/bulma.rb
CHANGED
@@ -4,8 +4,7 @@
|
|
4
4
|
require 'pagy/extras/shared'
|
5
5
|
|
6
6
|
class Pagy
|
7
|
-
module
|
8
|
-
|
7
|
+
module BulmaExtra
|
9
8
|
# Pagination for Bulma: it returns the html with the series of links to the pages
|
10
9
|
def pagy_bulma_nav(pagy, pagy_id: nil, link_extra: '')
|
11
10
|
p_id = %( id="#{pagy_id}") if pagy_id
|
@@ -16,67 +15,76 @@ class Pagy
|
|
16
15
|
html << %(<ul class="pagination-list">)
|
17
16
|
pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
|
18
17
|
html << case item
|
19
|
-
when Integer
|
20
|
-
|
21
|
-
when
|
18
|
+
when Integer
|
19
|
+
%(<li>#{link.call item, item, %(class="pagination-link" aria-label="goto page #{item}")}</li>)
|
20
|
+
when String
|
21
|
+
%(<li>#{link.call item, item,
|
22
|
+
%(class="pagination-link is-current" aria-label="page #{item}" aria-current="page")}</li>)
|
23
|
+
when :gap
|
24
|
+
%(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.nav.gap'}</span></li>)
|
22
25
|
end
|
23
26
|
end
|
24
27
|
html << %(</ul></nav>)
|
25
28
|
end
|
26
29
|
|
27
|
-
def pagy_bulma_nav_js(pagy,
|
28
|
-
pagy_id = Pagy.deprecated_arg(:id, deprecated_id, :pagy_id, pagy_id) if deprecated_id
|
30
|
+
def pagy_bulma_nav_js(pagy, pagy_id: nil, link_extra: '', steps: nil)
|
29
31
|
p_id = %( id="#{pagy_id}") if pagy_id
|
30
32
|
link = pagy_link_proc(pagy, link_extra: link_extra)
|
31
33
|
tags = { 'before' => %(#{pagy_bulma_prev_next_html(pagy, link)}<ul class="pagination-list">),
|
32
|
-
'link' => %(<li>#{link.call PAGE_PLACEHOLDER, PAGE_PLACEHOLDER,
|
33
|
-
|
34
|
-
'
|
34
|
+
'link' => %(<li>#{link.call PAGE_PLACEHOLDER, PAGE_PLACEHOLDER,
|
35
|
+
%(class="pagination-link" aria-label="goto page #{PAGE_PLACEHOLDER}")}</li>),
|
36
|
+
'active' => %(<li>#{link.call PAGE_PLACEHOLDER, PAGE_PLACEHOLDER,
|
37
|
+
%(class="pagination-link is-current" aria-current="page" aria-label="page #{
|
38
|
+
PAGE_PLACEHOLDER}")}</li>),
|
39
|
+
'gap' => %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.nav.gap'}</span></li>),
|
35
40
|
'after' => '</ul>' }
|
36
41
|
|
37
|
-
%(<nav#{p_id} class="pagy-njs pagy-bulma-nav-js pagination is-centered" aria-label="pagination" #{pagy_json_attr(
|
42
|
+
%(<nav#{p_id} class="pagy-njs pagy-bulma-nav-js pagination is-centered" aria-label="pagination" #{pagy_json_attr(
|
43
|
+
pagy, :nav, tags, pagy.sequels(steps)
|
44
|
+
)}></nav>)
|
38
45
|
end
|
39
46
|
|
40
47
|
# Javascript combo pagination for Bulma: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
|
41
|
-
def pagy_bulma_combo_nav_js(pagy,
|
42
|
-
pagy_id = Pagy.deprecated_arg(:id, deprecated_id, :pagy_id, pagy_id) if deprecated_id
|
48
|
+
def pagy_bulma_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
|
43
49
|
p_id = %( id="#{pagy_id}") if pagy_id
|
44
50
|
link = pagy_link_proc(pagy, link_extra: link_extra)
|
45
51
|
p_page = pagy.page
|
46
52
|
p_pages = pagy.pages
|
47
|
-
input = %(<input class="input" type="number" min="1" max="#{p_pages}" value="#{
|
53
|
+
input = %(<input class="input" type="number" min="1" max="#{p_pages}" value="#{
|
54
|
+
p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length + 1}rem; margin:0 0.3rem;">)
|
48
55
|
|
49
|
-
%(<nav#{p_id} class="pagy-bulma-combo-nav-js" aria-label="pagination"
|
50
|
-
|
51
|
-
|
56
|
+
html = %(<nav#{p_id} class="pagy-bulma-combo-nav-js" aria-label="pagination">)
|
57
|
+
%(#{html}<div class="field is-grouped is-grouped-centered" role="group" #{
|
58
|
+
pagy_json_attr pagy, :combo_nav, p_page, pagy_marked_link(link)}>#{
|
52
59
|
if (p_prev = pagy.prev)
|
53
60
|
%(<p class="control">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'class="button" aria-label="previous page"'}</p>)
|
54
61
|
else
|
55
62
|
%(<p class="control"><a class="button" disabled>#{pagy_t 'pagy.nav.prev'}</a></p>)
|
56
63
|
end
|
57
|
-
|
64
|
+
}<div class="pagy-combo-input control level is-mobile">#{
|
65
|
+
pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</div>#{
|
58
66
|
if (p_next = pagy.next)
|
59
67
|
%(<p class="control">#{link.call p_next, pagy_t('pagy.nav.next'), 'class="button" aria-label="next page"'}</p>)
|
60
68
|
else
|
61
69
|
%(<p class="control"><a class="button" disabled>#{pagy_t 'pagy.nav.next'}</a></p>)
|
62
70
|
end
|
63
|
-
|
71
|
+
}</div></nav>)
|
64
72
|
end
|
65
73
|
|
66
74
|
private
|
67
75
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
def pagy_bulma_prev_next_html(pagy, link)
|
77
|
+
html = +if (p_prev = pagy.prev)
|
78
|
+
link.call p_prev, pagy_t('pagy.nav.prev'), 'class="pagination-previous" aria-label="previous page"'
|
79
|
+
else
|
80
|
+
%(<a class="pagination-previous" disabled>#{pagy_t 'pagy.nav.prev'}</a>)
|
81
|
+
end
|
82
|
+
html << if (p_next = pagy.next)
|
83
|
+
link.call p_next, pagy_t('pagy.nav.next'), 'class="pagination-next" aria-label="next page"'
|
84
|
+
else
|
85
|
+
%(<a class="pagination-next" disabled>#{pagy_t 'pagy.nav.next'}</a>)
|
86
|
+
end
|
87
|
+
end
|
81
88
|
end
|
89
|
+
Frontend.prepend BulmaExtra
|
82
90
|
end
|
@@ -4,22 +4,21 @@
|
|
4
4
|
require 'pagy/countless'
|
5
5
|
|
6
6
|
class Pagy
|
7
|
+
DEFAULT[:countless_minimal] = false
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
module Backend
|
11
|
-
private # the whole module is private so no problem with including it in a controller
|
9
|
+
module CountlessExtra
|
10
|
+
private
|
12
11
|
|
13
12
|
# Return Pagy object and items
|
14
|
-
def pagy_countless(collection, vars={})
|
13
|
+
def pagy_countless(collection, vars = {})
|
15
14
|
pagy = Pagy::Countless.new(pagy_countless_get_vars(collection, vars))
|
16
|
-
[
|
15
|
+
[pagy, pagy_countless_get_items(collection, pagy)]
|
17
16
|
end
|
18
17
|
|
19
18
|
# Sub-method called only by #pagy_countless: here for easy customization of variables by overriding
|
20
19
|
def pagy_countless_get_vars(_collection, vars)
|
21
|
-
pagy_set_items_from_params(vars) if defined?(
|
22
|
-
vars[:page] ||= params[
|
20
|
+
pagy_set_items_from_params(vars) if defined?(ItemsExtra)
|
21
|
+
vars[:page] ||= params[vars[:page_param] || DEFAULT[:page_param]]
|
23
22
|
vars
|
24
23
|
end
|
25
24
|
|
@@ -35,6 +34,6 @@ class Pagy
|
|
35
34
|
pagy.finalize(items_size)
|
36
35
|
items
|
37
36
|
end
|
38
|
-
|
39
37
|
end
|
38
|
+
Backend.prepend CountlessExtra
|
40
39
|
end
|
@@ -2,60 +2,77 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
class Pagy
|
5
|
+
DEFAULT[:elasticsearch_rails_search_method] ||= :pagy_search
|
5
6
|
|
6
|
-
|
7
|
+
module ElasticsearchRailsExtra
|
8
|
+
module_function
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
# Get the count from different version of ElasticsearchRails
|
11
|
+
def total_count(response)
|
12
|
+
total = if response.respond_to?(:raw_response)
|
13
|
+
response.raw_response['hits']['total']
|
14
|
+
else
|
15
|
+
response.response['hits']['total']
|
16
|
+
end
|
17
|
+
total.is_a?(Hash) ? total['value'] : total
|
16
18
|
end
|
17
|
-
alias_method VARS[:elasticsearch_rails_search_method], :pagy_elasticsearch_rails
|
18
|
-
end
|
19
|
-
|
20
|
-
# create a Pagy object from an Elasticsearch::Model::Response::Response object
|
21
|
-
def self.new_from_elasticsearch_rails(response, vars={})
|
22
|
-
vars[:items] = response.search.options[:size] || 10
|
23
|
-
vars[:page] = (response.search.options[:from] || 0) / vars[:items] + 1
|
24
|
-
total = response.respond_to?(:raw_response) ? response.raw_response['hits']['total'] : response.response['hits']['total']
|
25
|
-
vars[:count] = total.is_a?(Hash) ? total['value'] : total
|
26
|
-
new(vars)
|
27
|
-
end
|
28
19
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
response = model.search(query_or_payload, **options)
|
40
|
-
total = response.respond_to?(:raw_response) ? response.raw_response['hits']['total'] : response.response['hits']['total']
|
41
|
-
vars[:count] = total.is_a?(Hash) ? total['value'] : total
|
42
|
-
|
43
|
-
pagy = Pagy.new(vars)
|
44
|
-
# with :last_page overflow we need to re-run the method in order to get the hits
|
45
|
-
return pagy_elasticsearch_rails(pagy_search_args, vars.merge(page: pagy.page)) \
|
46
|
-
if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
|
47
|
-
|
48
|
-
[ pagy, called.empty? ? response : response.send(*called) ]
|
20
|
+
module ElasticsearchRails
|
21
|
+
# Return an array used to delay the call of #search
|
22
|
+
# after the pagination variables are merged to the options
|
23
|
+
# it also pushes to the same array an eventually called method
|
24
|
+
def pagy_elasticsearch_rails(query_or_payload, **options)
|
25
|
+
[self, query_or_payload, options].tap do |args|
|
26
|
+
args.define_singleton_method(:method_missing) { |*a| args += a }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
alias_method Pagy::DEFAULT[:elasticsearch_rails_search_method], :pagy_elasticsearch_rails
|
49
30
|
end
|
50
31
|
|
51
|
-
#
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
32
|
+
# Additions for the Pagy class
|
33
|
+
module Pagy
|
34
|
+
# Create a Pagy object from an Elasticsearch::Model::Response::Response object
|
35
|
+
def new_from_elasticsearch_rails(response, vars = {})
|
36
|
+
vars[:items] = response.search.options[:size] || 10
|
37
|
+
vars[:page] = ((response.search.options[:from] || 0) / vars[:items]) + 1
|
38
|
+
vars[:count] = ElasticsearchRailsExtra.total_count(response)
|
39
|
+
new(vars)
|
40
|
+
end
|
58
41
|
end
|
59
42
|
|
43
|
+
# Add specialized backend methods to paginate ElasticsearchRails searches
|
44
|
+
module Backend
|
45
|
+
private
|
46
|
+
|
47
|
+
# Return Pagy object and items
|
48
|
+
def pagy_elasticsearch_rails(pagy_search_args, vars = {})
|
49
|
+
model, query_or_payload,
|
50
|
+
options, *called = pagy_search_args
|
51
|
+
vars = pagy_elasticsearch_rails_get_vars(nil, vars)
|
52
|
+
options[:size] = vars[:items]
|
53
|
+
options[:from] = vars[:items] * (vars[:page] - 1)
|
54
|
+
response = model.search(query_or_payload, **options)
|
55
|
+
vars[:count] = ElasticsearchRailsExtra.total_count(response)
|
56
|
+
|
57
|
+
pagy = ::Pagy.new(vars)
|
58
|
+
# with :last_page overflow we need to re-run the method in order to get the hits
|
59
|
+
return pagy_elasticsearch_rails(pagy_search_args, vars.merge(page: pagy.page)) \
|
60
|
+
if defined?(::Pagy::OverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
|
61
|
+
|
62
|
+
[pagy, called.empty? ? response : response.send(*called)]
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sub-method called only by #pagy_elasticsearch_rails: here for easy customization of variables by overriding
|
66
|
+
# the _collection argument is not available when the method is called
|
67
|
+
def pagy_elasticsearch_rails_get_vars(_collection, vars)
|
68
|
+
pagy_set_items_from_params(vars) if defined?(ItemsExtra)
|
69
|
+
vars[:items] ||= DEFAULT[:items]
|
70
|
+
vars[:page] ||= (params[vars[:page_param] || DEFAULT[:page_param]] || 1).to_i
|
71
|
+
vars
|
72
|
+
end
|
73
|
+
end
|
60
74
|
end
|
75
|
+
ElasticsearchRails = ElasticsearchRailsExtra::ElasticsearchRails
|
76
|
+
extend ElasticsearchRailsExtra::Pagy
|
77
|
+
Backend.prepend ElasticsearchRailsExtra::Backend
|
61
78
|
end
|
@@ -4,8 +4,7 @@
|
|
4
4
|
require 'pagy/extras/shared'
|
5
5
|
|
6
6
|
class Pagy
|
7
|
-
module
|
8
|
-
|
7
|
+
module FoundationExtra
|
9
8
|
# Pagination for Foundation: it returns the html with the series of links to the pages
|
10
9
|
def pagy_foundation_nav(pagy, pagy_id: nil, link_extra: '')
|
11
10
|
p_id = %( id="#{pagy_id}") if pagy_id
|
@@ -25,8 +24,7 @@ class Pagy
|
|
25
24
|
end
|
26
25
|
|
27
26
|
# Javascript pagination for foundation: it returns a nav and a JSON tag used by the Pagy.nav javascript
|
28
|
-
def pagy_foundation_nav_js(pagy,
|
29
|
-
pagy_id = Pagy.deprecated_arg(:id, deprecated_id, :pagy_id, pagy_id) if deprecated_id
|
27
|
+
def pagy_foundation_nav_js(pagy, pagy_id: nil, link_extra: '', steps: nil)
|
30
28
|
p_id = %( id="#{pagy_id}") if pagy_id
|
31
29
|
link = pagy_link_proc(pagy, link_extra: link_extra)
|
32
30
|
tags = { 'before' => %(<ul class="pagination">#{pagy_foundation_prev_html pagy, link}),
|
@@ -35,52 +33,54 @@ class Pagy
|
|
35
33
|
'gap' => %(<li class="ellipsis gap" aria-hidden="true"></li>),
|
36
34
|
'after' => %(#{pagy_foundation_next_html pagy, link}</ul>) }
|
37
35
|
|
38
|
-
%(<nav#{p_id} class="pagy-njs pagy-foundation-nav-js" aria-label="Pagination" #{
|
36
|
+
%(<nav#{p_id} class="pagy-njs pagy-foundation-nav-js" aria-label="Pagination" #{
|
37
|
+
pagy_json_attr(pagy, :nav, tags, pagy.sequels(steps))}></nav>)
|
39
38
|
end
|
40
39
|
|
41
40
|
# Javascript combo pagination for Foundation: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
|
42
|
-
def pagy_foundation_combo_nav_js(pagy,
|
43
|
-
pagy_id = Pagy.deprecated_arg(:id, deprecated_id, :pagy_id, pagy_id) if deprecated_id
|
41
|
+
def pagy_foundation_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
|
44
42
|
p_id = %( id="#{pagy_id}") if pagy_id
|
45
43
|
link = pagy_link_proc(pagy, link_extra: link_extra)
|
46
44
|
p_page = pagy.page
|
47
45
|
p_pages = pagy.pages
|
48
|
-
input = %(<input class="input-group-field cell shrink" type="number" min="1" max="#{
|
46
|
+
input = %(<input class="input-group-field cell shrink" type="number" min="1" max="#{
|
47
|
+
p_pages}" value="#{p_page}" style="width: #{
|
48
|
+
p_pages.to_s.length + 1}rem; padding: 0 0.3rem; margin: 0 0.3rem;">)
|
49
49
|
|
50
50
|
%(<nav#{p_id} class="pagy-foundation-combo-nav-js" aria-label="Pagination"><div class="input-group" #{
|
51
|
-
pagy_json_attr pagy, :combo_nav, p_page, pagy_marked_link(link)
|
52
|
-
}>#{
|
51
|
+
pagy_json_attr pagy, :combo_nav, p_page, pagy_marked_link(link)}>#{
|
53
52
|
if (p_prev = pagy.prev)
|
54
|
-
link.call p_prev, pagy_t('pagy.nav.prev'),
|
53
|
+
link.call p_prev, pagy_t('pagy.nav.prev'),
|
54
|
+
'style="margin-bottom: 0" aria-label="previous" class="prev button primary"'
|
55
55
|
else
|
56
56
|
%(<a style="margin-bottom: 0" class="prev button primary disabled" href="#">#{pagy_t 'pagy.nav.prev'}</a>)
|
57
57
|
end
|
58
|
-
|
58
|
+
}<span class="input-group-label">#{pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</span>#{
|
59
59
|
if (p_next = pagy.next)
|
60
60
|
link.call p_next, pagy_t('pagy.nav.next'), 'style="margin-bottom: 0" aria-label="next" class="next button primary"'
|
61
61
|
else
|
62
62
|
%(<a style="margin-bottom: 0" class="next button primary disabled" href="#">#{pagy_t 'pagy.nav.next'}</a>)
|
63
63
|
end
|
64
|
-
|
64
|
+
}</div></nav>)
|
65
65
|
end
|
66
66
|
|
67
67
|
private
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
69
|
+
def pagy_foundation_prev_html(pagy, link)
|
70
|
+
if (p_prev = pagy.prev)
|
71
|
+
%(<li class="prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>)
|
72
|
+
else
|
73
|
+
%(<li class="prev disabled">#{pagy_t 'pagy.nav.prev'}</li>)
|
75
74
|
end
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
77
|
+
def pagy_foundation_next_html(pagy, link)
|
78
|
+
if (p_next = pagy.next)
|
79
|
+
%(<li class="next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li>)
|
80
|
+
else
|
81
|
+
%(<li class="next disabled">#{pagy_t 'pagy.nav.next'}</li>)
|
83
82
|
end
|
84
|
-
|
83
|
+
end
|
85
84
|
end
|
85
|
+
Frontend.prepend FoundationExtra
|
86
86
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/gearbox
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
class Pagy
|
5
|
+
DEFAULT[:gearbox_extra] = true # extra enabled by default
|
6
|
+
DEFAULT[:gearbox_items] = [15, 30, 60, 100]
|
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
|
10
|
+
module GearboxExtra
|
11
|
+
# Setup @items based on the :items variable
|
12
|
+
def setup_items_var
|
13
|
+
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
|
14
|
+
|
15
|
+
gearbox_items = @vars[:gearbox_items]
|
16
|
+
raise VariableError.new(self), "expected :gearbox_items to be an Array of positives; got #{gearbox_items.inspect}" \
|
17
|
+
unless gearbox_items.is_a?(Array) && gearbox_items.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
|
18
|
+
|
19
|
+
@items = gearbox_items[@page - 1] || gearbox_items.last
|
20
|
+
end
|
21
|
+
|
22
|
+
# Setup @pages and @last based on the :items variable
|
23
|
+
def setup_pages_var
|
24
|
+
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
|
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
|
+
reminder = @count
|
33
|
+
while reminder.positive?
|
34
|
+
pages += 1
|
35
|
+
reminder -= gearbox_items[pages - 1]
|
36
|
+
end
|
37
|
+
[pages, 1].max
|
38
|
+
end)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
prepend GearboxExtra
|
42
|
+
end
|
data/lib/pagy/extras/headers.rb
CHANGED
@@ -1,35 +1,43 @@
|
|
1
1
|
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/headers
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require 'pagy/url_helpers'
|
5
|
+
|
4
6
|
class Pagy
|
7
|
+
DEFAULT[:headers] = { page: 'Current-Page',
|
8
|
+
items: 'Page-Items',
|
9
|
+
count: 'Total-Count',
|
10
|
+
pages: 'Total-Pages' }
|
5
11
|
# Add specialized backend methods to add pagination response headers
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
VARS[:headers] = { page: 'Current-Page', items: 'Page-Items', count: 'Total-Count', pages: 'Total-Pages' }
|
12
|
+
module HeadersExtra
|
13
|
+
include UrlHelpers
|
10
14
|
|
11
|
-
|
15
|
+
private
|
12
16
|
|
17
|
+
# Merge the pagy headers into the response.headers
|
13
18
|
def pagy_headers_merge(pagy)
|
14
19
|
response.headers.merge!(pagy_headers(pagy))
|
15
20
|
end
|
16
21
|
|
22
|
+
# Generate a hash of RFC-8288 compliant http headers
|
17
23
|
def pagy_headers(pagy)
|
18
24
|
pagy_headers_hash(pagy).tap do |hash|
|
19
|
-
hash['Link'] = hash['Link'].map{|rel, link| %(<#{link}>; rel="#{rel}")}.join(', ')
|
25
|
+
hash['Link'] = hash['Link'].map { |rel, link| %(<#{link}>; rel="#{rel}") }.join(', ')
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
29
|
+
# Generates a hash structure of the headers
|
23
30
|
def pagy_headers_hash(pagy)
|
24
|
-
countless
|
25
|
-
|
26
|
-
|
27
|
-
url_str
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
countless = defined?(Pagy::Countless) && pagy.is_a?(Pagy::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_PLACEHOLDER, absolute: true)
|
35
|
+
link = rel.map do |r, num| # filter_map if ruby >=2.7
|
36
|
+
next unless num # rubocop:disable Layout/EmptyLineAfterGuardClause
|
37
|
+
[r, url_str.sub(PAGE_PLACEHOLDER, num.to_s)]
|
38
|
+
end.compact.to_h
|
39
|
+
hash = { 'Link' => link }
|
40
|
+
headers = pagy.vars[:headers]
|
33
41
|
hash[headers[:page]] = pagy.page.to_s if headers[:page]
|
34
42
|
hash[headers[:items]] = pagy.vars[:items].to_s if headers[:items]
|
35
43
|
unless countless
|
@@ -38,6 +46,6 @@ class Pagy
|
|
38
46
|
end
|
39
47
|
hash
|
40
48
|
end
|
41
|
-
|
42
49
|
end
|
50
|
+
Backend.prepend HeadersExtra
|
43
51
|
end
|
data/lib/pagy/extras/i18n.rb
CHANGED
@@ -3,22 +3,13 @@
|
|
3
3
|
|
4
4
|
class Pagy
|
5
5
|
# Use ::I18n gem
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# unload the pagy default constant for efficiency
|
11
|
-
Pagy::I18n.clear.instance_eval do
|
12
|
-
undef :load
|
13
|
-
undef :t
|
14
|
-
end
|
15
|
-
|
16
|
-
module UseI18nGem
|
17
|
-
def pagy_t(key, **opts)
|
18
|
-
::I18n.t(key, **opts)
|
19
|
-
end
|
6
|
+
module I18nExtra
|
7
|
+
def pagy_t(key, **opts)
|
8
|
+
::I18n.t(key, **opts)
|
20
9
|
end
|
21
|
-
prepend UseI18nGem
|
22
|
-
|
23
10
|
end
|
11
|
+
Frontend.prepend I18nExtra
|
12
|
+
|
13
|
+
# Add the pagy locales to the I18n.load_path
|
14
|
+
::I18n.load_path += Dir[Pagy.root.join('locales', '*.yml')]
|
24
15
|
end
|
data/lib/pagy/extras/items.rb
CHANGED
@@ -3,50 +3,49 @@
|
|
3
3
|
|
4
4
|
require 'pagy/extras/shared'
|
5
5
|
|
6
|
-
class Pagy
|
6
|
+
class Pagy # Default variables for this extra
|
7
|
+
DEFAULT[:items_param] = :items
|
8
|
+
DEFAULT[:max_items] = 100
|
9
|
+
DEFAULT[:items_extra] = true # extra enabled by default
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
VARS[:enable_items_extra] = true
|
13
|
-
|
14
|
-
ITEMS_PLACEHOLDER = '__pagy_items__'
|
15
|
-
|
16
|
-
module UseItemsExtra; end
|
17
|
-
|
18
|
-
module Backend
|
19
|
-
private
|
11
|
+
module ItemsExtra
|
12
|
+
module Backend
|
13
|
+
private
|
20
14
|
|
15
|
+
# Set the items variable considering the params and other pagy variables
|
21
16
|
def pagy_set_items_from_params(vars)
|
22
17
|
return if vars[:items]
|
23
|
-
return unless vars.key?(:
|
24
|
-
return unless (items = params[vars[:items_param] ||
|
25
|
-
vars[:items] = [items.to_i, vars.key?(:max_items) ? vars[:max_items] : VARS[:max_items]].compact.min # :items capped to :max_items
|
26
|
-
end
|
18
|
+
return unless vars.key?(:items_extra) ? vars[:items_extra] : DEFAULT[:items_extra]
|
19
|
+
return unless (items = params[vars[:items_param] || DEFAULT[:items_param]])
|
27
20
|
|
28
|
-
|
29
|
-
|
30
|
-
module Frontend
|
31
|
-
|
32
|
-
# Return the items selector HTML. For example "Show [20] items per page"
|
33
|
-
def pagy_items_selector_js(pagy, deprecated_id=nil, pagy_id: nil, item_name: nil, i18n_key: nil, link_extra: '')
|
34
|
-
return '' unless pagy.vars[:enable_items_extra]
|
35
|
-
pagy_id = Pagy.deprecated_arg(:id, deprecated_id, :pagy_id, pagy_id) if deprecated_id
|
36
|
-
p_id = %( id="#{pagy_id}") if pagy_id
|
37
|
-
p_vars = pagy.vars
|
38
|
-
p_items = p_vars[:items]
|
39
|
-
p_vars[:items] = ITEMS_PLACEHOLDER
|
40
|
-
link = pagy_marked_link(pagy_link_proc(pagy, link_extra: link_extra))
|
41
|
-
p_vars[:items] = p_items # restore the items
|
42
|
-
|
43
|
-
html = +%(<span#{p_id} class="pagy-items-selector-js" #{pagy_json_attr pagy, :items_selector, pagy.from, link}>)
|
44
|
-
input = %(<input type="number" min="1" max="#{p_vars[:max_items]}" value="#{p_items}" style="padding: 0; text-align: center; width: #{p_items.to_s.length+1}rem;">)
|
45
|
-
html << pagy_t('pagy.items_selector_js', item_name: item_name || pagy_t(i18n_key || p_vars[:i18n_key], count: p_items),
|
46
|
-
items_input: input,
|
47
|
-
count: p_items)
|
48
|
-
html << %(</span>)
|
21
|
+
vars[:items] = [items.to_i, vars.key?(:max_items) ? vars[:max_items] : DEFAULT[:max_items]].compact.min
|
22
|
+
end
|
49
23
|
end
|
50
24
|
|
25
|
+
module Frontend
|
26
|
+
ITEMS_PLACEHOLDER = '__pagy_items__'
|
27
|
+
|
28
|
+
# Return the items selector HTML. For example "Show [20] items per page"
|
29
|
+
def pagy_items_selector_js(pagy, pagy_id: nil, item_name: nil, i18n_key: nil, link_extra: '')
|
30
|
+
return '' unless pagy.vars[:items_extra]
|
31
|
+
|
32
|
+
p_id = %( id="#{pagy_id}") if pagy_id
|
33
|
+
p_vars = pagy.vars
|
34
|
+
p_items = p_vars[:items]
|
35
|
+
p_vars[:items] = ITEMS_PLACEHOLDER
|
36
|
+
link = pagy_marked_link(pagy_link_proc(pagy, link_extra: link_extra))
|
37
|
+
p_vars[:items] = p_items # restore the items
|
38
|
+
|
39
|
+
html = +%(<span#{p_id} class="pagy-items-selector-js" #{pagy_json_attr pagy, :items_selector, pagy.from, link}>)
|
40
|
+
input = %(<input type="number" min="1" max="#{p_vars[:max_items]}" value="#{
|
41
|
+
p_items}" style="padding: 0; text-align: center; width: #{p_items.to_s.length + 1}rem;">)
|
42
|
+
html << pagy_t('pagy.items_selector_js', item_name: item_name || pagy_t(i18n_key || p_vars[:i18n_key], count: p_items),
|
43
|
+
items_input: input,
|
44
|
+
count: p_items)
|
45
|
+
html << %(</span>)
|
46
|
+
end
|
47
|
+
end
|
51
48
|
end
|
49
|
+
Backend.prepend ItemsExtra::Backend
|
50
|
+
Frontend.prepend ItemsExtra::Frontend
|
52
51
|
end
|