From 39de2f704f5bd99f4a01f3fc39527a624d4cb93b Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Tue, 28 Nov 2023 15:20:44 +0500 Subject: [PATCH 01/39] #11068, add delete dropdown option # Conflicts: # app/views/admin/products_v3/components/_product_actions.html.haml --- app/controllers/spree/admin/products_controller.rb | 2 ++ .../products_v3/components/_product_actions.html.haml | 9 +++++++++ config/locales/en.yml | 1 + 3 files changed, 12 insertions(+) create mode 100644 app/views/admin/products_v3/components/_product_actions.html.haml diff --git a/app/controllers/spree/admin/products_controller.rb b/app/controllers/spree/admin/products_controller.rb index e153faff38..588b3bb186 100644 --- a/app/controllers/spree/admin/products_controller.rb +++ b/app/controllers/spree/admin/products_controller.rb @@ -88,6 +88,8 @@ module Spree redirect_to spree.admin_products_url end + def destroy; end + def group_buy_options @url_filters = ::ProductFilters.new.extract(request.query_parameters) end diff --git a/app/views/admin/products_v3/components/_product_actions.html.haml b/app/views/admin/products_v3/components/_product_actions.html.haml new file mode 100644 index 0000000000..ae114e2b66 --- /dev/null +++ b/app/views/admin/products_v3/components/_product_actions.html.haml @@ -0,0 +1,9 @@ +.vertical-ellipsis-menu{ "data-controller": "vertical-ellipsis-menu" } + %i.fa.fa-ellipsis-v{ "data-action": "click->vertical-ellipsis-menu#toggle" } + .vertical-ellipsis-menu-content{ "data-vertical-ellipsis-menu-target": "content" } + - if defined?(variant) + = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant), class: "vertical-ellipsis-menu-content-item" + - else + = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" + = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" + = link_to t('admin.products_page.actions.delete'), admin_product_path(product), method: :delete, class: "vertical-ellipsis-menu-content-item" diff --git a/config/locales/en.yml b/config/locales/en.yml index b9df0ba1f9..4120e755bc 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -580,6 +580,7 @@ en: actions: edit: Edit clone: Clone + delete: Delete adjustments: skipped_changing_canceled_order: "You can't change a cancelled order." # Common properties / models From 0ff1067bc676b9eea2f054463c8091b5dec654d9 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 25 Nov 2023 00:48:49 +0500 Subject: [PATCH 02/39] #11068, add delete option for product variant --- app/controllers/spree/admin/variants_controller.rb | 2 +- .../admin/products_v3/components/_product_actions.html.haml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/spree/admin/variants_controller.rb b/app/controllers/spree/admin/variants_controller.rb index 47505f7b1d..b481566d29 100644 --- a/app/controllers/spree/admin/variants_controller.rb +++ b/app/controllers/spree/admin/variants_controller.rb @@ -67,7 +67,7 @@ module Spree @variant = Spree::Variant.find(params[:id]) flash[:success] = delete_variant - redirect_to spree.admin_product_variants_url(params[:product_id], @url_filters) + redirect_to spree.admin_products_url end protected diff --git a/app/views/admin/products_v3/components/_product_actions.html.haml b/app/views/admin/products_v3/components/_product_actions.html.haml index ae114e2b66..c905d0d911 100644 --- a/app/views/admin/products_v3/components/_product_actions.html.haml +++ b/app/views/admin/products_v3/components/_product_actions.html.haml @@ -3,6 +3,8 @@ .vertical-ellipsis-menu-content{ "data-vertical-ellipsis-menu-target": "content" } - if defined?(variant) = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant), class: "vertical-ellipsis-menu-content-item" + - if product.variants.size > 1 + = link_to t('admin.products_page.actions.delete'), admin_product_variant_path(product, variant), method: :delete, class: "vertical-ellipsis-menu-content-item" - else = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" From 5d490ded1581f1bb687fd1067eb7e61b7db92902 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 25 Nov 2023 15:00:48 +0500 Subject: [PATCH 03/39] #11068, update ConfirmModalComponent to take more options --- app/components/confirm_modal_component.rb | 16 ++++++++++++++-- .../confirm_modal_component.html.haml | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index ccd0c67797..39ed7f90e0 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -1,14 +1,26 @@ # frozen_string_literal: true class ConfirmModalComponent < ModalComponent - def initialize(id:, confirm_actions: nil, reflex: nil, controller: nil, message: nil, - confirm_reflexes: nil) + def initialize( + id:, + reflex: nil, + controller: nil, + message: nil, + confirm_actions: nil, + confirm_reflexes: nil, + confirm_button_color: :primary, + confirm_button_text: I18n.t('js.admin.modals.confirm'), + cancel_button_text: I18n.t('js.admin.modals.cancel') + ) super(id:, close_button: true) @confirm_actions = confirm_actions @reflex = reflex @confirm_reflexes = confirm_reflexes @controller = controller @message = message + @confirm_button_color = confirm_button_color + @confirm_button_text = confirm_button_text + @cancel_button_text = cancel_button_text end private diff --git a/app/components/confirm_modal_component/confirm_modal_component.html.haml b/app/components/confirm_modal_component/confirm_modal_component.html.haml index 1b3e1ff217..5049e9e52c 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.html.haml +++ b/app/components/confirm_modal_component/confirm_modal_component.html.haml @@ -6,5 +6,5 @@ = render @message if @message .modal-actions - %input{ class: "button icon-plus #{close_button_class}", type: 'button', value: t('js.admin.modals.cancel'), "data-action": "click->modal#close" } - %input{ class: "button icon-plus primary", type: 'button', value: t('js.admin.modals.confirm'), "data-action": @confirm_actions, "data-reflex": @confirm_reflexes } + %input{ class: "button icon-plus #{close_button_class}", type: 'button', value: @cancel_button_text, "data-action": "click->modal#close" } + %input{ class: "button icon-plus #{@confirm_button_color}", type: 'button', value: @confirm_button_text, "data-action": @confirm_actions, "data-reflex": @confirm_reflexes } From 4f764786195c5658b4536684ea649c167b582342 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 25 Nov 2023 16:10:05 +0500 Subject: [PATCH 04/39] #11068, add delete modals --- .../components/_product_actions.html.haml | 16 ++++++++++++++-- app/views/admin/products_v3/index.html.haml | 16 ++++++++++++++++ config/locales/en.yml | 8 ++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/app/views/admin/products_v3/components/_product_actions.html.haml b/app/views/admin/products_v3/components/_product_actions.html.haml index c905d0d911..12bd9bfc24 100644 --- a/app/views/admin/products_v3/components/_product_actions.html.haml +++ b/app/views/admin/products_v3/components/_product_actions.html.haml @@ -4,8 +4,20 @@ - if defined?(variant) = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant), class: "vertical-ellipsis-menu-content-item" - if product.variants.size > 1 - = link_to t('admin.products_page.actions.delete'), admin_product_variant_path(product, variant), method: :delete, class: "vertical-ellipsis-menu-content-item" + %span{ + "data-controller": "modal-link", + "data-action": "click->modal-link#open", + "data-modal-link-target-value": "delete_variant", + "class": "vertical-ellipsis-menu-content-item" + } + = t('admin.products_page.actions.delete') - else = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" - = link_to t('admin.products_page.actions.delete'), admin_product_path(product), method: :delete, class: "vertical-ellipsis-menu-content-item" + %span{ + "data-controller": "modal-link", + "data-action": "click->modal-link#open", + "data-modal-link-target-value": "delete_product", + "class": "vertical-ellipsis-menu-content-item" + } + = t('admin.products_page.actions.delete') diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 82a4e5f38e..094cdd6d96 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -17,3 +17,19 @@ .spinner = t('.loading') #products-content + +- delete_product_modal = ConfirmModalComponent.new(id: "delete_product", + confirm_button_text: t('.delete_product_modal.confirmation_text'), + cancel_button_text: t('.delete_product_modal.cancellation_text'), + confirm_button_color: :red) += render delete_product_modal do + .margin-bottom-30 + = t('.delete_product_modal.prompt_html') + +- delete_variant_modal = ConfirmModalComponent.new(id: "delete_variant", + confirm_button_text: t('.delete_variant_modal.confirmation_text'), + cancel_button_text: t('.delete_variant_modal.cancellation_text'), + confirm_button_color: :red) += render delete_variant_modal do + .margin-bottom-30 + = t('.delete_variant_modal.prompt_html') diff --git a/config/locales/en.yml b/config/locales/en.yml index 4120e755bc..22df1141a1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -816,6 +816,14 @@ en: header: title: Bulk Edit Products loading: Loading your products + delete_product_modal: + prompt_html: "

Delete product


This will permanently remove it from your list." + confirmation_text: "Delete product" + cancellation_text: "Keep product" + delete_variant_modal: + prompt_html: "

Delete variant


