Skip to content

Commit

Permalink
feature: countless pagination (#1998)
Browse files Browse the repository at this point in the history
* feature: countless pagination

* i18n-tasks normalize

* refactor

* spec

* fix paginator render condition

* refactor

* tweak

* fix bug

* uncomment spec

* pagination_type refactor

* extract apply_pagination from index

* normal => default

* fr translations by @jetienne
  • Loading branch information
Paul-Bob committed Nov 16, 2023
1 parent 869bce2 commit b216d3e
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 86 deletions.
4 changes: 2 additions & 2 deletions app/components/avo/index/resource_table_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<div class="absolute z-30 w-full ml-10 pt-px hidden" data-item-select-all-target="selectAllOverlay">
<div class="bg-white flex items-center h-9 mt-0.5">
<div class="mt-1.5" data-item-select-all-target="unselectedMessage">
<%= t "avo.x_records_selected_from_a_total_of_x_html", selected: pagy.in, count: pagy.count %>
<%= selected_page_label %>
<%= a_link request.url,
size: :xs,
color: :primary,
Expand All @@ -22,7 +22,7 @@
<% end %>
</div>
<div class="mt-1.5" data-item-select-all-target="selectedMessage" class="hidden">
<%= t "avo.x_records_selected_from_all_pages_html", count: pagy.count %>
<%= selected_all_label %>
<%= a_link request.url,
size: :xs,
color: :primary,
Expand Down
16 changes: 16 additions & 0 deletions app/components/avo/index/resource_table_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,20 @@ def encrypted_query
purpose: :select_all
)
end

def selected_page_label
if @resource.pagination_type.countless?
t "avo.x_records_selected_from_page_html", selected: pagy.in
else
t "avo.x_records_selected_from_a_total_of_x_html", selected: pagy.in, count: pagy.count
end
end

def selected_all_label
if @resource.pagination_type.countless?
t "avo.records_selected_from_all_pages_html"
else
t "avo.x_records_selected_from_all_pages_html", count: pagy.count
end
end
end
69 changes: 29 additions & 40 deletions app/components/avo/paginator_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,47 +1,36 @@
<%
per_page_options = [*Avo.configuration.per_page_steps, Avo.configuration.per_page.to_i, index_params[:per_page].to_i]

if parent_model.present?
per_page_options.prepend Avo.configuration.via_per_page
end

per_page_options = per_page_options.sort.uniq
%>
<% unless @pagy.pages <= 1 && discreet_pagination %>
<div class="flex flex-col sm:flex-row items-center justify-between aborder-t aborder-slate-200 rounded-xl space-y-2 sm:space-y-0">
<div class="flex-2 sm:flex sm:items-center sm:justify-between">
<div>
<div class="text-sm leading-5 text-slate-600 flex items-center">
<div data-controller="per-page">
<div class="flex items-center">
<%= select_tag 'per_page',
options_for_select(per_page_options, index_params[:per_page]),
class: 'appearance-none inline-flex bg-white-100 disabled:bg-white-400 disabled:cursor-not-allowed focus:bg-white text-slate-700 disabled:text-slate-600 rounded-md py-1 px-2 leading-tight border border-slate-300 outline-none focus:border-slate-400 outline w-16 mr-1 text-sm',
data: {
'turbo-frame': turbo_frame,
'per-page-target': 'selector',
action: 'change->per-page#reload'
}
%> <%= t('avo.per_page').downcase %>
</div>
<% per_page_options.each do |option| %>
<%= link_to "Change to #{option} items per page", change_items_per_page_url(option), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
<% end %>
<div class="flex flex-col sm:flex-row items-center justify-between aborder-t aborder-slate-200 rounded-xl space-y-2 sm:space-y-0">
<div class="flex-2 sm:flex sm:items-center sm:justify-between">
<div>
<div class="text-sm leading-5 text-slate-600 flex items-center">
<div data-controller="per-page">
<div class="flex items-center">
<%= select_tag 'per_page',
options_for_select(per_page_options, index_params[:per_page]),
class: 'appearance-none inline-flex bg-white-100 disabled:bg-white-400 disabled:cursor-not-allowed focus:bg-white text-slate-700 disabled:text-slate-600 rounded-md py-1 px-2 leading-tight border border-slate-300 outline-none focus:border-slate-400 outline w-16 mr-1 text-sm',
data: {
'turbo-frame': turbo_frame,
'per-page-target': 'selector',
action: 'change->per-page#reload'
}
%> <%= t('avo.per_page').downcase %>
</div>
<% per_page_options.each do |option| %>
<%= link_to "Change to #{option} items per page", change_items_per_page_url(option), class: 'hidden', 'data-per-page-option': option, 'data-turbo-frame': turbo_frame %>
<% end %>
</div>
</div>
</div>
<div class="flex">
<div class="flex-2 sm:flex sm:items-center sm:justify-between space-y-2 sm:space-y-0 text-center sm:text-left">
<% if @pagy.count > 0 %>
<div class="text-sm text-slate-600 mr-4"><%== helpers.pagy_info @pagy %></div>
<% end %>
</div>
<div class="flex">
<div class="flex-2 sm:flex sm:items-center sm:justify-between space-y-2 sm:space-y-0 text-center sm:text-left">
<% if @resource.pagination_type.default? %>
<div class="text-sm text-slate-600 mr-4"><%== helpers.pagy_info @pagy %></div>
<% end %>
<% if @pagy.pages > 1 %>
<%# @todo: add first & last page. make the first and last buttons rounded %>
<%== helpers.pagy_nav @pagy %>
<% end %>
</div>
<% if pagy.pages > 1 %>
<%# @todo: add first & last page. make the first and last buttons rounded %>
<%== helpers.pagy_nav @pagy %>
<% end %>
</div>
</div>
<% end %>
</div>
18 changes: 18 additions & 0 deletions app/components/avo/paginator_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,22 @@ def change_items_per_page_url(option)
helpers.resources_path(resource: resource, per_page: option, keep_query_params: true, page: 1)
end
end

