pagy 5.7.5 → 8.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +745 -0
  4. data/apps/demo.ru +435 -0
  5. data/apps/rails.ru +213 -0
  6. data/apps/repro.ru +177 -0
  7. data/apps/tmp/calendar.sqlite3 +0 -0
  8. data/apps/tmp/calendar.sqlite3-shm +0 -0
  9. data/apps/tmp/calendar.sqlite3-wal +0 -0
  10. data/apps/tmp/local_secret.txt +1 -0
  11. data/bin/pagy +100 -0
  12. data/{lib/config → config}/pagy.rb +72 -96
  13. data/javascripts/pagy-module.js +100 -0
  14. data/javascripts/pagy.d.ts +5 -0
  15. data/javascripts/pagy.js +4 -0
  16. data/javascripts/pagy.min.js +4 -0
  17. data/javascripts/pagy.min.js.map +10 -0
  18. data/javascripts/pagy.mjs +100 -0
  19. data/lib/optimist.rb +1022 -0
  20. data/lib/pagy/backend.rb +16 -4
  21. data/lib/pagy/calendar/day.rb +22 -10
  22. data/lib/pagy/calendar/month.rb +35 -9
  23. data/lib/pagy/calendar/quarter.rb +36 -10
  24. data/lib/pagy/calendar/unit.rb +106 -0
  25. data/lib/pagy/calendar/week.rb +16 -16
  26. data/lib/pagy/calendar/year.rb +15 -9
  27. data/lib/pagy/calendar.rb +60 -68
  28. data/lib/pagy/console.rb +3 -3
  29. data/lib/pagy/countless.rb +17 -12
  30. data/lib/pagy/exceptions.rb +1 -1
  31. data/lib/pagy/extras/arel.rb +2 -2
  32. data/lib/pagy/extras/array.rb +2 -2
  33. data/lib/pagy/extras/bootstrap.rb +57 -53
  34. data/lib/pagy/extras/bulma.rb +53 -57
  35. data/lib/pagy/extras/calendar.rb +54 -37
  36. data/lib/pagy/extras/countless.rb +3 -3
  37. data/lib/pagy/extras/elasticsearch_rails.rb +12 -11
  38. data/lib/pagy/extras/foundation.rb +59 -54
  39. data/lib/pagy/extras/gearbox.rb +32 -19
  40. data/lib/pagy/extras/headers.rb +11 -11
  41. data/lib/pagy/extras/i18n.rb +5 -5
  42. data/lib/pagy/extras/items.rb +34 -24
  43. data/lib/pagy/extras/{frontend_helpers.rb → js_tools.rb} +24 -24
  44. data/lib/pagy/extras/jsonapi.rb +79 -0
  45. data/lib/pagy/extras/materialize.rb +63 -47
  46. data/lib/pagy/extras/meilisearch.rb +26 -22
  47. data/lib/pagy/extras/metadata.rb +13 -9
  48. data/lib/pagy/extras/overflow.rb +13 -10
  49. data/lib/pagy/extras/pagy.rb +82 -0
  50. data/lib/pagy/extras/searchkick.rb +12 -11
  51. data/lib/pagy/extras/semantic.rb +57 -45
  52. data/lib/pagy/extras/size.rb +40 -0
  53. data/lib/pagy/extras/standalone.rb +12 -16
  54. data/lib/pagy/extras/trim.rb +13 -13
  55. data/lib/pagy/extras/uikit.rb +60 -46
  56. data/lib/pagy/frontend.rb +62 -45
  57. data/lib/pagy/i18n.rb +4 -3
  58. data/lib/pagy/url_helpers.rb +13 -25
  59. data/lib/pagy.rb +61 -59
  60. data/locales/ar.yml +28 -0
  61. data/locales/be.yml +25 -0
  62. data/locales/bg.yml +21 -0
  63. data/locales/bs.yml +25 -0
  64. data/locales/ca.yml +21 -0
  65. data/locales/ckb.yml +18 -0
  66. data/locales/cs.yml +23 -0
  67. data/locales/da.yml +21 -0
  68. data/locales/de.yml +21 -0
  69. data/locales/en.yml +21 -0
  70. data/locales/es.yml +21 -0
  71. data/locales/fr.yml +21 -0
  72. data/locales/hr.yml +25 -0
  73. data/locales/id.yml +19 -0
  74. data/locales/it.yml +21 -0
  75. data/locales/ja.yml +19 -0
  76. data/locales/km.yml +19 -0
  77. data/locales/ko.yml +17 -0
  78. data/locales/nb.yml +21 -0
  79. data/locales/nl.yml +21 -0
  80. data/locales/nn.yml +21 -0
  81. data/locales/pl.yml +25 -0
  82. data/locales/pt-BR.yml +21 -0
  83. data/locales/pt.yml +21 -0
  84. data/locales/ru.yml +25 -0
  85. data/locales/sr.yml +25 -0
  86. data/locales/sv-SE.yml +21 -0
  87. data/locales/sv.yml +21 -0
  88. data/locales/sw.yml +23 -0
  89. data/locales/ta.yml +23 -0
  90. data/locales/tr.yml +19 -0
  91. data/locales/uk.yml +25 -0
  92. data/locales/vi.yml +17 -0
  93. data/locales/zh-CN.yml +19 -0
  94. data/locales/zh-HK.yml +19 -0
  95. data/locales/zh-TW.yml +19 -0
  96. data/stylesheets/pagy.css +46 -0
  97. data/stylesheets/pagy.scss +48 -0
  98. data/stylesheets/pagy.tailwind.css +21 -0
  99. metadata +79 -66
  100. data/lib/javascripts/pagy-dev.js +0 -118
  101. data/lib/javascripts/pagy-module.d.ts +0 -30
  102. data/lib/javascripts/pagy-module.js +0 -117
  103. data/lib/javascripts/pagy.js +0 -1
  104. data/lib/locales/ar.yml +0 -26
  105. data/lib/locales/bg.yml +0 -22
  106. data/lib/locales/bs.yml +0 -24
  107. data/lib/locales/ca.yml +0 -22
  108. data/lib/locales/cs.yml +0 -22
  109. data/lib/locales/da.yml +0 -22
  110. data/lib/locales/de.yml +0 -22
  111. data/lib/locales/en.yml +0 -22
  112. data/lib/locales/es.yml +0 -22
  113. data/lib/locales/fr.yml +0 -22
  114. data/lib/locales/hr.yml +0 -24
  115. data/lib/locales/id.yml +0 -20
  116. data/lib/locales/it.yml +0 -22
  117. data/lib/locales/ja.yml +0 -20
  118. data/lib/locales/km.yml +0 -19
  119. data/lib/locales/ko.yml +0 -20
  120. data/lib/locales/nb.yml +0 -22
  121. data/lib/locales/nl.yml +0 -22
  122. data/lib/locales/pl.yml +0 -24
  123. data/lib/locales/pt-BR.yml +0 -22
  124. data/lib/locales/pt.yml +0 -22
  125. data/lib/locales/ru.yml +0 -24
  126. data/lib/locales/sr.yml +0 -23
  127. data/lib/locales/sv-SE.yml +0 -23
  128. data/lib/locales/sv.yml +0 -23
  129. data/lib/locales/sw.yml +0 -22
  130. data/lib/locales/ta.yml +0 -22
  131. data/lib/locales/tr.yml +0 -20
  132. data/lib/locales/uk.yml +0 -24
  133. data/lib/locales/zh-CN.yml +0 -20
  134. data/lib/locales/zh-HK.yml +0 -20
  135. data/lib/locales/zh-TW.yml +0 -20
  136. data/lib/pagy/calendar/month_mixin.rb +0 -49
  137. data/lib/pagy/extras/navs.rb +0 -63
  138. data/lib/pagy/extras/support.rb +0 -54
  139. data/lib/templates/bootstrap_nav.html.erb +0 -24
  140. data/lib/templates/bootstrap_nav.html.haml +0 -34
  141. data/lib/templates/bootstrap_nav.html.slim +0 -34
  142. data/lib/templates/bulma_nav.html.erb +0 -24
  143. data/lib/templates/bulma_nav.html.haml +0 -32
  144. data/lib/templates/bulma_nav.html.slim +0 -32
  145. data/lib/templates/foundation_nav.html.erb +0 -24
  146. data/lib/templates/foundation_nav.html.haml +0 -34
  147. data/lib/templates/foundation_nav.html.slim +0 -34
  148. data/lib/templates/nav.html.erb +0 -22
  149. data/lib/templates/nav.html.haml +0 -30
  150. data/lib/templates/nav.html.slim +0 -29
  151. data/lib/templates/uikit_nav.html.erb +0 -15
  152. data/lib/templates/uikit_nav.html.haml +0 -28
  153. data/lib/templates/uikit_nav.html.slim +0 -28
