pagy 9.4.0 → 43.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/apps/calendar.ru +548 -552
  3. data/apps/demo.ru +224 -181
  4. data/apps/index.rb +3 -1
  5. data/apps/keynav+root_key.ru +321 -0
  6. data/apps/keynav.ru +260 -0
  7. data/apps/{keyset_ar.ru → keyset.ru} +26 -32
  8. data/apps/{keyset_s.ru → keyset_sequel.ru} +23 -29
  9. data/apps/rails.ru +51 -48
  10. data/apps/repro.ru +51 -47
  11. data/bin/pagy +20 -21
  12. data/config/pagy.rb +35 -207
  13. data/javascripts/ai_widget.js +90 -0
  14. data/javascripts/pagy.js +153 -0
  15. data/javascripts/pagy.js.map +10 -0
  16. data/javascripts/pagy.min.js +2 -4
  17. data/javascripts/pagy.mjs +113 -63
  18. data/javascripts/wand.js +1172 -0
  19. data/lib/pagy/classes/calendar/calendar.rb +96 -0
  20. data/lib/pagy/{calendar → classes/calendar}/day.rb +7 -11
  21. data/lib/pagy/{calendar → classes/calendar}/month.rb +5 -10
  22. data/lib/pagy/{calendar → classes/calendar}/quarter.rb +10 -15
  23. data/lib/pagy/classes/calendar/unit.rb +93 -0
  24. data/lib/pagy/{calendar → classes/calendar}/week.rb +5 -9
  25. data/lib/pagy/{calendar → classes/calendar}/year.rb +5 -6
  26. data/lib/pagy/classes/exceptions.rb +25 -0
  27. data/lib/pagy/classes/keyset/active_record.rb +11 -0
  28. data/lib/pagy/classes/keyset/adapters/active_record.rb +50 -0
  29. data/lib/pagy/classes/keyset/adapters/sequel.rb +63 -0
  30. data/lib/pagy/classes/keyset/keynav/active_record.rb +13 -0
  31. data/lib/pagy/classes/keyset/keynav/sequel.rb +13 -0
  32. data/lib/pagy/classes/keyset/keynav.rb +79 -0
  33. data/lib/pagy/classes/keyset/keyset.rb +126 -0
  34. data/lib/pagy/classes/keyset/sequel.rb +11 -0
  35. data/lib/pagy/classes/offset/countish.rb +17 -0
  36. data/lib/pagy/classes/offset/countless.rb +61 -0
  37. data/lib/pagy/classes/offset/offset.rb +56 -0
  38. data/lib/pagy/classes/offset/search.rb +32 -0
  39. data/lib/pagy/classes/request.rb +36 -0
  40. data/lib/pagy/console.rb +3 -20
  41. data/lib/pagy/modules/abilities/configurable.rb +36 -0
  42. data/lib/pagy/modules/abilities/countable.rb +23 -0
  43. data/lib/pagy/modules/abilities/linkable.rb +60 -0
  44. data/lib/pagy/modules/abilities/rangeable.rb +16 -0
  45. data/lib/pagy/modules/abilities/shiftable.rb +12 -0
  46. data/lib/pagy/{b64.rb → modules/b64.rb} +3 -7
  47. data/lib/pagy/modules/console.rb +24 -0
  48. data/lib/pagy/modules/i18n/i18n.rb +48 -0
  49. data/lib/pagy/modules/i18n/p11n/arabic.rb +29 -0
  50. data/lib/pagy/modules/i18n/p11n/east_slavic.rb +26 -0
  51. data/lib/pagy/modules/i18n/p11n/one_other.rb +15 -0
  52. data/lib/pagy/modules/i18n/p11n/one_upto_two_other.rb +15 -0
  53. data/lib/pagy/modules/i18n/p11n/other.rb +13 -0
  54. data/lib/pagy/modules/i18n/p11n/polish.rb +26 -0
  55. data/lib/pagy/modules/i18n/p11n/west_slavic.rb +22 -0
  56. data/lib/pagy/modules/i18n/p11n.rb +16 -0
  57. data/lib/pagy/modules/searcher.rb +17 -0
  58. data/lib/pagy/toolbox/helpers/anchor_tags.rb +25 -0
  59. data/lib/pagy/toolbox/helpers/bootstrap/input_nav_js.rb +24 -0
  60. data/lib/pagy/toolbox/helpers/bootstrap/previous_next_html.rb +18 -0
  61. data/lib/pagy/toolbox/helpers/bootstrap/series_nav.rb +29 -0
  62. data/lib/pagy/toolbox/helpers/bootstrap/series_nav_js.rb +21 -0
  63. data/lib/pagy/toolbox/helpers/bulma/input_nav_js.rb +21 -0
  64. data/lib/pagy/toolbox/helpers/bulma/previous_next_html.rb +19 -0
  65. data/lib/pagy/toolbox/helpers/bulma/series_nav.rb +28 -0
  66. data/lib/pagy/toolbox/helpers/bulma/series_nav_js.rb +20 -0
  67. data/lib/pagy/toolbox/helpers/data_hash.rb +27 -0
  68. data/lib/pagy/toolbox/helpers/headers_hash.rb +29 -0
  69. data/lib/pagy/toolbox/helpers/info_tag.rb +26 -0
  70. data/lib/pagy/toolbox/helpers/input_nav_js.rb +18 -0
  71. data/lib/pagy/toolbox/helpers/limit_tag_js.rb +23 -0
  72. data/lib/pagy/toolbox/helpers/loader.rb +33 -0
  73. data/lib/pagy/toolbox/helpers/page_url.rb +18 -0
  74. data/lib/pagy/toolbox/helpers/series_nav.rb +28 -0
  75. data/lib/pagy/toolbox/helpers/series_nav_js.rb +18 -0
  76. data/lib/pagy/toolbox/helpers/support/a_lambda.rb +35 -0
  77. data/lib/pagy/toolbox/helpers/support/data_pagy_attribute.rb +15 -0
  78. data/lib/pagy/toolbox/helpers/support/nav_aria_label_attribute.rb +12 -0
  79. data/lib/pagy/toolbox/helpers/support/series.rb +38 -0
  80. data/lib/pagy/toolbox/helpers/support/wrap_input_nav_js.rb +20 -0
  81. data/lib/pagy/toolbox/helpers/support/wrap_series_nav.rb +17 -0
  82. data/lib/pagy/toolbox/helpers/support/wrap_series_nav_js.rb +37 -0
  83. data/lib/pagy/toolbox/helpers/urls_hash.rb +13 -0
  84. data/lib/pagy/toolbox/paginators/calendar.rb +29 -0
  85. data/lib/pagy/toolbox/paginators/countish.rb +37 -0
  86. data/lib/pagy/toolbox/paginators/countless.rb +20 -0
  87. data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +50 -0
  88. data/lib/pagy/toolbox/paginators/keynav_js.rb +26 -0
  89. data/lib/pagy/toolbox/paginators/keyset.rb +15 -0
  90. data/lib/pagy/toolbox/paginators/meilisearch.rb +31 -0
  91. data/lib/pagy/toolbox/paginators/method.rb +35 -0
  92. data/lib/pagy/toolbox/paginators/offset.rb +18 -0
  93. data/lib/pagy/toolbox/paginators/searchkick.rb +31 -0
  94. data/lib/pagy.rb +59 -97
  95. data/locales/ar.yml +9 -6
  96. data/locales/be.yml +9 -6
  97. data/locales/bg.yml +9 -6
  98. data/locales/bs.yml +9 -6
  99. data/locales/ca.yml +9 -6
  100. data/locales/ckb.yml +8 -6
  101. data/locales/cs.yml +9 -6
  102. data/locales/da.yml +9 -6
  103. data/locales/de.yml +9 -6
  104. data/locales/dz.yml +9 -6
  105. data/locales/en.yml +9 -6
  106. data/locales/es.yml +9 -6
  107. data/locales/fr.yml +9 -6
  108. data/locales/hr.yml +9 -6
  109. data/locales/id.yml +10 -9
  110. data/locales/it.yml +9 -6
  111. data/locales/ja.yml +10 -9
  112. data/locales/km.yml +10 -9
  113. data/locales/ko.yml +9 -6
  114. data/locales/nb.yml +9 -6
  115. data/locales/nl.yml +9 -6
  116. data/locales/nn.yml +9 -6
  117. data/locales/pl.yml +9 -6
  118. data/locales/pt-BR.yml +10 -7
  119. data/locales/pt.yml +10 -7
  120. data/locales/ru.yml +9 -6
  121. data/locales/sk.yml +9 -6
  122. data/locales/sr.yml +9 -6
  123. data/locales/sv-SE.yml +9 -6
  124. data/locales/sv.yml +9 -6
  125. data/locales/sw.yml +12 -9
  126. data/locales/ta.yml +9 -6
  127. data/locales/tr.yml +17 -12
  128. data/locales/uk.yml +9 -6
  129. data/locales/vi.yml +9 -6
  130. data/locales/zh-CN.yml +9 -6
  131. data/locales/zh-HK.yml +9 -6
  132. data/locales/zh-TW.yml +9 -6
  133. data/stylesheets/pagy-tailwind.css +64 -0
  134. data/stylesheets/pagy.css +63 -27
  135. metadata +118 -52
  136. data/javascripts/pagy.min.js.map +0 -10
  137. data/lib/pagy/backend.rb +0 -44
  138. data/lib/pagy/calendar/unit.rb +0 -103
  139. data/lib/pagy/calendar.rb +0 -84
  140. data/lib/pagy/countless.rb +0 -38
  141. data/lib/pagy/exceptions.rb +0 -25
  142. data/lib/pagy/extras/arel.rb +0 -28
  143. data/lib/pagy/extras/array.rb +0 -19
  144. data/lib/pagy/extras/bootstrap.rb +0 -97
  145. data/lib/pagy/extras/bulma.rb +0 -93
  146. data/lib/pagy/extras/calendar.rb +0 -79
  147. data/lib/pagy/extras/countless.rb +0 -32
  148. data/lib/pagy/extras/elasticsearch_rails.rb +0 -71
  149. data/lib/pagy/extras/gearbox.rb +0 -55
  150. data/lib/pagy/extras/headers.rb +0 -54
  151. data/lib/pagy/extras/i18n.rb +0 -26
  152. data/lib/pagy/extras/js_tools.rb +0 -70
  153. data/lib/pagy/extras/jsonapi.rb +0 -88
  154. data/lib/pagy/extras/keyset.rb +0 -30
  155. data/lib/pagy/extras/limit.rb +0 -63
  156. data/lib/pagy/extras/meilisearch.rb +0 -57
  157. data/lib/pagy/extras/metadata.rb +0 -42
  158. data/lib/pagy/extras/overflow.rb +0 -81
  159. data/lib/pagy/extras/pagy.rb +0 -82
  160. data/lib/pagy/extras/searchkick.rb +0 -59
  161. data/lib/pagy/extras/size.rb +0 -40
  162. data/lib/pagy/extras/standalone.rb +0 -60
  163. data/lib/pagy/extras/trim.rb +0 -29
  164. data/lib/pagy/frontend.rb +0 -99
  165. data/lib/pagy/i18n.rb +0 -167
  166. data/lib/pagy/keyset/active_record.rb +0 -44
  167. data/lib/pagy/keyset/sequel.rb +0 -57
  168. data/lib/pagy/keyset.rb +0 -118
  169. data/lib/pagy/shared_methods.rb +0 -26
  170. data/lib/pagy/url_helpers.rb +0 -26
  171. data/stylesheets/pagy.scss +0 -48
  172. data/stylesheets/pagy.tailwind.css +0 -21