def render?
return false if discreet_pagination && pagy.pages <= 1

@pagy.items > 0
end

def per_page_options
@per_page_options ||= begin
options = [*Avo.configuration.per_page_steps, Avo.configuration.per_page.to_i, index_params[:per_page].to_i]

if parent_model.present?
options.prepend Avo.configuration.via_per_page
end

options.sort.uniq
end
end
end
1 change: 0 additions & 1 deletion app/controllers/avo/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ class ApplicationController < ::ActionController::Base
Avo::ApplicationController.include Pundit
end

include Pagy::Backend
include Avo::ApplicationHelper
include Avo::UrlHelpers
include Avo::Concerns::Breadcrumbs
Expand Down
13 changes: 5 additions & 8 deletions app/controllers/avo/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,7 @@ def index
).apply_query request, @query, filter_value
end

extra_pagy_params = {}

# Reset open filters when a user navigates to a new page
extra_pagy_params[:keep_filters_panel_open] = if params[:keep_filters_panel_open] == "1"
"0"
end

@pagy, @models = pagy(@query, items: @index_params[:per_page], link_extra: "data-turbo-frame=\"#{params[:turbo_frame]}\"", size: [1, 2, 2, 1], params: extra_pagy_params)
apply_pagination

# Create resources for each model
@resources = @models.map do |model|
Expand Down Expand Up @@ -543,5 +536,9 @@ def is_associated_record?
def set_pagy_locale
@pagy_locale = locale.to_s || Avo.configuration.locale || "en"
end

def apply_pagination
@pagy, @models = @resource.apply_pagination(index_params: @index_params, query: @query)
end
end
end
1 change: 1 addition & 0 deletions config/initializers/pagy.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "pagy/extras/trim"
require "pagy/extras/countless"

# For locales without native pagy i18n support
def pagy_locale_path(file_name)
Expand Down
1 change: 1 addition & 0 deletions lib/avo/base_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class BaseResource
include Avo::Concerns::HasEditableControls
include Avo::Concerns::HasStimulusControllers
include Avo::Concerns::ModelClassConstantized
include Avo::Concerns::Pagination

delegate :view_context, to: ::Avo::App
delegate :current_user, to: ::Avo::App
Expand Down
53 changes: 53 additions & 0 deletions lib/avo/concerns/pagination.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module Avo
module Concerns
module Pagination
extend ActiveSupport::Concern

included do
include Pagy::Backend

class_attribute :pagination, default: {}

PAGINATION_METHOD = {
default: :pagy,
countless: :pagy_countless,
} unless defined? PAGINATION_METHOD

PAGINATION_DEFAULTS = {
type: :default,
size: [1, 2, 2, 1],
} unless defined? PAGINATION_DEFAULTS
end

def pagination_type
@pagination_type ||= ActiveSupport::StringInquirer.new(pagination_hash[:type].to_s)
end

def apply_pagination(index_params:, query:)
extra_pagy_params = {}

# Reset open filters when a user navigates to a new page
extra_pagy_params[:keep_filters_panel_open] = if params[:keep_filters_panel_open] == "1"
"0"
end

send PAGINATION_METHOD[pagination_type.to_sym],
query,
items: index_params[:per_page],
link_extra: "data-turbo-frame=\"#{params[:turbo_frame]}\"",
params: extra_pagy_params,
size: pagination_hash[:size]
end