@@ -1,4 +1,4 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/array
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/array
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Pagy # :nodoc:
@@ -16,7 +16,7 @@ class Pagy # :nodoc:
16
16
  def pagy_array_get_vars(array, vars)
17
17
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
18
18
  vars[:count] ||= array.size
19
- vars[:page] ||= params[vars[:page_param] || DEFAULT[:page_param]]
19
+ vars[:page] ||= pagy_get_page(vars)
20
20
  vars
21
21
  end
22
22
  end
@@ -1,91 +1,95 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/bootstrap
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/bootstrap
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/frontend_helpers'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
8
8
  # The resulting code may not look very elegant, but produces the best benchmarks
9
9
  module BootstrapExtra
10
10
  # Pagination for bootstrap: it returns the html with the series of links to the pages
11
- def pagy_bootstrap_nav(pagy, pagy_id: nil, link_extra: '', **vars)
12
- p_id = %( id="#{pagy_id}") if pagy_id
13
- link = pagy_link_proc(pagy, link_extra: %(class="page-link" #{link_extra}))
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)
14
14
 
15
- html = +%(<nav#{p_id} class="pagy-bootstrap-nav" aria-label="pager"><ul class="pagination">)
16
- html << pagy_bootstrap_prev_html(pagy, link)
15
+ html = %(<nav#{id} class="pagy-bootstrap nav" #{nav_aria_label(pagy, aria_label:)}><ul class="#{classes}">#{
16
+ bootstrap_prev_html(pagy, a)})
17
17
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
18
18
  html << case item
19
19
  when Integer
20
- %(<li class="page-item">#{link.call item}</li>)
20
+ %(<li class="page-item">#{a.(item, classes: 'page-link')}</li>)
21
21
  when String
22
- %(<li class="page-item active">#{link.call item}</li>)
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>)
23
24
  when :gap
24
- %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.gap'}</a></li>)
25
+ %(<li class="page-item gap disabled"><a role="link" class="page-link" aria-disabled="true">#{
26
+ pagy_t('pagy.gap')}</a></li>)
25
27
  else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
26
28
  end
27
29
  end
28
- html << pagy_bootstrap_next_html(pagy, link)
29
- html << %(</ul></nav>)
30
+ html << %(#{bootstrap_next_html(pagy, a)}</ul></nav>)
30
31
  end
31
32
 
32
- # Javascript pagination for bootstrap: it returns a nav and a JSON tag used by the pagy.js file
33
- def pagy_bootstrap_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
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)
34
35
  sequels = pagy.sequels(**vars)
35
- p_id = %( id="#{pagy_id}") if pagy_id
36
- link = pagy_link_proc(pagy, link_extra: %(class="page-link" #{link_extra}))
37
- tags = { 'before' => %(<ul class="pagination">#{pagy_bootstrap_prev_html pagy, link}),
38
- 'link' => %(<li class="page-item">#{mark = link.call(PAGE_PLACEHOLDER, LABEL_PLACEHOLDER)}</li>),
39
- 'active' => %(<li class="page-item active">#{mark}</li>),
40
- 'gap' => %(<li class="page-item gap disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.gap'}</a></li>),
41
- 'after' => %(#{pagy_bootstrap_next_html pagy, link}</ul>) }
36
+ id = %( id="#{id}") if id
37
+ a = pagy_anchor(pagy)
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>) }
42
45
 
43
- %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-bootstrap-nav-js" aria-label="pager" #{
44
- pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></nav>)
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>)
45
50
  end
46
51
 
47
- # Javascript combo pagination for bootstrap: it returns a nav and a JSON tag used by the pagy.js file
48
- def pagy_bootstrap_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
49
- p_id = %( id="#{pagy_id}") if pagy_id
50
- link = pagy_link_proc(pagy, link_extra: link_extra)
51
- p_page = pagy.page
52
- p_pages = pagy.pages
53
- input = %(<input type="number" min="1" max="#{p_pages}" value="#{
54
- p_page}" class="text-primary" style="padding: 0; border: none; text-align: center; width: #{
55
- p_pages.to_s.length + 1}rem;">)
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)
54
+ id = %( id="#{id}") if id
55
+ a = pagy_anchor(pagy)
56
+ pages = pagy.pages
56
57
 
57
- %(<nav#{p_id} class="pagy-bootstrap-combo-nav-js pagination" aria-label="pager"><div class="btn-group" role="group" #{
58
- pagy_json_attr pagy, :combo, pagy_marked_link(link)}>#{
59
- if (p_prev = pagy.prev)
60
- link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous" class="prev btn btn-primary"'
61
- else
62
- %(<a class="prev btn btn-primary disabled" href="#">#{pagy_t('pagy.nav.prev')}</a>)
63
- end
64
- }<div class="pagy-combo-input btn btn-primary disabled" style="white-space: nowrap;">#{
65
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</div>#{
66
- if (p_next = pagy.next)
67
- link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next" class="next btn btn-primary"'
68
- else
69
- %(<a class="next btn btn-primary disabled" href="#">#{pagy_t 'pagy.nav.next'}</a>)
70
- end
71
- }</div></nav>)
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))
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
72
  end
73
73
 
74
74
  private
75
75
 
76
- def pagy_bootstrap_prev_html(pagy, link)
76
+ def bootstrap_prev_html(pagy, a)
77
77
  if (p_prev = pagy.prev)
78
- %(<li class="page-item prev">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'}</li>)
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>)
79
80
  else
80
- %(<li class="page-item prev disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.prev'}</a></li>)
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>)
81
83
  end
82
84
  end
83
85
 
84
- def pagy_bootstrap_next_html(pagy, link)
86
+ def bootstrap_next_html(pagy, a)
85
87
  if (p_next = pagy.next)
86
- %(<li class="page-item next">#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'}</li>)
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>)
87
90
  else
88
- %(<li class="page-item next disabled"><a href="#" class="page-link">#{pagy_t 'pagy.nav.next'}</a></li>)
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>)
89
93
  end
90
94
  end
91
95
  end
@@ -1,92 +1,88 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/bulma
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/bulma
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/frontend_helpers'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Frontend modules are specially optimized for performance.
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, pagy_id: nil, link_extra: '', **vars)
12
- p_id = %( id="#{pagy_id}") if pagy_id
13
- link = pagy_link_proc(pagy, link_extra: link_extra)
11
+ def pagy_bulma_nav(pagy, id: nil, classes: 'pagy-bulma nav pagination is-centered', aria_label: nil, **vars)
12
+ id = %( id="#{id}") if id
13
+ a = pagy_anchor(pagy)
14
14
 