This will permanently remove it from your list." + confirmation_text: "Delete variant" + cancellation_text: "Keep variant" sort: pagination: total_html: "%{total} products found for your search criteria. Showing %{from} to %{to}." From bf0943e6559f0b20c839db51fc0912fbb5ab2f82 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 25 Nov 2023 19:33:13 +0500 Subject: [PATCH 05/39] #11068, add ProductDeleter --- app/services/product_deleter.rb | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 app/services/product_deleter.rb diff --git a/app/services/product_deleter.rb b/app/services/product_deleter.rb new file mode 100644 index 0000000000..c78743afdf --- /dev/null +++ b/app/services/product_deleter.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# This soft deletes the product +class ProductDeleter + def self.delete(product) + product.destroy + end +end From 2f0965aa6201149569311d45f175971ba1c87069 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 25 Nov 2023 19:38:43 +0500 Subject: [PATCH 06/39] #11068, add product_actions_controller --- app/views/admin/products_v3/index.html.haml | 5 ++++- app/webpacker/controllers/product_actions_controller.js | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 app/webpacker/controllers/product_actions_controller.js diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 094cdd6d96..4e36663acf 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -21,7 +21,10 @@ - delete_product_modal = ConfirmModalComponent.new(id: "delete_product", confirm_button_text: t('.delete_product_modal.confirmation_text'), cancel_button_text: t('.delete_product_modal.cancellation_text'), - confirm_button_color: :red) + confirm_button_color: :red, + controller: "product-actions", + confirm_actions: "click->product-actions#delete", + confirm_reflexes: nil) = render delete_product_modal do .margin-bottom-30 = t('.delete_product_modal.prompt_html') diff --git a/app/webpacker/controllers/product_actions_controller.js b/app/webpacker/controllers/product_actions_controller.js new file mode 100644 index 0000000000..2d2523e629 --- /dev/null +++ b/app/webpacker/controllers/product_actions_controller.js @@ -0,0 +1,9 @@ +import ApplicationController from "./application_controller"; + +export default class extends ApplicationController { + static values = {currentId: Number, currentVariantId: Number}; + + delete() { + + } +} From d7f2cbf8820730c18d0fe1d3953ba42ef38a54a2 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 25 Nov 2023 19:44:33 +0500 Subject: [PATCH 07/39] 11068, revert controller changes --- app/controllers/spree/admin/products_controller.rb | 2 -- app/controllers/spree/admin/variants_controller.rb | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/controllers/spree/admin/products_controller.rb b/app/controllers/spree/admin/products_controller.rb index 588b3bb186..e153faff38 100644 --- a/app/controllers/spree/admin/products_controller.rb +++ b/app/controllers/spree/admin/products_controller.rb @@ -88,8 +88,6 @@ module Spree redirect_to spree.admin_products_url end - def destroy; end - def group_buy_options @url_filters = ::ProductFilters.new.extract(request.query_parameters) end diff --git a/app/controllers/spree/admin/variants_controller.rb b/app/controllers/spree/admin/variants_controller.rb index b481566d29..47505f7b1d 100644 --- a/app/controllers/spree/admin/variants_controller.rb +++ b/app/controllers/spree/admin/variants_controller.rb @@ -67,7 +67,7 @@ module Spree @variant = Spree::Variant.find(params[:id]) flash[:success] = delete_variant - redirect_to spree.admin_products_url + redirect_to spree.admin_product_variants_url(params[:product_id], @url_filters) end protected From d1224ea0228e2a52a94a1e9914e607f649c95aa0 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Tue, 28 Nov 2023 15:55:30 +0500 Subject: [PATCH 08/39] #11068, resolve conflicts --- .../vertical_ellipsis_menu/component.scss | 3 ++- app/views/admin/products_v3/_table.html.haml | 8 +++++++ .../components/_product_actions.html.haml | 23 ------------------- 3 files changed, 10 insertions(+), 24 deletions(-) delete mode 100644 app/views/admin/products_v3/components/_product_actions.html.haml diff --git a/app/components/vertical_ellipsis_menu/component.scss b/app/components/vertical_ellipsis_menu/component.scss index 03b5cb39d8..7730b384ce 100644 --- a/app/components/vertical_ellipsis_menu/component.scss +++ b/app/components/vertical_ellipsis_menu/component.scss @@ -30,7 +30,8 @@ display: block; } - & > a { + & > a, + p { display: block; padding: 5px 10px; cursor: pointer; diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 0462529857..40938e3ac4 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -70,6 +70,10 @@ = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product) = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product) + %p{"data-controller": "modal-link", "data-action": "click->modal-link#open", + "data-modal-link-target-value": "delete_product", "class": "delete" + } + = t('admin.products_page.actions.delete') - product.variants.each_with_index do |variant, variant_index| = form.fields_for("products][#{product_index}][variants_attributes][", variant, variant_index:) do |variant_form| @@ -108,3 +112,7 @@ %td.align-right = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant) + %p{"data-controller": "modal-link", "data-action": "click->modal-link#open", + "data-modal-link-target-value": "delete_variant", "class": "delete" + } + = t('admin.products_page.actions.delete') diff --git a/app/views/admin/products_v3/components/_product_actions.html.haml b/app/views/admin/products_v3/components/_product_actions.html.haml deleted file mode 100644 index 12bd9bfc24..0000000000 --- a/app/views/admin/products_v3/components/_product_actions.html.haml +++ /dev/null @@ -1,23 +0,0 @@ -.vertical-ellipsis-menu{ "data-controller": "vertical-ellipsis-menu" } - %i.fa.fa-ellipsis-v{ "data-action": "click->vertical-ellipsis-menu#toggle" } - .vertical-ellipsis-menu-content{ "data-vertical-ellipsis-menu-target": "content" } - - if defined?(variant) - = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant), class: "vertical-ellipsis-menu-content-item" - - if product.variants.size > 1 - %span{ - "data-controller": "modal-link", - "data-action": "click->modal-link#open", - "data-modal-link-target-value": "delete_variant", - "class": "vertical-ellipsis-menu-content-item" - } - = t('admin.products_page.actions.delete') - - else - = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" - = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product), class: "vertical-ellipsis-menu-content-item" - %span{ - "data-controller": "modal-link", - "data-action": "click->modal-link#open", - "data-modal-link-target-value": "delete_product", - "class": "vertical-ellipsis-menu-content-item" - } - = t('admin.products_page.actions.delete') From 0efd78b979b06575d3b3111b0a0f07e805f3dab3 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sun, 3 Dec 2023 23:01:56 +0500 Subject: [PATCH 09/39] #11068: update confirm_modal_component to accept controller values --- app/components/confirm_modal_component.rb | 18 +++++++++++++++++- .../confirm_modal_component.html.haml | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index 39ed7f90e0..32cdebe5ba 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class ConfirmModalComponent < ModalComponent + # @param controller_data_values [Array(Hash)] format: {: value1, : value2} def initialize( id:, reflex: nil, @@ -10,7 +11,8 @@ class ConfirmModalComponent < ModalComponent confirm_reflexes: nil, confirm_button_color: :primary, confirm_button_text: I18n.t('js.admin.modals.confirm'), - cancel_button_text: I18n.t('js.admin.modals.cancel') + cancel_button_text: I18n.t('js.admin.modals.cancel'), + controller_data_values: {} ) super(id:, close_button: true) @confirm_actions = confirm_actions @@ -21,6 +23,7 @@ class ConfirmModalComponent < ModalComponent @confirm_button_color = confirm_button_color @confirm_button_text = confirm_button_text @cancel_button_text = cancel_button_text + @controller_data_values = transform_values_for_controller(controller_data_values) end private @@ -28,4 +31,17 @@ class ConfirmModalComponent < ModalComponent def close_button_class "secondary" end + + def modal_attrs + @modal_attrs ||= { + id: @id, + "data-controller": "modal #{@controller}", + "data-action": "keyup@document->modal#closeIfEscapeKey", + "data-#{@controller}-reflex-value": @reflex + }.merge(@controller_data_values) + end + + def transform_values_for_controller(values) + values.transform_keys { |value_name| "data-#{@controller}-#{value_name}-value" } + end end diff --git a/app/components/confirm_modal_component/confirm_modal_component.html.haml b/app/components/confirm_modal_component/confirm_modal_component.html.haml index 5049e9e52c..3ab7e1b281 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.html.haml +++ b/app/components/confirm_modal_component/confirm_modal_component.html.haml @@ -1,4 +1,4 @@ -%div{ id: @id, "data-controller": "modal #{@controller}", "data-action": "keyup@document->modal#closeIfEscapeKey", "data-#{@controller}-reflex-value": @reflex } +%div{ **modal_attrs } .reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" } .reveal-modal.fade.tiny.help-modal{ "data-modal-target": "modal" } = content From c202324cb0fb17712a3c1a4836fbc233a3f36a57 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sun, 3 Dec 2023 23:04:34 +0500 Subject: [PATCH 10/39] #11068: add product_v3 delete_modals partial --- .../admin/products_v3/_delete_modals.html.haml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 app/views/admin/products_v3/_delete_modals.html.haml diff --git a/app/views/admin/products_v3/_delete_modals.html.haml b/app/views/admin/products_v3/_delete_modals.html.haml new file mode 100644 index 0000000000..5053dee80e --- /dev/null +++ b/app/views/admin/products_v3/_delete_modals.html.haml @@ -0,0 +1,14 @@ +- object_ids.each do |object_id| + - delete_modal = ConfirmModalComponent.new(id: "delete_#{object_type}_#{object_id}", + confirm_button_text: t(".delete_#{object_type}_modal.confirmation_text"), + cancel_button_text: t(".delete_#{object_type}_modal.cancellation_text"), + confirm_button_color: :red, + controller: "product-actions", + confirm_actions: "click->product-actions#delete#{object_type.titleize}", + confirm_reflexes: nil, + controller_data_values: {"current-id": object_id}, + ) + = render delete_modal do + .margin-bottom-30 + = t(".delete_#{object_type}_modal.prompt_html") + .margin-bottom-30 From 5d90993f2146013f147e164ff69edd049da04c20 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sun, 3 Dec 2023 23:07:53 +0500 Subject: [PATCH 11/39] 11068, apply delete_modals partial --- app/reflexes/products_reflex.rb | 25 +++++++++++++++++++++ app/views/admin/products_v3/index.html.haml | 21 ++--------------- config/locales/en.yml | 1 + 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 4154a7b61f..fb25c955de 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -77,6 +77,9 @@ class ProductsReflex < ApplicationReflex category_options: categories, category_id: @category_id }) ).broadcast + render_product_delete_modals + render_variant_delete_modals + cable_ready.replace_state( url: current_url, ).broadcast_later @@ -84,6 +87,28 @@ class ProductsReflex < ApplicationReflex morph :nothing end + def render_product_delete_modals + product_ids = @products.pluck(:id) + cable_ready.replace( + selector: "#products-delete-action-modals", + html: render( + partial: "admin/products_v3/delete_modals", + locals: { object_ids: product_ids, object_type: 'product' } + ) + ).broadcast + end + + def render_variant_delete_modals + variant_ids = @products.joins(:variants).pluck('spree_variants.id') + cable_ready.replace( + selector: "#variant-delete-action-modals", + html: render( + partial: "admin/products_v3/delete_modals", + locals: { object_ids: variant_ids, object_type: 'variant' } + ) + ).broadcast + end + def render_products_form_with_flash locals = { products: @products } locals[:error_counts] = @error_counts if @error_counts.present? diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 4e36663acf..2031eadf41 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -17,22 +17,5 @@ .spinner = t('.loading') #products-content - -- delete_product_modal = ConfirmModalComponent.new(id: "delete_product", - confirm_button_text: t('.delete_product_modal.confirmation_text'), - cancel_button_text: t('.delete_product_modal.cancellation_text'), - confirm_button_color: :red, - controller: "product-actions", - confirm_actions: "click->product-actions#delete", - confirm_reflexes: nil) -= render delete_product_modal do - .margin-bottom-30 - = t('.delete_product_modal.prompt_html') - -- delete_variant_modal = ConfirmModalComponent.new(id: "delete_variant", - confirm_button_text: t('.delete_variant_modal.confirmation_text'), - cancel_button_text: t('.delete_variant_modal.cancellation_text'), - confirm_button_color: :red) -= render delete_variant_modal do - .margin-bottom-30 - = t('.delete_variant_modal.prompt_html') + #products-delete-action-modals + #variant-delete-action-modals diff --git a/config/locales/en.yml b/config/locales/en.yml index 22df1141a1..d6ffd0c001 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -816,6 +816,7 @@ en: header: title: Bulk Edit Products loading: Loading your products + delete_modals: delete_product_modal: prompt_html: "

Delete product


