From 23c9410a25c18ef59decfd29c3728e331fee0fed Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 22 Aug 2025 12:54:37 +0100 Subject: [PATCH 1/7] Replace darker-background angular directive --- .../darkswarm/directives/darker_background.js.coffee | 11 ----------- app/helpers/shop_helper.rb | 6 ++++++ app/views/shop/messages/_closed_shop.html.haml | 2 +- app/views/shop/messages/_customer_required.html.haml | 2 +- app/views/shop/messages/_select_oc.html.haml | 2 +- app/views/shopping_shared/_tabs.html.haml | 4 ++-- app/webpacker/css/darkswarm/_shop-product-rows.scss | 2 ++ 7 files changed, 13 insertions(+), 16 deletions(-) delete mode 100644 app/assets/javascripts/darkswarm/directives/darker_background.js.coffee diff --git a/app/assets/javascripts/darkswarm/directives/darker_background.js.coffee b/app/assets/javascripts/darkswarm/directives/darker_background.js.coffee deleted file mode 100644 index b41541fab1..0000000000 --- a/app/assets/javascripts/darkswarm/directives/darker_background.js.coffee +++ /dev/null @@ -1,11 +0,0 @@ -angular.module('Darkswarm').directive "darkerBackground", -> - restrict: "A" - link: (scope, elm, attr)-> - toggleClass = (value) -> - elm.closest('.page-view').toggleClass("with-darker-background", value) - - toggleClass(true) - - # if an OrderCycle is selected, disable darker background - scope.$watch 'order_cycle.order_cycle_id', (newvalue, oldvalue) -> - toggleClass(false) if newvalue diff --git a/app/helpers/shop_helper.rb b/app/helpers/shop_helper.rb index fa248c8047..5fcdedc0d9 100644 --- a/app/helpers/shop_helper.rb +++ b/app/helpers/shop_helper.rb @@ -62,6 +62,12 @@ module ShopHelper true end + def shop_tab_class(tab) + return unless (tab == "home" && show_home_tab?) || current_order(false)&.order_cycle.nil? + + "with-darker-background" + end + private def show_groups_tabs? diff --git a/app/views/shop/messages/_closed_shop.html.haml b/app/views/shop/messages/_closed_shop.html.haml index 7c65eeaef4..185306b6b3 100644 --- a/app/views/shop/messages/_closed_shop.html.haml +++ b/app/views/shop/messages/_closed_shop.html.haml @@ -1,7 +1,7 @@ .closed-shop-header .row .small-12.columns - .content{ "darker-background" => true } + .content %h4 .warning-sign .rectangle diff --git a/app/views/shop/messages/_customer_required.html.haml b/app/views/shop/messages/_customer_required.html.haml index 844621ce28..9b358f1e6e 100644 --- a/app/views/shop/messages/_customer_required.html.haml +++ b/app/views/shop/messages/_customer_required.html.haml @@ -1,4 +1,4 @@ -.content{ "darker-background" => true } +.content .row.footer-pad .small-12.columns{ "data-controller": "login-modal" } %strong diff --git a/app/views/shop/messages/_select_oc.html.haml b/app/views/shop/messages/_select_oc.html.haml index 6256789d32..74376d178e 100644 --- a/app/views/shop/messages/_select_oc.html.haml +++ b/app/views/shop/messages/_select_oc.html.haml @@ -1,4 +1,4 @@ -.content.footer-pad{ "darker-background" => true, "ng-show" => "order_cycle.order_cycle_id == null" } +.content.footer-pad{ "ng-show" => "order_cycle.order_cycle_id == null" } .row .small-12.columns .select-oc-message diff --git a/app/views/shopping_shared/_tabs.html.haml b/app/views/shopping_shared/_tabs.html.haml index 92d288a9f9..31870b7b38 100644 --- a/app/views/shopping_shared/_tabs.html.haml +++ b/app/views/shopping_shared/_tabs.html.haml @@ -10,8 +10,8 @@ .columns.large-4.show-for-large-up = render partial: "shopping_shared/order_cycles" - shop_tabs.each do |tab| - %div{id: "#{tab[:name]}_panel", "data-tabs-and-panels-target": "panel #{'default' if tab[:default]} #{'shop' if tab[:shop]}" } - .page-view + %div{id: "#{tab[:name]}_panel", "data-tabs-and-panels-target": "panel #{'default' if tab[:default]} #{'shop' if tab[:shop]}" } + .page-view{ class: shop_tab_class(tab[:name]) } - if tab[:custom] = render "shopping_shared/tabs/custom" - else diff --git a/app/webpacker/css/darkswarm/_shop-product-rows.scss b/app/webpacker/css/darkswarm/_shop-product-rows.scss index ddf25d6d51..edbe9fb00a 100644 --- a/app/webpacker/css/darkswarm/_shop-product-rows.scss +++ b/app/webpacker/css/darkswarm/_shop-product-rows.scss @@ -1,5 +1,7 @@ .darkswarm { products { + background-color: white; + product { @import "shop_partials/shop-product-rows"; } From 32e3fc0175440b02ea2e475c77d69d59ba4cab46 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 22 Aug 2025 14:20:14 +0100 Subject: [PATCH 2/7] Replace disable-dynamically angular directive --- .../directives/disable_dynamically.js.coffee | 14 -------------- app/views/spree/orders/form/_cart_links.html.haml | 4 ++-- 2 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 app/assets/javascripts/darkswarm/directives/disable_dynamically.js.coffee diff --git a/app/assets/javascripts/darkswarm/directives/disable_dynamically.js.coffee b/app/assets/javascripts/darkswarm/directives/disable_dynamically.js.coffee deleted file mode 100644 index 33df890ead..0000000000 --- a/app/assets/javascripts/darkswarm/directives/disable_dynamically.js.coffee +++ /dev/null @@ -1,14 +0,0 @@ -# Allows disabling of link buttons via disabled attribute. -# This is normally ignored, ie the link appears disabled but is still clickable. - -angular.module('Darkswarm').directive "disableDynamically", -> - restrict: 'A' - - link: (scope, element, attrs) -> - element.on 'click', (e) -> - if attrs.disabled - e.preventDefault() - return - - scope.$on "$destroy", -> - element.off("click") diff --git a/app/views/spree/orders/form/_cart_links.html.haml b/app/views/spree/orders/form/_cart_links.html.haml index 5eaac48a55..a3114cb670 100644 --- a/app/views/spree/orders/form/_cart_links.html.haml +++ b/app/views/spree/orders/form/_cart_links.html.haml @@ -1,5 +1,5 @@ .row.links - %a.continue-shopping.button.secondary{href: current_shop_products_path, "ng-disabled" => "#{@insufficient_stock_lines.any?}", "disable-dynamically" => true} + %a.continue-shopping.button.secondary{ @insufficient_stock_lines.any? ? { disabled: "disabled" } : { href: current_shop_products_path } } = t :orders_edit_continue - %a#checkout-link.button.primary.right{href: main_app.checkout_path, "ng-disabled" => "#{@insufficient_stock_lines.any?}", "disable-dynamically" => true} + %a#checkout-link.button.primary.right{ @insufficient_stock_lines.any? ? { disabled: "disabled" } : { href: main_app.checkout_path } } = t :orders_edit_checkout From 7a3b4d394bd1a98c148e5fa1f428ae7e43f87548 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 22 Aug 2025 15:04:39 +0100 Subject: [PATCH 3/7] Replace inline-alert angular directive --- .../darkswarm/directives/inline_alert.js.coffee | 7 ------- app/views/registration/steps/_about.html.haml | 4 ++-- app/views/spree/shared/_order_details.html.haml | 4 ++-- 3 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 app/assets/javascripts/darkswarm/directives/inline_alert.js.coffee diff --git a/app/assets/javascripts/darkswarm/directives/inline_alert.js.coffee b/app/assets/javascripts/darkswarm/directives/inline_alert.js.coffee deleted file mode 100644 index 217a82b35b..0000000000 --- a/app/assets/javascripts/darkswarm/directives/inline_alert.js.coffee +++ /dev/null @@ -1,7 +0,0 @@ -angular.module('Darkswarm').directive "ofnInlineAlert", -> - restrict: 'A' - scope: true - link: (scope, elem, attrs) -> - scope.visible = true - scope.close = -> - scope.visible = false diff --git a/app/views/registration/steps/_about.html.haml b/app/views/registration/steps/_about.html.haml index 9a18dbd55a..4265fc148f 100644 --- a/app/views/registration/steps/_about.html.haml +++ b/app/views/registration/steps/_about.html.haml @@ -13,10 +13,10 @@ %form{ name: 'about', novalidate: true, "ng-controller": "RegistrationFormCtrl", "ng-submit": "selectIfValid('images', about)" } .row .small-12.columns - .alert-box.info{ "ofn-inline-alert": true, "ng-show": "visible" } + .alert-box.info{ "data-controller": "toggle-control", "data-toggle-control-target": "content", style: "display: block;" } %h6{ "ng-bind" => "'registration.steps.about.success' | t:{enterprise: enterprise.name}" } %span= t(".registration_exit_message") - %a.close{ "ng-click": "close()" } × + %a.close{ "data-action": "toggle-control#toggleDisplay" } × .small-12.large-8.columns .row diff --git a/app/views/spree/shared/_order_details.html.haml b/app/views/spree/shared/_order_details.html.haml index de68929af7..0038ea7309 100644 --- a/app/views/spree/shared/_order_details.html.haml +++ b/app/views/spree/shared/_order_details.html.haml @@ -42,9 +42,9 @@ .row .columns.large-12 - if order.changes_allowed? - .alert-box.order-summary{ "ofn-inline-alert" => true, "ng-show" => "visible" } + .alert-box.order-summary{ "data-controller": "toggle-control", "data-toggle-control-target": "content", style: "display: block;" } = t(:orders_changeable_orders_alert_html, oc_close: l(order.order_cycle.orders_close_at, format: "%b %d, %Y %H:%M")) - %a.close{ "ng-click" => "close()" } × + %a.close{ "data-action": "toggle-control#toggleDisplay" } × = form_for order, url: main_app.order_path(order), html: {id: 'update-order', name: 'update_order_form' } do |order_form| - if order.changes_allowed? From c057c723217a47207819b4be65cd4a2ed5d96c4c Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 22 Aug 2025 15:53:39 +0100 Subject: [PATCH 4/7] Replace ofn-page-alert angular directive --- .../darkswarm/directives/page_alert.js.coffee | 21 ------------ app/views/shared/menu/_alert.html.haml | 4 +-- .../controllers/page_alert_controller.js | 34 +++++++++++++++++++ 3 files changed, 36 insertions(+), 23 deletions(-) delete mode 100644 app/assets/javascripts/darkswarm/directives/page_alert.js.coffee create mode 100644 app/webpacker/controllers/page_alert_controller.js diff --git a/app/assets/javascripts/darkswarm/directives/page_alert.js.coffee b/app/assets/javascripts/darkswarm/directives/page_alert.js.coffee deleted file mode 100644 index d0fadadde7..0000000000 --- a/app/assets/javascripts/darkswarm/directives/page_alert.js.coffee +++ /dev/null @@ -1,21 +0,0 @@ -angular.module('Darkswarm').directive "ofnPageAlert", ($timeout) -> - restrict: 'A' - scope: true - link: (scope, elem, attrs) -> - moveSelectors = [".off-canvas-wrap .inner-wrap", - ".off-canvas-wrap .inner-wrap .fixed", - ".off-canvas-fixed .top-bar", - ".off-canvas-fixed ofn-flash", - ".off-canvas-fixed nav.tab-bar", - ".off-canvas-fixed .page-alert"] - - container_elems = $(moveSelectors.join(", ")) - - # Wait a moment after page load before showing the alert. Otherwise we often miss the - # start of the animation. - $timeout -> - container_elems.addClass("move-up") - , 1000 - - scope.close = -> - container_elems.removeClass("move-up") diff --git a/app/views/shared/menu/_alert.html.haml b/app/views/shared/menu/_alert.html.haml index 787c1258cc..c2bd5e43a5 100644 --- a/app/views/shared/menu/_alert.html.haml +++ b/app/views/shared/menu/_alert.html.haml @@ -1,4 +1,4 @@ -.text-center.page-alert.fixed{ "ofn-page-alert" => true } +.text-center.page-alert.fixed{ "data-controller" => "page-alert" } .alert-box = render 'shared/page_alert' - %a.close{ "ng-click": "close()" } × + %a.close{ "data-action" => "page-alert#close" } × diff --git a/app/webpacker/controllers/page_alert_controller.js b/app/webpacker/controllers/page_alert_controller.js new file mode 100644 index 0000000000..a7bd46dc03 --- /dev/null +++ b/app/webpacker/controllers/page_alert_controller.js @@ -0,0 +1,34 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + moveSelectors = [".off-canvas-wrap .inner-wrap", + ".off-canvas-wrap .inner-wrap .fixed", + ".off-canvas-fixed .top-bar", + ".off-canvas-fixed ofn-flash", + ".off-canvas-fixed nav.tab-bar", + ".off-canvas-fixed .page-alert"]; + + connect() { + // Wait a moment after page load before showing the alert. Otherwise we often miss the + // start of the animation. + setTimeout(this.#show, 1000); + } + + close() { + this.#moveElements().forEach((element) => { + element.classList.remove("move-up"); + }); + } + + // private + + #moveElements() { + return document.querySelectorAll(this.moveSelectors.join(",")); + } + + #show = () => { + this.#moveElements().forEach((element) => { + element.classList.add("move-up"); + }); + }; +} From 6f7a547e15067687002b1e994f6de58360a5aee2 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 29 Aug 2025 14:21:14 +0100 Subject: [PATCH 5/7] Add a :link_to_or_disabled helper method --- app/helpers/link_helper.rb | 23 +++++++++++++++++++ .../spree/orders/form/_cart_links.html.haml | 6 ++--- .../css/admin_v3/components/buttons.scss | 4 ++++ spec/helpers/link_helper_spec.rb | 21 +++++++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/app/helpers/link_helper.rb b/app/helpers/link_helper.rb index dde2433446..fced430271 100644 --- a/app/helpers/link_helper.rb +++ b/app/helpers/link_helper.rb @@ -1,6 +1,29 @@ # frozen_string_literal: true module LinkHelper + def link_to_or_disabled(name = nil, options = nil, html_options = nil, &block) + html_options, options, name = options, name, block if block_given? + html_options ||= {} + + if !!html_options.delete(:disabled) + # https://www.scottohara.me/blog/2021/05/28/disabled-links.html + html_options.merge!( + 'aria-disabled': true, + class: (html_options[:class].to_s.split + ["disabled"]).uniq.join(" "), + role: "link" + ) + if block_given? + content_tag("a", name, **html_options, &block) + else + content_tag("a", name, **html_options) + end + elsif block_given? + link_to options, html_options, &block + else + link_to name, options, html_options + end + end + def link_to_service(baseurl, name, html_options = {}, &) return if name.blank? diff --git a/app/views/spree/orders/form/_cart_links.html.haml b/app/views/spree/orders/form/_cart_links.html.haml index a3114cb670..a9b17a2172 100644 --- a/app/views/spree/orders/form/_cart_links.html.haml +++ b/app/views/spree/orders/form/_cart_links.html.haml @@ -1,5 +1,3 @@ .row.links - %a.continue-shopping.button.secondary{ @insufficient_stock_lines.any? ? { disabled: "disabled" } : { href: current_shop_products_path } } - = t :orders_edit_continue - %a#checkout-link.button.primary.right{ @insufficient_stock_lines.any? ? { disabled: "disabled" } : { href: main_app.checkout_path } } - = t :orders_edit_checkout + = link_to_or_disabled t(:orders_edit_continue), current_shop_products_path, class: "continue-shopping button secondary", disabled: @insufficient_stock_lines.any? + = link_to_or_disabled t(:orders_edit_checkout), main_app.checkout_path, class: "button primary right", disabled: @insufficient_stock_lines.any?, id: "checkout-link" diff --git a/app/webpacker/css/admin_v3/components/buttons.scss b/app/webpacker/css/admin_v3/components/buttons.scss index 01ede577d1..7de1a2ab6e 100644 --- a/app/webpacker/css/admin_v3/components/buttons.scss +++ b/app/webpacker/css/admin_v3/components/buttons.scss @@ -182,6 +182,10 @@ a.button { text-decoration: none; } +a[aria-disabled] { + pointer-events: none; +} + .button.disruptive::before { margin-right: 3px; diff --git a/spec/helpers/link_helper_spec.rb b/spec/helpers/link_helper_spec.rb index 14dc507343..aceeca8cf7 100644 --- a/spec/helpers/link_helper_spec.rb +++ b/spec/helpers/link_helper_spec.rb @@ -9,4 +9,25 @@ RSpec.describe LinkHelper do expect(helper.ext_url("http://example.com/", "bla")).to eq("http://example.com/bla") end end + + describe "link_to_or_disabled" do + it "behaves like the standard :link_to method e.g. it accepts the same arguments and accepts + blocks, etc." do + expect(helper.link_to_or_disabled("Go", "http://example.com/")).to eq( + "Go" + ) + expect(helper.link_to_or_disabled("Go", "http://example.com/", class: "button")).to eq( + "Go" + ) + expect(helper.link_to_or_disabled("http://example.com/") { "Go" }).to eq( + "Go" + ) + end + + it "accepts an additional boolean :disabled argument, which if true renders a disabled link" do + expect(helper.link_to_or_disabled("Go", "http://example.com/", disabled: true)).to eq( + "Go" + ) + end + end end From 66859f44ca91d414e1e3fc5911aaf39b2232cd7c Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 29 Aug 2025 14:33:49 +0100 Subject: [PATCH 6/7] Include LinkHelper which includes new :link_to_or_disable method to fix spec/views/spree/orders/edit.html.haml_spec.rb test --- spec/views/spree/orders/edit.html.haml_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/views/spree/orders/edit.html.haml_spec.rb b/spec/views/spree/orders/edit.html.haml_spec.rb index 2d1b6b65fd..f6b2988edb 100644 --- a/spec/views/spree/orders/edit.html.haml_spec.rb +++ b/spec/views/spree/orders/edit.html.haml_spec.rb @@ -7,6 +7,7 @@ RSpec.describe "spree/orders/edit.html.haml" do helper ShopHelper helper ApplicationHelper helper CheckoutHelper + helper LinkHelper helper SharedHelper helper FooterLinksHelper helper MarkdownHelper From 74e7bd5172b01187d7de92ab00dd6782055dbaf6 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 29 Aug 2025 14:45:44 +0100 Subject: [PATCH 7/7] Update spec/system/consumer/shopping/cart_spec.rb test to use new disabled selector --- spec/system/consumer/shopping/cart_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/system/consumer/shopping/cart_spec.rb b/spec/system/consumer/shopping/cart_spec.rb index ed039bc28d..6026f20d5e 100644 --- a/spec/system/consumer/shopping/cart_spec.rb +++ b/spec/system/consumer/shopping/cart_spec.rb @@ -241,8 +241,8 @@ RSpec.describe "full-page cart" do 'Please update the selected quantities.' # "Continue Shopping" and "Checkout" buttons are disabled - expect(page).to have_selector "a.continue-shopping[disabled=disabled]" - expect(page).to have_selector "a#checkout-link[disabled=disabled]" + expect(page).to have_selector "a.continue-shopping[aria-disabled=true]" + expect(page).to have_selector "a#checkout-link[aria-disabled=true]" # Quantity field clearly marked as invalid and "Update" button is not highlighted expect(page).to have_selector "#order_line_items_attributes_0_quantity.ng-invalid-stock" @@ -260,8 +260,8 @@ RSpec.describe "full-page cart" do click_button 'Update' # "Continue Shopping" and "Checkout" buttons are not disabled after cart is updated - expect(page).not_to have_selector "a.continue-shopping[disabled=disabled]" - expect(page).not_to have_selector "a#checkout-link[disabled=disabled]" + expect(page).not_to have_selector "a.continue-shopping[aria-disabled=true]" + expect(page).not_to have_selector "a#checkout-link[aria-disabled=true]" end end end