@@ -0,0 +1,321 @@
1
+ # frozen_string_literal: true
2
+
3
+ # DESCRIPTION
4
+ # Showcase the Keynav pagination with independent instances
5
+ #
6
+ # DOC
7
+ # https://ddnexus.github.io/pagy/playground/#keyset-apps
8
+ #
9
+ # BIN HELP
10
+ # pagy -h
11
+ #
12
+ # DEV USAGE
13
+ # pagy clone keynav
14
+ # pagy ./keynav.ru
15
+ #
16
+ # URL
17
+ # http://127.0.0.1:8000
18
+
19
+ VERSION = '43.2.0'
20
+
21
+ if VERSION != Pagy::VERSION
22
+ Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
23
+ end
24
+
25
+ # Bundle
26
+ require 'bundler/inline'
27
+ gemfile(!Pagy::ROOT.join('pagy.gemspec').exist?) do
28
+ source 'https://rubygems.org'
29
+ gem 'activerecord'
30
+ gem 'puma'
31
+ gem 'sinatra'
32
+ gem 'sqlite3'
33
+ end
34
+
35
+ # Sinatra setup
36
+ require 'sinatra/base'
37
+ # Sinatra application
38
+ class PagyKeynav < Sinatra::Base
39
+ include Pagy::Method
40
+
41
+ get('/javascripts/:file') do
42
+ format = params[:file].split('.').last
43
+ if format == 'js'
44
+ content_type 'application/javascript'
45
+ elsif format == 'map'
46
+ content_type 'application/json'
47
+ end
48
+ send_file Pagy::ROOT.join('javascripts', params[:file])
49
+ end
50
+
51
+ # Root route/action
52
+ get '/' do
53
+ Time.zone = 'UTC'
54
+
55
+ @order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }
56
+ @pagy1, @pets1 = pagy(:keynav_js, Pet.order(@order), limit: 4, root_key: 'animal1')
57
+ @ids1 = @pets1.pluck(:id)
58
+ @pagy2, @pets2 = pagy(:keynav_js, Pet.order(@order), limit: 4, root_key: 'animal2')
59
+ @ids2 = @pets2.pluck(:id)
60
+ erb :main
61
+ end
62
+
63
+ helpers do
64
+ def order_symbol(dir)
65
+ { asc: '&#x2197;', desc: '&#x2198;' }[dir]
66
+ end
67
+ end
68
+
69
+ # Views
70
+ template :layout do
71
+ <<~ERB
72
+ <!DOCTYPE html>
73
+ <html lang="en">
74
+ <html>
75
+ <head>
76
+ <title>Pagy Keynav (root_key) App</title>
77
+ <script src="javascripts/pagy.js"></script>
78
+ <script>
79
+ window.addEventListener("load", Pagy.init);
80
+ </script>
81
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
82
+ <style type="text/css">
83
+ @media screen { html, body {
84
+ font-size: 1rem;
85
+ line-height: 1.2s;
86
+ padding: 0;
87
+ margin: 0;
88
+ } }
89
+ body {
90
+ background: white !important;
91
+ margin: 0 !important;
92
+ font-family: sans-serif !important;
93
+ }
94
+ .main-content {
95
+ padding: 1rem 1.5rem 2rem !important;
96
+ }
97
+ #content {
98
+ display: flex; /* Enables Flexbox */
99
+ flex-wrap: wrap; /* Allows stacking */
100
+ gap: 20px; /* Gap between items */
101
+ /* Just for visual clarity of the container boundaries */
102
+ /*padding: 10px;
103
+ background-color: #e0e7ff;
104
+ border-radius: 8px;
105
+ border: 2px dashed #6366f1; */
106
+ }
107
+ .box {
108
+ flex: 1; /* Grow to fill space */
109
+ min-width: 300px; /* Stack if space < 300px */
110
+ /* Visual Styling */
111
+ background-color: white;
112
+ padding: 25px;
113
+ border-radius: 6px;
114
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
115
+ border: 1px solid #ddd;
116
+ }
117
+ .pagy {
118
+ padding: .5em;
119
+ margin: .3em 0;
120
+ width: fit-content;
121
+ box-shadow: 5px 5px 10px 0px rgba(0,0,0,0.2);
122
+ }
123
+ <%= Pagy::ROOT.join('stylesheets/pagy.css').read %>
124
+ </style>
125
+ </head>
126
+ <body>
127
+ <%= yield %>
128
+ </body>
129
+ </html>
130
+ ERB
131
+ end
132
+
133
+ template :main do
134
+ <<~ERB
135
+ <div class="main-content">
136
+ <h1>Pagy Keynav App</h1>
137
+ <p>Self-contained, standalone app usable to easily reproduce any Keynav related pagy issue
138
+ with ActiveRecord sets.</p>
139
+ <p>The panels below show how to use the <code>:root_key</code> option for independent instances in the same request.</p>
140
+
141
+ <p>Notice that Keynav works also with Sequel sets.</p>
142
+
143
+ <h2>Versions</h2>
144
+ <ul>
145
+ <li>Ruby: <%= RUBY_VERSION %></li>
146
+ <li>Rack: <%= Rack::RELEASE %></li>
147
+ <li>Sinatra: <%= Sinatra::VERSION %></li>
148
+ <li>Pagy: <%= Pagy::VERSION %></li>
149
+ </ul>
150
+
151
+ <div id="content">
152
+ <div class="box">
153
+ <h3>Collection 1</h3>
154
+ <p id="records">@ids: <%= @ids1.join(',') %></p>
155
+ <div class="collection">
156
+ <table border="1" style="border-collapse: collapse; border-spacing: 0; padding: 0.2rem;">
157
+ <tr>
158
+ <th scope="col">animal <%= order_symbol(@order[:animal]) %></th>
159
+ <th scope="col">name <%= order_symbol(@order[:name]) %></th>
160
+ <th scope="col">birthdate <%= order_symbol(@order[:birthdate]) %></th>
161
+ <th scope="col">id <%= order_symbol(@order[:id]) %></th>
162
+ </tr>
163
+ <% @pets1.each do |pet| %>
164
+ <tr>
165
+ <td><%= pet.animal %></td>
166
+ <td><%= pet.name %></td>
167
+ <td><%= pet.birthdate %></td>
168
+ <td><%= pet.id %></td>
169
+ </tr>
170
+ <% end %>
171
+ </table>
172
+ </div>
173
+
174
+ <h4>@pagy.series_nav</h4>
175
+ <%= @pagy1.series_nav(id: 'series-nav',
176
+ aria_label: 'Pages (nav)') %>
177
+
178
+ <h4>@pagy.series_nav_js (responsive)</h4>
179
+ <%= @pagy1.series_nav_js(id: 'series-nav-js-responsive',
180
+ aria_label: 'Pages (nav_js_responsive)',
181
+ steps: { 0 => 5, 500 => 7, 750 => 9, 1000 => 11 }) %>
182
+ <h4>@pagy.input_nav_js</h4>
183
+ <%= @pagy1.input_nav_js(id: 'input-nav-js',
184
+ aria_label: 'Pages (input_nav_js)') %>
185
+
186
+ <h4>@pagy.info_tag</h4>
187
+ <%= @pagy1.info_tag(id: 'pagy-info') %>
188
+ </div>
189
+
190
+ <div class="box">
191
+ <h3>Collection 2</h3>
192
+ <p id="records">@ids: <%= @ids2.join(',') %></p>
193
+ <div class="collection">
194
+ <table border="1" style="border-collapse: collapse; border-spacing: 0; padding: 0.2rem;">
195
+ <tr>
196
+ <th scope="col">animal <%= order_symbol(@order[:animal]) %></th>
197
+ <th scope="col">name <%= order_symbol(@order[:name]) %></th>
198
+ <th scope="col">birthdate <%= order_symbol(@order[:birthdate]) %></th>
199
+ <th scope="col">id <%= order_symbol(@order[:id]) %></th>
200
+ </tr>
201
+ <% @pets2.each do |pet| %>
202
+ <tr>
203
+ <td><%= pet.animal %></td>
204
+ <td><%= pet.name %></td>
205
+ <td><%= pet.birthdate %></td>
206
+ <td><%= pet.id %></td>
207
+ </tr>
208
+ <% end %>
209
+ </table>
210
+ </div>
211
+
212
+ <h4>@pagy.series_nav</h4>
213
+ <%= @pagy2.series_nav(id: 'series-nav',
214
+ aria_label: 'Pages (nav)') %>
215
+
216
+ <h4>@pagy.series_nav_js (responsive)</h4>
217
+ <%= @pagy2.series_nav_js(id: 'series-nav-js-responsive',
218
+ aria_label: 'Pages (nav_js_responsive)',
219
+ steps: { 0 => 5, 500 => 7, 750 => 9, 1000 => 11 }) %>
220
+ <h4>@pagy.input_nav_js</h4>
221
+ <%= @pagy2.input_nav_js(id: 'input-nav-js',
222
+ aria_label: 'Pages (input_nav_js)') %>
223
+
224
+ <h4>@pagy.info_tag</h4>
225
+ <%= @pagy2.info_tag(id: 'pagy-info') %>
226
+ </div>
227
+ </div>
228
+ </div>
229
+ ERB
230
+ end
231
+ end
232
+
233
+ # ActiveRecord setup
234
+ require 'active_record'
235
+
236
+ # Match the microsecods with the strings stored into the time columns of SQLite
237
+ # ActiveSupport::JSON::Encoding.time_precision = 6
238
+
239
+ # Log
240
+ output = ENV['APP_ENV'].equal?('showcase') ? IO::NULL : $stdout
241
+ ActiveRecord::Base.logger = Logger.new(output)
242
+ # SQLite DB files
243
+ dir = ENV['APP_ENV'].equal?('development') ? '.' : Dir.pwd # app dir in dev or pwd otherwise
244
+ abort "ERROR: Cannot create DB files: the directory #{dir.inspect} is not writable." \
245
+ unless File.writable?(dir)
246
+ # Connection
247
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "#{dir}/tmp/pagy-keyset-ar.sqlite3")
248
+ # Schema
249
+ ActiveRecord::Schema.define do
250
+ create_table :pets, force: true do |t|
251
+ t.string :animal
252
+ t.string :name
253
+ t.date :birthdate
254
+ end
255
+ end
256
+
257
+ # Models
258
+ class Pet < ActiveRecord::Base; end
259
+
260
+ data = <<~DATA
261
+ Luna | dog | 2018-03-10
262
+ Coco | cat | 2019-05-15
263
+ Dodo | dog | 2020-06-25
264
+ Wiki | bird | 2018-03-12
265
+ Baby | rabbit | 2020-01-13
266
+ Neki | horse | 2021-07-20
267
+ Tino | donkey | 2019-06-18
268
+ Plot | cat | 2022-09-21
269
+ Riki | cat | 2018-09-14
270
+ Susi | horse | 2018-10-26
271
+ Coco | pig | 2020-08-29
272
+ Momo | bird | 2023-08-25
273
+ Lili | cat | 2021-07-22
274
+ Beli | pig | 2020-07-26
275
+ Rocky | bird | 2022-08-19
276
+ Vyvy | dog | 2018-05-16
277
+ Susi | horse | 2024-01-25
278
+ Ella | cat | 2020-02-20
279
+ Rocky | dog | 2019-09-19
280
+ Juni | rabbit | 2020-08-24
281
+ Coco | bird | 2021-03-17
282
+ Susi | dog | 2021-07-28
283
+ Luna | horse | 2023-05-14
284
+ Gigi | pig | 2022-05-19
285
+ Coco | cat | 2020-02-20
286
+ Nino | donkey | 2019-06-17
287
+ Luna | cat | 2022-02-09
288
+ Popi | dog | 2020-09-26
289
+ Lili | pig | 2022-06-18
290
+ Mina | horse | 2021-04-21
291
+ Susi | rabbit | 2023-05-18
292
+ Toni | donkey | 2018-06-22
293
+ Rocky | horse | 2019-09-28
294
+ Lili | cat | 2019-03-18
295
+ Roby | cat | 2022-06-19
296
+ Anto | horse | 2022-08-18
297
+ Susi | pig | 2021-04-21
298
+ Boly | bird | 2020-03-29
299
+ Sky | cat | 2023-07-19
300
+ Lili | dog | 2020-01-28
301
+ Fami | snake | 2023-04-27
302
+ Lopi | pig | 2019-06-19
303
+ Rocky | snake | 2022-03-13
304
+ Denis | dog | 2022-06-19
305
+ Maca | cat | 2022-06-19
306
+ Luna | dog | 2022-08-15
307
+ Jeme | horse | 2019-08-08
308
+ Sary | bird | 2023-04-29
309
+ Rocky | bird | 2023-05-14
310
+ Coco | dog | 2023-05-27
311
+ DATA
312
+
313
+ # DB seed
314
+ pets = []
315
+ data.each_line(chomp: true) do |pet|
316
+ name, animal, birthdate = pet.split('|').map(&:strip)
317
+ pets << { name:, animal:, birthdate: }
318
+ end
319
+ Pet.insert_all(pets)
320
+
321
+ run PagyKeynav
data/apps/keynav.ru ADDED
@@ -0,0 +1,260 @@
1
+ # frozen_string_literal: true
2
+
3
+ # DESCRIPTION
4
+ # Showcase the Keynav pagination (ActiveRecord example)
5
+ #
6
+ # DOC
7
+ # https://ddnexus.github.io/pagy/playground/#keyset-apps
8
+ #
9
+ # BIN HELP
10
+ # pagy -h
11
+ #
12
+ # DEV USAGE
13
+ # pagy clone keynav
14
+ # pagy ./keynav.ru
15
+ #
16
+ # URL
17
+ # http://127.0.0.1:8000
18
+
19
+ VERSION = '43.2.0'
20
+
21
+ if VERSION != Pagy::VERSION
22
+ Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
23
+ end
24
+
25
+ # Bundle
26
+ require 'bundler/inline'
27
+ gemfile(!Pagy::ROOT.join('pagy.gemspec').exist?) do
28
+ source 'https://rubygems.org'
29
+ gem 'activerecord'
30
+ gem 'puma'
31
+ gem 'sinatra'
32
+ gem 'sqlite3'
33
+ end
34
+
35
+ # Sinatra setup
36
+ require 'sinatra/base'
37
+ # Sinatra application
38
+ class PagyKeynav < Sinatra::Base
39
+ include Pagy::Method
40
+
41
+ get('/javascripts/:file') do
42
+ format = params[:file].split('.').last
43
+ if format == 'js'
44
+ content_type 'application/javascript'
45
+ elsif format == 'map'
46
+ content_type 'application/json'
47
+ end
48
+ send_file Pagy::ROOT.join('javascripts', params[:file])
49
+ end
50
+
51
+ # Root route/action
52
+ get '/' do
53
+ Time.zone = 'UTC'
54
+
55
+ @order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }
56
+ @pagy, @pets = pagy(:keynav_js, Pet.order(@order), limit: 4, client_max_limit: 100)
57
+ # Support also root_key for replacing url in javascript
58
+ # @pagy, @pets = pagy(:keynav_js, Pet.order(@order), limit: 4, client_max_limit: 100, root_key: 'animal')
59
+ @ids = @pets.pluck(:id)
60
+ erb :main
61
+ end
62
+
63
+ helpers do
64
+ def order_symbol(dir)
65
+ { asc: '&#x2197;', desc: '&#x2198;' }[dir]
66
+ end
67
+ end
68
+
69
+ # Views
70
+ template :layout do
71
+ <<~ERB
72
+ <!DOCTYPE html>
73
+ <html lang="en">
74
+ <html>
75
+ <head>
76
+ <title>Pagy Keynav App</title>
77
+ <script src="javascripts/pagy.js"></script>
78
+ <script>
79
+ window.addEventListener("load", Pagy.init);
80
+ </script>
81
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
82
+ <style type="text/css">
83
+ @media screen { html, body {
84
+ font-size: 1rem;
85
+ line-height: 1.2s;
86
+ padding: 0;
87
+ margin: 0;
88
+ } }
89
+ body {
90
+ background: white !important;
91
+ margin: 0 !important;
92
+ font-family: sans-serif !important;
93
+ }
94
+ .main-content {
95
+ padding: 1rem 1.5rem 2rem !important;
96
+ }
97
+ .pagy {
98
+ padding: .5em;
99
+ margin: .3em 0;
100
+ width: fit-content;
101
+ box-shadow: 5px 5px 10px 0px rgba(0,0,0,0.2);
102
+ }
103
+
104
+
105
+ <%= Pagy::ROOT.join('stylesheets/pagy.css').read %>
106
+ </style>
107
+ </head>
108
+ <body>
109
+ <%= yield %>
110
+ </body>
111
+ </html>
112
+ ERB
113
+ end
114
+
115
+ template :main do
116
+ <<~ERB
117
+ <div class="main-content">
118
+ <h1>Pagy Keynav App</h1>
119
+ <p>Self-contained, standalone app usable to easily reproduce any Keynav related pagy issue
120
+ with ActiveRecord sets.</p>
121
+
122
+ <p>Notice that Keynav works also with Sequel sets.</p>
123
+
124
+ <h2>Versions</h2>
125
+ <ul>
126
+ <li>Ruby: <%= RUBY_VERSION %></li>
127
+ <li>Rack: <%= Rack::RELEASE %></li>
128
+ <li>Sinatra: <%= Sinatra::VERSION %></li>
129
+ <li>Pagy: <%= Pagy::VERSION %></li>
130
+ </ul>
131
+
132
+ <h3>Collection</h3>
133
+ <p id="records">@ids: <%= @ids.join(',') %></p>
134
+ <div class="collection">
135
+ <table border="1" style="border-collapse: collapse; border-spacing: 0; padding: 0.2rem;">
136
+ <tr>
137
+ <th scope="col">animal <%= order_symbol(@order[:animal]) %></th>
138
+ <th scope="col">name <%= order_symbol(@order[:name]) %></th>
139
+ <th scope="col">birthdate <%= order_symbol(@order[:birthdate]) %></th>
140
+ <th scope="col">id <%= order_symbol(@order[:id]) %></th>
141
+ </tr>
142
+ <% @pets.each do |pet| %>
143
+ <tr>
144
+ <td><%= pet.animal %></td>
145
+ <td><%= pet.name %></td>
146
+ <td><%= pet.birthdate %></td>
147
+ <td><%= pet.id %></td>
148
+ </tr>
149
+ <% end %>
150
+ </table>
151
+ </div>
152
+
153
+ <h4>@pagy.series_nav</h4>
154
+ <%= @pagy.series_nav(id: 'series-nav',
155
+ aria_label: 'Pages (nav)') %>
156
+
157
+ <h4>@pagy.series_nav_js (responsive)</h4>
158
+ <%= @pagy.series_nav_js(id: 'series-nav-js-responsive',
159
+ aria_label: 'Pages (nav_js_responsive)',
160
+ steps: { 0 => 5, 500 => 7, 750 => 9, 1000 => 11 }) %>
161
+ <h4>@pagy.input_nav_js</h4>
162
+ <%= @pagy.input_nav_js(id: 'input-nav-js',
163
+ aria_label: 'Pages (input_nav_js)') %>
164
+
165
+ <h4>@pagy.info_tag</h4>
166
+ <%= @pagy.info_tag(id: 'pagy-info') %>
167
+ </div>
168
+ ERB
169
+ end
170
+ end
171
+
172
+ # ActiveRecord setup
173
+ require 'active_record'
174
+
175
+ # Match the microsecods with the strings stored into the time columns of SQLite
176
+ # ActiveSupport::JSON::Encoding.time_precision = 6
177
+
178
+ # Log
179
+ output = ENV['APP_ENV'].equal?('showcase') ? IO::NULL : $stdout
180
+ ActiveRecord::Base.logger = Logger.new(output)
181
+ # SQLite DB files
182
+ dir = ENV['APP_ENV'].equal?('development') ? '.' : Dir.pwd # app dir in dev or pwd otherwise
183
+ abort "ERROR: Cannot create DB files: the directory #{dir.inspect} is not writable." \
184
+ unless File.writable?(dir)
185
+ # Connection
186
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "#{dir}/tmp/pagy-keyset-ar.sqlite3")
187
+ # Schema
188
+ ActiveRecord::Schema.define do
189
+ create_table :pets, force: true do |t|
190
+ t.string :animal
191
+ t.string :name
192
+ t.date :birthdate
193
+ end
194
+ end
195
+
196
+ # Models
197
+ class Pet < ActiveRecord::Base; end
198
+
199
+ data = <<~DATA
200
+ Luna | dog | 2018-03-10
201
+ Coco | cat | 2019-05-15
202
+ Dodo | dog | 2020-06-25
203
+ Wiki | bird | 2018-03-12
204
+ Baby | rabbit | 2020-01-13
205
+ Neki | horse | 2021-07-20
206
+ Tino | donkey | 2019-06-18
207
+ Plot | cat | 2022-09-21
208
+ Riki | cat | 2018-09-14
209
+ Susi | horse | 2018-10-26
210
+ Coco | pig | 2020-08-29
211
+ Momo | bird | 2023-08-25
212
+ Lili | cat | 2021-07-22
213
+ Beli | pig | 2020-07-26
214
+ Rocky | bird | 2022-08-19
215
+ Vyvy | dog | 2018-05-16
216
+ Susi | horse | 2024-01-25
217
+ Ella | cat | 2020-02-20
218
+ Rocky | dog | 2019-09-19
219
+ Juni | rabbit | 2020-08-24
220
+ Coco | bird | 2021-03-17
221
+ Susi | dog | 2021-07-28
222
+ Luna | horse | 2023-05-14
223
+ Gigi | pig | 2022-05-19
224
+ Coco | cat | 2020-02-20
225
+ Nino | donkey | 2019-06-17
226
+ Luna | cat | 2022-02-09
227
+ Popi | dog | 2020-09-26
228
+ Lili | pig | 2022-06-18
229
+ Mina | horse | 2021-04-21
230
+ Susi | rabbit | 2023-05-18
231
+ Toni | donkey | 2018-06-22
232
+ Rocky | horse | 2019-09-28
233
+ Lili | cat | 2019-03-18
234
+ Roby | cat | 2022-06-19
235
+ Anto | horse | 2022-08-18
236
+ Susi | pig | 2021-04-21
237
+ Boly | bird | 2020-03-29
238
+ Sky | cat | 2023-07-19
239
+ Lili | dog | 2020-01-28
240
+ Fami | snake | 2023-04-27
241
+ Lopi | pig | 2019-06-19
242
+ Rocky | snake | 2022-03-13
243
+ Denis | dog | 2022-06-19
244
+ Maca | cat | 2022-06-19
245
+ Luna | dog | 2022-08-15
246
+ Jeme | horse | 2019-08-08
247
+ Sary | bird | 2023-04-29
248
+ Rocky | bird | 2023-05-14
249
+ Coco | dog | 2023-05-27
250
+ DATA
251
+
252
+ # DB seed
253
+ pets = []
254
+ data.each_line(chomp: true) do |pet|
255
+ name, animal, birthdate = pet.split('|').map(&:strip)
256
+ pets << { name:, animal:, birthdate: }
257
+ end
258
+ Pet.insert_all(pets)
259
+
260
+ run PagyKeynav