diff --git a/app/controllers/admin/products_v3_controller.rb b/app/controllers/admin/products_v3_controller.rb index fb5efe5d1a..667706aeba 100644 --- a/app/controllers/admin/products_v3_controller.rb +++ b/app/controllers/admin/products_v3_controller.rb @@ -18,11 +18,13 @@ module Admin if product_set.save flash[:success] = I18n.t('admin.products_v3.bulk_update.success') - redirect_to [:index, { page: @page, per_page: @per_page }] + redirect_to [:index, + { page: @page, per_page: @per_page, search_term: @search_term, + producer_id: @producer_id, category_id: @category_id }] elsif product_set.errors.present? @error_counts = { saved: product_set.saved_count, invalid: product_set.invalid.count } - render "index", locals: { producers:, categories:, flash: } + render "index", status: :unprocessable_entity, locals: { producers:, categories:, flash: } end end diff --git a/app/views/admin/products_v3/_content.html.haml b/app/views/admin/products_v3/_content.html.haml index 64e6620ef9..dcb29e945f 100644 --- a/app/views/admin/products_v3/_content.html.haml +++ b/app/views/admin/products_v3/_content.html.haml @@ -1,4 +1,8 @@ -#products-content +%turbo-frame#products-content{ target: "_top", refresh: "morph" } + .spinner-overlay{ "data-controller": "loading", "data-products-target": "loading", class: "hidden" } + .spinner-container + .spinner + = t('.loading') .container .sixteen.columns = render partial: 'admin/shared/flashes', locals: { flashes: } if defined? flashes diff --git a/app/views/admin/products_v3/_filters.html.haml b/app/views/admin/products_v3/_filters.html.haml index 30a95abc08..2a0aa55428 100644 --- a/app/views/admin/products_v3/_filters.html.haml +++ b/app/views/admin/products_v3/_filters.html.haml @@ -1,4 +1,4 @@ -= form_with url: admin_products_path, id: "filters", method: :get, data: { remote: false, "search-target": "form" } do += form_with url: admin_products_path, id: "filters", method: :get, data: { "search-target": "form", 'turbo-frame': "_self" } do = hidden_field_tag :page, nil, class: "page" = hidden_field_tag :per_page, nil, class: "per-page" diff --git a/app/views/admin/products_v3/_product_row.html.haml b/app/views/admin/products_v3/_product_row.html.haml index 4a8b0c8ce3..5e11301a5e 100644 --- a/app/views/admin/products_v3/_product_row.html.haml +++ b/app/views/admin/products_v3/_product_row.html.haml @@ -36,8 +36,8 @@ .content= product.inherits_properties ? 'YES' : 'NO' #TODO: consider using https://github.com/RST-J/human_attribute_values, else use I18n.t (also below) %td.align-right = 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) + = link_to t('admin.products_page.actions.edit'), edit_admin_product_path(product), 'data-turbo': false + = link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product), 'data-turbo': false %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 } diff --git a/app/views/admin/products_v3/_sort.html.haml b/app/views/admin/products_v3/_sort.html.haml index 8bd5b249bc..f53eec4e76 100644 --- a/app/views/admin/products_v3/_sort.html.haml +++ b/app/views/admin/products_v3/_sort.html.haml @@ -4,7 +4,7 @@ = t(".pagination.total_html", total: pagy.count, from: pagy.from, to: pagy.to) - if search_term.present? || producer_id.present? || category_id.present? - %a{ href: url_for(page: 1), class: "button disruptive" } + %a{ href: url_for(page: 1), class: "button disruptive", 'data-turbo-frame': "_self" } = t(".pagination.clear_search") %form.with-dropdown diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 4a34b81258..78d32be8b2 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -1,12 +1,17 @@ = form_with url: bulk_update_admin_products_path, method: :post, id: "products-form", builder: BulkFormBuilder, - html: { data: { controller: "bulk-form", 'bulk-form-disable-selector-value': "#sort,#filters", + html: { data: { 'turbo-frame': "_self", + controller: "bulk-form", + 'bulk-form-disable-selector-value': "#sort,#filters", 'bulk-form-error-value': defined?(@error_counts), } } do |form| = render(partial: "admin/shared/flashes", locals: { flashes: }) if defined? flashes = hidden_field_tag :page, @page = hidden_field_tag :per_page, @per_page + = hidden_field_tag :search_term, @search_term + = hidden_field_tag :producer_id, @producer_id + = hidden_field_tag :category_id, @category_id %table.products %colgroup @@ -39,7 +44,7 @@ -# Y products could not be saved correctly. Please review errors and try again = t('.error_summary.invalid', count: @error_counts[:invalid]) .form-buttons - %a.button.reset.medium{ href: admin_products_path(page: @page, per_page: @per_page) } + %a.button.reset.medium{ href: admin_products_path(page: @page, per_page: @per_page, search_term: @search_term, producer_id: @producer_id, category_id: @category_id), 'data-turbo': "false" } = t('.reset') = form.submit t('.save'), class: "medium" %tr diff --git a/app/views/admin/products_v3/index.html.haml b/app/views/admin/products_v3/index.html.haml index 2ac344c476..4200cd0176 100644 --- a/app/views/admin/products_v3/index.html.haml +++ b/app/views/admin/products_v3/index.html.haml @@ -1,5 +1,3 @@ -- content_for :body_class do - products_v3_page - content_for :page_title do = t('.header.title') - content_for :page_actions do @@ -13,12 +11,7 @@ = render partial: 'spree/admin/shared/product_sub_menu' -#products_v3_page{ "data-controller": "products" } - .spinner-overlay{ "data-controller": "loading", "data-products-target": "loading", class: "hidden" } - .spinner-container - .spinner - = t('.loading') - +#products_v3_page{ "data-controller": "products", 'data-turbo': true } = render partial: "content", locals: { products: @products, pagy: @pagy, search_term: @search_term, producer_options: producers, producer_id: @producer_id, category_options: categories, category_id: @category_id, diff --git a/app/webpacker/css/admin/products_v3.scss b/app/webpacker/css/admin/products_v3.scss index a2c835ccd0..8cb8ccbce2 100644 --- a/app/webpacker/css/admin/products_v3.scss +++ b/app/webpacker/css/admin/products_v3.scss @@ -1,5 +1,6 @@ // Customisations for the new Bulk Edit Products page only -.products_v3_page { +// Scoped to containing div, because Turbo messes with body classes +#products_v3_page { #content > .row:first-child > .container:first-child { // Allow table to extend to full width of available screen space // TODO: move this to a generic rule, eg body.full-width{}. Then it can be included on any page. diff --git a/app/webpacker/css/admin_v3/components/spinner.scss b/app/webpacker/css/admin_v3/components/spinner.scss index fd7235ffe3..9f8d8a15e6 100644 --- a/app/webpacker/css/admin_v3/components/spinner.scss +++ b/app/webpacker/css/admin_v3/components/spinner.scss @@ -6,6 +6,11 @@ min-height: 200px; background: rgba(255, 255, 255, 0.8); z-index: 2; + + // Show when inside a loading Turbo Frame + turbo-frame[aria-busy="true"] > & { + display: flex; + } } .spinner-container { @@ -28,7 +33,9 @@ height: 56px; border-radius: 50%; border: 9px solid $teal; - animation: spinner-bulqg1 0.8s infinite linear alternate, spinner-oaa3wk 1.6s infinite linear; + animation: + spinner-bulqg1 0.8s infinite linear alternate, + spinner-oaa3wk 1.6s infinite linear; } } diff --git a/config/locales/en.yml b/config/locales/en.yml index 662b5fe984..2777dab7ad 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -844,6 +844,7 @@ en: index: header: title: Bulk Edit Products + content: loading: Loading your products delete_modal: delete_product_modal: diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index 74dcc2d051..6581ddc657 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -58,7 +58,7 @@ describe 'As an admin, I can manage products', feature: :admin_style_v3 do select "50", from: "per_page" - expect(page).to have_content "Showing 1 to 50" + expect(page).to have_content "Showing 1 to 50", wait: 10 expect_page_to_be 1 expect_per_page_to_be 50 expect_products_count_to_be 50 @@ -130,13 +130,29 @@ describe 'As an admin, I can manage products', feature: :admin_style_v3 do # create a product with a different supplier let!(:producer) { create(:supplier_enterprise, name: "Producer 1") } - let!(:product_by_supplier) { create(:simple_product, supplier: producer) } + let!(:product_by_supplier) { create(:simple_product, name: "Apples", supplier: producer) } - it "can search for a product" do + it "can search for and update a product" do visit admin_products_url search_by_producer "Producer 1" + # expect(page).to have_content "1 product found for your search criteria." + expect(page).to have_select "producer_id", selected: "Producer 1", wait: 5 + expect_products_count_to_be 1 + + within row_containing_name("Apples") do + fill_in "Name", with: "Pommes" + end + + expect { + click_button "Save changes" + + expect(page).to have_content "Changes saved" + product_by_supplier.reload + }.to change { product_by_supplier.name }.to("Pommes") + + # Search is still applied # expect(page).to have_content "1 product found for your search criteria." expect(page).to have_select "producer_id", selected: "Producer 1" expect_products_count_to_be 1 @@ -976,13 +992,12 @@ describe 'As an admin, I can manage products', feature: :admin_style_v3 do end def search_by_producer(producer) - # TODO: use a helper to more reliably select the tom-select component - select producer, from: "producer_id" + tomselect_select producer, from: "producer_id" click_button "Search" end def search_by_category(category) - select category, from: "category_id" + tomselect_select category, from: "category_id" click_button "Search" end