15
- html = +%(<nav#{p_id} class="pagy-bulma-nav pagination is-centered" aria-label="pagination">)
16
- html << pagy_bulma_prev_next_html(pagy, link)
15
+ html = %(<nav#{id} class="#{classes}" #{nav_aria_label(pagy, aria_label:)}>)
16
+ html << bulma_prev_next_html(pagy, a)
17
17
  html << %(<ul class="pagination-list">)
18
18
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
19
19
  html << case item
20
20
  when Integer
21
- %(<li>#{link.call item, pagy.label_for(item), %(class="pagination-link" aria-label="goto page #{item}")}</li>)
21
+ %(<li>#{a.(item, pagy.label_for(item), classes: 'pagination-link')}</li>)
22
22
  when String
23
- %(<li>#{link.call item, pagy.label_for(item),
24
- %(class="pagination-link is-current" aria-label="page #{item}" aria-current="page")}</li>)
23
+ %(<li><a role="link" class="pagination-link is-current" aria-current="page" aria-disabled="true">#{
24
+ pagy.label_for(item)}</a></li>)
25
25
  when :gap
26
- %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.nav.gap'}</span></li>)
26
+ %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.gap'}</span></li>)
27
27
  else raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
28
28
  end
29
29
  end
30
30
  html << %(</ul></nav>)
31
31
  end
32
32
 
33
- # Javascript pagination for bulma: it returns a nav and a JSON tag used by the Pagy.nav javascript
34
- def pagy_bulma_nav_js(pagy, pagy_id: nil, link_extra: '', **vars)
33
+ # 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
35
  sequels = pagy.sequels(**vars)
36
- p_id = %( id="#{pagy_id}") if pagy_id
37
- link = pagy_link_proc(pagy, link_extra: link_extra)
38
- tags = { 'before' => %(#{pagy_bulma_prev_next_html(pagy, link)}<ul class="pagination-list">),
39
- 'link' => %(<li>#{link.call PAGE_PLACEHOLDER, LABEL_PLACEHOLDER,
40
- %(class="pagination-link" aria-label="goto page #{PAGE_PLACEHOLDER}")}</li>),
41
- 'active' => %(<li>#{link.call PAGE_PLACEHOLDER, LABEL_PLACEHOLDER,
42
- %(class="pagination-link is-current" aria-current="page" aria-label="page #{
43
- PAGE_PLACEHOLDER}")}</li>),
44
- 'gap' => %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.nav.gap'}</span></li>),
45
- 'after' => '</ul>' }
36
+ id = %( id="#{id}") if id
37
+ a = pagy_anchor(pagy)
38
+ tokens = { 'before' => %(#{bulma_prev_next_html(pagy, a)}<ul class="pagination-list">),
39
+ 'a' => %(<li>#{a.(PAGE_TOKEN, LABEL_TOKEN, classes: 'pagination-link')}</li>),
40
+ 'current' => %(<li><a role="link" class="pagination-link is-current" aria-current="page" aria-disabled="true">#{
41
+ LABEL_TOKEN}</a></li>),
42
+ 'gap' => %(<li><span class="pagination-ellipsis">#{pagy_t 'pagy.gap'}</span></li>),
43
+ 'after' => '</ul>' }
46
44
 
47
- %(<nav#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-bulma-nav-js pagination is-centered" aria-label="pagination" #{
48
- pagy_json_attr(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></nav>)
45
+ %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}#{classes}" #{
46
+ nav_aria_label(pagy, aria_label:)} #{
47
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
48
+ }></nav>)
49
49
  end
50
50
 
51
- # Javascript combo pagination for bulma: it returns a nav and a JSON tag used by the pagy.js file
52
- def pagy_bulma_combo_nav_js(pagy, pagy_id: nil, link_extra: '')
53
- p_id = %( id="#{pagy_id}") if pagy_id
54
- link = pagy_link_proc(pagy, link_extra: link_extra)
55
- p_page = pagy.page
56
- p_pages = pagy.pages
57
- input = %(<input class="input" type="number" min="1" max="#{p_pages}" value="#{
58
- p_page}" style="padding: 0; text-align: center; width: #{p_pages.to_s.length + 1}rem; margin:0 0.3rem;">)
51
+ # 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)
53
+ id = %( id="#{id}") if id
54
+ a = pagy_anchor(pagy)
55
+ pages = pagy.pages
59
56
 
60
- html = %(<nav#{p_id} class="pagy-bulma-combo-nav-js" aria-label="pagination">)
61
- %(#{html}<div class="field is-grouped is-grouped-centered" role="group" #{
62
- pagy_json_attr pagy, :combo, pagy_marked_link(link)}>#{
63
- if (p_prev = pagy.prev)
64
- %(<p class="control">#{link.call p_prev, pagy_t('pagy.nav.prev'), 'class="button" aria-label="previous page"'}</p>)
65
- else
66
- %(<p class="control"><a class="button" disabled>#{pagy_t 'pagy.nav.prev'}</a></p>)
67
- end
68
- }<div class="pagy-combo-input control level is-mobile">#{
69
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</div>#{
70
- if (p_next = pagy.next)
71
- %(<p class="control">#{link.call p_next, pagy_t('pagy.nav.next'), 'class="button" aria-label="next page"'}</p>)
72
- else
73
- %(<p class="control"><a class="button" disabled>#{pagy_t 'pagy.nav.next'}</a></p>)
74
- end
75
- }</div></nav>)
57
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page") <<
58
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; height: 1.7rem; margin:0 0.3rem; ) <<
59
+ %(border: none; border-radius: 4px; padding: 0; font-size: 1.1rem; color: white; ) <<
60
+ %(background-color: #485fc7;">#{JSTools::A_TAG})
61
+
62
+ %(<nav#{id} class="#{classes}" #{
63
+ nav_aria_label(pagy, aria_label:)} #{
64
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
65
+ }>#{
66
+ bulma_prev_next_html(pagy, a)
67
+ }<ul class="pagination-list"><li class="pagination-link"><label>#{
68
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
69
+ }</label></li></ul></nav>)
76
70
  end
