Add pagination with pagy

For `admin_style_v3` use `<` and `>` for next and previous link

instead of `next` and `previous` string

Extract a mixin for a default box-shadow

Maybe this needs to be redefined. Let's see how next things goes.

When a table is followed by a pagination, remove its margin-bottom + border

Finally, design the pagination component

Add sorting/pagination module, on top of table

We use `cablea_ready.replace`, so need to add `#products-content` id

Use a `pagy` partial with reflex action, instead of the legacy one

- revert the legacy one to its previous state
 - in reflex, fetch product with page attribute, 1 by default

Move `pagy` into `admin/shared/v3/` to be reusable

+ use fontawesome icons for next and previous page

Remove useless line
This commit is contained in:
Jean-Baptiste Bellet
2023-06-21 11:00:33 +02:00
parent 69cff85577
commit 47f21cb59e
11 changed files with 82 additions and 20 deletions

View File

@@ -2,12 +2,15 @@
module Admin
class ProductsV3Reflex < ApplicationReflex
before_reflex :fetch_products, only: [:fetch]
include Pagy::Backend
def fetch
fetch_products(element.dataset.page || 1)
cable_ready.replace(
selector: "#products-content",
html: render(partial: "admin/products_v3/content", locals: { products: @products })
html: render(partial: "admin/products_v3/content",
locals: { products: @products, pagy: @pagy })
).broadcast
morph :nothing
@@ -16,10 +19,10 @@ module Admin
private
# copied from ProductsTableComponent
def fetch_products
def fetch_products(page)
product_query = OpenFoodNetwork::Permissions.new(current_user)
.editable_products.merge(product_scope)
@products = product_query.order(:name).limit(50)
@pagy, @products = pagy(product_query.order(:name), items: 15, page:)
end
def product_scope

View File

@@ -1,10 +1,15 @@
- if products.any?
= render partial: 'table', locals: { products: products }
- else
#no-products
= t('.no_products_found')
#no-products-actions
%a{ href: "/admin/products/new", class: "button icon-plus", icon: "icon-plus" }
= t(:new_product)
%a{ href: "/admin/products/import", class: "button icon-upload secondary", icon: "icon-upload" }
= t(".import_products")
#products-content
- if products.any?
.container
.sixteen.columns
= render partial: 'sort', locals: { pagy: pagy }
= render partial: 'table', locals: { products: products }
= render partial: 'admin/shared/v3/pagy', locals: { pagy: pagy, reflex: "click->Admin::ProductsV3#fetch" }
- else
#no-products
= t('.no_products_found')
#no-products-actions
%a{ href: "/admin/products/new", class: "button icon-plus", icon: "icon-plus" }
= t(:new_product)
%a{ href: "/admin/products/import", class: "button icon-upload secondary", icon: "icon-upload" }
= t(".import_products")

View File

@@ -0,0 +1,2 @@
#sort
= t(".pagination.total_html", total: pagy.count, from: pagy.from, to: pagy.to)

View File

@@ -0,0 +1,21 @@
%nav.pagy_nav.pagination{"aria-label" => "pager", :role => "navigation"}
- if pagy.prev
%a.page.previous{ href: "#", "data-reflex": reflex, "data-page": pagy.prev || 1, "aria-label": "previous"}
%i.icon-chevron-left
- else
%span.page.prev.disabled
%i.icon-chevron-left
- pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
- if item.is_a?(Integer) # page link
%a.page{ href: "#", "data-reflex": reflex, "data-page": item, "aria-label": "page #{item}"}
= item
- elsif item.is_a?(String) # current page
%span.page.current= item
- elsif item == :gap # page gap
%span.page.gap &hellip;
- if pagy.next
%a.page.next{ href: "#", "data-reflex": reflex, "data-page": pagy.next || pagy.last, "aria-label": "next"}
%i.icon-chevron-right
- else
%span.page.next.disabled
%i.icon-chevron-right

View File

@@ -78,4 +78,8 @@
gap: 20px;
}
}
#sort {
margin-bottom: 1em;
}
}

View File

@@ -22,6 +22,7 @@
@import "globals/variables"; // admin_v3
@import "../admin/variables";
@import "../admin/globals/mixins";
@import "mixins"; // admin_v3
@import "../admin/plugins/font-awesome";

View File

@@ -61,7 +61,7 @@ nav.menu {
}
#admin-menu {
box-shadow: 0px 1px 0px rgba(0, 0, 0, 0.05), 0px 2px 2px rgba(0, 0, 0, 0.07);
@include defaultBoxShadow;
li {
.dropdown {

View File

@@ -1,21 +1,37 @@
.pagination {
text-align: center;
margin: 2em 0 1em;
margin: 0 0 1em;
padding: 10px 0;
background-color: $light-grey;
background-color: $color-7;
.page {
padding: 5px 8px;
width: 40px;
line-height: 40px;
text-align: center;
display: inline-block;
text-align: center;
background-color: $color-1;
@include defaultBoxShadow;
border-radius: 4px;
color: $color-9;
&.current {
background-color: $green;
border-radius: 3px;
background-color: $color-5;
color: $white;
}
&.prev {
margin-right: 20px;
}
&.next {
margin-left: 20px;
}
&.disabled {
cursor: default;
}
}
button {

View File

@@ -0,0 +1,3 @@
@mixin defaultBoxShadow {
box-shadow: 0px 1px 0px rgba(0, 0, 0, 0.05), 0px 2px 2px rgba(0, 0, 0, 0.07);
}

View File

@@ -205,3 +205,7 @@ table {
}
}
}
table + .pagination {
margin-top: -18px;
}

View File

@@ -767,6 +767,9 @@ en:
header:
title: Bulk Edit Products
loading: Loading your products
sort:
pagination:
total_html: "<strong>%{total} products</strong> in your catalogue. Showing %{from} to %{to}."
content:
no_products_found: No products found
import_products: Import multiple products