switch to pagy for pagination
This commit is contained in:
@@ -47,6 +47,9 @@ gem "thruster", require: false
|
|||||||
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
|
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
|
||||||
gem "image_processing", "~> 1.2"
|
gem "image_processing", "~> 1.2"
|
||||||
|
|
||||||
|
# Pagination [https://github.com/ddnexus/pagy]
|
||||||
|
gem "pagy", "~> 8.0"
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
|
||||||
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
|
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ GEM
|
|||||||
nokogiri (1.19.0-x86_64-linux-gnu)
|
nokogiri (1.19.0-x86_64-linux-gnu)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
ostruct (0.6.3)
|
ostruct (0.6.3)
|
||||||
|
pagy (8.6.3)
|
||||||
parallel (1.27.0)
|
parallel (1.27.0)
|
||||||
parser (3.3.10.1)
|
parser (3.3.10.1)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
@@ -430,6 +431,7 @@ DEPENDENCIES
|
|||||||
importmap-rails
|
importmap-rails
|
||||||
jbuilder
|
jbuilder
|
||||||
kamal
|
kamal
|
||||||
|
pagy (~> 8.0)
|
||||||
propshaft
|
propshaft
|
||||||
puma (>= 5.0)
|
puma (>= 5.0)
|
||||||
rails (~> 8.1.2)
|
rails (~> 8.1.2)
|
||||||
@@ -531,6 +533,7 @@ CHECKSUMS
|
|||||||
nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
|
nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
|
||||||
nokogiri (1.19.0-x86_64-linux-gnu) sha256=f482b95c713d60031d48c44ce14562f8d2ce31e3a9e8dd0ccb131e9e5a68b58c
|
nokogiri (1.19.0-x86_64-linux-gnu) sha256=f482b95c713d60031d48c44ce14562f8d2ce31e3a9e8dd0ccb131e9e5a68b58c
|
||||||
ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
|
ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912
|
||||||
|
pagy (8.6.3) sha256=537b2ee3119f237dd6c4a0d0a35c67a77b9d91ebb9d4f85e31407c2686774fb2
|
||||||
parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
|
parallel (1.27.0) sha256=4ac151e1806b755fb4e2dc2332cbf0e54f2e24ba821ff2d3dcf86bf6dc4ae130
|
||||||
parser (3.3.10.1) sha256=06f6a725d2cd91e5e7f2b7c32ba143631e1f7c8ae2fb918fc4cebec187e6a688
|
parser (3.3.10.1) sha256=06f6a725d2cd91e5e7f2b7c32ba143631e1f7c8ae2fb918fc4cebec187e6a688
|
||||||
pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
|
pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
include BotBlocker
|
include BotBlocker
|
||||||
|
include Pagy::Backend
|
||||||
|
|
||||||
# Changes to the importmap will invalidate the etag for HTML responses
|
# Changes to the importmap will invalidate the etag for HTML responses
|
||||||
stale_when_importmap_changes
|
stale_when_importmap_changes
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ class EntriesController < ApplicationController
|
|||||||
@category = params[:category].presence
|
@category = params[:category].presence
|
||||||
@query = params[:q].to_s.strip
|
@query = params[:q].to_s.strip
|
||||||
@starts_with = params[:starts_with].presence
|
@starts_with = params[:starts_with].presence
|
||||||
@page = [ params[:page].to_i, 1 ].max
|
|
||||||
@per_page = 25
|
|
||||||
|
|
||||||
entries_scope = Entry.active_entries
|
entries_scope = Entry.active_entries
|
||||||
entries_scope = entries_scope.with_category(@category)
|
entries_scope = entries_scope.with_category(@category)
|
||||||
@@ -16,9 +14,8 @@ class EntriesController < ApplicationController
|
|||||||
entries_scope = entries_scope.alphabetical_for(@language_code) if @query.blank? && @starts_with.blank? && @language_code.present?
|
entries_scope = entries_scope.alphabetical_for(@language_code) if @query.blank? && @starts_with.blank? && @language_code.present?
|
||||||
entries_scope = entries_scope.order(created_at: :desc) if entries_scope.order_values.empty?
|
entries_scope = entries_scope.order(created_at: :desc) if entries_scope.order_values.empty?
|
||||||
|
|
||||||
@total_entries = entries_scope.count
|
@pagy, @entries = pagy(entries_scope, items: 25)
|
||||||
@total_pages = (@total_entries.to_f / @per_page).ceil
|
@total_entries = @pagy.count
|
||||||
@entries = entries_scope.offset((@page - 1) * @per_page).limit(@per_page)
|
|
||||||
|
|
||||||
@entry_count = Entry.active_entries.count
|
@entry_count = Entry.active_entries.count
|
||||||
@requested_count = Entry.requested.count
|
@requested_count = Entry.requested.count
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
|
include Pagy::Frontend
|
||||||
|
|
||||||
def language_name(code)
|
def language_name(code)
|
||||||
supported_languages.find { |l| l.code == code }&.name
|
supported_languages.find { |l| l.code == code }&.name
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -86,17 +86,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center justify-between mt-4 text-sm text-slate-600">
|
<div class="flex items-center justify-between mt-4 text-sm text-slate-600">
|
||||||
<div>Page <%= @page %> of <%= [@total_pages, 1].max %></div>
|
<div><%= pagy_info(@pagy) %></div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<% previous_page = @page > 1 ? @page - 1 : nil %>
|
<%
|
||||||
<% next_page = @page < @total_pages ? @page + 1 : nil %>
|
pagination_params = { q: @query.presence, category: @category.presence, language: @language_code.presence, starts_with: @starts_with.presence }.compact
|
||||||
<% pagination_params = { q: @query.presence, category: @category.presence, language: @language_code.presence, starts_with: @starts_with.presence }.compact %>
|
prev_url = @pagy.prev ? entries_path(pagination_params.merge(page: @pagy.prev)) : nil
|
||||||
<%= link_to "Previous", previous_page ? entries_path(pagination_params.merge(page: previous_page)) : "#",
|
next_url = @pagy.next ? entries_path(pagination_params.merge(page: @pagy.next)) : nil
|
||||||
class: "px-3 py-1.5 rounded-md border border-slate-200 #{previous_page ? 'hover:border-indigo-300' : 'text-slate-300 cursor-not-allowed'}",
|
%>
|
||||||
data: { turbo_stream: true } %>
|
<%= link_to "Previous", prev_url || "#",
|
||||||
<%= link_to "Next", next_page ? entries_path(pagination_params.merge(page: next_page)) : "#",
|
class: "px-3 py-1.5 rounded-md border border-slate-200 #{'opacity-50 pointer-events-none' unless prev_url}",
|
||||||
class: "px-3 py-1.5 rounded-md border border-slate-200 #{next_page ? 'hover:border-indigo-300' : 'text-slate-300 cursor-not-allowed'}",
|
data: (prev_url ? { turbo_stream: true } : {}) %>
|
||||||
data: { turbo_stream: true } %>
|
<%= link_to "Next", next_url || "#",
|
||||||
|
class: "px-3 py-1.5 rounded-md border border-slate-200 #{'opacity-50 pointer-events-none' unless next_url}",
|
||||||
|
data: (next_url ? { turbo_stream: true } : {}) %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Pagy Configuration
|
||||||
|
require "pagy/extras/overflow"
|
||||||
|
|
||||||
|
Pagy::DEFAULT[:items] = 25 # Match current 25 items per page
|
||||||
|
Pagy::DEFAULT[:page_param] = :page
|
||||||
|
Pagy::DEFAULT[:overflow] = :last_page
|
||||||
@@ -41,7 +41,8 @@ class EntriesControllerTest < ActionDispatch::IntegrationTest
|
|||||||
test "should paginate results" do
|
test "should paginate results" do
|
||||||
get entries_url, params: { page: 2 }
|
get entries_url, params: { page: 2 }
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_select "div", text: /Page 2 of/i
|
assert_not_nil assigns(:pagy)
|
||||||
|
assert_select "div", text: /Displaying/i
|
||||||
end
|
end
|
||||||
|
|
||||||
test "should handle invalid language code" do
|
test "should handle invalid language code" do
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class PublicBrowsingTest < ApplicationSystemTestCase
|
|||||||
visit root_path
|
visit root_path
|
||||||
|
|
||||||
assert_selector ".entry-row", count: 25
|
assert_selector ".entry-row", count: 25
|
||||||
assert_link "2"
|
assert_link "Next"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "visitor sees entry statistics" do
|
test "visitor sees entry statistics" do
|
||||||
|
|||||||
Reference in New Issue
Block a user