diff --git a/Gemfile b/Gemfile index 6cc70a4e0..612c8b44b 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ gem "datagrid", "~> 1.x" gem "dry-struct" gem "faraday" gem "kaminari" # TODO: Remove when removing datagrid -gem "pagy" +gem "pagy", "~> 43.0" gem "pg" # Reduces boot times through caching; required in config/boot.rb diff --git a/Gemfile.lock b/Gemfile.lock index 100e24eec..3d46e4091 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -401,7 +401,10 @@ GEM validate_url webfinger (~> 2.0) orm_adapter (0.5.0) - pagy (9.3.3) + pagy (43.5.0) + json + uri + yaml parallel (2.0.1) parser (3.3.11.1) ast (~> 2.4.1) @@ -664,6 +667,7 @@ GEM websocket-extensions (0.1.5) xpath (3.2.0) nokogiri (~> 1.8) + yaml (0.4.0) yard (0.9.41) zeitwerk (2.7.5) @@ -718,7 +722,7 @@ DEPENDENCIES omniauth (~> 2.1) omniauth-rails_csrf_protection omniauth_openid_connect (~> 0.8) - pagy + pagy (~> 43.0) passenger (~> 6.0) pg puma @@ -884,7 +888,7 @@ CHECKSUMS omniauth_openid_connect (0.8.0) sha256=1f2f3890386e2a742221cee0d2e903b78d874e6fab9ea3bfa31c1462f4793d25 openid_connect (2.3.1) sha256=5d808380cff80d78e3d3d54cfaebe2d6461d835c674faa29e2314a402c1b2182 orm_adapter (0.5.0) sha256=aa5d0be5d540cbb46d3a93e88061f4ece6a25f6e97d6a47122beb84fe595e9b9 - pagy (9.3.3) sha256=4831418eb4ec7cc5658ea57de559cc3a960286db36f98d4c1c65e19db0e2bb60 + pagy (43.5.0) sha256=58885d5f659e8db5b92cf35eeba674113e4e7bda12649b603c2d6908402570a4 parallel (2.0.1) sha256=337782d3e39f4121e67563bf91dd8ece67f48923d90698614773a0ec9a5b2c7d parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54 passenger (6.1.2) sha256=235a5ab2ad6dd56000ff401cb2f8ec92d67d17390a99425806cce6618405ee55 @@ -985,6 +989,7 @@ CHECKSUMS websocket-driver (0.8.0) sha256=ed0dba4b943c22f17f9a734817e808bc84cdce6a7e22045f5315aa57676d4962 websocket-extensions (0.1.5) sha256=1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241 xpath (3.2.0) sha256=6dfda79d91bb3b949b947ecc5919f042ef2f399b904013eb3ef6d20dd3a4082e + yaml (0.4.0) sha256=240e69d1e6ce3584d6085978719a0faa6218ae426e034d8f9b02fb54d3471942 yard (0.9.41) sha256=2fad2f362bceb63101f37aeb81d35cfc50b4ae1c11cf22f54b8d46626877a89f zeitwerk (2.7.5) sha256=d8da92128c09ea6ec62c949011b00ed4a20242b255293dd66bf41545398f73dd diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 078fb91e0..7cfe76844 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -850,7 +850,7 @@ body { overflow-wrap: break-word; } - nav.pagy-bootstrap.nav .pagination { + nav.pagy-bootstrap.series-nav .pagination { margin-bottom: 0; } diff --git a/app/components/export_dropdown_component.rb b/app/components/export_dropdown_component.rb index 27e58de04..0bfe9bacb 100644 --- a/app/components/export_dropdown_component.rb +++ b/app/components/export_dropdown_component.rb @@ -36,11 +36,11 @@ def initialize(url:, pagy:, **params) def current_page_export(format:) params = @params.dup - params[@pagy.vars[:page_param].to_s] = @pagy.page + params[@pagy.options[:page_key]] = @pagy.page public_send(@url, format:, **params) end def all_pages_export(format:) - public_send(@url, format:, **@params.except(@pagy.vars[:page_param].to_s)) + public_send(@url, format:, **@params.except(@pagy.options[:page_key])) end end diff --git a/app/components/pagination_component.rb b/app/components/pagination_component.rb index b5806c2f6..3b5ddfd1f 100644 --- a/app/components/pagination_component.rb +++ b/app/components/pagination_component.rb @@ -1,21 +1,20 @@ # frozen_string_literal: true class PaginationComponent < ApplicationComponent - include Pagy::Frontend - erb_template <<~ERB
- <%== pagy_bootstrap_nav(@pagy) %> + <%== @pagy.series_nav(:bootstrap) %> <%= form_with url: url_for, method: :get, data: { controller: "form-update" }, class: "d-flex align-items-baseline gap-2" do |f| %> <%= helpers.hash_to_hidden_fields(query_parameters) %> - <%= f.label @pagy.vars[:limit_param], t(".items_per_page"), class: "form-label text-nowrap text-secondary" %> - <%= f.select @pagy.vars[:limit_param], options_for_select(User::AVAILABLE_ITEMS_PER_PAGE, @pagy.limit), - {}, - class: "form-select form-select-sm", - data: { action: "change->form-update#update" } %> + <%= f.label @pagy.options[:limit_key], t(".items_per_page"), class: "form-label text-nowrap text-secondary" %> + <%= f.select @pagy.options[:limit_key], + options_for_select(User::AVAILABLE_ITEMS_PER_PAGE, @pagy.limit), + {}, + class: "form-select form-select-sm", + data: { action: "change->form-update#update" } %> <% end %>
ERB @@ -30,6 +29,6 @@ def initialize(pagy:, params: nil) private def query_parameters - (@params || request.query_parameters).merge(@pagy.vars[:page_param] => 1) + (@params || request.query_parameters).merge(@pagy.options[:page_key] => 1) end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index ecb2d100c..51fe27574 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,7 +3,7 @@ class ApplicationController < ActionController::Base include ChangelogContextApplication include Localization - include Pagy::Backend + include Pagy::Method include Authorization acts_as_token_authentication_handler_for User @@ -93,12 +93,6 @@ def current_user_has_permission? private - def pagy_get_limit(vars) - limit_params = vars[:limit] || Pagy::DEFAULT[:limit_param] - - params[limit_params] || current_user.items_per_page - end - def prepare_exception_notifier request.env["exception_notifier.exception_data"] = { current_user: current_user, diff --git a/app/controllers/cables_controller.rb b/app/controllers/cables_controller.rb index bcd2c73c8..9405df012 100644 --- a/app/controllers/cables_controller.rb +++ b/app/controllers/cables_controller.rb @@ -16,7 +16,7 @@ def index .order(created_at: :desc) @filter = ProcessorFilter.new(@cables, params) - @pagy, @cables = pagy(@filter.results.distinct) + @pagy, @cables = pagy(:countish, @filter.results.distinct, limit: pagy_get_limit(params)) end end diff --git a/app/controllers/changelog_entries_controller.rb b/app/controllers/changelog_entries_controller.rb index 24ac1a704..198c7417e 100644 --- a/app/controllers/changelog_entries_controller.rb +++ b/app/controllers/changelog_entries_controller.rb @@ -6,7 +6,7 @@ def index authorize! @changelog_entries, context: { scoped_object: } @filter = ProcessorFilter.new(@changelog_entries, params) - @pagy, @changelog_entries = pagy(@filter.results) + @pagy, @changelog_entries = pagy(:countish, @filter.results, limit: pagy_get_limit(params)) end def show diff --git a/app/controllers/external_app_records_controller.rb b/app/controllers/external_app_records_controller.rb index e335b1967..d9fd1df94 100644 --- a/app/controllers/external_app_records_controller.rb +++ b/app/controllers/external_app_records_controller.rb @@ -10,7 +10,7 @@ def index @filter = ProcessorFilter.new(@external_app_records, params) @external_app_records = @filter.results - @pagy, @external_app_records = pagy(@external_app_records) + @pagy, @external_app_records = pagy(@external_app_records, limit: pagy_get_limit(params)) end def settings diff --git a/app/controllers/power_distribution_units_controller.rb b/app/controllers/power_distribution_units_controller.rb index f862d4d60..a05ee82b2 100644 --- a/app/controllers/power_distribution_units_controller.rb +++ b/app/controllers/power_distribution_units_controller.rb @@ -18,7 +18,7 @@ def index respond_to do |format| format.json - format.html { @pagy, @pdus = pagy(@pdus) } + format.html { @pagy, @pdus = pagy(@pdus, limit: pagy_get_limit(params)) } end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 59eabaa10..755187f51 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true module ApplicationHelper - include Pagy::Frontend - CREATE_ANOTHER_ONE_ACTIONS = %w[new create].freeze def accepted_format_for_attachment(model_klass, attribute_name) diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index 76e4b8524..2b0d039cb 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -7,7 +7,7 @@ def redirect_to_on_success_hidden_field_tag(redirect_to_on_success) def pagy_to_hidden_fields(pagy) hash_to_hidden_fields( - pagy.vars[:limit_param] => pagy.vars[pagy.vars[:limit_param]], + pagy.options[:limit_key] => pagy.options[pagy.options[:limit_key]], ) end diff --git a/config/initializers/pagy.rb b/config/initializers/pagy.rb index e7b1f1003..d711499c1 100644 --- a/config/initializers/pagy.rb +++ b/config/initializers/pagy.rb @@ -1,222 +1,58 @@ # frozen_string_literal: true -# Pagy initializer file (9.1.0) -# Customize only what you really need and notice that the core Pagy works also without any of the following lines. -# Should you just cherry pick part of this file, please maintain the require-order of the extras +# Pagy initializer file (43.5.0) +# See https://ddnexus.github.io/pagy/toolbox/configuration/initializer/ -# Pagy Variables -# See https://ddnexus.github.io/pagy/docs/api/pagy#variables -# You can set any pagy variable as a Pagy::DEFAULT. They can also be overridden per instance by just passing them to -# Pagy.new|Pagy::Countless.new|Pagy::Calendar::*.new or any of the #pagy* controller methods -# Here are the few that make more sense as DEFAULTs: -# Pagy::DEFAULT[:limit] = 20 # default -# Pagy::DEFAULT[:size] = 7 # default -# Pagy::DEFAULT[:ends] = true # default -# Pagy::DEFAULT[:page_param] = :page # default -# Pagy::DEFAULT[:count_args] = [] # example for non AR ORMs -# Pagy::DEFAULT[:max_pages] = 3000 # example -# Extras -# See https://ddnexus.github.io/pagy/categories/extra - -# Legacy Compatibility Extras - -# Size extra: Enable the Array type for the `:size` variable (e.g. `size: [1,4,4,1]`) -# See https://ddnexus.github.io/pagy/docs/extras/size -# require 'pagy/extras/size' # must be required before the other extras - -# Backend Extras - -# Arel extra: For better performance utilizing grouped ActiveRecord collections: -# See: https://ddnexus.github.io/pagy/docs/extras/arel -# require 'pagy/extras/arel' - -# Array extra: Paginate arrays efficiently, avoiding expensive array-wrapping and without overriding -# See https://ddnexus.github.io/pagy/docs/extras/array -# require 'pagy/extras/array' - -# Calendar extra: Add pagination filtering by calendar time unit (year, quarter, month, week, day) -# See https://ddnexus.github.io/pagy/docs/extras/calendar -# require 'pagy/extras/calendar' -# Default for each calendar unit class in IRB: -# >> Pagy::Calendar::Year::DEFAULT -# >> Pagy::Calendar::Quarter::DEFAULT -# >> Pagy::Calendar::Month::DEFAULT -# >> Pagy::Calendar::Week::DEFAULT -# >> Pagy::Calendar::Day::DEFAULT +############ Global Options ################################################################ +# See https://ddnexus.github.io/pagy/toolbox/configuration/options/ for details. +# Add your global options below. They will be applied globally. +# For example: # -# Uncomment the following lines, if you need calendar localization without using the I18n extra -# module LocalizePagyCalendar -# def localize(time, opts) -# ::I18n.l(time, **opts) -# end -# end -# Pagy::Calendar.prepend LocalizePagyCalendar - -# Countless extra: Paginate without any count, saving one query per rendering -# See https://ddnexus.github.io/pagy/docs/extras/countless -# require 'pagy/extras/countless' -# Pagy::DEFAULT[:countless_minimal] = false # default (eager loading) - -# Elasticsearch Rails extra: Paginate `ElasticsearchRails::Results` objects -# See https://ddnexus.github.io/pagy/docs/extras/elasticsearch_rails -# Default :pagy_search method: change only if you use also -# the searchkick or meilisearch extra that defines the same -# Pagy::DEFAULT[:elasticsearch_rails_pagy_search] = :pagy_search -# Default original :search method called internally to do the actual search -# Pagy::DEFAULT[:elasticsearch_rails_search] = :search -# require 'pagy/extras/elasticsearch_rails' - -# Headers extra: http response headers (and other helpers) useful for API pagination -# See https://ddnexus.github.io/pagy/docs/extras/headers -# require 'pagy/extras/headers' -# Pagy::DEFAULT[:headers] = { page: 'Current-Page', -# limit: 'Page-Items', -# count: 'Total-Count', -# pages: 'Total-Pages' } # default - -# Keyset extra: Paginate with the Pagy keyset pagination technique -# See https://ddnexus.github.io/pagy/docs/extras/keyset -# require 'pagy/extras/keyset' - -# Meilisearch extra: Paginate `Meilisearch` result objects -# See https://ddnexus.github.io/pagy/docs/extras/meilisearch -# Default :pagy_search method: change only if you use also -# the elasticsearch_rails or searchkick extra that define the same method -# Pagy::DEFAULT[:meilisearch_pagy_search] = :pagy_search -# Default original :search method called internally to do the actual search -# Pagy::DEFAULT[:meilisearch_search] = :ms_search -# require 'pagy/extras/meilisearch' - -# Metadata extra: Provides the pagination metadata to Javascript frameworks like Vue.js, react.js, etc. -# See https://ddnexus.github.io/pagy/docs/extras/metadata -# you must require the JS Tools internal extra (BEFORE the metadata extra) ONLY if you need also the :sequels -# require 'pagy/extras/js_tools' -# require 'pagy/extras/metadata' -# For performance reasons, you should explicitly set ONLY the metadata you use in the frontend -# Pagy::DEFAULT[:metadata] = %i[scaffold_url page prev next last] # example - -# Searchkick extra: Paginate `Searchkick::Results` objects -# See https://ddnexus.github.io/pagy/docs/extras/searchkick -# Default :pagy_search method: change only if you use also -# the elasticsearch_rails or meilisearch extra that defines the same -# Pagy::DEFAULT[:searchkick_pagy_search] = :pagy_search -# Default original :search method called internally to do the actual search -# Pagy::DEFAULT[:searchkick_search] = :search -# require 'pagy/extras/searchkick' -# uncomment if you are going to use Searchkick.pagy_search -# Searchkick.extend Pagy::Searchkick - -# Frontend Extras - -# Bootstrap extra: Add nav, nav_js and combo_nav_js helpers and templates for Bootstrap pagination -# See https://ddnexus.github.io/pagy/docs/extras/bootstrap -# require "pagy/extras/bootstrap" +# Pagy::OPTIONS[:limit] = 10 # Limit the items per page +# Pagy::OPTIONS[:max_limit] = 100 # The client is allowed to request a limit up to 100 +# Pagy::OPTIONS[:jsonapi] = true # Use JSON:API compliant URLs -# Bulma extra: Add nav, nav_js and combo_nav_js helpers and templates for Bulma pagination -# See https://ddnexus.github.io/pagy/docs/extras/bulma -# require 'pagy/extras/bulma' +Pagy::OPTIONS[:limit] = 100 +Pagy::OPTIONS[:max_limit] = 200 -# Pagy extra: Add the pagy styled versions of the javascript-powered navs -# and a few other components to the Pagy::Frontend module. -# See https://ddnexus.github.io/pagy/docs/extras/pagy -# require 'pagy/extras/pagy' +Pagy::OPTIONS.freeze -# Multi size var used by the *_nav_js helpers -# See https://ddnexus.github.io/pagy/docs/extras/pagy#steps -# Pagy::DEFAULT[:steps] = { 0 => 5, 540 => 7, 720 => 9 } # example -# Feature Extras - -# Gearbox extra: Automatically change the limit per page depending on the page number -# See https://ddnexus.github.io/pagy/docs/extras/gearbox -# require 'pagy/extras/gearbox' -# set to false only if you want to make :gearbox_extra an opt-in variable -# Pagy::DEFAULT[:gearbox_extra] = false # default true -# Pagy::DEFAULT[:gearbox_limit] = [15, 30, 60, 100] # default - -# Limit extra: Allow the client to request a custom limit per page with an optional selector UI -# See https://ddnexus.github.io/pagy/docs/extras/limit -# require 'pagy/extras/limit' -# set to false only if you want to make :limit_extra an opt-in variable -# Pagy::DEFAULT[:limit_extra] = false # default true -# Pagy::DEFAULT[:limit_param] = :limit # default -# Pagy::DEFAULT[:limit_max] = 100 # default - -# Overflow extra: Allow for easy handling of overflowing pages -# See https://ddnexus.github.io/pagy/docs/extras/overflow -# require 'pagy/extras/overflow' -# Pagy::DEFAULT[:overflow] = :empty_page # default (other options: :last_page and :exception) - -# Trim extra: Remove the page=1 param from links -# See https://ddnexus.github.io/pagy/docs/extras/trim -# require 'pagy/extras/trim' -# set to false only if you want to make :trim_extra an opt-in variable -# Pagy::DEFAULT[:trim_extra] = false # default true - -# Standalone extra: Use pagy in non Rack environment/gem -# See https://ddnexus.github.io/pagy/docs/extras/standalone -# require 'pagy/extras/standalone' -# Pagy::DEFAULT[:url] = 'http://www.example.com/subdir' # optional default - -# Jsonapi extra: Implements JSON:API specifications -# See https://ddnexus.github.io/pagy/docs/extras/jsonapi -# require 'pagy/extras/jsonapi' # must be required after the other extras -# set to false only if you want to make :jsonapi an opt-in variable -# Pagy::DEFAULT[:jsonapi] = false # default true - -# Rails -# Enable the .js file required by the helpers that use javascript -# (pagy*_nav_js, pagy*_combo_nav_js, and pagy_limit_selector_js) -# See https://ddnexus.github.io/pagy/docs/api/javascript - -# With the asset pipeline -# Sprockets need to look into the pagy javascripts dir, so add it to the assets paths -# Rails.application.config.assets.paths << Pagy.root.join('javascripts') - -# I18n - -# Pagy internal I18n: ~18x faster using ~10x less memory than the i18n gem -# See https://ddnexus.github.io/pagy/docs/api/i18n -# Notice: No need to configure anything in this section if your app uses only "en" -# or if you use the i18n extra below +############ JS and CSS Resources ########################################################## +# See https://ddnexus.github.io/pagy/resources/javascript/ +# and https://ddnexus.github.io/pagy/resources/stylesheets/ for more resources and details. +# Copy and keep the resource files synced in the app. For example: # -# Examples: -# load the "de" built-in locale: -# Pagy::I18n.load(locale: 'de') -# -# load the "de" locale defined in the custom file at :filepath: -# Pagy::I18n.load(locale: 'de', filepath: 'path/to/pagy-de.yml') +# if Rails.env.development? +# Pagy.sync(:javascript, Rails.root.join('app/javascript'), 'pagy.mjs') +# Pagy.sync(:stylesheet, Rails.root.join('app/stylesheets'), 'pagy.css') +# end # -# load the "de", "en" and "es" built-in locales: -# (the first passed :locale will be used also as the default_locale) -# Pagy::I18n.load({ locale: 'de' }, -# { locale: 'en' }, -# { locale: 'es' }) +# As an alternative, use this config ONLY for apps with an asset pipeline # -# load the "en" built-in locale, a custom "es" locale, -# and a totally custom locale complete with a custom :pluralize proc: -# (the first passed :locale will be used also as the default_locale) -# Pagy::I18n.load({ locale: 'en' }, -# { locale: 'es', filepath: 'path/to/pagy-es.yml' }, -# { locale: 'xyz', # not built-in -# filepath: 'path/to/pagy-xyz.yml', -# pluralize: lambda{ |count| ... } ) +# Rails.application.config.assets.paths << Pagy::ROOT.join(':javascripts') +# Rails.application.config.assets.paths << Pagy::ROOT.join(':stylesheets') -# I18n extra: uses the standard i18n gem which is ~18x slower using ~10x more memory -# than the default pagy internal i18n (see above) -# See https://ddnexus.github.io/pagy/docs/extras/i18n -# require 'pagy/extras/i18n' -Pagy::DEFAULT[:limit] = 100 +############# Overriding Pagy::I18n Lookup ################################################# +# Refer to https://ddnexus.github.io/pagy/resources/i18n/ for details. +# Override the I18n lookup by dropping your custom dictionary in some pagy dir. +# Example for Rails: +# +# Pagy::I18n.pathnames << Rails.root.join('config/locales/pagy') -require "pagy/extras/size" -Pagy::DEFAULT[:size] = [2, 2, 2, 2] -require "pagy/extras/limit" -Pagy::DEFAULT[:limit_max] = 200 +############# I18n Gem Translation ######################################################### +# See https://ddnexus.github.io/pagy/resources/i18n/ for details. +# +# Pagy.translate_with_the_slower_i18n_gem! -require "pagy/extras/bootstrap" -# When you are done setting your own default freeze it, so it will not get changed accidentally -Pagy::DEFAULT.freeze +############# Calendar Localization for non-en locales #################################### +# See https://ddnexus.github.io/pagy/toolbox/paginators/calendar#localization for details. +# Add your desired locales to the list and uncomment the following line to enable them, +# regardless of whether you use the I18n gem for translations or not, whether with +# Rails or not. +# +# Pagy::Calendar.localize_with_rails_i18n_gem(*your_locales) diff --git a/spec/components/export_dropdown_component_spec.rb b/spec/components/export_dropdown_component_spec.rb index c30613ecd..505fe0692 100644 --- a/spec/components/export_dropdown_component_spec.rb +++ b/spec/components/export_dropdown_component_spec.rb @@ -5,7 +5,7 @@ RSpec.describe ExportDropdownComponent, type: :component do let(:component) { described_class.new(url: :root_path, pagy:, param: :filter) } let(:rendered_component) { render_inline(component) } - let(:pagy) { Pagy.new(count: 101, vars: { page_param: :page }) } + let(:pagy) { Pagy.new(count: 101, vars: { page_key: "page" }) } context "with next page" do it "renders the component" do # rubocop:disable RSpec/ExampleLength @@ -19,7 +19,7 @@ end context "with no next page" do - let(:pagy) { Pagy.new(count: 10, vars: { page_param: :page }) } + let(:pagy) { Pagy.new(count: 10, vars: { page_key: "page" }) } it "renders the component" do # rubocop:disable RSpec/ExampleLength expect(rendered_component.to_html).to have_tag("div.dropdown") do diff --git a/spec/components/pagination_component_spec.rb b/spec/components/pagination_component_spec.rb index 84315d071..a0942d3b5 100644 --- a/spec/components/pagination_component_spec.rb +++ b/spec/components/pagination_component_spec.rb @@ -3,9 +3,11 @@ require "rails_helper" RSpec.describe PaginationComponent, type: :component do + require "pagy/console" + let(:rendered_component) { render_inline(component) } let(:component) { described_class.new(pagy:) } - let(:pagy) { Pagy.new(count: 101, limit: 100) } + let(:pagy) { Pagy::Offset.new(count: 101, limit: 100) } before do allow(component).to receive(:url_for).and_return("/path")