Refactor bulk_action stimulus controller and handle orders bulk actions with turbo_stream

This commit is contained in:
wandji20
2024-10-19 22:58:28 +01:00
parent 1f77f190da
commit 17a782df2a
8 changed files with 102 additions and 36 deletions

View File

@@ -17,7 +17,7 @@
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "send_invoice" }
= t('spree.admin.orders.index.send_invoice')
%div.menu_item
%span.name{ "data-controller": "bulk-actions", "data-action": "click->bulk-actions#perform", "data-bulk-actions-reflex-value": "Admin::Orders#bulk_invoice" }
%span.name{ data: { controller: "bulk-actions", action: "click->bulk-actions#printInvoices", url: spree.bulk_invoice_admin_orders_path } }
= t('spree.admin.orders.index.print_invoices')
%div.menu_item
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "cancel_orders" }

View File

@@ -0,0 +1,2 @@
= turbo_stream.append 'orders-index' do
= render partial: "spree/admin/orders/bulk/invoice_modal", locals: { invoice_url: "/admin/orders/invoices/#{@file_id}" }

View File

@@ -0,0 +1,3 @@
- @cancelled_orders.each do |order|
= turbo_stream.replace dom_id(order) do
= render partial: "spree/admin/orders/table_row", locals: { order: }

View File

@@ -21,14 +21,36 @@
= render 'spree/admin/shared/custom-confirm'
= render ConfirmModalComponent.new(id: "resend_confirmation", confirm_actions: "click->bulk-actions#perform", controller: "bulk-actions", reflex: "Admin::Orders#resend_confirmation_emails") do
.margin-bottom-30
= t('.resend_confirmation_confirm_html')
= render ModalComponent.new(id: "resend_confirmation", modal_class: 'tiny', close_button: false) do
= form_with(url: resend_confirmation_emails_admin_orders_path, method: :post, data: { turbo: true, controller: 'bulk-actions' }) do
.margin-bottom-30
= t('.resend_confirmation_confirm_html')
%p.modal-actions.justify-space-around
%button.button.secondary{ type: "button", 'data-action': 'click->modal#close' }
= t('js.admin.modals.cancel')
%button.button.primary{ type: 'submit' }
= t('js.admin.modals.confirm')
= render ConfirmModalComponent.new(id: "send_invoice", confirm_actions: "click->bulk-actions#perform", controller: "bulk-actions", reflex: "Admin::Orders#send_invoices") do
.margin-bottom-30
= t('.send_invoice_confirm_html')
= render ModalComponent.new(id: "send_invoice", modal_class: 'tiny', close_button: false) do
= form_with(url: send_invoices_admin_orders_path, method: :post, data: { turbo: true, controller: 'bulk-actions' }) do
.margin-bottom-30
= t('.send_invoice_confirm_html')
%p.modal-actions.justify-space-around
%button.button.secondary{ type: "button", 'data-action': 'click->modal#close' }
= t('js.admin.modals.cancel')
%button.button.primary{ type: 'submit' }
= t('js.admin.modals.confirm')
= render ConfirmModalComponent.new(id: "cancel_orders", confirm_actions: "click->bulk-actions#perform", controller: "bulk-actions", reflex: "Admin::Orders#cancel_orders", message: "spree/admin/orders/messages/cancel_orders") do
.margin-bottom-30
= t("js.admin.orders.cancel_the_order_html")
= render ModalComponent.new(id: "cancel_orders", modal_class: 'tiny', close_button: false) do
= form_with(url: cancel_orders_admin_orders_path, method: :post, data: { turbo: true, controller: 'bulk-actions' }) do
.margin-bottom-30
= t("js.admin.orders.cancel_the_order_html")
.margin-bottom-30
= render partial: "spree/admin/orders/messages/cancel_orders"
%p.modal-actions.justify-space-around
%button.button.secondary{ type: "button", 'data-action': 'click->modal#close' }
= t('js.admin.modals.cancel')
%button.button.primary{ type: 'submit' }
= t('js.admin.modals.confirm')