private

def pagination_hash
@pagination ||= PAGINATION_DEFAULTS.merge Avo::ExecutionContext.new(
target: pagination,
resource: self,
view: @view
).handle
end
end
end
end
2 changes: 2 additions & 0 deletions lib/generators/avo/templates/locales/avo.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ en:
to_top: Move record to top
per_page: Per page
prev_page: Previous page
records_selected_from_all_pages_html: All records selected from all pages
remove_selection: Remove selection
reset_filters: Reset filters
resource_created: Record created
Expand Down Expand Up @@ -121,4 +122,5 @@ en:
zero: no more items
x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> records selected on this page from a total of <span class="font-bold text-gray-700">%{count}</span>
x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> records selected from all pages
x_records_selected_from_page_html: <span class="font-bold text-gray-700">%{selected}</span> records selected on this page
you_missed_something_check_form: You might have missed something. Please check the form.
2 changes: 2 additions & 0 deletions lib/generators/avo/templates/locales/avo.fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ fr:
to_top: Déplacer tout en haut
per_page: Par page
prev_page: Page précédente
records_selected_from_all_pages_html: tous les éléments sélectionnés de toutes les pages
remove_selection: Supprimer la sélection
reset_filters: Réinitialiser les filtres
resource_created: Ressource créee
Expand Down Expand Up @@ -117,4 +118,5 @@ fr:
zero: aucun élément supplémentaire
x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> enregistrements sélectionnés sur cette page sur un total de <span class="font-bold text-gray-700">%{count}</span>
x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> enregistrements sélectionnés dans toutes les pages
x_records_selected_from_page_html: <span class="font-bold text-gray-700">%{selected}</span> éléments sélectionnés de cette page
you_missed_something_check_form: Vous avez peut-être oublié quelque chose. Veuillez vérifier le formulaire
2 changes: 2 additions & 0 deletions lib/generators/avo/templates/locales/avo.pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ pt-BR:
to_top: Mover registro para cima
per_page: Por página
prev_page: Página anterior
records_selected_from_all_pages_html: Todos os registros de todas as páginas selecionados
remove_selection: Remover seleção
reset_filters: Limpar filtros
resource_created: Recurso criado
Expand Down Expand Up @@ -117,4 +118,5 @@ pt-BR:
zero: mais nenhum item
x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> registros selecionados nesta página de um total de <span class="font-bold text-gray-700">%{count}</span>
x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> registros selecionados de todas as páginas
x_records_selected_from_page_html: <span class="font-bold text-gray-700">%{selected}</span> registros selecionados nesta página
you_missed_something_check_form: Você pode ter esquecido algo. Por favor, cheque o formulário.
2 changes: 2 additions & 0 deletions lib/generators/avo/templates/locales/avo.pt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ pt:
to_top: Mover recurso para o topo
per_page: Por página
prev_page: Página anterior
records_selected_from_all_pages_html: Todos os itens de todas as páginas selecionados
remove_selection: Remover seleção
reset_filters: Limpar filtros
resource_created: Recurso criado
Expand Down Expand Up @@ -117,4 +118,5 @@ pt:
zero: mais nenhum item
x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> itens selecionados nesta página de um total de <span class="font-bold text-gray-700">%{count}</span>
x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> itens selecionados de todas as páginas
x_records_selected_from_page_html: <span class="font-bold text-gray-700">%{selected}</span> itens selecionados nesta página
you_missed_something_check_form: Pode ter-se esquecido algo. Por favor, verifique o formulário.
2 changes: 2 additions & 0 deletions lib/generators/avo/templates/locales/avo.ro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ ro:
to_top: Mutați înregistrarea sus de tot
per_page: Pe pagină
prev_page: Pagina anterioara
records_selected_from_all_pages_html: Toate selectate din toate paginile
remove_selection: Șterge selecția
reset_filters: Resetați filtrele
resource_created: Resursă creata
Expand Down Expand Up @@ -117,4 +118,5 @@ ro:
zero: zero articole
x_records_selected_from_a_total_of_x_html: <span class="font-bold text-gray-700">%{selected}</span> selectate dintr-un total de <span class="font-bold text-gray-700">%{count}</span>
x_records_selected_from_all_pages_html: <span class="font-bold text-gray-700">%{count}</span> selectate din toate paginile
x_records_selected_from_page_html: <span class="font-bold text-gray-700">%{selected}</span> selectate
you_missed_something_check_form: S-ar putea să fi omis ceva. Vă rugăm să verificați formularul.
Loading

0 comments on commit b216d3e

Please sign in to comment.