use beforeFetch and afterFetch lifecycle methods

+ Move outside `Admin` module the reflex

Therefore, this reflex should be _equivalent_ to its javascript controller: `ProductsV3` (relation is made through names)

Remove unwanted line

Actually call StimulusJS controller instead of calling the reflex itself

In order to have this "showLoading", "hideLoading" behavior.

It seems to be possible to directly use the Reflex itself (use `data-reflex` instead of `data-action`) but I can't make it work: the `stimulus-controller:after` event is never broadcasted/catched (but `stimulus-controller:before` yes...)

Documentation:
https://docs.stimulusreflex.com/guide/reflexes.html#understanding-stimulusreflex-controllers
https://docs.stimulusreflex.com/guide/lifecycle.html#generic-life-cycle-methods

Maybe @dacook if you want to have a look...
This commit is contained in:
Jean-Baptiste Bellet
2023-06-27 11:44:36 +02:00
parent 3b61508652
commit 5aebbe4102
5 changed files with 68 additions and 59 deletions

View File

@@ -1,51 +0,0 @@
# frozen_string_literal: true
module Admin
class ProductsV3Reflex < ApplicationReflex
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, pagy: @pagy })
).broadcast
morph :nothing
end
private
# copied from ProductsTableComponent
def fetch_products(page)
product_query = OpenFoodNetwork::Permissions.new(current_user)
.editable_products.merge(product_scope)
@pagy, @products = pagy(product_query.order(:name), items: 15, page:)
end
def product_scope
scope = if current_user.has_spree_role?("admin") || current_user.enterprises.present?
Spree::Product
else
Spree::Product.active
end
scope.includes(product_query_includes)
end
# Optimise by pre-loading required columns
def product_query_includes
# TODO: add other fields used in columns? (eg supplier: [:name])
[
# variants: [
# :default_price,
# :stock_locations,
# :stock_items,
# :variant_overrides
# ]
]
end
end
end

View File

@@ -0,0 +1,49 @@
# frozen_string_literal: true
class ProductsV3Reflex < ApplicationReflex
include Pagy::Backend
def fetch
fetch_products(element.dataset.page || 1, element.dataset.per_page || 15)
cable_ready.replace(
selector: "#products-content",
html: render(partial: "admin/products_v3/content",
locals: { products: @products, pagy: @pagy })
).broadcast
morph :nothing
end
private
# copied from ProductsTableComponent
def fetch_products(page, per_page)
product_query = OpenFoodNetwork::Permissions.new(current_user)
.editable_products.merge(product_scope)
@pagy, @products = pagy(product_query.order(:name), items: per_page, page:)
end
def product_scope
scope = if current_user.has_spree_role?("admin") || current_user.enterprises.present?
Spree::Product
else
Spree::Product.active
end
scope.includes(product_query_includes)
end
# Optimise by pre-loading required columns
def product_query_includes
# TODO: add other fields used in columns? (eg supplier: [:name])
[
# variants: [
# :default_price,
# :stock_locations,
# :stock_items,
# :variant_overrides
# ]
]
end
end

View File

@@ -4,7 +4,7 @@
.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" }
= render partial: 'admin/shared/v3/pagy', locals: { pagy: pagy, action: "click->productsV3#fetch" }
- else
#no-products
= t('.no_products_found')

View File

@@ -1,20 +1,20 @@
%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"}
%a.page.prev{ href: "#", "data-action": action, "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}"}
%a.page{ href: "#", "data-action": action, "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"}
%a.page.next{ href: "#", "data-action": action, "data-page": pagy.next || pagy.last, "aria-label": "next"}
%i.icon-chevron-right
- else
%span.page.next.disabled

View File

@@ -6,12 +6,15 @@ export default class extends ApplicationController {
connect() {
super.connect();
// Fetch the products on page load
this.load();
this.fetch();
}
load = () => {
this.showLoading();
this.stimulate("Admin::ProductsV3#fetch").then(() => this.hideLoading());
fetch = (event = {}) => {
if (event && event.target) {
this.stimulate("ProductsV3#fetch", event.target);
return;
}
this.stimulate("ProductsV3#fetch");
};
hideLoading = () => {
@@ -21,4 +24,12 @@ export default class extends ApplicationController {
showLoading = () => {
this.loadingTarget.classList.remove("hidden");
};
beforeFetch(element, reflex, noop, reflexId) {
this.showLoading();
}
afterFetch(element, reflex, noop, reflexId) {
this.hideLoading();
}
}