View File

@@ -1,11 +1,10 @@
.modal-message
%form{ "data-bulk-actions-target": "extraParams" }
%input{ type: "checkbox", name: "send_cancellation_email", value: "1", id: "send_cancellation_email", checked: "true" }
%label{ for: "send_cancellation_email" }
= t("js.admin.orders.cancel_the_order_send_cancelation_email")
%br
%input{ type: "checkbox", name: "restock_items", value: "1", id: "restock_items", checked: "true" }
%label{ for: "restock_items" }
= t("js.admin.orders.restock_items")
.margin-bottom-30
%input{ type: "checkbox", name: "send_cancellation_email", value: "1", id: "send_cancellation_email", checked: "true" }
%label{ for: "send_cancellation_email" }
= t("js.admin.orders.cancel_the_order_send_cancelation_email")
%br
%input{ type: "checkbox", name: "restock_items", value: "1", id: "restock_items", checked: "true" }
%label{ for: "restock_items" }
= t("js.admin.orders.restock_items")
.margin-bottom-30

View File

@@ -0,0 +1,2 @@
= turbo_stream.append "flashes" do
= render partial: 'admin/shared/flashes', locals: { flashes: flash }

View File

@@ -0,0 +1,2 @@
= turbo_stream.append "flashes" do
= render partial: 'admin/shared/flashes', locals: { flashes: flash }

View File

@@ -1,25 +1,44 @@
import ApplicationController from "./application_controller";
export default class extends ApplicationController {
static targets = ["extraParams"]
static values = { reflex: String }
import { Controller } from "stimulus";
export default class extends Controller {
connect() {
super.connect();
this.element.addEventListener('turbo:submit-end', this.closeModal.bind(this));
document.addEventListener('modal-open', this.modalOpen.bind(this));
document.addEventListener('modal-close', this.modalClose.bind(this));
}
perform() {
let params = { bulk_ids: this.getSelectedIds() };
disconnect() {
this.element.removeEventListener('turbo:submit-end', this.closeModal);
document.removeEventListener('modal-open', this.modalOpen);
document.removeEventListener('modal-close', this.modalClose);
}
if (this.hasExtraParamsTarget) {
Object.assign(params, this.extraFormData())
printInvoices(e) {
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
const data = { bulk_ids: this.getSelectedIds() };
fetch(e.target.getAttribute('data-url'), {
method: "POST",
headers: {
Accept: "text/vnd.turbo-stream.html",
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken
},
body: JSON.stringify(data),
})
.then((response) => response.text())
.then((html) => {
Turbo.renderStreamMessage(html);
})
.catch((error) => console.error(error));
}
closeModal(event) {
if (event.detail.success) {
this.element.querySelector("button[type='button']").click();
}
this.stimulate(this.reflexValue, params);
}
// private
getSelectedIds() {
const checkboxes = document.querySelectorAll(
"table input[name='bulk_ids[]']:checked"
@@ -27,9 +46,26 @@ export default class extends ApplicationController {
return Array.from(checkboxes).map((checkbox) => checkbox.value);
}
extraFormData() {
if (this.extraParamsTarget.constructor.name !== "HTMLFormElement") { return {} }
modalOpen(e) {
if (!e.target.contains(this.element)) return;
return Object.fromEntries(new FormData(this.extraParamsTarget).entries())
this.getSelectedIds().forEach((value) => {
const input = Object.assign(document.createElement("input"), {
type: "hidden",
name: "bulk_ids[]",
value,
});
this.element.appendChild(input);
});
this.element.querySelectorAll("input[type='checkbox']").forEach(element => {
element.checked = true;
});
}
modalClose(e) {
if (!e.target.contains(this.element)) return;
this.element.querySelectorAll("input[name='bulk_ids[]']").forEach(ele => ele.remove());
}
}