77
71
 
78
72
  private
79
73
 
80
- def pagy_bulma_prev_next_html(pagy, link)
81
- html = +if (p_prev = pagy.prev)
82
- link.call p_prev, pagy_t('pagy.nav.prev'), 'class="pagination-previous" aria-label="previous page"'
83
- else
84
- %(<a class="pagination-previous" disabled>#{pagy_t 'pagy.nav.prev'}</a>)
85
- end
74
+ def bulma_prev_next_html(pagy, a)
75
+ html = if (p_prev = pagy.prev)
76
+ a.(p_prev, pagy_t('pagy.prev'), classes: 'pagination-previous', aria_label: pagy_t('pagy.aria_label.prev'))
77
+ else
78
+ %(<a role="link" class="pagination-previous" disabled aria-disabled="true" aria-label="#{
79
+ pagy_t('pagy.aria_label.prev')}">#{pagy_t 'pagy.prev'}</a>)
80
+ end
86
81
  html << if (p_next = pagy.next)
87
- link.call p_next, pagy_t('pagy.nav.next'), 'class="pagination-next" aria-label="next page"'
82
+ a.(p_next, pagy_t('pagy.next'), classes: 'pagination-next', aria_label: pagy_t('pagy.aria_label.next'))
88
83
  else
89
- %(<a class="pagination-next" disabled>#{pagy_t 'pagy.nav.next'}</a>)
84
+ %(<a role="link" class="pagination-next" disabled aria-disabled="true" aria-label="#{
85
+ pagy_t('pagy.aria_label.next')}">#{pagy_t('pagy.next')}</a>)
90
86
  end
91
87
  end
92
88
  end
@@ -1,66 +1,83 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/calendar
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/calendar
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/calendar'
4
+ require_relative '../calendar'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  # Add pagination filtering by calendar unit (:year, :quarter, :month, :week, :day) to the regular pagination
8
8
  module CalendarExtra
9
9
  # Additions for the Backend module
10
- module Backend
10
+ module BackendAddOn
11
11
  CONF_KEYS = (Calendar::UNITS + %i[pagy active]).freeze
12
12
 
13
13
  private
14
14
 
15
15
  # Take a collection and a conf Hash with keys in CONF_KEYS and return an array with 3 items: [calendar, pagy, results]
16
16
  def pagy_calendar(collection, conf)
17
- unless conf.is_a?(Hash) && (conf.keys - CONF_KEYS).empty? && conf.all? { |k, v| v.is_a?(Hash) || k == :active }
18
- raise ArgumentError, "keys must be in #{CONF_KEYS.inspect} and object values must be Hashes; got #{conf.inspect}"
19
- end
20
-
21
- conf[:pagy] = {} unless conf[:pagy] # use default Pagy object when omitted
22
- calendar, collection = pagy_setup_calendar(collection, conf) unless conf.key?(:active) && !conf[:active]
23
- pagy, results = send(conf[:pagy][:backend] || :pagy, collection, conf[:pagy]) # use backend: :pagy when omitted
24
- [calendar, pagy, results]
25
- end
17
+ raise ArgumentError, "keys must be in #{CONF_KEYS.inspect}" \
18
+ unless conf.is_a?(Hash) && (conf.keys - CONF_KEYS).empty?
26
19
 
27
- # Setup and return the calendar objects and the filtered collection
28
- def pagy_setup_calendar(collection, conf)
29
- units = Calendar::UNITS & conf.keys # get the units in time length desc order
30
- raise ArgumentError, 'no calendar unit found in pagy_calendar configuration' if units.empty?
31
-
32
- page_param = conf[:pagy][:page_param] || DEFAULT[:page_param]
33
- units.each do |unit| # set all the :page_param vars for later deletion
34
- unit_page_param = :"#{unit}_#{page_param}"
35
- conf[unit][:page_param] = unit_page_param
36
- conf[unit][:page] = params[unit_page_param]
37
- end
38
- calendar = {}
39
- last_obj = nil
40
- units.each_with_index do |unit, index|
41
- params_to_delete = units[(index + 1), units.size].map { |sub| conf[sub][:page_param] } + [page_param]
42
- conf[unit][:params] = lambda do |params| # delete page_param from the sub-units
43
- params_to_delete.each { |p| params.delete(p.to_s) } # Hash#except missing from ruby 2.5 baseline
44
- params
45
- end
46
- conf[unit][:period] = last_obj&.send(:active_period) || pagy_calendar_period(collection)
47
- calendar[unit] = last_obj = Calendar.send(:create, unit, conf[unit])
20
+ conf[:pagy] ||= {}
21
+ unless conf.key?(:active) && !conf[:active]
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)
48
29
  end
49
- [calendar, pagy_calendar_filter(collection, last_obj.from, last_obj.to)]
30
+ pagy, results = send(conf[:pagy][:backend] || :pagy, collection, conf[:pagy]) # use backend: :pagy when omitted
31
+ [calendar, pagy, results]
50
32
  end
51
33
 
52
34
  # This method must be implemented by the application
53
35
  def pagy_calendar_period(*)
54
36
  raise NoMethodError, 'the pagy_calendar_period method must be implemented by the application ' \
55
- '(see https://ddnexus.github.io/pagy/extras/calendar#pagy_calendar_periodcollection)'
37
+ '(see https://ddnexus.github.io/pagy/docs/extras/calendar/#pagy-calendar-period-collection)'
56
38
  end
57
39
 
58
40
  # This method must be implemented by the application
59
41
  def pagy_calendar_filter(*)
60
42
  raise NoMethodError, 'the pagy_calendar_filter method must be implemented by the application ' \
61
- '(see https://ddnexus.github.io/pagy/extras/calendar#pagy_calendar_filtercollection-from-to)'
43
+ '(see https://ddnexus.github.io/pagy/docs/extras/calendar/#pagy-calendar-filter-collection-from-to)'
44
+ end
45
+ end
46
+
47
+ # Override the pagy_anchor
48
+ module FrontendOverride
49
+ # Consider the vars[:count]
50
+ def pagy_anchor(pagy)
51
+ return super unless (counts = pagy.vars[:counts])
52
+
53
+ a_string = pagy.vars[:anchor_string]
54
+ a_string = %( #{a_string}) if a_string
55
+ left, right = %(<a#{a_string} href="#{pagy_url_for(pagy, PAGE_TOKEN)}").split(PAGE_TOKEN, 2)
56
+ # lambda used by all the helpers
57
+ lambda do |page, text = pagy.label_for(page), classes: nil, aria_label: nil|
58
+ count = counts[page - 1]
59
+ item_name = pagy_t('pagy.item_name', count:)
60
+ if count.zero?
61
+ classes = "#{classes && (classes + ' ')}empty-page"
62
+ title = %( title="#{pagy_t('pagy.info.no_items', item_name:, count:)}")
63
+ else
64
+ title = %( title="#{pagy_t('pagy.info.single_page', item_name:, count:)}")
65
+ end
66
+ classes = %( class="#{classes}") if classes
67
+ aria_label = %( aria-label="#{aria_label}") if aria_label
68
+ %(#{left}#{page}#{right}#{title}#{classes}#{aria_label}>#{text}</a>)
69
+ end
70
+ end
71
+ end
72
+
73
+ # Additions for the Frontend module
74
+ module UrlHelperAddOn
75
+ # Return the url for the calendar page at time
76
+ def pagy_calendar_url_at(calendar, time, **opts)
77
+ pagy_url_for(calendar.send(:calendar_at, time, **opts), 1, **opts)
62
78
  end
63
79
  end
64
80
  end
65
- Backend.prepend CalendarExtra::Backend
81
+ Backend.prepend CalendarExtra::BackendAddOn, CalendarExtra::UrlHelperAddOn
82
+ Frontend.prepend CalendarExtra::UrlHelperAddOn, CalendarExtra::FrontendOverride
66
83
  end
@@ -1,7 +1,7 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/countless
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/countless
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/countless'
4
+ require_relative '../countless'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:countless_minimal] = false
@@ -19,7 +19,7 @@ class Pagy # :nodoc:
19
19
  # Sub-method called only by #pagy_countless: here for easy customization of variables by overriding
20
20
  def pagy_countless_get_vars(_collection, vars)
21
21
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
22
- vars[:page] ||= params[vars[:page_param] || DEFAULT[:page_param]]
22
+ vars[:page] ||= pagy_get_page(vars)
23
23
  vars
24
24
  end
25
25
 
@@ -1,8 +1,9 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/extras/elasticsearch_rails
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/elasticsearch_rails
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class Pagy # :nodoc:
5
- DEFAULT[:elasticsearch_rails_search_method] ||= :pagy_search
5
+ DEFAULT[:elasticsearch_rails_search] ||= :search
6
+ DEFAULT[:elasticsearch_rails_pagy_search] ||= :pagy_search
6
7
 
7
8
  # Paginate ElasticsearchRails response objects
8
9
  module ElasticsearchRailsExtra
@@ -18,7 +19,7 @@ class Pagy # :nodoc:
18
19
  total.is_a?(Hash) ? total['value'] : total
19
20
  end
20
21
 
21
- module ElasticsearchRails # :nodoc:
22
+ module ModelExtension # :nodoc:
22
23
  # Return an array used to delay the call of #search
23
24
  # after the pagination variables are merged to the options.
24
25
  # It also pushes to the same array an optional method call.
@@ -27,11 +28,12 @@ class Pagy # :nodoc:
27
28
  args.define_singleton_method(:method_missing) { |*a| args += a }
28
29
  end
29
30
  end
30
- alias_method Pagy::DEFAULT[:elasticsearch_rails_search_method], :pagy_elasticsearch_rails
31
+ alias_method Pagy::DEFAULT[:elasticsearch_rails_pagy_search], :pagy_elasticsearch_rails
31
32
  end
33
+ Pagy::ElasticsearchRails = ModelExtension
32
34
 
33
35
  # Additions for the Pagy class
34
- module Pagy
36
+ module PagyAddOn
35
37
  # Create a Pagy object from an Elasticsearch::Model::Response::Response object
36
38
  def new_from_elasticsearch_rails(response, vars = {})
37
39
  vars[:items] = response.search.options[:size] || 10
@@ -40,9 +42,10 @@ class Pagy # :nodoc:
40
42
  new(vars)
41
43
  end
42
44
  end
45
+ Pagy.extend PagyAddOn
43
46
 
44
47
  # Add specialized backend methods to paginate ElasticsearchRails searches
45
- module Backend
48
+ module BackendAddOn
46
49
  private
47
50
 
48
51
  # Return Pagy object and items
@@ -52,7 +55,7 @@ class Pagy # :nodoc:
52
55
  vars = pagy_elasticsearch_rails_get_vars(nil, vars)
53
56
  options[:size] = vars[:items]
54
57
  options[:from] = vars[:items] * (vars[:page] - 1)
55
- response = model.search(query_or_payload, **options)
58
+ response = model.send(DEFAULT[:elasticsearch_rails_search], query_or_payload, **options)
56
59
  vars[:count] = ElasticsearchRailsExtra.total_count(response)
57
60
 
58
61
  pagy = ::Pagy.new(vars)
@@ -68,12 +71,10 @@ class Pagy # :nodoc:
68
71
  def pagy_elasticsearch_rails_get_vars(_collection, vars)
69
72
  pagy_set_items_from_params(vars) if defined?(ItemsExtra)
70
73
  vars[:items] ||= DEFAULT[:items]
71
- vars[:page] ||= (params[vars[:page_param] || DEFAULT[:page_param]] || 1).to_i
74
+ vars[:page] ||= pagy_get_page(vars)
72
75
  vars
73
76
  end
74
77
  end
78
+ Backend.prepend BackendAddOn
75
79
  end
76
- ElasticsearchRails = ElasticsearchRailsExtra::ElasticsearchRails
77
- extend ElasticsearchRailsExtra::Pagy
78
- Backend.prepend ElasticsearchRailsExtra::Backend
79
80
  end