This will permanently remove it from your list." confirmation_text: "Delete product" From eca83eeec3c7b93e7aacab4c1725809d19138316 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sun, 3 Dec 2023 23:08:48 +0500 Subject: [PATCH 12/39] #11068, update delete links for uniq modal ids --- app/views/admin/products_v3/_table.html.haml | 13 ++++++------- .../controllers/product_actions_controller.js | 8 ++++++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 40938e3ac4..5066b023d2 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -70,9 +70,8 @@ = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product) = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product) - %p{"data-controller": "modal-link", "data-action": "click->modal-link#open", - "data-modal-link-target-value": "delete_product", "class": "delete" - } + %p{ "data-controller": "modal-link", "data-action": "click->modal-link#open", + "data-modal-link-target-value": "delete_product_#{product.id}", "class": "delete" } = t('admin.products_page.actions.delete') - product.variants.each_with_index do |variant, variant_index| @@ -112,7 +111,7 @@ %td.align-right = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant) - %p{"data-controller": "modal-link", "data-action": "click->modal-link#open", - "data-modal-link-target-value": "delete_variant", "class": "delete" - } - = t('admin.products_page.actions.delete') + - if product.variants.size > 1 + %p{ "data-controller": "modal-link", "data-action": "click->modal-link#open", + "data-modal-link-target-value": "delete_variant_#{variant.id}", "class": "delete" } + = t('admin.products_page.actions.delete') diff --git a/app/webpacker/controllers/product_actions_controller.js b/app/webpacker/controllers/product_actions_controller.js index 2d2523e629..0d60b6ba15 100644 --- a/app/webpacker/controllers/product_actions_controller.js +++ b/app/webpacker/controllers/product_actions_controller.js @@ -1,9 +1,13 @@ import ApplicationController from "./application_controller"; export default class extends ApplicationController { - static values = {currentId: Number, currentVariantId: Number}; + static values = {currentId: Number}; - delete() { + deleteProduct() { + debugger + } + deleteVariant(){ + debugger } } From 05e7674805f5eb0c2f354e8b5590c2c7d1086e76 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Wed, 13 Dec 2023 03:51:23 +0500 Subject: [PATCH 13/39] #11068: add delete variant and product reflexes --- app/reflexes/products_reflex.rb | 18 ++++++++++++++++++ app/services/product_deleter.rb | 6 ++++-- .../products_v3/_delete_modals.html.haml | 4 ++-- .../controllers/products_controller.js | 19 ++++++++++++++++++- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index fb25c955de..8a6c3a8127 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -46,6 +46,24 @@ class ProductsReflex < ApplicationReflex render_products_form_with_flash end + def delete_product(product_id) + if ProductDeleter.delete(product_id) + puts "Deleted Successfully" + else + puts "Failure" + end + fetch_and_render_products + end + + def delete_variant(variant_id) + if VariantDeleter.new.delete(variant_id) + puts "Deleted Successfully" + else + puts "Failure" + end + fetch_and_render_products + end + private def init_filters_params diff --git a/app/services/product_deleter.rb b/app/services/product_deleter.rb index c78743afdf..5c6ce96fb8 100644 --- a/app/services/product_deleter.rb +++ b/app/services/product_deleter.rb @@ -2,7 +2,9 @@ # This soft deletes the product class ProductDeleter - def self.delete(product) - product.destroy + # @param id [int] ID of the product to be deleted + def self.delete(id) + product = Spree::Product.find_by(id:) + product&.destroy end end diff --git a/app/views/admin/products_v3/_delete_modals.html.haml b/app/views/admin/products_v3/_delete_modals.html.haml index 5053dee80e..5a8e9bd69c 100644 --- a/app/views/admin/products_v3/_delete_modals.html.haml +++ b/app/views/admin/products_v3/_delete_modals.html.haml @@ -3,9 +3,9 @@ confirm_button_text: t(".delete_#{object_type}_modal.confirmation_text"), cancel_button_text: t(".delete_#{object_type}_modal.cancellation_text"), confirm_button_color: :red, - controller: "product-actions", - confirm_actions: "click->product-actions#delete#{object_type.titleize}", confirm_reflexes: nil, + controller: "products", + confirm_actions: "click->products#delete#{object_type.titleize}", controller_data_values: {"current-id": object_id}, ) = render delete_modal do diff --git a/app/webpacker/controllers/products_controller.js b/app/webpacker/controllers/products_controller.js index c8a1dc6963..27ef661923 100644 --- a/app/webpacker/controllers/products_controller.js +++ b/app/webpacker/controllers/products_controller.js @@ -2,6 +2,7 @@ import ApplicationController from "./application_controller"; export default class extends ApplicationController { static targets = ["loading"]; + static values = {currentId: Number}; connect() { super.connect(); @@ -9,6 +10,15 @@ export default class extends ApplicationController { this.stimulate("Products#fetch"); } + deleteProduct() { + window.dispatchEvent(new Event('modal:close')); + this.stimulate('Products#delete_product', this.currentIdValue) + } + + deleteVariant() { + this.stimulate('Products#delete_variant', this.currentIdValue) + } + beforeReflex() { this.showLoading(); this.scrollToElement(); @@ -35,8 +45,15 @@ export default class extends ApplicationController { }; getLoadingController = () => { + let loadingSpinner = null; + try { + loadingSpinner = this.loadingTarget; // throws missing loading target error + } catch (error) { + loadingSpinner = document.getElementById('loading-spinner'); + } + return (this.loadingController ||= this.application.getControllerForElementAndIdentifier( - this.loadingTarget, + loadingSpinner, "loading" )); }; From d8eace8dff631f2fc4bcb470d7001dbd3b9e98ab Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Wed, 13 Dec 2023 03:52:45 +0500 Subject: [PATCH 14/39] #11068: remove product_actions_controller.js --- .../controllers/product_actions_controller.js | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 app/webpacker/controllers/product_actions_controller.js diff --git a/app/webpacker/controllers/product_actions_controller.js b/app/webpacker/controllers/product_actions_controller.js deleted file mode 100644 index 0d60b6ba15..0000000000 --- a/app/webpacker/controllers/product_actions_controller.js +++ /dev/null @@ -1,13 +0,0 @@ -import ApplicationController from "./application_controller"; - -export default class extends ApplicationController { - static values = {currentId: Number}; - - deleteProduct() { - debugger - } - - deleteVariant(){ - debugger - } -} From a71bb217890cffa2d313bebf4940e172ef907d97 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 14 Dec 2023 00:32:40 +0500 Subject: [PATCH 15/39] 11068: update confirm_button_color to confirm_button_class --- app/components/confirm_modal_component.rb | 4 ++-- .../confirm_modal_component/confirm_modal_component.html.haml | 2 +- app/views/admin/products_v3/_delete_modals.html.haml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index 32cdebe5ba..2aafd0bb37 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -9,7 +9,7 @@ class ConfirmModalComponent < ModalComponent message: nil, confirm_actions: nil, confirm_reflexes: nil, - confirm_button_color: :primary, + confirm_button_class: :primary, confirm_button_text: I18n.t('js.admin.modals.confirm'), cancel_button_text: I18n.t('js.admin.modals.cancel'), controller_data_values: {} @@ -20,7 +20,7 @@ class ConfirmModalComponent < ModalComponent @confirm_reflexes = confirm_reflexes @controller = controller @message = message - @confirm_button_color = confirm_button_color + @confirm_button_class = confirm_button_class @confirm_button_text = confirm_button_text @cancel_button_text = cancel_button_text @controller_data_values = transform_values_for_controller(controller_data_values) diff --git a/app/components/confirm_modal_component/confirm_modal_component.html.haml b/app/components/confirm_modal_component/confirm_modal_component.html.haml index 3ab7e1b281..7d7b5cd77a 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.html.haml +++ b/app/components/confirm_modal_component/confirm_modal_component.html.haml @@ -7,4 +7,4 @@ .modal-actions %input{ class: "button icon-plus #{close_button_class}", type: 'button', value: @cancel_button_text, "data-action": "click->modal#close" } - %input{ class: "button icon-plus #{@confirm_button_color}", type: 'button', value: @confirm_button_text, "data-action": @confirm_actions, "data-reflex": @confirm_reflexes } + %input{ class: "button icon-plus #{@confirm_button_class}", type: 'button', value: @confirm_button_text, "data-action": @confirm_actions, "data-reflex": @confirm_reflexes } diff --git a/app/views/admin/products_v3/_delete_modals.html.haml b/app/views/admin/products_v3/_delete_modals.html.haml index 5a8e9bd69c..d2091f792b 100644 --- a/app/views/admin/products_v3/_delete_modals.html.haml +++ b/app/views/admin/products_v3/_delete_modals.html.haml @@ -2,8 +2,8 @@ - delete_modal = ConfirmModalComponent.new(id: "delete_#{object_type}_#{object_id}", confirm_button_text: t(".delete_#{object_type}_modal.confirmation_text"), cancel_button_text: t(".delete_#{object_type}_modal.cancellation_text"), - confirm_button_color: :red, confirm_reflexes: nil, + confirm_button_class: :red, controller: "products", confirm_actions: "click->products#delete#{object_type.titleize}", controller_data_values: {"current-id": object_id}, From 26d102f66b9e95d6eb9db4e4ea665323b7143966 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 14 Dec 2023 01:20:33 +0500 Subject: [PATCH 16/39] 11068: update product/varaint delete actions --- app/reflexes/products_reflex.rb | 26 ++++++++++++++++--- app/services/product_deleter.rb | 10 ------- .../controllers/products_controller.js | 1 + 3 files changed, 23 insertions(+), 14 deletions(-) delete mode 100644 app/services/product_deleter.rb diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 8a6c3a8127..ab15b122b8 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -46,21 +46,31 @@ class ProductsReflex < ApplicationReflex render_products_form_with_flash end - def delete_product(product_id) - if ProductDeleter.delete(product_id) + def delete_product(id) + authorize! :delete, Spree::Product + product = product_finder(id).find_product + authorize! :delete, product + + if product.destroy puts "Deleted Successfully" else puts "Failure" end + fetch_and_render_products end - def delete_variant(variant_id) - if VariantDeleter.new.delete(variant_id) + def delete_variant(id) + authorize! :delete, Spree::Variant + variant = variant_scope.find(id) + authorize! :delete, variant + + if VariantDeleter.new.delete(variant) puts "Deleted Successfully" else puts "Failure" end + fetch_and_render_products end @@ -238,4 +248,12 @@ class ProductsReflex < ApplicationReflex params.permit(products: ::PermittedAttributes::Product.attributes) .to_h.with_indifferent_access end + + def product_finder(id) + ProductScopeQuery.new(current_user, {id:}) + end + + def variant_scope + Spree::Variant.active + end end diff --git a/app/services/product_deleter.rb b/app/services/product_deleter.rb deleted file mode 100644 index 5c6ce96fb8..0000000000 --- a/app/services/product_deleter.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -# This soft deletes the product -class ProductDeleter - # @param id [int] ID of the product to be deleted - def self.delete(id) - product = Spree::Product.find_by(id:) - product&.destroy - end -end diff --git a/app/webpacker/controllers/products_controller.js b/app/webpacker/controllers/products_controller.js index 27ef661923..e9ba45e46a 100644 --- a/app/webpacker/controllers/products_controller.js +++ b/app/webpacker/controllers/products_controller.js @@ -16,6 +16,7 @@ export default class extends ApplicationController { } deleteVariant() { + window.dispatchEvent(new Event('modal:close')); this.stimulate('Products#delete_variant', this.currentIdValue) } From a321a962a512efec889b47d741489292939e3d1d Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 14 Dec 2023 01:45:39 +0500 Subject: [PATCH 17/39] 11068: separate prompt_html into individual translation --- app/views/admin/products_v3/_delete_modals.html.haml | 11 +++++++---- config/locales/en.yml | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/views/admin/products_v3/_delete_modals.html.haml b/app/views/admin/products_v3/_delete_modals.html.haml index d2091f792b..815913925a 100644 --- a/app/views/admin/products_v3/_delete_modals.html.haml +++ b/app/views/admin/products_v3/_delete_modals.html.haml @@ -1,7 +1,8 @@ +- base_translation_key = ".delete_#{object_type}_modal" - object_ids.each do |object_id| - delete_modal = ConfirmModalComponent.new(id: "delete_#{object_type}_#{object_id}", - confirm_button_text: t(".delete_#{object_type}_modal.confirmation_text"), - cancel_button_text: t(".delete_#{object_type}_modal.cancellation_text"), + confirm_button_text: t("#{base_translation_key}.confirmation_text"), + cancel_button_text: t("#{base_translation_key}.cancellation_text"), confirm_reflexes: nil, confirm_button_class: :red, controller: "products", @@ -9,6 +10,8 @@ controller_data_values: {"current-id": object_id}, ) = render delete_modal do - .margin-bottom-30 - = t(".delete_#{object_type}_modal.prompt_html") + %h2.margin-bottom-20{style:'color: black'} + = t("#{base_translation_key}.heading") + %p + = t("#{base_translation_key}.prompt") .margin-bottom-30 diff --git a/config/locales/en.yml b/config/locales/en.yml index d6ffd0c001..4f2801982c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -818,11 +818,13 @@ en: loading: Loading your products delete_modals: delete_product_modal: - prompt_html: "

