From 17a782df2a34997ee3f13f76a52374fb19b8955e Mon Sep 17 00:00:00 2001 From: wandji20 Date: Sat, 19 Oct 2024 22:58:28 +0100 Subject: [PATCH] Refactor bulk_action stimulus controller and handle orders bulk actions with turbo_stream --- .../admin/orders/_bulk_actions.html.haml | 2 +- .../orders/bulk_invoice.turbo_stream.haml | 2 + .../orders/cancel_orders.turbo_stream.haml | 3 + app/views/spree/admin/orders/index.html.haml | 40 ++++++++--- .../orders/messages/_cancel_orders.html.haml | 17 +++-- ...send_confirmation_emails.turbo_stream.haml | 2 + .../orders/send_invoices.turbo_stream.haml | 2 + .../controllers/bulk_actions_controller.js | 70 ++++++++++++++----- 8 files changed, 102 insertions(+), 36 deletions(-) create mode 100644 app/views/spree/admin/orders/bulk_invoice.turbo_stream.haml create mode 100644 app/views/spree/admin/orders/cancel_orders.turbo_stream.haml create mode 100644 app/views/spree/admin/orders/resend_confirmation_emails.turbo_stream.haml create mode 100644 app/views/spree/admin/orders/send_invoices.turbo_stream.haml diff --git a/app/views/spree/admin/orders/_bulk_actions.html.haml b/app/views/spree/admin/orders/_bulk_actions.html.haml index 74c032ed55..6b07e372be 100644 --- a/app/views/spree/admin/orders/_bulk_actions.html.haml +++ b/app/views/spree/admin/orders/_bulk_actions.html.haml @@ -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" } diff --git a/app/views/spree/admin/orders/bulk_invoice.turbo_stream.haml b/app/views/spree/admin/orders/bulk_invoice.turbo_stream.haml new file mode 100644 index 0000000000..49e4173495 --- /dev/null +++ b/app/views/spree/admin/orders/bulk_invoice.turbo_stream.haml @@ -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}" } diff --git a/app/views/spree/admin/orders/cancel_orders.turbo_stream.haml b/app/views/spree/admin/orders/cancel_orders.turbo_stream.haml new file mode 100644 index 0000000000..297ff64831 --- /dev/null +++ b/app/views/spree/admin/orders/cancel_orders.turbo_stream.haml @@ -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: } diff --git a/app/views/spree/admin/orders/index.html.haml b/app/views/spree/admin/orders/index.html.haml index ed1028848b..50975535d1 100644 --- a/app/views/spree/admin/orders/index.html.haml +++ b/app/views/spree/admin/orders/index.html.haml @@ -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') diff --git a/app/views/spree/admin/orders/messages/_cancel_orders.html.haml b/app/views/spree/admin/orders/messages/_cancel_orders.html.haml index 9b689ff75e..78690d2d2a 100644 --- a/app/views/spree/admin/orders/messages/_cancel_orders.html.haml +++ b/app/views/spree/admin/orders/messages/_cancel_orders.html.haml @@ -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 diff --git a/app/views/spree/admin/orders/resend_confirmation_emails.turbo_stream.haml b/app/views/spree/admin/orders/resend_confirmation_emails.turbo_stream.haml new file mode 100644 index 0000000000..bbf577bbee --- /dev/null +++ b/app/views/spree/admin/orders/resend_confirmation_emails.turbo_stream.haml @@ -0,0 +1,2 @@ += turbo_stream.append "flashes" do + = render partial: 'admin/shared/flashes', locals: { flashes: flash } \ No newline at end of file diff --git a/app/views/spree/admin/orders/send_invoices.turbo_stream.haml b/app/views/spree/admin/orders/send_invoices.turbo_stream.haml new file mode 100644 index 0000000000..bbf577bbee --- /dev/null +++ b/app/views/spree/admin/orders/send_invoices.turbo_stream.haml @@ -0,0 +1,2 @@ += turbo_stream.append "flashes" do + = render partial: 'admin/shared/flashes', locals: { flashes: flash } \ No newline at end of file diff --git a/app/webpacker/controllers/bulk_actions_controller.js b/app/webpacker/controllers/bulk_actions_controller.js index 9de40fe8cb..bc9f3f5fb4 100644 --- a/app/webpacker/controllers/bulk_actions_controller.js +++ b/app/webpacker/controllers/bulk_actions_controller.js @@ -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()); } }