pagy 5.7.5 → 8.6.2
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.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/apps/calendar.ru +745 -0
- data/apps/demo.ru +435 -0
- data/apps/rails.ru +213 -0
- data/apps/repro.ru +177 -0
- data/apps/tmp/calendar.sqlite3 +0 -0
- data/apps/tmp/calendar.sqlite3-shm +0 -0
- data/apps/tmp/calendar.sqlite3-wal +0 -0
- data/apps/tmp/local_secret.txt +1 -0
- data/bin/pagy +100 -0
- data/{lib/config → config}/pagy.rb +72 -96
- data/javascripts/pagy-module.js +100 -0
- data/javascripts/pagy.d.ts +5 -0
- data/javascripts/pagy.js +4 -0
- data/javascripts/pagy.min.js +4 -0
- data/javascripts/pagy.min.js.map +10 -0
- data/javascripts/pagy.mjs +100 -0
- data/lib/optimist.rb +1022 -0
- data/lib/pagy/backend.rb +16 -4
- data/lib/pagy/calendar/day.rb +22 -10
- data/lib/pagy/calendar/month.rb +35 -9
- data/lib/pagy/calendar/quarter.rb +36 -10
- data/lib/pagy/calendar/unit.rb +106 -0
- data/lib/pagy/calendar/week.rb +16 -16
- data/lib/pagy/calendar/year.rb +15 -9
- data/lib/pagy/calendar.rb +60 -68
- data/lib/pagy/console.rb +3 -3
- data/lib/pagy/countless.rb +17 -12
- data/lib/pagy/exceptions.rb +1 -1
- data/lib/pagy/extras/arel.rb +2 -2
- data/lib/pagy/extras/array.rb +2 -2
- data/lib/pagy/extras/bootstrap.rb +57 -53
- data/lib/pagy/extras/bulma.rb +53 -57
- data/lib/pagy/extras/calendar.rb +54 -37
- data/lib/pagy/extras/countless.rb +3 -3
- data/lib/pagy/extras/elasticsearch_rails.rb +12 -11
- data/lib/pagy/extras/foundation.rb +59 -54
- data/lib/pagy/extras/gearbox.rb +32 -19
- data/lib/pagy/extras/headers.rb +11 -11
- data/lib/pagy/extras/i18n.rb +5 -5
- data/lib/pagy/extras/items.rb +34 -24
- data/lib/pagy/extras/{frontend_helpers.rb → js_tools.rb} +24 -24
- data/lib/pagy/extras/jsonapi.rb +79 -0
- data/lib/pagy/extras/materialize.rb +63 -47
- data/lib/pagy/extras/meilisearch.rb +26 -22
- data/lib/pagy/extras/metadata.rb +13 -9
- data/lib/pagy/extras/overflow.rb +13 -10
- data/lib/pagy/extras/pagy.rb +82 -0
- data/lib/pagy/extras/searchkick.rb +12 -11
- data/lib/pagy/extras/semantic.rb +57 -45
- data/lib/pagy/extras/size.rb +40 -0
- data/lib/pagy/extras/standalone.rb +12 -16
- data/lib/pagy/extras/trim.rb +13 -13
- data/lib/pagy/extras/uikit.rb +60 -46
- data/lib/pagy/frontend.rb +62 -45
- data/lib/pagy/i18n.rb +4 -3
- data/lib/pagy/url_helpers.rb +13 -25
- data/lib/pagy.rb +61 -59
- data/locales/ar.yml +28 -0
- data/locales/be.yml +25 -0
- data/locales/bg.yml +21 -0
- data/locales/bs.yml +25 -0
- data/locales/ca.yml +21 -0
- data/locales/ckb.yml +18 -0
- data/locales/cs.yml +23 -0
- data/locales/da.yml +21 -0
- data/locales/de.yml +21 -0
- data/locales/en.yml +21 -0
- data/locales/es.yml +21 -0
- data/locales/fr.yml +21 -0
- data/locales/hr.yml +25 -0
- data/locales/id.yml +19 -0
- data/locales/it.yml +21 -0
- data/locales/ja.yml +19 -0
- data/locales/km.yml +19 -0
- data/locales/ko.yml +17 -0
- data/locales/nb.yml +21 -0
- data/locales/nl.yml +21 -0
- data/locales/nn.yml +21 -0
- data/locales/pl.yml +25 -0
- data/locales/pt-BR.yml +21 -0
- data/locales/pt.yml +21 -0
- data/locales/ru.yml +25 -0
- data/locales/sr.yml +25 -0
- data/locales/sv-SE.yml +21 -0
- data/locales/sv.yml +21 -0
- data/locales/sw.yml +23 -0
- data/locales/ta.yml +23 -0
- data/locales/tr.yml +19 -0
- data/locales/uk.yml +25 -0
- data/locales/vi.yml +17 -0
- data/locales/zh-CN.yml +19 -0
- data/locales/zh-HK.yml +19 -0
- data/locales/zh-TW.yml +19 -0
- data/stylesheets/pagy.css +46 -0
- data/stylesheets/pagy.scss +48 -0
- data/stylesheets/pagy.tailwind.css +21 -0
- metadata +79 -66
- data/lib/javascripts/pagy-dev.js +0 -118
- data/lib/javascripts/pagy-module.d.ts +0 -30
- data/lib/javascripts/pagy-module.js +0 -117
- data/lib/javascripts/pagy.js +0 -1
- data/lib/locales/ar.yml +0 -26
- data/lib/locales/bg.yml +0 -22
- data/lib/locales/bs.yml +0 -24
- data/lib/locales/ca.yml +0 -22
- data/lib/locales/cs.yml +0 -22
- data/lib/locales/da.yml +0 -22
- data/lib/locales/de.yml +0 -22
- data/lib/locales/en.yml +0 -22
- data/lib/locales/es.yml +0 -22
- data/lib/locales/fr.yml +0 -22
- data/lib/locales/hr.yml +0 -24
- data/lib/locales/id.yml +0 -20
- data/lib/locales/it.yml +0 -22
- data/lib/locales/ja.yml +0 -20
- data/lib/locales/km.yml +0 -19
- data/lib/locales/ko.yml +0 -20
- data/lib/locales/nb.yml +0 -22
- data/lib/locales/nl.yml +0 -22
- data/lib/locales/pl.yml +0 -24
- data/lib/locales/pt-BR.yml +0 -22
- data/lib/locales/pt.yml +0 -22
- data/lib/locales/ru.yml +0 -24
- data/lib/locales/sr.yml +0 -23
- data/lib/locales/sv-SE.yml +0 -23
- data/lib/locales/sv.yml +0 -23
- data/lib/locales/sw.yml +0 -22
- data/lib/locales/ta.yml +0 -22
- data/lib/locales/tr.yml +0 -20
- data/lib/locales/uk.yml +0 -24
- data/lib/locales/zh-CN.yml +0 -20
- data/lib/locales/zh-HK.yml +0 -20
- data/lib/locales/zh-TW.yml +0 -20
- data/lib/pagy/calendar/month_mixin.rb +0 -49
- data/lib/pagy/extras/navs.rb +0 -63
- data/lib/pagy/extras/support.rb +0 -54
- data/lib/templates/bootstrap_nav.html.erb +0 -24
- data/lib/templates/bootstrap_nav.html.haml +0 -34
- data/lib/templates/bootstrap_nav.html.slim +0 -34
- data/lib/templates/bulma_nav.html.erb +0 -24
- data/lib/templates/bulma_nav.html.haml +0 -32
- data/lib/templates/bulma_nav.html.slim +0 -32
- data/lib/templates/foundation_nav.html.erb +0 -24
- data/lib/templates/foundation_nav.html.haml +0 -34
- data/lib/templates/foundation_nav.html.slim +0 -34
- data/lib/templates/nav.html.erb +0 -22
- data/lib/templates/nav.html.haml +0 -30
- data/lib/templates/nav.html.slim +0 -29
- data/lib/templates/uikit_nav.html.erb +0 -15
- data/lib/templates/uikit_nav.html.haml +0 -28
- data/lib/templates/uikit_nav.html.slim +0 -28
@@ -1,88 +1,93 @@
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/foundation
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
warn '[PAGY WARNING] The foundation extra has been discontinued and it will be removed in v9 ' \
|
4
|
+
'(https://github.com/ddnexus/pagy/discussions/672#discussioncomment-9212328)'
|
5
|
+
|
6
|
+
require_relative 'js_tools'
|
5
7
|
|
6
8
|
class Pagy # :nodoc:
|
7
9
|
# Frontend modules are specially optimized for performance.
|
8
10
|
# The resulting code may not look very elegant, but produces the best benchmarks
|
9
11
|
module FoundationExtra
|
10
12
|
# Pagination for Foundation: it returns the html with the series of links to the pages
|
11
|
-
def pagy_foundation_nav(pagy,
|
12
|
-
|
13
|
-
|
13
|
+
def pagy_foundation_nav(pagy, id: nil, aria_label: nil, **vars)
|
14
|
+
id = %( id="#{id}") if id
|
15
|
+
a = pagy_anchor(pagy)
|
14
16
|
|
15
|
-
html = +%(<nav#{
|
16
|
-
|
17
|
+
html = +%(<nav#{id} class="pagy-foundation-nav" #{
|
18
|
+
nav_aria_label(pagy, aria_label:)}><ul class="pagination"> #{
|
19
|
+
foundation_prev_html(pagy, a)})
|
17
20
|
pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
|
18
21
|
html << case item
|
19
|
-
when Integer
|
20
|
-
|
21
|
-
when
|
22
|
-
|
22
|
+
when Integer
|
23
|
+
%(<li>#{a.(item)}</li>)
|
24
|
+
when String
|
25
|
+
%(<li class="current" role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</li>)
|
26
|
+
when :gap
|
27
|
+
%(<li class="ellipsis gap"></li>)
|
28
|
+
else
|
29
|
+
raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
|
23
30
|
end
|
24
31
|
end
|
25
|
-
html <<
|
26
|
-
html << %(</ul></nav>)
|
32
|
+
html << %(#{foundation_next_html(pagy, a)}</ul></nav>)
|
27
33
|
end
|
28
34
|
|
29
|
-
# Javascript pagination for foundation: it returns a nav
|
30
|
-
def pagy_foundation_nav_js(pagy,
|
35
|
+
# Javascript pagination for foundation: it returns a nav with a data-pagy attribute used by the pagy.js file
|
36
|
+
def pagy_foundation_nav_js(pagy, id: nil, aria_label: nil, **vars)
|
31
37
|
sequels = pagy.sequels(**vars)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
id = %( id="#{id}") if id
|
39
|
+
a = pagy_anchor(pagy)
|
40
|
+
tokens = { 'before' => %(<ul class="pagination">#{foundation_prev_html pagy, a}),
|
41
|
+
'a' => %(<li>#{a.(PAGE_TOKEN, LABEL_TOKEN)}</li>),
|
42
|
+
'current' => %(<li class="current" role="link" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</li>),
|
43
|
+
'gap' => %(<li class="ellipsis gap"></li>),
|
44
|
+
'after' => %(#{foundation_next_html pagy, a}</ul>) }
|
39
45
|
|
40
|
-
%(<nav#{
|
41
|
-
|
46
|
+
%(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-foundation-nav-js" #{
|
47
|
+
nav_aria_label(pagy, aria_label:)} #{
|
48
|
+
pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
|
49
|
+
}></nav>)
|
42
50
|
end
|
43
51
|
|
44
|
-
# Javascript combo pagination for Foundation: it returns a nav
|
45
|
-
def pagy_foundation_combo_nav_js(pagy,
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
52
|
+
# Javascript combo pagination for Foundation: it returns a nav with a data-pagy attribute used by the pagy.js file
|
53
|
+
def pagy_foundation_combo_nav_js(pagy, id: nil, aria_label: nil)
|
54
|
+
id = %( id="#{id}") if id
|
55
|
+
a = pagy_anchor(pagy)
|
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; ) <<
|
60
|
+
%(height: 1.5rem; padding: .5rem; margin: 0 .4rem; font-size: .875rem;" class="current">#{JSTools::A_TAG})
|
53
61
|
|
54
|
-
%(<nav#{
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
link.call p_next, pagy_t('pagy.nav.next'), 'style="margin-bottom: 0" aria-label="next" class="next button primary"'
|
65
|
-
else
|
66
|
-
%(<a style="margin-bottom: 0" class="next button primary disabled" href="#">#{pagy_t 'pagy.nav.next'}</a>)
|
67
|
-
end
|
68
|
-
}</div></nav>)
|
62
|
+
%(<nav#{id} class="pagy-foundation-combo-nav-js" #{
|
63
|
+
nav_aria_label(pagy, aria_label:)} #{
|
64
|
+
pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
|
65
|
+
}><ul class="pagination">#{
|
66
|
+
foundation_prev_html(pagy, a)
|
67
|
+
}<li style="padding: 0 .3rem"><label style="display: flex; align-items: center; white-space: nowrap">#{
|
68
|
+
pagy_t('pagy.combo_nav_js', page_input:, pages:)
|
69
|
+
}</label></li>#{
|
70
|
+
foundation_next_html(pagy, a)
|
71
|
+
}</ul></nav>)
|
69
72
|
end
|
70
73
|
|
71
74
|
private
|
72
75
|
|
73
|
-
def
|
76
|
+
def foundation_prev_html(pagy, a)
|
74
77
|
if (p_prev = pagy.prev)
|
75
|
-
%(<li class="prev">#{
|
78
|
+
%(<li class="prev">#{a.(p_prev, pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'))}</li>)
|
76
79
|
else
|
77
|
-
%(<li class="prev disabled"
|
80
|
+
%(<li class="prev disabled" role="link" aria-disabled="true" aria-label="#{
|
81
|
+
pagy_t('pagy.aria_label.prev')}">#{pagy_t('pagy.prev')}</li>)
|
78
82
|
end
|
79
83
|
end
|
80
84
|
|
81
|
-
def
|
85
|
+
def foundation_next_html(pagy, a)
|
82
86
|
if (p_next = pagy.next)
|
83
|
-
%(<li class="next">#{
|
87
|
+
%(<li class="next">#{a.(p_next, pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.next'))}</li>)
|
84
88
|
else
|
85
|
-
%(<li class="next disabled"
|
89
|
+
%(<li class="next disabled" role="link" aria-disabled="true" aria-label="#{
|
90
|
+
pagy_t('pagy.aria_label.next')}">#{pagy_t('pagy.next')}</li>)
|
86
91
|
end
|
87
92
|
end
|
88
93
|
end
|
data/lib/pagy/extras/gearbox.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/gearbox
|
1
|
+
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/gearbox
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
class Pagy # :nodoc:
|
@@ -12,30 +12,43 @@ class Pagy # :nodoc:
|
|
12
12
|
def setup_items_var
|
13
13
|
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
|
14
14
|
|
15
|
-
|
16
|
-
raise VariableError.new(self, :gearbox_items, 'to be an Array of positives',
|
17
|
-
unless
|
15
|
+
gears = @vars[:gearbox_items]
|
16
|
+
raise VariableError.new(self, :gearbox_items, '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 =
|
19
|
+
@items = gears[@page - 1] || gears.last
|
20
20
|
end
|
21
21
|
|
22
|
-
# Setup @
|
23
|
-
def
|
22
|
+
# Setup @offset based on the :gearbox_items variable
|
23
|
+
def setup_offset_var
|
24
24
|
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
|
25
25
|
|
26
|
-
|
26
|
+
gears = @vars[:gearbox_items]
|
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
|
32
|
+
end
|
33
|
+
|
34
|
+
# Setup Pagy @last based on the :gearbox_items variable and @count
|
35
|
+
def setup_last_var
|
36
|
+
return super if !@vars[:gearbox_extra] || @vars[:items_extra]
|
37
|
+
|
38
|
+
gears = @vars[:gearbox_items]
|
27
39
|
# This algorithm is thousands of times faster than the one in the geared_pagination gem
|
28
|
-
@
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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]
|
39
52
|
end
|
40
53
|
end
|
41
54
|
prepend GearboxExtra
|
data/lib/pagy/extras/headers.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/headers
|
1
|
+
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/headers
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
require_relative '../url_helpers'
|
5
5
|
|
6
6
|
class Pagy # :nodoc:
|
7
|
-
DEFAULT[:headers] = { page: '
|
8
|
-
items: '
|
9
|
-
count: '
|
10
|
-
pages: '
|
7
|
+
DEFAULT[:headers] = { page: 'current-page',
|
8
|
+
items: 'page-items',
|
9
|
+
count: 'total-count',
|
10
|
+
pages: 'total-pages' }
|
11
11
|
# Add specialized backend methods to add pagination response headers
|
12
12
|
module HeadersExtra
|
13
13
|
include UrlHelpers
|
@@ -22,7 +22,7 @@ class Pagy # :nodoc:
|
|
22
22
|
# Generate a hash of RFC-8288 compliant http headers
|
23
23
|
def pagy_headers(pagy)
|
24
24
|
pagy_headers_hash(pagy).tap do |hash|
|
25
|
-
hash['
|
25
|
+
hash['link'] = hash['link'].map { |rel, link| %(<#{link}>; rel="#{rel}") }.join(', ')
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -31,12 +31,12 @@ class Pagy # :nodoc:
|
|
31
31
|
countless = defined?(Countless) && pagy.is_a?(Countless)
|
32
32
|
rel = { 'first' => 1, 'prev' => pagy.prev, 'next' => pagy.next }
|
33
33
|
rel['last'] = pagy.last unless countless
|
34
|
-
url_str = pagy_url_for(pagy,
|
35
|
-
link = rel.
|
34
|
+
url_str = pagy_url_for(pagy, PAGE_TOKEN, absolute: true)
|
35
|
+
link = rel.filter_map do |r, num|
|
36
36
|
next unless num # rubocop:disable Layout/EmptyLineAfterGuardClause
|
37
|
-
[r, url_str.sub(
|
37
|
+
[r, url_str.sub(PAGE_TOKEN, num.to_s)]
|
38
38
|
end.compact.to_h
|
39
|
-
hash = { '
|
39
|
+
hash = { 'link' => link }
|
40
40
|
headers = pagy.vars[:headers]
|
41
41
|
hash[headers[:page]] = pagy.page.to_s if headers[:page]
|
42
42
|
if headers[:items] && !(defined?(Calendar) && pagy.is_a?(Calendar)) # items is not for Calendar
|
data/lib/pagy/extras/i18n.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/i18n
|
1
|
+
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/i18n
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
class Pagy # :nodoc:
|
5
5
|
# Use ::I18n gem
|
6
6
|
module I18nExtra
|
7
7
|
# Frontend overriding for translation
|
8
|
-
module
|
8
|
+
module FrontendOverride
|
9
9
|
def pagy_t(key, **opts)
|
10
10
|
::I18n.t(key, **opts)
|
11
11
|
end
|
12
12
|
end
|
13
|
+
Frontend.prepend I18nExtra::FrontendOverride
|
13
14
|
|
14
15
|
# Calendar overriding for localization (see also the block in the calendar section of the config/pagy.rb initializer)
|
15
|
-
module
|
16
|
+
module CalendarOverride
|
16
17
|
def localize(time, opts)
|
17
18
|
::I18n.l(time, **opts)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
21
|
-
|
22
|
-
Calendar.prepend I18nExtra::Calendar 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')]
|
data/lib/pagy/extras/items.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/items
|
1
|
+
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/items
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
require_relative 'js_tools'
|
5
5
|
|
6
6
|
class Pagy # :nodoc:
|
7
7
|
DEFAULT[:items_param] = :items
|
@@ -11,44 +11,54 @@ class Pagy # :nodoc:
|
|
11
11
|
# Allow the client to request a custom number of items per page with an optional selector UI
|
12
12
|
module ItemsExtra
|
13
13
|
# Additions for the Backend module
|
14
|
-
module
|
14
|
+
module BackendAddOn
|
15
15
|
private
|
16
16
|
|
17
17
|
# Set the items variable considering the params and other pagy variables
|
18
18
|
def pagy_set_items_from_params(vars)
|
19
19
|
return if vars[:items] # :items explicitly set
|
20
20
|
return unless vars.key?(:items_extra) ? vars[:items_extra] : DEFAULT[:items_extra] # :items_extra is false
|
21
|
-
return unless (
|
21
|
+
return unless (items_count = pagy_get_items_size(vars)) # no items from request params
|
22
22
|
|
23
|
-
vars[:items] = [
|
23
|
+
vars[:items] = [items_count.to_i, vars.key?(:max_items) ? vars[:max_items] : DEFAULT[:max_items]].compact.min
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the items count from the params
|
27
|
+
# Overridable by the jsonapi extra
|
28
|
+
def pagy_get_items_size(vars)
|
29
|
+
params[vars[:items_param] || DEFAULT[:items_param]]
|
24
30
|
end
|
25
31
|
end
|
32
|
+
Backend.prepend ItemsExtra::BackendAddOn
|
26
33
|
|
27
34
|
# Additions for the Frontend module
|
28
|
-
module
|
29
|
-
|
35
|
+
module FrontendAddOn
|
36
|
+
ITEMS_TOKEN = '__pagy_items__'
|
30
37
|
|
31
38
|
# Return the items selector HTML. For example "Show [20] items per page"
|
32
|
-
def pagy_items_selector_js(pagy,
|
39
|
+
def pagy_items_selector_js(pagy, id: nil, item_name: nil)
|
33
40
|
return '' unless pagy.vars[:items_extra]
|
34
41
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
id = %( id="#{id}") if id
|
43
|
+
vars = pagy.vars
|
44
|
+
items = vars[:items]
|
45
|
+
vars[:items] = ITEMS_TOKEN
|
46
|
+
url_token = pagy_url_for(pagy, PAGE_TOKEN)
|
47
|
+
vars[:items] = items # restore the items
|
48
|
+
|
49
|
+
items_input = %(<input name="items" type="number" min="1" max="#{vars[:max_items]}" value="#{
|
50
|
+
items}" style="padding: 0; text-align: center; width: #{items.to_s.length + 1}rem;">#{JSTools::A_TAG})
|
51
|
+
|
52
|
+
%(<span#{id} class="pagy items-selector-js" #{
|
53
|
+
pagy_data(pagy, :selector, pagy.from, url_token)
|
54
|
+
}><label>#{
|
55
|
+
pagy_t('pagy.items_selector_js',
|
56
|
+
item_name: item_name || pagy_t('pagy.item_name', count: items),
|
57
|
+
items_input:,
|
58
|
+
count: items)
|
59
|
+
}</label></span>)
|
49
60
|
end
|
50
61
|
end
|
62
|
+
Frontend.prepend ItemsExtra::FrontendAddOn
|
51
63
|
end
|
52
|
-
Backend.prepend ItemsExtra::Backend
|
53
|
-
Frontend.prepend ItemsExtra::Frontend
|
54
64
|
end
|
@@ -1,22 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'digest'
|
4
|
-
|
5
3
|
class Pagy # :nodoc:
|
6
4
|
DEFAULT[:steps] = false # default false will use {0 => @vars[:size]}
|
7
5
|
|
8
6
|
# Private module documented in the main classes
|
9
|
-
module
|
7
|
+
module JSTools
|
8
|
+
# Dummy tag for input helpers: needed because Turbo does not intercept window.location changes
|
9
|
+
A_TAG = '<a href="#" style="display: none;">#</a>'
|
10
|
+
|
10
11
|
# Additions for the Pagy class
|
11
|
-
module
|
12
|
+
module PagyAddOn
|
12
13
|
# `Pagy` instance method used by the `pagy*_nav_js` helpers.
|
13
14
|
# It returns the sequels of width/series generated from the :steps hash
|
14
15
|
# Example:
|
15
|
-
# >> pagy = Pagy.new(count:1000, page: 20, steps: {0 =>
|
16
|
+
# >> pagy = Pagy.new(count:1000, page: 20, steps: {0 => 5, 350 => 7, 550 => 9})
|
16
17
|
# >> pagy.sequels
|
17
|
-
# #=> { "0" => [
|
18
|
-
# "350" => [1,
|
19
|
-
# "550" => [1
|
18
|
+
# #=> { "0" => [18, 19, "20", 21, 22],
|
19
|
+
# "350" => [1, :gap, 19, "20", 21, :gap, 50],
|
20
|
+
# "550" => [1 :gap, 18, 19, "20", 21, 22, :gap, 50] }
|
20
21
|
# Notice: if :steps is false it will use the single {0 => @vars[:size]} size
|
21
22
|
def sequels(steps: @vars[:steps] || { 0 => @vars[:size] }, **_)
|
22
23
|
raise VariableError.new(self, :steps, 'to define the 0 width', steps) unless steps.key?(0)
|
@@ -29,9 +30,10 @@ class Pagy # :nodoc:
|
|
29
30
|
# Support for the Calendar API
|
30
31
|
def label_sequels(*); end
|
31
32
|
end
|
33
|
+
Pagy.prepend PagyAddOn
|
32
34
|
|
33
35
|
# Additions for Calendar class
|
34
|
-
module
|
36
|
+
module CalendarOverride
|
35
37
|
def label_sequels(sequels = self.sequels)
|
36
38
|
{}.tap do |label_sequels|
|
37
39
|
sequels.each do |width, series|
|
@@ -40,31 +42,29 @@ class Pagy # :nodoc:
|
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
45
|
+
Calendar::Unit.prepend CalendarOverride if defined?(Calendar::Unit)
|
43
46
|
|
44
47
|
# Additions for the Frontend
|
45
|
-
module
|
48
|
+
module FrontendAddOn
|
46
49
|
if defined?(Oj)
|
47
|
-
# Return a
|
48
|
-
|
50
|
+
# Return a data tag with the base64 encoded JSON-serialized args generated with the faster oj gem
|
51
|
+
# Base64 encoded JSON is smaller than HTML escaped JSON
|
52
|
+
def pagy_data(pagy, *args)
|
49
53
|
args << pagy.vars[:page_param] if pagy.vars[:trim_extra]
|
50
|
-
|
54
|
+
strict_base64_encoded = [Oj.dump(args, mode: :strict)].pack('m0')
|
55
|
+
%(data-pagy="#{strict_base64_encoded}")
|
51
56
|
end
|
52
57
|
else
|
53
58
|
require 'json'
|
54
|
-
# Return a
|
55
|
-
|
59
|
+
# Return a data tag with the base64 encoded JSON-serialized args generated with the slower to_json
|
60
|
+
# Base64 encoded JSON is smaller than HTML escaped JSON
|
61
|
+
def pagy_data(pagy, *args)
|
56
62
|
args << pagy.vars[:page_param] if pagy.vars[:trim_extra]
|
57
|
-
|
63
|
+
strict_base64_encoded = [args.to_json].pack('m0')
|
64
|
+
%(data-pagy="#{strict_base64_encoded}")
|
58
65
|
end
|
59
66
|
end
|
60
|
-
|
61
|
-
# Return the marked link to used by pagy.js
|
62
|
-
def pagy_marked_link(link)
|
63
|
-
link.call PAGE_PLACEHOLDER, '', 'style="display: none;"'
|
64
|
-
end
|
65
67
|
end
|
68
|
+
Frontend.prepend FrontendAddOn
|
66
69
|
end
|
67
|
-
prepend FrontendHelpers::Pagy
|
68
|
-
Calendar.prepend FrontendHelpers::Calendar if defined?(Calendar)
|
69
|
-
Frontend.prepend FrontendHelpers::Frontend
|
70
70
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/jsonapi
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../url_helpers'
|
5
|
+
|
6
|
+
class Pagy # :nodoc:
|
7
|
+
DEFAULT[:jsonapi] = true
|
8
|
+
|
9
|
+
# Add a specialized backend method compliant with JSON:API
|
10
|
+
module JsonApiExtra
|
11
|
+
# JsonApi :page param error
|
12
|
+
class ReservedParamError < StandardError
|
13
|
+
# Inform about the actual value
|
14
|
+
def initialize(value)
|
15
|
+
super("expected reserved :page param to be nil or Hash-like; got #{value.inspect}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Module overriding Backend
|
20
|
+
module BackendOverride
|
21
|
+
private
|
22
|
+
|
23
|
+
include UrlHelpers
|
24
|
+
|
25
|
+
# Return the jsonapi links
|
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 }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Should skip the jsonapi
|
34
|
+
def pagy_skip_jsonapi?(vars)
|
35
|
+
return true if vars[:jsonapi] == false || (vars[:jsonapi].nil? && DEFAULT[:jsonapi] == false)
|
36
|
+
# check the reserved :page param
|
37
|
+
raise ReservedParamError, params[:page] unless params[:page].respond_to?(:fetch) || params[:page].nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
# Override the Backend method
|
41
|
+
def pagy_get_page(vars)
|
42
|
+
return super if pagy_skip_jsonapi?(vars)
|
43
|
+
return 1 if params[:page].nil?
|
44
|
+
|
45
|
+
[params[:page][vars[:page_param] || DEFAULT[:page_param]].to_i, 1].max
|
46
|
+
end
|
47
|
+
end
|
48
|
+
Backend.prepend BackendOverride
|
49
|
+
|
50
|
+
# Module overriding ItemsExtra
|
51
|
+
module ItemsExtraOverride
|
52
|
+
private
|
53
|
+
|
54
|
+
# Override the ItemsExtra::Backend method
|
55
|
+
def pagy_get_items_size(vars)
|
56
|
+
return super if pagy_skip_jsonapi?(vars)
|
57
|
+
return if params[:page].nil?
|
58
|
+
|
59
|
+
params[:page][vars[:items_param] || DEFAULT[:items_param]]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
# :nocov:
|
63
|
+
ItemsExtra::BackendAddOn.prepend ItemsExtraOverride if defined?(ItemsExtra::BackendAddOn)
|
64
|
+
# :nocov:
|
65
|
+
|
66
|
+
# Module overriding UrlHelper
|
67
|
+
module UrlHelperOverride
|
68
|
+
# Override UrlHelper method
|
69
|
+
def pagy_set_query_params(page, vars, params)
|
70
|
+
return super unless vars[:jsonapi]
|
71
|
+
|
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]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
UrlHelpers.prepend UrlHelperOverride
|
78
|
+
end
|
79
|
+
end
|