pagy 43.0.7 → 43.1.4
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/apps/calendar.ru +1 -1
- data/apps/demo.ru +3 -3
- data/apps/keynav+root_key.ru +321 -0
- data/apps/keynav.ru +3 -1
- data/apps/keyset.ru +1 -1
- data/apps/keyset_sequel.ru +1 -1
- data/apps/rails.ru +1 -1
- data/apps/repro.ru +4 -4
- data/bin/pagy +1 -1
- data/config/pagy.rb +1 -1
- data/javascripts/ai_widget.js +1 -1
- data/javascripts/pagy.js +11 -10
- data/javascripts/pagy.js.map +3 -3
- data/javascripts/pagy.min.js +1 -1
- data/javascripts/pagy.mjs +10 -9
- data/lib/pagy/classes/exceptions.rb +0 -8
- data/lib/pagy/classes/keyset/keynav.rb +2 -1
- data/lib/pagy/classes/offset/countless.rb +18 -13
- data/lib/pagy/classes/request.rb +14 -15
- data/lib/pagy/modules/abilities/linkable.rb +12 -15
- data/lib/pagy/modules/abilities/rangeable.rb +3 -2
- data/lib/pagy/modules/console.rb +2 -16
- data/lib/pagy/modules/searcher.rb +5 -7
- data/lib/pagy/toolbox/helpers/support/a_lambda.rb +1 -1
- data/lib/pagy/toolbox/paginators/calendar.rb +0 -1
- data/lib/pagy/toolbox/paginators/countless.rb +10 -15
- data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +16 -19
- data/lib/pagy/toolbox/paginators/keynav_js.rb +13 -16
- data/lib/pagy/toolbox/paginators/keyset.rb +6 -9
- data/lib/pagy/toolbox/paginators/meilisearch.rb +16 -19
- data/lib/pagy/toolbox/paginators/method.rb +10 -3
- data/lib/pagy/toolbox/paginators/offset.rb +7 -10
- data/lib/pagy/toolbox/paginators/searchkick.rb +16 -19
- data/lib/pagy.rb +6 -4
- data/locales/id.yml +1 -3
- data/locales/ja.yml +1 -3
- data/locales/km.yml +1 -3
- data/locales/sw.yml +2 -2
- metadata +2 -1
data/javascripts/pagy.mjs
CHANGED
|
@@ -23,18 +23,18 @@ const Pagy = (() => {
|
|
|
23
23
|
}));
|
|
24
24
|
const B64SafeEncode = (unicode) => btoa(String.fromCharCode(...new TextEncoder().encode(unicode))).replace(/[+/=]/g, (m) => m == "+" ? "-" : m == "/" ? "_" : ""), B64Decode = (base64) => new TextDecoder().decode(Uint8Array.from(atob(base64), (c) => c.charCodeAt(0)));
|
|
25
25
|
const randKey = () => Math.floor(Math.random() * 36 ** 3).toString(36);
|
|
26
|
-
const augmentKeynav = async (nav, [storageKey, pageKey, last, spliceArgs]) => {
|
|
27
|
-
let
|
|
26
|
+
const augmentKeynav = async (nav, [storageKey, rootKey, pageKey, last, spliceArgs]) => {
|
|
27
|
+
let augmentPage;
|
|
28
28
|
const browserKey = document.cookie.split(/;\s+/).find((row) => row.startsWith(pagy + "="))?.split("=")[1] ?? randKey();
|
|
29
29
|
document.cookie = pagy + "=" + browserKey;
|
|
30
30
|
if (storageKey && !(storageKey in storage)) {
|
|
31
31
|
sync.postMessage({ from: tabId, key: storageKey });
|
|
32
32
|
await new Promise((resolve) => setTimeout(() => resolve(""), 100));
|
|
33
33
|
if (!(storageKey in storage)) {
|
|
34
|
-
|
|
34
|
+
augmentPage = (page) => page + "+" + last;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
if (!
|
|
37
|
+
if (!augmentPage) {
|
|
38
38
|
if (!storageKey) {
|
|
39
39
|
do {
|
|
40
40
|
storageKey = randKey();
|
|
@@ -45,7 +45,7 @@ const Pagy = (() => {
|
|
|
45
45
|
cutoffs.splice(...spliceArgs);
|
|
46
46
|
storage.setItem(storageKey, JSON.stringify(cutoffs));
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
augmentPage = (page) => {
|
|
49
49
|
const pageNum = parseInt(page);
|
|
50
50
|
return B64SafeEncode(JSON.stringify([
|
|
51
51
|
browserKey,
|
|
@@ -57,11 +57,12 @@ const Pagy = (() => {
|
|
|
57
57
|
]));
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
+
const search = rootKey ? `${rootKey}%5B${pageKey}%5D` : pageKey;
|
|
61
|
+
const re = new RegExp(`(?<=\\?.*)(\\b${search}=)(\\d+)`);
|
|
60
62
|
for (const a of nav.querySelectorAll("a[href]")) {
|
|
61
|
-
|
|
62
|
-
a.href = url.replace(re, pageKey + "=" + augment(url.match(re)[1]));
|
|
63
|
+
a.href = a.href.replace(re, (_match, prefix, digit) => `${prefix}${augmentPage(digit)}`);
|
|
63
64
|
}
|
|
64
|
-
return
|
|
65
|
+
return augmentPage;
|
|
65
66
|
};
|
|
66
67
|
const buildNavJs = (nav, [
|
|
67
68
|
[before, anchor, current, gap, after],
|
|
@@ -123,7 +124,7 @@ const Pagy = (() => {
|
|
|
123
124
|
});
|
|
124
125
|
};
|
|
125
126
|
return {
|
|
126
|
-
version: "43.
|
|
127
|
+
version: "43.1.4",
|
|
127
128
|
init(arg) {
|
|
128
129
|
const target = arg instanceof HTMLElement ? arg : document, elements = target.querySelectorAll("[data-pagy]");
|
|
129
130
|
for (const element of elements) {
|
|
@@ -22,12 +22,4 @@ class Pagy
|
|
|
22
22
|
|
|
23
23
|
# Generic internal error
|
|
24
24
|
class InternalError < StandardError; end
|
|
25
|
-
|
|
26
|
-
# JsonApi :page param error
|
|
27
|
-
class JsonapiReservedParamError < StandardError
|
|
28
|
-
# Inform about the actual value
|
|
29
|
-
def initialize(value)
|
|
30
|
-
super("expected reserved :page param to be nil or Hash-like; got #{value.inspect}")
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
25
|
end
|
|
@@ -27,6 +27,7 @@ class Pagy
|
|
|
27
27
|
# Prepare the @update for the client when it's a new page, and return the next page number
|
|
28
28
|
def next
|
|
29
29
|
records
|
|
30
|
+
@count = 0 if !@more && @page == 1 # empty records (trigger the right info message for known 0 count)
|
|
30
31
|
return if !@more || (@options[:max_pages] && @page >= @options[:max_pages])
|
|
31
32
|
|
|
32
33
|
@next ||= begin
|
|
@@ -50,7 +51,7 @@ class Pagy
|
|
|
50
51
|
else
|
|
51
52
|
@page = @last = 1
|
|
52
53
|
end
|
|
53
|
-
@update = [storage_key, @options[:page_key]]
|
|
54
|
+
@update = [storage_key, @options[:root_key], @options[:page_key]]
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
# Use a compound predicate to fetch the records
|
|
@@ -8,7 +8,7 @@ class Pagy
|
|
|
8
8
|
assign_options(**)
|
|
9
9
|
assign_and_check(limit: 1, page: 1)
|
|
10
10
|
@page = upto_max_pages(@page)
|
|
11
|
-
|
|
11
|
+
@last = upto_max_pages(@options[:last]) unless @options[:headless]
|
|
12
12
|
assign_offset
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -25,32 +25,37 @@ class Pagy
|
|
|
25
25
|
def countless? = true
|
|
26
26
|
|
|
27
27
|
def upto_max_pages(value)
|
|
28
|
-
return value unless @options[:max_pages]
|
|
28
|
+
return value unless value && @options[:max_pages]
|
|
29
29
|
|
|
30
30
|
[value, @options[:max_pages]].min
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
def assign_last
|
|
34
|
-
return unless @options[:last]
|
|
35
|
-
|
|
36
|
-
@last = upto_max_pages(@options[:last].to_i)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
33
|
# Finalize the instance variables based on the fetched size
|
|
40
34
|
def finalize(fetched_size)
|
|
35
|
+
# empty records (trigger the right info message for known 0 count)
|
|
36
|
+
@count = 0 if fetched_size.zero? && @page == 1
|
|
41
37
|
return self unless in_range? { fetched_size.positive? || @page == 1 }
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
@last = upto_max_pages(fetched_size > @limit ? @page + 1 : @page)
|
|
47
|
-
end
|
|
39
|
+
past = @last && @page < @last # this page has been past
|
|
40
|
+
more = fetched_size > @limit # more pages after this one
|
|
41
|
+
@last = upto_max_pages(more ? @page + 1 : @page) unless past && more
|
|
48
42
|
@in = [fetched_size, @limit].min
|
|
49
43
|
@from = @in.zero? ? 0 : @offset + 1
|
|
50
44
|
@to = @offset + @in
|
|
51
45
|
assign_previous_and_next
|
|
52
46
|
self
|
|
53
47
|
end
|
|
48
|
+
|
|
49
|
+
# Called by false in_range?
|
|
50
|
+
def assign_empty_page_variables
|
|
51
|
+
@in = @from = @to = 0
|
|
52
|
+
target_last = [@page - 1, 1].max
|
|
53
|
+
@last = [@last || target_last, target_last].min
|
|
54
|
+
@previous = @last
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Support easy countless page param overriding (for legacy param and behavior)
|
|
58
|
+
def compose_page_param(page) = "#{page || 1}+#{@last}"
|
|
54
59
|
end
|
|
55
60
|
end
|
|
56
61
|
end
|
data/lib/pagy/classes/request.rb
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class Pagy
|
|
4
|
-
# Decouple the
|
|
5
|
-
# Resolve :page and :limit
|
|
6
|
-
#
|
|
4
|
+
# Decouple the request from the env, allowing non-rack apps to use pagy by passing a hash.
|
|
5
|
+
# Resolve the :page and :limit options from params.
|
|
7
6
|
class Request
|
|
8
|
-
def initialize(
|
|
7
|
+
def initialize(options)
|
|
8
|
+
@options = options
|
|
9
|
+
request = @options[:request]
|
|
9
10
|
@base_url, @path, @params, @cookie =
|
|
10
11
|
if request.is_a?(Hash)
|
|
11
12
|
request.values_at(:base_url, :path, :params, :cookie)
|
|
12
13
|
else
|
|
13
14
|
[request.base_url, request.path, request.GET.merge(request.POST), request.cookies['pagy']]
|
|
14
15
|
end
|
|
15
|
-
@jsonapi = @params['page'] && options[:jsonapi]
|
|
16
|
-
raise JsonapiReservedParamError, @params['page'] if @jsonapi && !@params['page'].respond_to?(:fetch)
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
attr_reader :base_url, :path, :params, :cookie
|
|
20
19
|
|
|
21
|
-
def resolve_page(
|
|
22
|
-
page_key = options[:page_key] || DEFAULT[:page_key]
|
|
23
|
-
page = @
|
|
20
|
+
def resolve_page(force_integer: true)
|
|
21
|
+
page_key = @options[:page_key] || DEFAULT[:page_key]
|
|
22
|
+
page = @params.dig(@options[:root_key], page_key) || @params[page_key]
|
|
24
23
|
page = nil if page == '' # fix for app-generated queries like ?page=
|
|
25
24
|
force_integer ? (page || 1).to_i : page
|
|
26
25
|
end
|
|
27
26
|
|
|
28
|
-
def resolve_limit
|
|
29
|
-
limit_key = options[:limit_key] || DEFAULT[:limit_key]
|
|
30
|
-
return options[:limit] || DEFAULT[:limit] \
|
|
31
|
-
unless options[:client_max_limit] &&
|
|
32
|
-
(requested_limit = @
|
|
27
|
+
def resolve_limit
|
|
28
|
+
limit_key = @options[:limit_key] || DEFAULT[:limit_key]
|
|
29
|
+
return @options[:limit] || DEFAULT[:limit] \
|
|
30
|
+
unless @options[:client_max_limit] &&
|
|
31
|
+
(requested_limit = @params.dig(@options[:root_key], limit_key) || @params[limit_key])
|
|
33
32
|
|
|
34
|
-
[requested_limit.to_i, options[:client_max_limit]].min
|
|
33
|
+
[requested_limit.to_i, @options[:client_max_limit]].min
|
|
35
34
|
end
|
|
36
35
|
end
|
|
37
36
|
end
|
|
@@ -9,25 +9,22 @@ class Pagy
|
|
|
9
9
|
module_function
|
|
10
10
|
|
|
11
11
|
# Extracted from Rack::Utils and reformatted for rubocop
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
-
def build_nested_query(value, prefix = nil, unescaped = [])
|
|
12
|
+
# Allow unescaped Pagy::RawQueryValue
|
|
13
|
+
def build_nested_query(value, prefix = nil)
|
|
15
14
|
case value
|
|
16
15
|
when Array
|
|
17
|
-
value.map { |v| build_nested_query(v, "#{prefix}[]"
|
|
16
|
+
value.map { |v| build_nested_query(v, "#{prefix}[]") }.join('&')
|
|
18
17
|
when Hash
|
|
19
18
|
value.map do |k, v|
|
|
20
|
-
|
|
21
|
-
unescaped[unescaped.find_index(k)] = new_k if unescaped.size.positive? && new_k != k && unescaped.include?(k)
|
|
22
|
-
build_nested_query(v, new_k, unescaped)
|
|
19
|
+
build_nested_query(v, prefix ? "#{prefix}[#{k}]" : k)
|
|
23
20
|
end.delete_if(&:empty?).join('&')
|
|
24
21
|
when nil
|
|
25
22
|
escape(prefix)
|
|
26
23
|
else
|
|
27
24
|
raise ArgumentError, 'value must be a Hash' if prefix.nil?
|
|
28
|
-
return "#{escape(prefix)}=#{value}" if unescaped.include?(prefix)
|
|
29
25
|
|
|
30
|
-
|
|
26
|
+
final_value = value.is_a?(RawQueryValue) ? value.to_s : escape(value)
|
|
27
|
+
"#{escape(prefix)}=#{final_value}"
|
|
31
28
|
end
|
|
32
29
|
end
|
|
33
30
|
|
|
@@ -40,18 +37,18 @@ class Pagy
|
|
|
40
37
|
|
|
41
38
|
# Return the URL for the page, relying on the Pagy::Request
|
|
42
39
|
def compose_page_url(page, limit_token: nil, **options)
|
|
43
|
-
|
|
40
|
+
root_key, page_key, limit_key, limit, client_max_limit, querify, absolute, path, fragment =
|
|
44
41
|
@options.merge(options)
|
|
45
|
-
.values_at(:
|
|
42
|
+
.values_at(:root_key, :page_key, :limit_key, :limit, :client_max_limit, :querify, :absolute, :path, :fragment)
|
|
46
43
|
params = @request.params.clone(freeze: false)
|
|
47
|
-
params.delete(
|
|
44
|
+
params.delete(root_key || page_key)
|
|
48
45
|
factors = {}.tap do |h|
|
|
49
|
-
h[page_key] = countless? ?
|
|
46
|
+
h[page_key] = countless? ? RawQueryValue.new(compose_page_param(page)) : page
|
|
50
47
|
h[limit_key] = limit_token || limit if client_max_limit
|
|
51
48
|
end.compact # No empty params
|
|
52
|
-
params.merge!(
|
|
49
|
+
params.merge!(root_key ? { root_key => factors } : factors) if factors.size.positive?
|
|
53
50
|
querify&.(params) # Must modify the params: the returned value is ignored
|
|
54
|
-
query_string = QueryUtils.build_nested_query(params
|
|
51
|
+
query_string = QueryUtils.build_nested_query(params)
|
|
55
52
|
query_string = "?#{query_string}" unless query_string.empty?
|
|
56
53
|
fragment &&= %(##{fragment}) unless fragment&.start_with?('#')
|
|
57
54
|
"#{@request.base_url if absolute}#{path || @request.path}#{query_string}#{fragment}"
|
|
@@ -5,11 +5,12 @@ class Pagy
|
|
|
5
5
|
module Rangeable
|
|
6
6
|
# Check if in range
|
|
7
7
|
def in_range?
|
|
8
|
-
return @in_range if defined?(@in_range)
|
|
8
|
+
return @in_range if defined?(@in_range)
|
|
9
|
+
return true if (@in_range = yield)
|
|
9
10
|
raise RangeError.new(self, :page, "in 1..#{@last}", @page) if @options[:raise_range_error]
|
|
10
11
|
|
|
11
12
|
assign_empty_page_variables
|
|
12
|
-
false
|
|
13
|
+
@in_range = false
|
|
13
14
|
end
|
|
14
15
|
end
|
|
15
16
|
end
|
data/lib/pagy/modules/console.rb
CHANGED
|
@@ -3,20 +3,6 @@
|
|
|
3
3
|
class Pagy
|
|
4
4
|
# Provide a ready to use pagy environment when included in irb/rails console
|
|
5
5
|
module Console
|
|
6
|
-
class Request
|
|
7
|
-
attr_accessor :base_url, :path, :params
|
|
8
|
-
|
|
9
|
-
def initialize
|
|
10
|
-
@base_url = 'http://www.example.com'
|
|
11
|
-
@path = '/path'
|
|
12
|
-
@params = { example: '123' }
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def GET = @params # rubocop:disable Naming/MethodName
|
|
16
|
-
|
|
17
|
-
def cookies = {}
|
|
18
|
-
end
|
|
19
|
-
|
|
20
6
|
class Collection < Array
|
|
21
7
|
def initialize(arr = Array(1..1000))
|
|
22
8
|
super
|
|
@@ -31,8 +17,8 @@ class Pagy
|
|
|
31
17
|
include Method
|
|
32
18
|
|
|
33
19
|
# Direct reference to request.params via a method
|
|
34
|
-
def
|
|
35
|
-
def
|
|
20
|
+
def request = @request ||= { base_url: 'http://www.example.com', path: '/path', params: { example: '123' } }
|
|
21
|
+
def params = request[:params]
|
|
36
22
|
def collection = Collection
|
|
37
23
|
end
|
|
38
24
|
end
|
|
@@ -6,13 +6,11 @@ class Pagy
|
|
|
6
6
|
module_function
|
|
7
7
|
|
|
8
8
|
# Common search logic
|
|
9
|
-
def wrap(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
pagy, results = yield
|
|
15
|
-
calling = pagy_search_args[4..]
|
|
9
|
+
def wrap(pagy_search_args, options)
|
|
10
|
+
options[:page] ||= options[:request].resolve_page
|
|
11
|
+
options[:limit] = options[:request].resolve_limit
|
|
12
|
+
pagy, results = yield
|
|
13
|
+
calling = pagy_search_args[4..]
|
|
16
14
|
[pagy, calling.empty? ? results : results.send(*calling)]
|
|
17
15
|
end
|
|
18
16
|
end
|
|
@@ -18,7 +18,7 @@ class Pagy
|
|
|
18
18
|
%( #{anchor_string}) if anchor_string}).split(PAGE_TOKEN, 2)
|
|
19
19
|
|
|
20
20
|
lambda do |page, text = page_label(page), classes: nil, aria_label: nil|
|
|
21
|
-
title = if (counts = @options[:counts]) # only for calendar
|
|
21
|
+
title = if (counts = @options[:counts]) # only for calendar with counts
|
|
22
22
|
count = counts[page - 1]
|
|
23
23
|
classes = classes ? "#{classes} empty-page" : 'empty-page' if count.zero?
|
|
24
24
|
info_key = count.zero? ? 'pagy.info_tag.no_items' : 'pagy.info_tag.single_page'
|
|
@@ -11,7 +11,6 @@ class Pagy
|
|
|
11
11
|
raise ArgumentError, "keys must be in #{allowed_options.inspect}" \
|
|
12
12
|
unless config.is_a?(Hash) && (config.keys - allowed_options).empty?
|
|
13
13
|
|
|
14
|
-
config[:request] = Request.new(config[:request] || request)
|
|
15
14
|
config[:offset] ||= {}
|
|
16
15
|
unless config[:disabled]
|
|
17
16
|
calendar, from, to =
|
|
@@ -4,22 +4,17 @@ class Pagy
|
|
|
4
4
|
module CountlessPaginator
|
|
5
5
|
module_function
|
|
6
6
|
|
|
7
|
-
# Return
|
|
8
|
-
def paginate(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
p, l = page.split(/ /, 2).map(&:to_i)
|
|
15
|
-
options[:page] = p if p.positive?
|
|
16
|
-
options[:last] = l if l&.positive?
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
options[:limit] = request.resolve_limit(options)
|
|
20
|
-
pagy = Offset::Countless.new(**options, request:)
|
|
21
|
-
[pagy, pagy.records(collection)]
|
|
7
|
+
# Return the Offset::Countless instance and records
|
|
8
|
+
def paginate(collection, options)
|
|
9
|
+
options[:page] ||= options[:request].resolve_page(force_integer: false) # accept nil and strings
|
|
10
|
+
if options[:page].is_a?(String)
|
|
11
|
+
page, last = options[:page].split(/ /, 2).map(&:to_i) # decoded '+' added by the compose_page_url
|
|
12
|
+
options[:page] = page
|
|
13
|
+
options[:last] = last if last&.positive?
|
|
22
14
|
end
|
|
15
|
+
options[:limit] = options[:request].resolve_limit
|
|
16
|
+
pagy = Offset::Countless.new(**options)
|
|
17
|
+
[pagy, pagy.records(collection)]
|
|
23
18
|
end
|
|
24
19
|
end
|
|
25
20
|
end
|
|
@@ -7,26 +7,23 @@ class Pagy
|
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
9
|
# Paginate from the search object
|
|
10
|
-
def paginate(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
options[:count] = ElasticsearchRails.total_count(results)
|
|
21
|
-
[ElasticsearchRails.new(**options), results]
|
|
22
|
-
end
|
|
23
|
-
else
|
|
24
|
-
# The search is an elasticsearch_rails response
|
|
25
|
-
options[:limit] = search.search.options[:size] || 10
|
|
26
|
-
options[:page] = ((search.search.options[:from] || 0) / options[:limit]) + 1
|
|
27
|
-
options[:count] = ElasticsearchRails.total_count(search)
|
|
28
|
-
ElasticsearchRails.new(**options)
|
|
10
|
+
def paginate(search, options)
|
|
11
|
+
if search.is_a?(Search::Arguments)
|
|
12
|
+
# The search is the array of pagy_search arguments
|
|
13
|
+
Searcher.wrap(search, options) do
|
|
14
|
+
model, query_or_payload, search_options = search
|
|
15
|
+
search_options[:size] = options[:limit]
|
|
16
|
+
search_options[:from] = options[:limit] * ((options[:page] || 1) - 1)
|
|
17
|
+
results = model.send(ElasticsearchRails::DEFAULT[:search_method], query_or_payload, **search_options)
|
|
18
|
+
options[:count] = ElasticsearchRails.total_count(results)
|
|
19
|
+
[ElasticsearchRails.new(**options), results]
|
|
29
20
|
end
|
|
21
|
+
else
|
|
22
|
+
# The search is an elasticsearch_rails response
|
|
23
|
+
options[:limit] = search.search.options[:size] || 10
|
|
24
|
+
options[:page] = ((search.search.options[:from] || 0) / options[:limit]) + 1
|
|
25
|
+
options[:count] = ElasticsearchRails.total_count(search)
|
|
26
|
+
ElasticsearchRails.new(**options)
|
|
30
27
|
end
|
|
31
28
|
end
|
|
32
29
|
end
|
|
@@ -6,24 +6,21 @@ class Pagy
|
|
|
6
6
|
module KeynavJsPaginator
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
|
-
# Return Pagy::Keyset::Keynav
|
|
9
|
+
# Return the Pagy::Keyset::Keynav instance and paginated records.
|
|
10
10
|
# Fall back to :countless if the :page has no client data.
|
|
11
|
-
def paginate(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# Restart the pagination from page 1 if the url has been requested from another browser
|
|
20
|
-
options[:page] = page_arguments if request.cookie == page_arguments.shift
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
options[:limit] = request.resolve_limit(options)
|
|
24
|
-
pagy = Keyset::Keynav.new(set, **options, request:)
|
|
25
|
-
[pagy, pagy.records]
|
|
11
|
+
def paginate(set, options)
|
|
12
|
+
page = options[:request].resolve_page(force_integer: false) # allow nil
|
|
13
|
+
if page&.match(' ') # countless page -> no augmentation -> fallback
|
|
14
|
+
return CountlessPaginator.paginate(set, page:, **options)
|
|
15
|
+
elsif page.is_a?(String) # keynav page param
|
|
16
|
+
page_arguments = JSON.parse(B64.urlsafe_decode(page))
|
|
17
|
+
# Restart the pagination from page 1/nil if the url has been requested from another browser
|
|
18
|
+
options[:page] = page_arguments if options[:request].cookie == page_arguments.shift
|
|
26
19
|
end
|
|
20
|
+
|
|
21
|
+
options[:limit] = options[:request].resolve_limit
|
|
22
|
+
pagy = Keyset::Keynav.new(set, **options)
|
|
23
|
+
[pagy, pagy.records]
|
|
27
24
|
end
|
|
28
25
|
end
|
|
29
26
|
end
|
|
@@ -4,15 +4,12 @@ class Pagy
|
|
|
4
4
|
module KeysetPaginator
|
|
5
5
|
module_function
|
|
6
6
|
|
|
7
|
-
# Return Pagy::Keyset
|
|
8
|
-
def paginate(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
pagy = Keyset.new(set, **options, request:)
|
|
14
|
-
[pagy, pagy.records]
|
|
15
|
-
end
|
|
7
|
+
# Return Pagy::Keyset instance and paginated records
|
|
8
|
+
def paginate(set, options)
|
|
9
|
+
options[:page] ||= options[:request].resolve_page(force_integer: false) # allow nil
|
|
10
|
+
options[:limit] = options[:request].resolve_limit
|
|
11
|
+
pagy = Keyset.new(set, **options)
|
|
12
|
+
[pagy, pagy.records]
|
|
16
13
|
end
|
|
17
14
|
end
|
|
18
15
|
end
|
|
@@ -7,26 +7,23 @@ class Pagy
|
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
9
|
# Paginate from the search object
|
|
10
|
-
def paginate(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
options[:count] = results.raw_answer['totalHits']
|
|
21
|
-
[Meilisearch.new(**options), results]
|
|
22
|
-
end
|
|
23
|
-
else
|
|
24
|
-
# The search is a meilisearch results object
|
|
25
|
-
options[:limit] = search.raw_answer['hitsPerPage']
|
|
26
|
-
options[:page] = search.raw_answer['page']
|
|
27
|
-
options[:count] = search.raw_answer['totalHits']
|
|
28
|
-
Meilisearch.new(**options)
|
|
10
|
+
def paginate(search, options)
|
|
11
|
+
if search.is_a?(Search::Arguments)
|
|
12
|
+
# The search is the array of pagy_search arguments
|
|
13
|
+
Searcher.wrap(search, options) do
|
|
14
|
+
model, term, search_options = search
|
|
15
|
+
search_options[:hits_per_page] = options[:limit]
|
|
16
|
+
search_options[:page] = options[:page]
|
|
17
|
+
results = model.send(Meilisearch::DEFAULT[:search_method], term, search_options)
|
|
18
|
+
options[:count] = results.raw_answer['totalHits']
|
|
19
|
+
[Meilisearch.new(**options), results]
|
|
29
20
|
end
|
|
21
|
+
else
|
|
22
|
+
# The search is a meilisearch results object
|
|
23
|
+
options[:limit] = search.raw_answer['hitsPerPage']
|
|
24
|
+
options[:page] = search.raw_answer['page']
|
|
25
|
+
options[:count] = search.raw_answer['totalHits']
|
|
26
|
+
Meilisearch.new(**options)
|
|
30
27
|
end
|
|
31
28
|
end
|
|
32
29
|
end
|
|
@@ -15,13 +15,20 @@ class Pagy
|
|
|
15
15
|
path = Pathname.new(__dir__)
|
|
16
16
|
paginators.each { |symbol, name| autoload name, path.join(symbol.to_s) }
|
|
17
17
|
|
|
18
|
-
#
|
|
18
|
+
# Pagy::Method defines the #pagy method to be included in the app controller/view.
|
|
19
19
|
Method = Module.new do
|
|
20
20
|
protected
|
|
21
21
|
|
|
22
22
|
define_method :pagy do |paginator = :offset, collection, **options|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
arguments = if paginator == :calendar
|
|
24
|
+
[self, collection, options]
|
|
25
|
+
else
|
|
26
|
+
[collection, options = Pagy.options.merge(options)]
|
|
27
|
+
end
|
|
28
|
+
options[:root_key] = 'page' if options[:jsonapi] # enforce 'page' root_key for JSON:API
|
|
29
|
+
options[:request] ||= request # user set request or self.request
|
|
30
|
+
options[:request] = Request.new(options) # Pagy::Request
|
|
31
|
+
Pagy.const_get(paginators[paginator]).paginate(*arguments)
|
|
25
32
|
end
|
|
26
33
|
end
|
|
27
34
|
end
|
|
@@ -4,16 +4,13 @@ class Pagy
|
|
|
4
4
|
module OffsetPaginator
|
|
5
5
|
module_function
|
|
6
6
|
|
|
7
|
-
# Return instance and
|
|
8
|
-
def paginate(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
pagy = Offset.new(**options, request:)
|
|
15
|
-
[pagy, collection.instance_of?(Array) ? collection[pagy.offset, pagy.limit] : pagy.records(collection)]
|
|
16
|
-
end
|
|
7
|
+
# Return the Pagy::Offset instance and results
|
|
8
|
+
def paginate(collection, options)
|
|
9
|
+
options[:page] ||= options[:request].resolve_page
|
|
10
|
+
options[:limit] = options[:request].resolve_limit
|
|
11
|
+
options[:count] ||= collection.instance_of?(Array) ? collection.size : OffsetPaginator.get_count(collection, options)
|
|
12
|
+
pagy = Offset.new(**options)
|
|
13
|
+
[pagy, collection.instance_of?(Array) ? collection[pagy.offset, pagy.limit] : pagy.records(collection)]
|
|
17
14
|
end
|
|
18
15
|
|
|
19
16
|
# Get the collection count
|
|
@@ -7,26 +7,23 @@ class Pagy
|
|
|
7
7
|
module_function
|
|
8
8
|
|
|
9
9
|
# Paginate from the search object
|
|
10
|
-
def paginate(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
options[:count] = results.total_count
|
|
21
|
-
[Searchkick.new(**options), results]
|
|
22
|
-
end
|
|
23
|
-
else
|
|
24
|
-
# The search is a searchkick results object
|
|
25
|
-
options[:limit] = search.respond_to?(:options) ? search.options[:per_page] : search.per_page
|
|
26
|
-
options[:page] = search.respond_to?(:options) ? search.options[:page] : search.current_page
|
|
27
|
-
options[:count] = search.total_count
|
|
28
|
-
Searchkick.new(**options)
|
|
10
|
+
def paginate(search, options)
|
|
11
|
+
if search.is_a?(Search::Arguments)
|
|
12
|
+
# The search is the array of pagy_search arguments
|
|
13
|
+
Searcher.wrap(search, options) do
|
|
14
|
+
model, term, search_options, block = search
|
|
15
|
+
search_options[:per_page] = options[:limit]
|
|
16
|
+
search_options[:page] = options[:page]
|
|
17
|
+
results = model.send(Searchkick::DEFAULT[:search_method], term || '*', **search_options, &block)
|
|
18
|
+
options[:count] = results.total_count
|
|
19
|
+
[Searchkick.new(**options), results]
|
|
29
20
|
end
|
|
21
|
+
else
|
|
22
|
+
# The search is a searchkick results object
|
|
23
|
+
options[:limit] = search.respond_to?(:options) ? search.options[:per_page] : search.per_page
|
|
24
|
+
options[:page] = search.respond_to?(:options) ? search.options[:page] : search.current_page
|
|
25
|
+
options[:count] = search.total_count
|
|
26
|
+
Searchkick.new(**options)
|
|
30
27
|
end
|
|
31
28
|
end
|
|
32
29
|
end
|