Delete product


This will permanently remove it from your list." + heading: "Delete product" + prompt: "This will permanently remove it from your list." confirmation_text: "Delete product" cancellation_text: "Keep product" delete_variant_modal: - prompt_html: "

Delete variant


This will permanently remove it from your list." + heading: "Delete variant" + prompt: "This will permanently remove it from your list." confirmation_text: "Delete variant" cancellation_text: "Keep variant" sort: From 1936adc82fe84d77bda349fdde3e8fde23d73178 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 14 Dec 2023 01:56:30 +0500 Subject: [PATCH 18/39] 11068: fix lint issues --- app/components/confirm_modal_component.rb | 7 ++++--- app/reflexes/products_reflex.rb | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index 2aafd0bb37..e519a6c227 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true class ConfirmModalComponent < ModalComponent - # @param controller_data_values [Array(Hash)] format: {: value1, : value2} + # @param controller_data_values [Array(Hash)] + # format: {: value1, : value2} def initialize( id:, reflex: nil, @@ -35,8 +36,8 @@ class ConfirmModalComponent < ModalComponent def modal_attrs @modal_attrs ||= { id: @id, - "data-controller": "modal #{@controller}", - "data-action": "keyup@document->modal#closeIfEscapeKey", + 'data-controller': "modal #{@controller}", + 'data-action': "keyup@document->modal#closeIfEscapeKey", "data-#{@controller}-reflex-value": @reflex }.merge(@controller_data_values) end diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index ab15b122b8..9768a43ef9 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -250,7 +250,7 @@ class ProductsReflex < ApplicationReflex end def product_finder(id) - ProductScopeQuery.new(current_user, {id:}) + ProductScopeQuery.new(current_user, { id: }) end def variant_scope From 9cf51f3453178e5346e3efce4d3685aed716583b Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Fri, 15 Dec 2023 02:43:39 +0500 Subject: [PATCH 19/39] 11068: add success and failure messages --- app/reflexes/products_reflex.rb | 25 ++++++++++--------- .../admin/products_v3/_content.html.haml | 1 + config/locales/en.yml | 6 +++++ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 9768a43ef9..876a1cf1d1 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -6,20 +6,20 @@ class ProductsReflex < ApplicationReflex before_reflex :init_filters_params, :init_pagination_params def fetch - fetch_and_render_products + fetch_and_render_products_with_flash end def change_per_page @per_page = element.value.to_i @page = 1 - fetch_and_render_products + fetch_and_render_products_with_flash end def filter @page = 1 - fetch_and_render_products + fetch_and_render_products_with_flash end def clear_search @@ -28,7 +28,7 @@ class ProductsReflex < ApplicationReflex @category_id = nil @page = 1 - fetch_and_render_products + fetch_and_render_products_with_flash end def bulk_update @@ -52,12 +52,12 @@ class ProductsReflex < ApplicationReflex authorize! :delete, product if product.destroy - puts "Deleted Successfully" + flash[:success] = I18n.t('admin.products_v3.delete_product.success') else - puts "Failure" + flash[:error] = I18n.t('admin.products_v3.delete_product.error') end - fetch_and_render_products + fetch_and_render_products_with_flash end def delete_variant(id) @@ -66,12 +66,12 @@ class ProductsReflex < ApplicationReflex authorize! :delete, variant if VariantDeleter.new.delete(variant) - puts "Deleted Successfully" + flash[:success] = I18n.t('admin.products_v3.delete_variant.success') else - puts "Failure" + flash[:error] = I18n.t('admin.products_v3.delete_variant.error') end - fetch_and_render_products + fetch_and_render_products_with_flash end private @@ -91,7 +91,7 @@ class ProductsReflex < ApplicationReflex @per_page = element.dataset.perpage || params[:_per_page] || 15 end - def fetch_and_render_products + def fetch_and_render_products_with_flash fetch_products render_products end @@ -102,7 +102,8 @@ class ProductsReflex < ApplicationReflex html: render(partial: "admin/products_v3/content", locals: { products: @products, pagy: @pagy, search_term: @search_term, producer_options: producers, producer_id: @producer_id, - category_options: categories, category_id: @category_id }) + category_options: categories, category_id: @category_id, + flashes: flash }) ).broadcast render_product_delete_modals diff --git a/app/views/admin/products_v3/_content.html.haml b/app/views/admin/products_v3/_content.html.haml index 0cda71ff9a..b805747b71 100644 --- a/app/views/admin/products_v3/_content.html.haml +++ b/app/views/admin/products_v3/_content.html.haml @@ -1,6 +1,7 @@ #products-content .container .sixteen.columns + = render partial: 'admin/shared/flashes', locals: { flashes: } if defined? flashes = render partial: 'filters', locals: { search_term: search_term, producer_id: producer_id, producer_options: producer_options, diff --git a/config/locales/en.yml b/config/locales/en.yml index 4f2801982c..d5fde0c609 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -865,6 +865,12 @@ en: reset: Discard changes bulk_update: success: Changes saved + delete_product: + success: Successfully deleted the product + error: Unable to delete the product + delete_variant: + success: Successfully deleted the variant + error: Unable to delete the variant product_import: title: Product Import file_not_found: File not found or could not be opened From f44476b9afb9638268670694f9a0e1549214db70 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 16 Dec 2023 21:06:38 +0500 Subject: [PATCH 20/39] 11068: code refactoring - Make use of reflexes when deleting the product and variant - Add reflex dataset param to confirm_modal_component --- app/components/confirm_modal_component.rb | 24 +++++++++-------- .../confirm_modal_component.html.haml | 4 +-- app/reflexes/products_reflex.rb | 12 ++++++--- .../products_v3/_delete_modals.html.haml | 6 ++--- app/views/admin/products_v3/index.html.haml | 2 +- .../controllers/products_controller.js | 27 +++++-------------- 6 files changed, 34 insertions(+), 41 deletions(-) diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index e519a6c227..be1653cc6f 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -13,7 +13,7 @@ class ConfirmModalComponent < ModalComponent confirm_button_class: :primary, confirm_button_text: I18n.t('js.admin.modals.confirm'), cancel_button_text: I18n.t('js.admin.modals.cancel'), - controller_data_values: {} + confirm_reflex_data: {} ) super(id:, close_button: true) @confirm_actions = confirm_actions @@ -24,7 +24,7 @@ class ConfirmModalComponent < ModalComponent @confirm_button_class = confirm_button_class @confirm_button_text = confirm_button_text @cancel_button_text = cancel_button_text - @controller_data_values = transform_values_for_controller(controller_data_values) + @confirm_reflex_data = transform_values_for_dataset(confirm_reflex_data) end private @@ -33,16 +33,18 @@ class ConfirmModalComponent < ModalComponent "secondary" end - def modal_attrs - @modal_attrs ||= { - id: @id, - 'data-controller': "modal #{@controller}", - 'data-action': "keyup@document->modal#closeIfEscapeKey", - "data-#{@controller}-reflex-value": @reflex - }.merge(@controller_data_values) + def confirm_button_attrs + @confirm_button_attrs ||= { + class: "button icon-plus #{@confirm_button_class}", + type: 'button', + value: @confirm_button_text, + 'data-action': @confirm_actions, + 'data-reflex': @confirm_reflexes, + id: 'confirmModalButton' + }.merge(@confirm_reflex_data) end - def transform_values_for_controller(values) - values.transform_keys { |value_name| "data-#{@controller}-#{value_name}-value" } + def transform_values_for_dataset(values) + values.transform_keys { |value_name| "data-#{value_name}" } end end diff --git a/app/components/confirm_modal_component/confirm_modal_component.html.haml b/app/components/confirm_modal_component/confirm_modal_component.html.haml index 7d7b5cd77a..6174da3174 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.html.haml +++ b/app/components/confirm_modal_component/confirm_modal_component.html.haml @@ -1,4 +1,4 @@ -%div{ **modal_attrs } +%div{ id: @id, "data-controller": "modal #{@controller}", "data-action": "keyup@document->modal#closeIfEscapeKey", "data-#{@controller}-reflex-value": @reflex } .reveal-modal-bg.fade{ "data-modal-target": "background", "data-action": "click->modal#close" } .reveal-modal.fade.tiny.help-modal{ "data-modal-target": "modal" } = content @@ -7,4 +7,4 @@ .modal-actions %input{ class: "button icon-plus #{close_button_class}", type: 'button', value: @cancel_button_text, "data-action": "click->modal#close" } - %input{ class: "button icon-plus #{@confirm_button_class}", type: 'button', value: @confirm_button_text, "data-action": @confirm_actions, "data-reflex": @confirm_reflexes } + %input{ **confirm_button_attrs } diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 876a1cf1d1..095aa5ba88 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -46,7 +46,8 @@ class ProductsReflex < ApplicationReflex render_products_form_with_flash end - def delete_product(id) + def delete_product + id = current_id_from_element(element) authorize! :delete, Spree::Product product = product_finder(id).find_product authorize! :delete, product @@ -60,7 +61,8 @@ class ProductsReflex < ApplicationReflex fetch_and_render_products_with_flash end - def delete_variant(id) + def delete_variant + id = current_id_from_element(element) authorize! :delete, Spree::Variant variant = variant_scope.find(id) authorize! :delete, variant @@ -119,7 +121,7 @@ class ProductsReflex < ApplicationReflex def render_product_delete_modals product_ids = @products.pluck(:id) cable_ready.replace( - selector: "#products-delete-action-modals", + selector: "#product-delete-action-modals", html: render( partial: "admin/products_v3/delete_modals", locals: { object_ids: product_ids, object_type: 'product' } @@ -257,4 +259,8 @@ class ProductsReflex < ApplicationReflex def variant_scope Spree::Variant.active end + + def current_id_from_element(element) + element.dataset.current_id + end end diff --git a/app/views/admin/products_v3/_delete_modals.html.haml b/app/views/admin/products_v3/_delete_modals.html.haml index 815913925a..ff4c89e3f1 100644 --- a/app/views/admin/products_v3/_delete_modals.html.haml +++ b/app/views/admin/products_v3/_delete_modals.html.haml @@ -3,11 +3,9 @@ - delete_modal = ConfirmModalComponent.new(id: "delete_#{object_type}_#{object_id}", confirm_button_text: t("#{base_translation_key}.confirmation_text"), cancel_button_text: t("#{base_translation_key}.cancellation_text"), - confirm_reflexes: nil, + confirm_reflexes: "click->products#delete_#{object_type}", confirm_button_class: :red, - controller: "products", - confirm_actions: "click->products#delete#{object_type.titleize}", - controller_data_values: {"current-id": object_id}, + confirm_reflex_data: {"current-id": object_id}, ) = render delete_modal do %h2.margin-bottom-20{style:'color: black'} diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 2031eadf41..98a2eb6e1a 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -17,5 +17,5 @@ .spinner = t('.loading') #products-content - #products-delete-action-modals + #product-delete-action-modals #variant-delete-action-modals diff --git a/app/webpacker/controllers/products_controller.js b/app/webpacker/controllers/products_controller.js index e9ba45e46a..d4ba466373 100644 --- a/app/webpacker/controllers/products_controller.js +++ b/app/webpacker/controllers/products_controller.js @@ -2,7 +2,7 @@ import ApplicationController from "./application_controller"; export default class extends ApplicationController { static targets = ["loading"]; - static values = {currentId: Number}; + static values = { currentId: Number }; connect() { super.connect(); @@ -10,17 +10,11 @@ export default class extends ApplicationController { this.stimulate("Products#fetch"); } - deleteProduct() { - window.dispatchEvent(new Event('modal:close')); - this.stimulate('Products#delete_product', this.currentIdValue) - } - - deleteVariant() { - window.dispatchEvent(new Event('modal:close')); - this.stimulate('Products#delete_variant', this.currentIdValue) - } - - beforeReflex() { + beforeReflex(element) { + // To prevent the double click on the confirm modal's confirmation button + if (element.id === "confirmModalButton") { + window.dispatchEvent(new Event("modal:close")); + } this.showLoading(); this.scrollToElement(); } @@ -46,15 +40,8 @@ export default class extends ApplicationController { }; getLoadingController = () => { - let loadingSpinner = null; - try { - loadingSpinner = this.loadingTarget; // throws missing loading target error - } catch (error) { - loadingSpinner = document.getElementById('loading-spinner'); - } - return (this.loadingController ||= this.application.getControllerForElementAndIdentifier( - loadingSpinner, + this.loadingTarget, "loading" )); }; From 9c321ef9c806d1aadbe69f97ce8ccf055fa29a3d Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 16 Dec 2023 21:24:48 +0500 Subject: [PATCH 21/39] 11068: update comment message --- app/components/confirm_modal_component.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index be1653cc6f..b71b2634e3 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class ConfirmModalComponent < ModalComponent - # @param controller_data_values [Array(Hash)] + # @param confirm_reflex_data [Array(Hash)] # format: {: value1, : value2} def initialize( id:, From d767529e117a4865ae903533f47113cccb582ec4 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 16 Dec 2023 21:57:48 +0500 Subject: [PATCH 22/39] 11068: add divs to contain modals --- .../products_v3/_delete_modals.html.haml | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/app/views/admin/products_v3/_delete_modals.html.haml b/app/views/admin/products_v3/_delete_modals.html.haml index ff4c89e3f1..07938e5cde 100644 --- a/app/views/admin/products_v3/_delete_modals.html.haml +++ b/app/views/admin/products_v3/_delete_modals.html.haml @@ -1,15 +1,17 @@ -- base_translation_key = ".delete_#{object_type}_modal" -- object_ids.each do |object_id| - - delete_modal = ConfirmModalComponent.new(id: "delete_#{object_type}_#{object_id}", - confirm_button_text: t("#{base_translation_key}.confirmation_text"), - cancel_button_text: t("#{base_translation_key}.cancellation_text"), - confirm_reflexes: "click->products#delete_#{object_type}", - confirm_button_class: :red, - confirm_reflex_data: {"current-id": object_id}, - ) - = render delete_modal do - %h2.margin-bottom-20{style:'color: black'} - = t("#{base_translation_key}.heading") - %p - = t("#{base_translation_key}.prompt") - .margin-bottom-30 +-# object_type can be 'variant' or 'product' +%div{ id: "#{object_type}-delete-action-modals" } + - base_translation_key = ".delete_#{object_type}_modal" + - object_ids.each do |object_id| + - delete_modal = ConfirmModalComponent.new(id: "delete_#{object_type}_#{object_id}", + confirm_button_text: t("#{base_translation_key}.confirmation_text"), + cancel_button_text: t("#{base_translation_key}.cancellation_text"), + confirm_reflexes: "click->products#delete_#{object_type}", + confirm_button_class: :red, + confirm_reflex_data: {"current-id": object_id}, + ) + = render delete_modal do + %h2.margin-bottom-20{style:'color: black'} + = t("#{base_translation_key}.heading") + %p + = t("#{base_translation_key}.prompt") + .margin-bottom-30 From 78f5a8ad30366fc292f8eb52145208a6a62c01b7 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Mon, 18 Dec 2023 01:12:10 +0500 Subject: [PATCH 23/39] 11068: add specs - For system's product delete action --- .../system/admin/products_v3/products_spec.rb | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index c34e40b934..87e8a7bee8 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -410,6 +410,179 @@ describe 'As an admin, I can see the new product page', feature: :admin_style_v3 end end + describe "Deleting Feature" do + let!(:product_a) { create(:simple_product, name: "Apples", sku: "APL-00") } + let(:delete_option_selector) { "p[data-controller='modal-link'].delete" } + let(:product_selector) { row_containing_name("Apples") } + let(:variant_selector) { row_containing_name("Medium box") } + let(:default_variant_selector) { "tr:has(input[aria-label=Price][value='#{product_a.price}'])" } + + before do + visit admin_products_url + end + + describe "Actions columns (delete)" do + it "shows an actions menu with a delete link when clicking on icon for product. " \ + "doesn't show delete link for the single variant" do + within product_selector do + page.find(".vertical-ellipsis-menu").click + expect(page).to have_css(delete_option_selector) + end + page.find("div#content").click # to close the vertical actions menu + + # to select the default variant + within default_variant_selector do + page.find(".vertical-ellipsis-menu").click + expect(page).to_not have_css(delete_option_selector) + end + end + + it "shows an actions menu with a delete link when clicking on icon for variant" \ + "if have multiple" do + create(:variant, + product: product_a, + display_name: "Medium box", + sku: "APL-01", + price: 5.25) + + # to select the default variant + within default_variant_selector do + page.find(".vertical-ellipsis-menu").click + expect(page).to have_css(delete_option_selector) + end + page.find("div#content").click # to close the vertical actions menu + + within variant_selector do + page.find(".vertical-ellipsis-menu").click + expect(page).to have_css(delete_option_selector) + end + end + end + + describe "Delete Action" do + let!(:variant_a1) { + create(:variant, + product: product_a, + display_name: "Medium box", + sku: "APL-01", + price: 5.25) + } + let(:modal_selector) { "div[data-modal-target=modal]" } + let(:dismiss_button_selector) { "button[data-action='click->flash#close']" } + + context "when 'keep product/variant' is selected" do + it 'should not delete the product/variant' do + # Keep Product + within product_selector do + page.find(".vertical-ellipsis-menu").click + page.find(delete_option_selector).click + end + keep_button_selector = "input[type=button][value='Keep product']" + within modal_selector do + page.find(keep_button_selector).click + end + + expect(page).to_not have_selector(modal_selector) + expect(page).to have_selector(product_selector) + + # Keep Variant + within variant_selector do + page.find(".vertical-ellipsis-menu").click + page.find(delete_option_selector).click + end + keep_button_selector = "input[type=button][value='Keep variant']" + within modal_selector do + page.find(keep_button_selector).click + end + + expect(page).to_not have_selector(modal_selector) + expect(page).to have_selector(variant_selector) + end + end + + context "when 'delete product/variant' is selected" do + let(:success_flash_message_selector) { "div.flash.success" } + let(:error_flash_message_selector) { "div.flash.error" } + it 'should successfully delete the product/variant' do + # Delete Variant + within variant_selector do + page.find(".vertical-ellipsis-menu").click + page.find(delete_option_selector).click + end + + delete_button_selector = "input[type=button][value='Delete variant']" + within modal_selector do + page.find(delete_button_selector).click + end + + expect(page).to_not have_selector(modal_selector) + sleep(0.5) # delay for loading spinner to complete + expect(page).to_not have_selector(variant_selector) + within success_flash_message_selector do + expect(page).to have_content("Successfully deleted the variant") + page.find(dismiss_button_selector).click + end + + # Delete product + within product_selector do + page.find(".vertical-ellipsis-menu").click + page.find(delete_option_selector).click + end + delete_button_selector = "input[type=button][value='Delete product']" + within modal_selector do + page.find(delete_button_selector).click + end + expect(page).to_not have_selector(modal_selector) + sleep(0.5) # delay for loading spinner to complete + expect(page).to_not have_selector(product_selector) + within success_flash_message_selector do + expect(page).to have_content("Successfully deleted the product") + end + end + + it 'should be failed to delete the product/variant' do + allow_any_instance_of(Spree::Product).to receive(:destroy).and_return(false) + allow_any_instance_of(Spree::Variant).to receive(:destroy).and_return(false) + + # Delete Variant + within variant_selector do + page.find(".vertical-ellipsis-menu").click + page.find(delete_option_selector).click + end + + delete_button_selector = "input[type=button][value='Delete variant']" + within modal_selector do + page.find(delete_button_selector).click + end + + expect(page).to_not have_selector(modal_selector) + sleep(0.5) # delay for loading spinner to complete + expect(page).to have_selector(variant_selector) + within error_flash_message_selector do + expect(page).to have_content("Unable to delete the variant") + page.find(dismiss_button_selector).click + end + + # Delete product + within product_selector do + page.find(".vertical-ellipsis-menu").click + page.find(delete_option_selector).click + end + delete_button_selector = "input[type=button][value='Delete product']" + within modal_selector do + page.find(delete_button_selector).click + end + expect(page).to_not have_selector(modal_selector) + sleep(0.5) # delay for loading spinner to complete + expect(page).to have_selector(product_selector) + within error_flash_message_selector do + expect(page).to have_content("Unable to delete the product") + end + end + end + end + end + def create_products(amount) amount.times do |i| create(:simple_product, name: "product #{i}") From 0290697fb7cf40c13aad4920b66de775175a8459 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Wed, 20 Dec 2023 01:11:37 +0500 Subject: [PATCH 24/39] 11068: add specs - For delete_product - For delete_variant --- spec/reflexes/products_reflex_spec.rb | 74 +++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/spec/reflexes/products_reflex_spec.rb b/spec/reflexes/products_reflex_spec.rb index a79b32b326..fa87b367e4 100644 --- a/spec/reflexes/products_reflex_spec.rb +++ b/spec/reflexes/products_reflex_spec.rb @@ -160,6 +160,80 @@ describe ProductsReflex, type: :reflex, feature: :admin_style_v3 do end end end + + describe '#delete_product' do + let(:product) { create(:simple_product) } + let(:action_name) { :delete_product } + + subject { build_reflex(method_name: action_name, **context) } + + before { subject.element.dataset.current_id = product.id } + + context 'given that the current user is admin' do + let(:current_user) { create(:admin_user) } + + it 'should successfully delete the product' do + subject.run(action_name) + product.reload + expect(product.deleted_at).not_to be_nil + expect(flash[:success]).to eq('Successfully deleted the product') + end + + it 'should be failed to delete the product' do + # mock db query failure + allow_any_instance_of(Spree::Product).to receive(:destroy).and_return(false) + subject.run(action_name) + product.reload + expect(product.deleted_at).to be_nil + expect(flash[:error]).to eq('Unable to delete the product') + end + end + + context 'given that the current user is not admin' do + let(:current_user) { create(:user) } + + it 'should raise the access denied exception' do + expect { subject.run(action_name) }.to raise_exception(CanCan::AccessDenied) + end + end + end + + describe '#delete_variant' do + let(:variant) { create(:variant) } + let(:action_name) { :delete_variant } + + subject { build_reflex(method_name: action_name, **context) } + + before { subject.element.dataset.current_id = variant.id } + + context 'given that the current user is admin' do + let(:current_user) { create(:admin_user) } + + it 'should successfully delete the variant' do + subject.run(action_name) + variant.reload + expect(variant.deleted_at).not_to be_nil + expect(flash[:success]).to eq('Successfully deleted the variant') + end + + it 'should be failed to delete the product' do + # mock db query failure + allow_any_instance_of(Spree::Variant).to receive(:destroy).and_return(false) + subject.run(action_name) + variant.reload + expect(variant.deleted_at).to be_nil + expect(flash[:error]).to eq('Unable to delete the variant') + end + end + + context 'given that the current user is not admin' do + let(:current_user) { create(:user) } + + it 'should raise the access denied exception' do + expect { subject.run(action_name) }.to raise_exception(CanCan::AccessDenied) + end + end + end end # Build and run a reflex using the context From 24fd75a85dcf01996e5ec130b9c35afddb1bdacc Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Fri, 22 Dec 2023 02:21:53 +0500 Subject: [PATCH 25/39] Update app/reflexes/products_reflex.rb 11068: remove overdefensive auth check Co-authored-by: Maikel --- app/reflexes/products_reflex.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 095aa5ba88..4f273d9d01 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -48,7 +48,6 @@ class ProductsReflex < ApplicationReflex def delete_product id = current_id_from_element(element) - authorize! :delete, Spree::Product product = product_finder(id).find_product authorize! :delete, product From dc78fa843a21f0e49c2b88ba104bac2c41e7da24 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Fri, 22 Dec 2023 02:24:28 +0500 Subject: [PATCH 26/39] Update app/reflexes/products_reflex.rb 11068: remove overdefensive auth check Co-authored-by: Maikel --- app/reflexes/products_reflex.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 4f273d9d01..8d6b5ee474 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -62,7 +62,6 @@ class ProductsReflex < ApplicationReflex def delete_variant id = current_id_from_element(element) - authorize! :delete, Spree::Variant variant = variant_scope.find(id) authorize! :delete, variant From 985487c0614c09320023ac89f3561d824499d28c Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Fri, 22 Dec 2023 03:10:52 +0500 Subject: [PATCH 27/39] 11068: update confirm_modal_component - add new position alignment for the modal actions - add 'justify-space-around' and 'justify-end' as new alignment classes - use the above classes accordingly --- app/components/confirm_modal_component.rb | 5 ++++- .../confirm_modal_component.html.haml | 2 +- .../confirm_modal_component.scss | 16 +++++++++++++++- .../admin/products_v3/_delete_modals.html.haml | 5 +++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index b71b2634e3..5c533dce3a 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -3,6 +3,7 @@ class ConfirmModalComponent < ModalComponent # @param confirm_reflex_data [Array(Hash)] # format: {: value1, : value2} + # @param actions_alignment_class [String] possible classes: 'justify-space-around', 'justify-end' def initialize( id:, reflex: nil, @@ -13,7 +14,8 @@ class ConfirmModalComponent < ModalComponent confirm_button_class: :primary, confirm_button_text: I18n.t('js.admin.modals.confirm'), cancel_button_text: I18n.t('js.admin.modals.cancel'), - confirm_reflex_data: {} + confirm_reflex_data: {}, + actions_alignment_class: 'justify-space-around' ) super(id:, close_button: true) @confirm_actions = confirm_actions @@ -25,6 +27,7 @@ class ConfirmModalComponent < ModalComponent @confirm_button_text = confirm_button_text @cancel_button_text = cancel_button_text @confirm_reflex_data = transform_values_for_dataset(confirm_reflex_data) + @actions_alignment_class = actions_alignment_class end private diff --git a/app/components/confirm_modal_component/confirm_modal_component.html.haml b/app/components/confirm_modal_component/confirm_modal_component.html.haml index 6174da3174..30ee073b1d 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.html.haml +++ b/app/components/confirm_modal_component/confirm_modal_component.html.haml @@ -5,6 +5,6 @@ = render @message if @message - .modal-actions + %div{ class: "modal-actions #{@actions_alignment_class}" } %input{ class: "button icon-plus #{close_button_class}", type: 'button', value: @cancel_button_text, "data-action": "click->modal#close" } %input{ **confirm_button_attrs } diff --git a/app/components/confirm_modal_component/confirm_modal_component.scss b/app/components/confirm_modal_component/confirm_modal_component.scss index ccbf18169c..1a23b71e35 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.scss +++ b/app/components/confirm_modal_component/confirm_modal_component.scss @@ -1,4 +1,18 @@ .modal-actions { display: flex; - justify-content: space-around; + + &.justify-space-around { + justify-content: space-around; + } + + &.justify-end { + justify-content: flex-end; + input[type="button"] { + margin: 0 5px; + } + + @media only screen and (max-width: 1024px) { + justify-content: space-around; + } + } } diff --git a/app/views/admin/products_v3/_delete_modals.html.haml b/app/views/admin/products_v3/_delete_modals.html.haml index 07938e5cde..6b7fb960e0 100644 --- a/app/views/admin/products_v3/_delete_modals.html.haml +++ b/app/views/admin/products_v3/_delete_modals.html.haml @@ -5,8 +5,9 @@ - delete_modal = ConfirmModalComponent.new(id: "delete_#{object_type}_#{object_id}", confirm_button_text: t("#{base_translation_key}.confirmation_text"), cancel_button_text: t("#{base_translation_key}.cancellation_text"), - confirm_reflexes: "click->products#delete_#{object_type}", confirm_button_class: :red, + actions_alignment_class: 'justify-end', + confirm_reflexes: "click->products#delete_#{object_type}", confirm_reflex_data: {"current-id": object_id}, ) = render delete_modal do @@ -14,4 +15,4 @@ = t("#{base_translation_key}.heading") %p = t("#{base_translation_key}.prompt") - .margin-bottom-30 + .margin-bottom-50 From 6ed447b6ac82f675f5424f45cea21b6d18cb93a8 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 23 Dec 2023 15:53:28 +0500 Subject: [PATCH 28/39] 11068: code refactor - Add single delete modal for product and variant each --- app/components/confirm_modal_component.rb | 17 ------------- .../confirm_modal_component.html.haml | 2 +- app/reflexes/products_reflex.rb | 25 ------------------- .../admin/products_v3/_delete_modal.html.haml | 15 +++++++++++ .../products_v3/_delete_modals.html.haml | 18 ------------- app/views/admin/products_v3/_table.html.haml | 8 +++--- app/views/admin/products_v3/index.html.haml | 4 +-- .../controllers/product_actions_controller.js | 18 +++++++++++++ .../controllers/products_controller.js | 2 +- config/locales/en.yml | 2 +- 10 files changed, 42 insertions(+), 69 deletions(-) create mode 100644 app/views/admin/products_v3/_delete_modal.html.haml delete mode 100644 app/views/admin/products_v3/_delete_modals.html.haml create mode 100644 app/webpacker/controllers/product_actions_controller.js diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index 5c533dce3a..69e84d922a 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true class ConfirmModalComponent < ModalComponent - # @param confirm_reflex_data [Array(Hash)] - # format: {: value1, : value2} # @param actions_alignment_class [String] possible classes: 'justify-space-around', 'justify-end' def initialize( id:, @@ -26,7 +24,6 @@ class ConfirmModalComponent < ModalComponent @confirm_button_class = confirm_button_class @confirm_button_text = confirm_button_text @cancel_button_text = cancel_button_text - @confirm_reflex_data = transform_values_for_dataset(confirm_reflex_data) @actions_alignment_class = actions_alignment_class end @@ -36,18 +33,4 @@ class ConfirmModalComponent < ModalComponent "secondary" end - def confirm_button_attrs - @confirm_button_attrs ||= { - class: "button icon-plus #{@confirm_button_class}", - type: 'button', - value: @confirm_button_text, - 'data-action': @confirm_actions, - 'data-reflex': @confirm_reflexes, - id: 'confirmModalButton' - }.merge(@confirm_reflex_data) - end - - def transform_values_for_dataset(values) - values.transform_keys { |value_name| "data-#{value_name}" } - end end diff --git a/app/components/confirm_modal_component/confirm_modal_component.html.haml b/app/components/confirm_modal_component/confirm_modal_component.html.haml index 30ee073b1d..5fe1d1300b 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.html.haml +++ b/app/components/confirm_modal_component/confirm_modal_component.html.haml @@ -7,4 +7,4 @@ %div{ class: "modal-actions #{@actions_alignment_class}" } %input{ class: "button icon-plus #{close_button_class}", type: 'button', value: @cancel_button_text, "data-action": "click->modal#close" } - %input{ **confirm_button_attrs } + %input{ id: 'modal-confirm-button', class: "button icon-plus #{@confirm_button_class}", type: 'button', value: @confirm_button_text, "data-action": @confirm_actions, "data-reflex": @confirm_reflexes } diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 8d6b5ee474..fc391fa715 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -106,9 +106,6 @@ class ProductsReflex < ApplicationReflex flashes: flash }) ).broadcast - render_product_delete_modals - render_variant_delete_modals - cable_ready.replace_state( url: current_url, ).broadcast_later @@ -116,28 +113,6 @@ class ProductsReflex < ApplicationReflex morph :nothing end - def render_product_delete_modals - product_ids = @products.pluck(:id) - cable_ready.replace( - selector: "#product-delete-action-modals", - html: render( - partial: "admin/products_v3/delete_modals", - locals: { object_ids: product_ids, object_type: 'product' } - ) - ).broadcast - end - - def render_variant_delete_modals - variant_ids = @products.joins(:variants).pluck('spree_variants.id') - cable_ready.replace( - selector: "#variant-delete-action-modals", - html: render( - partial: "admin/products_v3/delete_modals", - locals: { object_ids: variant_ids, object_type: 'variant' } - ) - ).broadcast - end - def render_products_form_with_flash locals = { products: @products } locals[:error_counts] = @error_counts if @error_counts.present? diff --git a/app/views/admin/products_v3/_delete_modal.html.haml b/app/views/admin/products_v3/_delete_modal.html.haml new file mode 100644 index 0000000000..a5f2ce01a9 --- /dev/null +++ b/app/views/admin/products_v3/_delete_modal.html.haml @@ -0,0 +1,15 @@ +-# object_type can be 'variant' or 'product' +- base_translation_key = ".delete_#{object_type}_modal" +- delete_modal = ConfirmModalComponent.new(id: "#{object_type}-delete-modal", + confirm_button_text: t("#{base_translation_key}.confirmation_text"), + cancel_button_text: t("#{base_translation_key}.cancellation_text"), + confirm_button_class: :red, + actions_alignment_class: 'justify-end', + confirm_reflexes: "click->products#delete_#{object_type}", + ) += render delete_modal do + %h2.margin-bottom-20{style:'color: black'} + = t("#{base_translation_key}.heading") + %p + = t("#{base_translation_key}.prompt") + .margin-bottom-50 diff --git a/app/views/admin/products_v3/_delete_modals.html.haml b/app/views/admin/products_v3/_delete_modals.html.haml deleted file mode 100644 index 6b7fb960e0..0000000000 --- a/app/views/admin/products_v3/_delete_modals.html.haml +++ /dev/null @@ -1,18 +0,0 @@ --# object_type can be 'variant' or 'product' -%div{ id: "#{object_type}-delete-action-modals" } - - base_translation_key = ".delete_#{object_type}_modal" - - object_ids.each do |object_id| - - delete_modal = ConfirmModalComponent.new(id: "delete_#{object_type}_#{object_id}", - confirm_button_text: t("#{base_translation_key}.confirmation_text"), - cancel_button_text: t("#{base_translation_key}.cancellation_text"), - confirm_button_class: :red, - actions_alignment_class: 'justify-end', - confirm_reflexes: "click->products#delete_#{object_type}", - confirm_reflex_data: {"current-id": object_id}, - ) - = render delete_modal do - %h2.margin-bottom-20{style:'color: black'} - = t("#{base_translation_key}.heading") - %p - = t("#{base_translation_key}.prompt") - .margin-bottom-50 diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 5066b023d2..9901a5a3d4 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -70,8 +70,8 @@ = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product) = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product) - %p{ "data-controller": "modal-link", "data-action": "click->modal-link#open", - "data-modal-link-target-value": "delete_product_#{product.id}", "class": "delete" } + %p{ "data-controller": "modal-link product-actions", "data-action": "click->product-actions#setDeleteModalDataSet click->modal-link#open", + "data-modal-link-target-value": "product-delete-modal", "class": "delete", "data-product-actions-id-value": product.id } = t('admin.products_page.actions.delete') - product.variants.each_with_index do |variant, variant_index| @@ -112,6 +112,6 @@ = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant) - if product.variants.size > 1 - %p{ "data-controller": "modal-link", "data-action": "click->modal-link#open", - "data-modal-link-target-value": "delete_variant_#{variant.id}", "class": "delete" } + %p{ "data-controller": "modal-link product-actions", "data-action": "click->product-actions#setDeleteModalDataSet click->modal-link#open", + "data-modal-link-target-value": "variant-delete-modal", "class": "delete", "data-product-actions-id-value": variant.id } = t('admin.products_page.actions.delete') diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 98a2eb6e1a..a7833c22df 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -17,5 +17,5 @@ .spinner = t('.loading') #products-content - #product-delete-action-modals - #variant-delete-action-modals + - %w[product variant].each do |object_type| + = render partial: 'delete_modal', locals: { object_type: } diff --git a/app/webpacker/controllers/product_actions_controller.js b/app/webpacker/controllers/product_actions_controller.js new file mode 100644 index 0000000000..605b3f5bd8 --- /dev/null +++ b/app/webpacker/controllers/product_actions_controller.js @@ -0,0 +1,18 @@ +import ApplicationController from "./application_controller"; + +export default class extends ApplicationController { + static values = { id: Number }; + + setDeleteModalDataSet(event) { + try { + const modalId = this.element.dataset.modalLinkTargetValue; // whether variant or product delete modal + const deleteButtonQuery = `#${modalId} #modal-confirm-button`; + const deleteButton = document.querySelector(deleteButtonQuery); + deleteButton.setAttribute("data-current-id", this.idValue); + } catch (e) { + // In case of any type of error in setting the dataset value, stop the further actions i.e. opening the modal + event.stopImmediatePropagation(); + throw e; + } + } +} diff --git a/app/webpacker/controllers/products_controller.js b/app/webpacker/controllers/products_controller.js index d4ba466373..770ad16944 100644 --- a/app/webpacker/controllers/products_controller.js +++ b/app/webpacker/controllers/products_controller.js @@ -12,7 +12,7 @@ export default class extends ApplicationController { beforeReflex(element) { // To prevent the double click on the confirm modal's confirmation button - if (element.id === "confirmModalButton") { + if (element.id === "modal-confirm-button") { window.dispatchEvent(new Event("modal:close")); } this.showLoading(); diff --git a/config/locales/en.yml b/config/locales/en.yml index d5fde0c609..e57a8a45ab 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -816,7 +816,7 @@ en: header: title: Bulk Edit Products loading: Loading your products - delete_modals: + delete_modal: delete_product_modal: heading: "Delete product" prompt: "This will permanently remove it from your list." From 87d328d6d6e18d3e76eb851602841aa435a4b224 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 23 Dec 2023 16:08:26 +0500 Subject: [PATCH 29/39] 11068: fix specs --- app/components/confirm_modal_component.rb | 2 -- spec/system/admin/products_v3/products_spec.rb | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/components/confirm_modal_component.rb b/app/components/confirm_modal_component.rb index 69e84d922a..8149a729e3 100644 --- a/app/components/confirm_modal_component.rb +++ b/app/components/confirm_modal_component.rb @@ -12,7 +12,6 @@ class ConfirmModalComponent < ModalComponent confirm_button_class: :primary, confirm_button_text: I18n.t('js.admin.modals.confirm'), cancel_button_text: I18n.t('js.admin.modals.cancel'), - confirm_reflex_data: {}, actions_alignment_class: 'justify-space-around' ) super(id:, close_button: true) @@ -32,5 +31,4 @@ class ConfirmModalComponent < ModalComponent def close_button_class "secondary" end - end diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index 87e8a7bee8..58b16a44ba 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -412,7 +412,7 @@ describe 'As an admin, I can see the new product page', feature: :admin_style_v3 describe "Deleting Feature" do let!(:product_a) { create(:simple_product, name: "Apples", sku: "APL-00") } - let(:delete_option_selector) { "p[data-controller='modal-link'].delete" } + let(:delete_option_selector) { "p[data-controller='modal-link product-actions'].delete" } let(:product_selector) { row_containing_name("Apples") } let(:variant_selector) { row_containing_name("Medium box") } let(:default_variant_selector) { "tr:has(input[aria-label=Price][value='#{product_a.price}'])" } From c5a86341dc2f5400af806a94ff3d913f5ded39d1 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sun, 24 Dec 2023 02:00:26 +0500 Subject: [PATCH 30/39] 11068: update sleep logic in specs --- spec/system/admin/products_v3/products_spec.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index 58b16a44ba..8f12b8d7c1 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -516,7 +516,8 @@ describe 'As an admin, I can see the new product page', feature: :admin_style_v3 end expect(page).to_not have_selector(modal_selector) - sleep(0.5) # delay for loading spinner to complete + # Make sure the products loading spinner is hidden + wait_for_class('.spinner-overlay', 'hidden') expect(page).to_not have_selector(variant_selector) within success_flash_message_selector do expect(page).to have_content("Successfully deleted the variant") @@ -533,7 +534,8 @@ describe 'As an admin, I can see the new product page', feature: :admin_style_v3 page.find(delete_button_selector).click end expect(page).to_not have_selector(modal_selector) - sleep(0.5) # delay for loading spinner to complete + # Make sure the products loading spinner is hidden + wait_for_class('.spinner-overlay', 'hidden') expect(page).to_not have_selector(product_selector) within success_flash_message_selector do expect(page).to have_content("Successfully deleted the product") @@ -623,4 +625,12 @@ describe 'As an admin, I can see the new product page', feature: :admin_style_v3 def row_containing_name(value) "tr:has(input[aria-label=Name][value='#{value}'])" end + + # Wait for an element with the given CSS selector and class to be present + def wait_for_class(selector, class_name) + max_wait_time = Capybara.default_max_wait_time + Timeout.timeout(max_wait_time) do + until page.has_css?(selector, class: class_name, visible: false); end + end + end end From 86c2397f63879772485ef9454dc2e14b7f81f57b Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Tue, 26 Dec 2023 15:41:38 +0500 Subject: [PATCH 31/39] 11068: update modal padding --- app/components/help_modal_component/help_modal_component.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/components/help_modal_component/help_modal_component.scss b/app/components/help_modal_component/help_modal_component.scss index 48f6255a2e..d323b47992 100644 --- a/app/components/help_modal_component/help_modal_component.scss +++ b/app/components/help_modal_component/help_modal_component.scss @@ -2,6 +2,9 @@ visibility: visible; position: fixed; top: 3em; + &.in { + padding: 1.2rem; + } } /* prevent arrow on selected admin menu item appearing above modal */ From 0fd868b6698ee02436f54fb43e2841a81e02449d Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 28 Dec 2023 17:06:21 +0500 Subject: [PATCH 32/39] 11068: update variant_scope method to inline --- app/reflexes/products_reflex.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index fc391fa715..711f4a577c 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -62,7 +62,7 @@ class ProductsReflex < ApplicationReflex def delete_variant id = current_id_from_element(element) - variant = variant_scope.find(id) + variant = Spree::Variant.active.find(id) authorize! :delete, variant if VariantDeleter.new.delete(variant) @@ -229,10 +229,6 @@ class ProductsReflex < ApplicationReflex ProductScopeQuery.new(current_user, { id: }) end - def variant_scope - Spree::Variant.active - end - def current_id_from_element(element) element.dataset.current_id end From 047e63541cb9c40dd64277d51574c9becb3da163 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 28 Dec 2023 17:06:56 +0500 Subject: [PATCH 33/39] 11068: add black-text css class --- app/views/admin/products_v3/_delete_modal.html.haml | 2 +- app/webpacker/css/admin_v3/shared/layout.scss | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/views/admin/products_v3/_delete_modal.html.haml b/app/views/admin/products_v3/_delete_modal.html.haml index a5f2ce01a9..446130cd95 100644 --- a/app/views/admin/products_v3/_delete_modal.html.haml +++ b/app/views/admin/products_v3/_delete_modal.html.haml @@ -8,7 +8,7 @@ confirm_reflexes: "click->products#delete_#{object_type}", ) = render delete_modal do - %h2.margin-bottom-20{style:'color: black'} + %h2.margin-bottom-20.black-text = t("#{base_translation_key}.heading") %p = t("#{base_translation_key}.prompt") diff --git a/app/webpacker/css/admin_v3/shared/layout.scss b/app/webpacker/css/admin_v3/shared/layout.scss index addd363521..e5a47dc247 100644 --- a/app/webpacker/css/admin_v3/shared/layout.scss +++ b/app/webpacker/css/admin_v3/shared/layout.scss @@ -135,3 +135,9 @@ display: none; } } + +// Text Colors +.black-text { + color: $near-black +} +//------------ From 813ebd912926fa55f0633a998dc20b714882207e Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 28 Dec 2023 17:07:18 +0500 Subject: [PATCH 34/39] 11068: add confirm_actions to close the modal --- app/views/admin/products_v3/_delete_modal.html.haml | 1 + app/webpacker/controllers/products_controller.js | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/views/admin/products_v3/_delete_modal.html.haml b/app/views/admin/products_v3/_delete_modal.html.haml index 446130cd95..40b6fbd32d 100644 --- a/app/views/admin/products_v3/_delete_modal.html.haml +++ b/app/views/admin/products_v3/_delete_modal.html.haml @@ -6,6 +6,7 @@ confirm_button_class: :red, actions_alignment_class: 'justify-end', confirm_reflexes: "click->products#delete_#{object_type}", + confirm_actions: "click->modal#close", ) = render delete_modal do %h2.margin-bottom-20.black-text diff --git a/app/webpacker/controllers/products_controller.js b/app/webpacker/controllers/products_controller.js index 770ad16944..6fe8662f50 100644 --- a/app/webpacker/controllers/products_controller.js +++ b/app/webpacker/controllers/products_controller.js @@ -10,11 +10,7 @@ export default class extends ApplicationController { this.stimulate("Products#fetch"); } - beforeReflex(element) { - // To prevent the double click on the confirm modal's confirmation button - if (element.id === "modal-confirm-button") { - window.dispatchEvent(new Event("modal:close")); - } + beforeReflex() { this.showLoading(); this.scrollToElement(); } From 548ffc0222821860a54ea02bffa8bd421cb8f1c6 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 28 Dec 2023 17:28:26 +0500 Subject: [PATCH 35/39] 11068: replace p tag with a tag --- app/components/vertical_ellipsis_menu/component.scss | 3 +-- app/views/admin/products_v3/_table.html.haml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/components/vertical_ellipsis_menu/component.scss b/app/components/vertical_ellipsis_menu/component.scss index 7730b384ce..03b5cb39d8 100644 --- a/app/components/vertical_ellipsis_menu/component.scss +++ b/app/components/vertical_ellipsis_menu/component.scss @@ -30,8 +30,7 @@ display: block; } - & > a, - p { + & > a { display: block; padding: 5px 10px; cursor: pointer; diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 9901a5a3d4..5573561121 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -70,7 +70,7 @@ = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product) = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product) - %p{ "data-controller": "modal-link product-actions", "data-action": "click->product-actions#setDeleteModalDataSet click->modal-link#open", + %a{ "data-controller": "modal-link product-actions", "data-action": "click->product-actions#setDeleteModalDataSet click->modal-link#open", "data-modal-link-target-value": "product-delete-modal", "class": "delete", "data-product-actions-id-value": product.id } = t('admin.products_page.actions.delete') @@ -112,6 +112,6 @@ = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant) - if product.variants.size > 1 - %p{ "data-controller": "modal-link product-actions", "data-action": "click->product-actions#setDeleteModalDataSet click->modal-link#open", + %a{ "data-controller": "modal-link product-actions", "data-action": "click->product-actions#setDeleteModalDataSet click->modal-link#open", "data-modal-link-target-value": "variant-delete-modal", "class": "delete", "data-product-actions-id-value": variant.id } = t('admin.products_page.actions.delete') From f194b03882294a542b7b285eb4f14b6d5dfc395f Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 28 Dec 2023 17:51:52 +0500 Subject: [PATCH 36/39] 11068: add sleep of 0.1s --- spec/system/admin/products_v3/products_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index 8f12b8d7c1..2039ad8906 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -412,7 +412,7 @@ describe 'As an admin, I can see the new product page', feature: :admin_style_v3 describe "Deleting Feature" do let!(:product_a) { create(:simple_product, name: "Apples", sku: "APL-00") } - let(:delete_option_selector) { "p[data-controller='modal-link product-actions'].delete" } + let(:delete_option_selector) { "a[data-controller='modal-link product-actions'].delete" } let(:product_selector) { row_containing_name("Apples") } let(:variant_selector) { row_containing_name("Medium box") } let(:default_variant_selector) { "tr:has(input[aria-label=Price][value='#{product_a.price}'])" } @@ -630,7 +630,7 @@ describe 'As an admin, I can see the new product page', feature: :admin_style_v3 def wait_for_class(selector, class_name) max_wait_time = Capybara.default_max_wait_time Timeout.timeout(max_wait_time) do - until page.has_css?(selector, class: class_name, visible: false); end + sleep(0.1) until page.has_css?(selector, class: class_name, visible: false) end end end From 17bd3bb0cc0d7201a40a4165b571837a2acd35e9 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 28 Dec 2023 21:34:37 +0500 Subject: [PATCH 37/39] 11068: update setModalDataset logic to generic logic --- app/views/admin/products_v3/_table.html.haml | 10 ++++++---- .../controllers/modal_link_controller.js | 17 ++++++++++++++++- .../controllers/product_actions_controller.js | 18 ------------------ 3 files changed, 22 insertions(+), 23 deletions(-) delete mode 100644 app/webpacker/controllers/product_actions_controller.js diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 5573561121..e34c4b786d 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -70,8 +70,9 @@ = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product) = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product) - %a{ "data-controller": "modal-link product-actions", "data-action": "click->product-actions#setDeleteModalDataSet click->modal-link#open", - "data-modal-link-target-value": "product-delete-modal", "class": "delete", "data-product-actions-id-value": product.id } + %a{ "data-controller": "modal-link", "data-action": "click->modal-link#setModalDataSetOnConfirm click->modal-link#open", + "data-modal-link-target-value": "product-delete-modal", "class": "delete", + "data-modal-link-modal-dataset-value": {'data-current-id': product.id}.to_json } = t('admin.products_page.actions.delete') - product.variants.each_with_index do |variant, variant_index| @@ -112,6 +113,7 @@ = render(VerticalEllipsisMenu::Component.new) do = link_to t('admin.products_page.actions.edit'), edit_admin_product_variant_path(product, variant) - if product.variants.size > 1 - %a{ "data-controller": "modal-link product-actions", "data-action": "click->product-actions#setDeleteModalDataSet click->modal-link#open", - "data-modal-link-target-value": "variant-delete-modal", "class": "delete", "data-product-actions-id-value": variant.id } + %a{ "data-controller": "modal-link", "data-action": "click->modal-link#setModalDataSetOnConfirm click->modal-link#open", + "data-modal-link-target-value": "variant-delete-modal", "class": "delete", + "data-modal-link-modal-dataset-value": {'data-current-id': variant.id}.to_json } = t('admin.products_page.actions.delete') diff --git a/app/webpacker/controllers/modal_link_controller.js b/app/webpacker/controllers/modal_link_controller.js index d4f58fb546..9eb765c35f 100644 --- a/app/webpacker/controllers/modal_link_controller.js +++ b/app/webpacker/controllers/modal_link_controller.js @@ -1,7 +1,7 @@ import { Controller } from "stimulus"; export default class extends Controller { - static values = { target: String }; + static values = { target: String, modalDataset: Object }; open() { let modal = document.getElementById(this.targetValue); @@ -12,6 +12,21 @@ export default class extends Controller { modalController.open(); } + setModalDataSetOnConfirm(event) { + try { + const modalId = this.targetValue; + const moodalConfirmButtonQuery = `#${modalId} #modal-confirm-button`; + const confirmButton = document.querySelector(moodalConfirmButtonQuery); + Object.keys(this.modalDatasetValue).forEach((datasetKey) => { + confirmButton.setAttribute(datasetKey, this.modalDatasetValue[datasetKey]); + }); + } catch (e) { + // In case of any type of error in setting the dataset value, stop the further actions i.e. opening the modal + event.stopImmediatePropagation(); + throw e; + } + } + getIdentifier() { return "modal"; } diff --git a/app/webpacker/controllers/product_actions_controller.js b/app/webpacker/controllers/product_actions_controller.js deleted file mode 100644 index 605b3f5bd8..0000000000 --- a/app/webpacker/controllers/product_actions_controller.js +++ /dev/null @@ -1,18 +0,0 @@ -import ApplicationController from "./application_controller"; - -export default class extends ApplicationController { - static values = { id: Number }; - - setDeleteModalDataSet(event) { - try { - const modalId = this.element.dataset.modalLinkTargetValue; // whether variant or product delete modal - const deleteButtonQuery = `#${modalId} #modal-confirm-button`; - const deleteButton = document.querySelector(deleteButtonQuery); - deleteButton.setAttribute("data-current-id", this.idValue); - } catch (e) { - // In case of any type of error in setting the dataset value, stop the further actions i.e. opening the modal - event.stopImmediatePropagation(); - throw e; - } - } -} From 1d6a089754e60d198ee6345dc5063970db3ad988 Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Thu, 28 Dec 2023 22:11:52 +0500 Subject: [PATCH 38/39] 11068: fix specs --- spec/system/admin/products_v3/products_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index 2039ad8906..f62be46a48 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -412,7 +412,7 @@ describe 'As an admin, I can see the new product page', feature: :admin_style_v3 describe "Deleting Feature" do let!(:product_a) { create(:simple_product, name: "Apples", sku: "APL-00") } - let(:delete_option_selector) { "a[data-controller='modal-link product-actions'].delete" } + let(:delete_option_selector) { "a[data-controller='modal-link'].delete" } let(:product_selector) { row_containing_name("Apples") } let(:variant_selector) { row_containing_name("Medium box") } let(:default_variant_selector) { "tr:has(input[aria-label=Price][value='#{product_a.price}'])" } From c2693d1a3293b96cee8b4c4388156012939619ac Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Fri, 29 Dec 2023 03:02:16 +0500 Subject: [PATCH 39/39] 11068: add responsiveness to delete modal actions --- .../confirm_modal_component/confirm_modal_component.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/components/confirm_modal_component/confirm_modal_component.scss b/app/components/confirm_modal_component/confirm_modal_component.scss index 1a23b71e35..2c54031f32 100644 --- a/app/components/confirm_modal_component/confirm_modal_component.scss +++ b/app/components/confirm_modal_component/confirm_modal_component.scss @@ -12,7 +12,11 @@ } @media only screen and (max-width: 1024px) { + flex-direction: column; justify-content: space-around; + input[type="button"] { + margin: 5px 0; + } } } }