From 0eb97f1cdc77ae2194c1a4537670109f9919568a Mon Sep 17 00:00:00 2001 From: Sebastian Castro Date: Tue, 11 Jan 2022 21:52:49 +0100 Subject: [PATCH 01/51] loading-popup: improve style --- .../layouts/admin/_progress_spinner.html.haml | 22 +------------ .../css/admin/components/progress.scss | 32 ++++++++----------- 2 files changed, 14 insertions(+), 40 deletions(-) diff --git a/app/views/spree/layouts/admin/_progress_spinner.html.haml b/app/views/spree/layouts/admin/_progress_spinner.html.haml index a28458afad..6d0c9c72ba 100644 --- a/app/views/spree/layouts/admin/_progress_spinner.html.haml +++ b/app/views/spree/layouts/admin/_progress_spinner.html.haml @@ -1,24 +1,4 @@ #progress - / By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL - %svg{:class => "spinner", :viewbox => "0 0 58 58", :xmlns => "http://www.w3.org/2000/svg"} - %g{:fill => "none", "fill-rule" => "evenodd"} - %g{:stroke => "currentColor", "stroke-width" => "1.5", :transform => "translate(2 1)"} - %circle{:cx => "42.601", :cy => "11.462", :fill => "currentColor", "fill-opacity" => "1", :r => "5"} - %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "1;0;0;0;0;0;0;0"} - %circle{:cx => "49.063", :cy => "27.063", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} - %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;1;0;0;0;0;0;0"} - %circle{:cx => "42.601", :cy => "42.663", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} - %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;1;0;0;0;0;0"} - %circle{:cx => "27", :cy => "49.125", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} - %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;1;0;0;0;0"} - %circle{:cx => "11.399", :cy => "42.663", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} - %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;0;1;0;0;0"} - %circle{:cx => "4.938", :cy => "27.063", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} - %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;0;0;1;0;0"} - %circle{:cx => "11.399", :cy => "11.462", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} - %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;0;0;0;1;0"} - %circle{:cx => "27", :cy => "5", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} - %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;0;0;0;0;1"} - + %i.spinner.fa.fa-spin.fa-circle-o-notch = Spree.t(:loading) \... diff --git a/app/webpacker/css/admin/components/progress.scss b/app/webpacker/css/admin/components/progress.scss index 8221701587..f62f64d85f 100644 --- a/app/webpacker/css/admin/components/progress.scss +++ b/app/webpacker/css/admin/components/progress.scss @@ -1,28 +1,22 @@ +// Loading throbber displayed when ajax request takes too long to complete #progress { - @include border-radius(10px); - position: fixed; - top: -10px; - left: 50%; - z-index: 1000; - opacity: 0.8; - width: 200px; - background-color: $spree-blue; - color: $color-1; display: none; - font-size: 120%; + @include border-radius(0 0 4px 4px); + position: fixed; + top: 0; + left: 50%; + transform: translateX(-50%); + z-index: 1000; + background-color: $spree-blue; + color: #FFFFFF; + opacity: .8; + font-size: 1rem; + padding: .5rem 1rem; font-weight: bold; - line-height: 40px; - margin-left: -100px; - padding-top: 15px; text-align: center; text-transform: uppercase; .spinner { - position: absolute; - left: 50%; - width: 30px; - height: 30px; - top: -5px; - margin-left: -15px; + margin-right: 5px; } } From 4a436978a9eade24dfc9b3e920c3db2ac48309e5 Mon Sep 17 00:00:00 2001 From: Sebastian Castro Date: Wed, 8 Dec 2021 11:25:29 +0100 Subject: [PATCH 02/51] loading-popup: debounce display --- app/assets/javascripts/admin/spree/progress.coffee | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/admin/spree/progress.coffee b/app/assets/javascripts/admin/spree/progress.coffee index f099e40842..e6b79c7b74 100644 --- a/app/assets/javascripts/admin/spree/progress.coffee +++ b/app/assets/javascripts/admin/spree/progress.coffee @@ -1,7 +1,11 @@ $(document).ready -> + progressTimer = null $(document).ajaxStart -> - $("#progress").fadeIn() + progressTimer = setTimeout -> + $("#progress").fadeIn() + , 500 $(document).ajaxStop -> - $("#progress").fadeOut() + clearTimeout(progressTimer) if progressTimer? + $("#progress").stop().hide() From 115dfe445b789bcf1221ec4387ebe5cdf29002b3 Mon Sep 17 00:00:00 2001 From: Sebastian Castro Date: Thu, 9 Dec 2021 10:07:53 +0100 Subject: [PATCH 03/51] loading-message: make them all look the same in admin use font awesome spinner instead of an image --- .../exchange_products_panel_footer.html.haml | 2 +- app/views/admin/customers/index.html.haml | 4 ++-- .../_enterprise_user_index.html.haml | 5 +++-- .../form/_primary_details.html.haml | 2 +- .../order_cycles/_loading_flash.html.haml | 6 +++--- .../subscriptions/_loading_flash.html.haml | 5 +++-- .../_loading_flash.html.haml | 5 +++-- app/views/components/_admin_spinner.haml | 1 + .../admin/orders/bulk_management.html.haml | 2 +- app/views/spree/admin/orders/index.html.haml | 11 ++++------ .../products/index/_indicators.html.haml | 6 +++--- app/views/spree/admin/taxonomies/edit.haml | 4 ---- .../layouts/admin/_progress_spinner.html.haml | 2 +- .../css/admin/components/progress.scss | 20 +++++++++++++++++++ app/webpacker/css/admin/openfoodnetwork.scss | 13 ------------ app/webpacker/css/admin/orders.scss | 12 ----------- .../admin/bulk_order_management_spec.rb | 2 +- spec/system/admin/bulk_product_update_spec.rb | 4 ++-- 18 files changed, 49 insertions(+), 57 deletions(-) create mode 100644 app/views/components/_admin_spinner.haml diff --git a/app/assets/javascripts/templates/admin/panels/exchange_products_panel_footer.html.haml b/app/assets/javascripts/templates/admin/panels/exchange_products_panel_footer.html.haml index df3c510fed..e458c913ff 100644 --- a/app/assets/javascripts/templates/admin/panels/exchange_products_panel_footer.html.haml +++ b/app/assets/javascripts/templates/admin/panels/exchange_products_panel_footer.html.haml @@ -6,6 +6,6 @@ .sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' } %br - %img.spinner{ src: image_path("/spinning-circles.svg")} + %i.spinner.fa.fa-spin.fa-circle-o-notch %h1 {{ 'js.admin.panels.exchange_products.loading_variants' | t }} diff --git a/app/views/admin/customers/index.html.haml b/app/views/admin/customers/index.html.haml index 877e9a1d91..52b844871d 100644 --- a/app/views/admin/customers/index.html.haml +++ b/app/views/admin/customers/index.html.haml @@ -35,9 +35,9 @@ .row{ 'ng-if' => 'shop_id && RequestMonitor.loading' } .sixteen.columns.alpha#loading - = render partial: "components/spinner" + = render partial: "components/admin_spinner" %h1 - =t :loading_customers + = t :loading_customers .row{ :class => "sixteen columns alpha", 'ng-show' => '!RequestMonitor.loading && filteredCustomers.length == 0'} %h1#no_results diff --git a/app/views/admin/enterprises/_enterprise_user_index.html.haml b/app/views/admin/enterprises/_enterprise_user_index.html.haml index b8426b104b..46090da6af 100644 --- a/app/views/admin/enterprises/_enterprise_user_index.html.haml +++ b/app/views/admin/enterprises/_enterprise_user_index.html.haml @@ -9,8 +9,9 @@ %columns-dropdown{ action: "#{controller_name}_#{action_name}" } .row{ 'ng-if' => '!loaded' } .sixteen.columns.alpha#loading - = render partial: "components/spinner" - %h1= t('.loading_enterprises') + = render partial: "components/admin_spinner" + %h1 + = t('.loading_enterprises') .row{ :class => "sixteen columns alpha", 'ng-show' => 'loaded && filteredEnterprises.length == 0'} %h1#no_results= t('.no_enterprises_found') diff --git a/app/views/admin/enterprises/form/_primary_details.html.haml b/app/views/admin/enterprises/form/_primary_details.html.haml index 6331d7c25f..28507311ea 100644 --- a/app/views/admin/enterprises/form/_primary_details.html.haml +++ b/app/views/admin/enterprises/form/_primary_details.html.haml @@ -57,7 +57,7 @@ = f.text_field :permalink, { 'ng-model' => "Enterprise.permalink", placeholder: "eg. your-shop-name", 'ng-model-options' => "{ updateOn: 'default blur', debounce: {'default': 300, 'blur': 0} }" } .two.columns.omega %div{ng: {show: "checking", cloak: true}, style: "width: 30px; height: 30px;"} - = render partial: "components/spinner" + = render partial: "components/admin_spinner" %span{ ng: { class: 'availability.toLowerCase()', hide: "checking" } } {{ availability }} %i{ ng: { class: "{'icon-ok-sign': availability == 'Available', 'icon-remove-sign': availability == 'Unavailable'}" } } diff --git a/app/views/admin/order_cycles/_loading_flash.html.haml b/app/views/admin/order_cycles/_loading_flash.html.haml index ffd05c59b1..64689ffe29 100644 --- a/app/views/admin/order_cycles/_loading_flash.html.haml +++ b/app/views/admin/order_cycles/_loading_flash.html.haml @@ -1,6 +1,6 @@ %div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'RequestMonitor.loading' } } - = render partial: "components/spinner" + = render partial: "components/admin_spinner" %h1{ ng: { hide: 'orderCycles.length > 0' } } - =t('.loading_order_cycles') + = t('.loading_order_cycles') %h1{ ng: { show: 'orderCycles.length > 0' } } - =t('.loading') + = t('.loading') diff --git a/app/views/admin/subscriptions/_loading_flash.html.haml b/app/views/admin/subscriptions/_loading_flash.html.haml index 130d92bb18..b4a85be210 100644 --- a/app/views/admin/subscriptions/_loading_flash.html.haml +++ b/app/views/admin/subscriptions/_loading_flash.html.haml @@ -1,3 +1,4 @@ %div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'shop_id && RequestMonitor.loading' } } - = render partial: "components/spinner" - %h1= t('.loading') + = render partial: "components/admin_spinner" + %h1 + = t('.loading') diff --git a/app/views/admin/variant_overrides/_loading_flash.html.haml b/app/views/admin/variant_overrides/_loading_flash.html.haml index 7832fd2160..0095c543e8 100644 --- a/app/views/admin/variant_overrides/_loading_flash.html.haml +++ b/app/views/admin/variant_overrides/_loading_flash.html.haml @@ -1,3 +1,4 @@ %div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'hub_id && products.length == 0 && RequestMonitor.loading' } } - = render partial: "components/spinner" - %h1= t('.loading_inventory') + = render partial: "components/admin_spinner" + %h1 + = t('.loading_inventory') diff --git a/app/views/components/_admin_spinner.haml b/app/views/components/_admin_spinner.haml new file mode 100644 index 0000000000..e54228246b --- /dev/null +++ b/app/views/components/_admin_spinner.haml @@ -0,0 +1 @@ +%i.spinner.fa.fa-spin.fa-circle-o-notch diff --git a/app/views/spree/admin/orders/bulk_management.html.haml b/app/views/spree/admin/orders/bulk_management.html.haml index 1177f7ae58..9aabb4c7e7 100644 --- a/app/views/spree/admin/orders/bulk_management.html.haml +++ b/app/views/spree/admin/orders/bulk_management.html.haml @@ -103,7 +103,7 @@ %columns-dropdown{ action: "#{controller_name}_#{action_name}" } %div.sixteen.columns.alpha#loading{ 'ng-if' => 'RequestMonitor.loading' } - = render partial: "components/spinner" + = render partial: "components/admin_spinner" %h1 = t("admin.orders.bulk_management.loading") diff --git a/app/views/spree/admin/orders/index.html.haml b/app/views/spree/admin/orders/index.html.haml index 0d889cce2c..f47102e916 100644 --- a/app/views/spree/admin/orders/index.html.haml +++ b/app/views/spree/admin/orders/index.html.haml @@ -92,13 +92,10 @@ %div{'ng-if' => 'order.ready_to_capture'} %button.icon-capture.icon_link.no-text{'ng-click' => 'capturePayment(order)', rel: 'nofollow', 'ofn-with-tip' => t('.capture')} -.orders-loading{'ng-show' => 'RequestMonitor.loading'} - .row - .small-12.columns.fullwidth.text-center - = render partial: "components/spinner" - .row - .small-12.columns.fullwidth.text-center - %span= t('.loading') +.sixteen.columns.alpha#loading{ 'ng-show' => 'RequestMonitor.loading' } + = render partial: "components/admin_spinner" + %h1 + = t('.loading') %div{'ng-show' => "!RequestMonitor.loading && orders.length > 0" } = render partial: 'admin/shared/angular_pagination' diff --git a/app/views/spree/admin/products/index/_indicators.html.haml b/app/views/spree/admin/products/index/_indicators.html.haml index ae68aa7b00..54ea6041ea 100644 --- a/app/views/spree/admin/products/index/_indicators.html.haml +++ b/app/views/spree/admin/products/index/_indicators.html.haml @@ -1,7 +1,7 @@ %div.sixteen.columns.alpha#loading{ 'ng-if' => 'RequestMonitor.loading' } - %br - = render partial: "components/spinner" - %h1= t('.title') + = render partial: "components/admin_spinner" + %h1 + = t('.title') %div.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && q.query.length == 0' } %h1#no_results= t('.no_products') diff --git a/app/views/spree/admin/taxonomies/edit.haml b/app/views/spree/admin/taxonomies/edit.haml index 1f11fbb56c..521efbc568 100755 --- a/app/views/spree/admin/taxonomies/edit.haml +++ b/app/views/spree/admin/taxonomies/edit.haml @@ -20,10 +20,6 @@ Spree.routes.taxonomy_taxons_path = "#{main_app.api_v0_taxonomy_taxons_path(@taxonomy)}"; Spree.routes.admin_taxonomy_taxons_path = "#{spree.admin_taxonomy_taxons_path(@taxonomy)}"; #taxonomy_tree.tree - #progress{style: "display:none;"} - = image_pack_tag 'select2-spinner.gif', title: 'Spinner', style: "vertical-align:bottom;" - = t("spree.updating") - \.. .info= t("spree.taxonomy_tree_instruction") %br/ .filter-actions.actions diff --git a/app/views/spree/layouts/admin/_progress_spinner.html.haml b/app/views/spree/layouts/admin/_progress_spinner.html.haml index 6d0c9c72ba..8ea8dbf5c3 100644 --- a/app/views/spree/layouts/admin/_progress_spinner.html.haml +++ b/app/views/spree/layouts/admin/_progress_spinner.html.haml @@ -1,4 +1,4 @@ #progress - %i.spinner.fa.fa-spin.fa-circle-o-notch + = render partial: "components/admin_spinner" = Spree.t(:loading) \... diff --git a/app/webpacker/css/admin/components/progress.scss b/app/webpacker/css/admin/components/progress.scss index f62f64d85f..2b2c9d0673 100644 --- a/app/webpacker/css/admin/components/progress.scss +++ b/app/webpacker/css/admin/components/progress.scss @@ -20,3 +20,23 @@ margin-right: 5px; } } + +// Loading message replacing a table when it's loading for example +#loading { + text-align: center; + padding: 2rem 0; + color: $color-4; + + i { + font-size: 2rem; + } + img.spinner { + border: 0px; + width: 100px; + height: 100px; + } + h1 { + margin-top: 20px; + color: inherit; + } +} diff --git a/app/webpacker/css/admin/openfoodnetwork.scss b/app/webpacker/css/admin/openfoodnetwork.scss index 5ba6b879db..a573de4126 100644 --- a/app/webpacker/css/admin/openfoodnetwork.scss +++ b/app/webpacker/css/admin/openfoodnetwork.scss @@ -203,19 +203,6 @@ table#listing_enterprise_groups { } } -#loading { - text-align: center; - img.spinner { - border: 0px; - width: 100px; - height: 100px; - } - h1 { - margin-top: 20px; - color: gray; - } -} - .field_with_errors > input { border-color: red; } diff --git a/app/webpacker/css/admin/orders.scss b/app/webpacker/css/admin/orders.scss index b107947151..2316b27f66 100644 --- a/app/webpacker/css/admin/orders.scss +++ b/app/webpacker/css/admin/orders.scss @@ -90,18 +90,6 @@ table.index td.actions { text-align: left; } -.orders-loading { - margin-top: 1em; - - img { - width: 85px; - } - - span { - font-size: 1.2em; - } -} - .index-controls { button { diff --git a/spec/system/admin/bulk_order_management_spec.rb b/spec/system/admin/bulk_order_management_spec.rb index 1a633554d4..e3a2d57288 100644 --- a/spec/system/admin/bulk_order_management_spec.rb +++ b/spec/system/admin/bulk_order_management_spec.rb @@ -418,7 +418,7 @@ describe ' expect(page).to have_select2 'order_cycle_filter', with_options: OrderCycle.pluck(:name).unshift("All") select2_select oc1.name, from: "order_cycle_filter" - expect(page).to have_no_selector "#loading img.spinner" + expect(page).to have_no_selector "#loading i" expect(page).to have_selector "tr#li_#{li1.id}" expect(page).to have_no_selector "tr#li_#{li2.id}" end diff --git a/spec/system/admin/bulk_product_update_spec.rb b/spec/system/admin/bulk_product_update_spec.rb index c340dc4167..63c3a323fc 100644 --- a/spec/system/admin/bulk_product_update_spec.rb +++ b/spec/system/admin/bulk_product_update_spec.rb @@ -852,10 +852,10 @@ describe ' attach_file 'image-upload', Rails.root.join("public/500.jpg"), visible: false # Shows spinner whilst loading - expect(page).to have_css "img.spinner", visible: true + expect(page).to have_css ".spinner", visible: true end - expect(page).to have_no_css "img.spinner", visible: true + expect(page).to have_no_css ".spinner", visible: true expect(page).to have_no_selector "div.reveal-modal" within "table#listing_products tr#p_#{product.id}" do From 26ac59fbbab22af73f8817ecc5531395a845a1ca Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sat, 15 Jan 2022 16:21:33 +0000 Subject: [PATCH 04/51] Move Matomo event tracking for login modal into Autherntication service --- .../darkswarm/services/authentication_service.js.coffee | 3 +++ app/assets/javascripts/templates/login.html.haml | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee b/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee index 1160535b0b..7c5711d992 100644 --- a/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee +++ b/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee @@ -21,6 +21,9 @@ angular.module('Darkswarm').factory "AuthenticationService", (Navigation, $modal @selectedPath = path || @selectedPath Navigation.navigate @selectedPath + if window._paq + window._paq.push(['trackEvent', 'Signin/Signup', 'Login Modal View', window.location.href]) + # Opens the /login tab if returning from email confirmation, # the /signup tab if opened from the enterprise registration page, # otherwise opens whichever tab is selected in the URL params ('/login', '/signup', or '/forgot') diff --git a/app/assets/javascripts/templates/login.html.haml b/app/assets/javascripts/templates/login.html.haml index cf92fa0f7c..7ca17bfbe9 100644 --- a/app/assets/javascripts/templates/login.html.haml +++ b/app/assets/javascripts/templates/login.html.haml @@ -42,7 +42,3 @@ tabindex: "4", type: "submit", value: "{{'label_login' | t}}"} -:javascript - if (window._paq) { - window._paq.push(['trackEvent', 'Signin/Signup', 'Login Modal View', window.location.href]); - } From e077607767dbfd7096d42a665b874263942921d8 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 21:31:42 +0000 Subject: [PATCH 05/51] Remove unused controller action --- .../spree/user_passwords_controller.rb | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/app/controllers/spree/user_passwords_controller.rb b/app/controllers/spree/user_passwords_controller.rb index 2b5b0a93b6..6b1572757c 100644 --- a/app/controllers/spree/user_passwords_controller.rb +++ b/app/controllers/spree/user_passwords_controller.rb @@ -16,24 +16,6 @@ module Spree include I18nHelper before_action :set_locale - # Overridden due to bug in Devise. - # respond_with resource, :location => new_session_path(resource_name) - # is generating bad url /session/new.user - # - # overridden to: - # respond_with resource, :location => spree.login_path - # - def create - self.resource = resource_class.send_reset_password_instructions(raw_params[resource_name]) - - if resource.errors.empty? - set_flash_message(:notice, :send_instructions) if is_navigational_format? - respond_with resource, location: spree.login_path - else - respond_with_navigational(resource) { render :new } - end - end - # Devise::PasswordsController allows for blank passwords. # Silly Devise::PasswordsController! # Fixes spree/spree#2190. From 23a7ba24799d1f956c5f44af9e8995b63156db36 Mon Sep 17 00:00:00 2001 From: "Nihal M. Kelanthodika" Date: Thu, 27 Jan 2022 15:50:20 +0530 Subject: [PATCH 06/51] Added before_save callback to convert variant weight to decimal and 0.0 if nil --- app/models/spree/variant.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index 1b2b085de1..8f61819708 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -79,6 +79,8 @@ module Spree after_create :create_stock_items after_create :set_position + before_save :convert_variant_weight_to_decimal + around_destroy :destruction # default variant scope only lists non-deleted variants @@ -243,5 +245,9 @@ module Spree self.unit_value = 1.0 end + + def convert_variant_weight_to_decimal + self.weight = weight.to_d + end end end From 4ace7efd97b9abec790ee849015f0b386dbd12e6 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 28 Jan 2022 10:40:01 +0000 Subject: [PATCH 07/51] Fix visual regression on filter buttons --- app/webpacker/css/admin/shared/forms.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/webpacker/css/admin/shared/forms.scss b/app/webpacker/css/admin/shared/forms.scss index 84d2c2bd9e..7e4dc7c3bb 100644 --- a/app/webpacker/css/admin/shared/forms.scss +++ b/app/webpacker/css/admin/shared/forms.scss @@ -184,6 +184,10 @@ fieldset { &:hover { border-color: $color-1; } + + &:first-of-type { + margin-right: 1.25em; + } } span.or { From 6c6e5ca3166709f710ea89d650e9e29a930d7f29 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 28 Jan 2022 11:38:23 +0000 Subject: [PATCH 08/51] Ensure fees are applied during checkout --- app/controllers/split_checkout_controller.rb | 1 + .../split_checkout_controller_spec.rb | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/app/controllers/split_checkout_controller.rb b/app/controllers/split_checkout_controller.rb index 63ca43a42b..ac3eefad89 100644 --- a/app/controllers/split_checkout_controller.rb +++ b/app/controllers/split_checkout_controller.rb @@ -71,6 +71,7 @@ class SplitCheckoutController < ::BaseController @order.select_shipping_method(params[:shipping_method_id]) @order.update(order_params) + @order.updater.update_totals_and_states validate_current_step! diff --git a/spec/controllers/split_checkout_controller_spec.rb b/spec/controllers/split_checkout_controller_spec.rb index 9d73967e63..e70836fc02 100644 --- a/spec/controllers/split_checkout_controller_spec.rb +++ b/spec/controllers/split_checkout_controller_spec.rb @@ -142,6 +142,34 @@ describe SplitCheckoutController, type: :controller do end end + context "with payment fees" do + let(:payment_method_with_fee) do + create(:payment_method, :flat_rate, amount: "1.23", distributors: [distributor]) + end + let(:checkout_params) do + { + order: { + payments_attributes: [ + { payment_method_id: payment_method_with_fee.id } + ] + } + } + end + + it "applies the fee and updates the order total" do + put :update, params: params + + expect(response).to redirect_to checkout_step_path(:summary) + + order.reload + + expect(order.state).to eq "confirmation" + expect(order.payments.first.adjustment.amount).to eq 1.23 + expect(order.adjustment_total).to eq 1.23 + expect(order.total).to eq order.item_total + order.adjustment_total + end + end + context "with a saved credit card" do let!(:saved_card) { create(:stored_credit_card, user: user) } let(:checkout_params) do From 798af2dafc22d046e132673c7a6e741d96662ecd Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 21:41:13 +0000 Subject: [PATCH 09/51] Drop unused #create action --- .../spree/user_passwords_controller.rb | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/app/controllers/spree/user_passwords_controller.rb b/app/controllers/spree/user_passwords_controller.rb index 2b5b0a93b6..6b1572757c 100644 --- a/app/controllers/spree/user_passwords_controller.rb +++ b/app/controllers/spree/user_passwords_controller.rb @@ -16,24 +16,6 @@ module Spree include I18nHelper before_action :set_locale - # Overridden due to bug in Devise. - # respond_with resource, :location => new_session_path(resource_name) - # is generating bad url /session/new.user - # - # overridden to: - # respond_with resource, :location => spree.login_path - # - def create - self.resource = resource_class.send_reset_password_instructions(raw_params[resource_name]) - - if resource.errors.empty? - set_flash_message(:notice, :send_instructions) if is_navigational_format? - respond_with resource, location: spree.login_path - else - respond_with_navigational(resource) { render :new } - end - end - # Devise::PasswordsController allows for blank passwords. # Silly Devise::PasswordsController! # Fixes spree/spree#2190. From 6561a7246bd90853fe1a5578c91a424e5e0c0f53 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 16 Jan 2022 12:44:30 +0000 Subject: [PATCH 10/51] Delete unused partial --- app/views/shared/_login.html.haml | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 app/views/shared/_login.html.haml diff --git a/app/views/shared/_login.html.haml b/app/views/shared/_login.html.haml deleted file mode 100644 index 5c4d579944..0000000000 --- a/app/views/shared/_login.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -- if spree_current_user.nil? - %li#login-link= link_to t(:label_login), "#login", id: "sidebarLoginButton", class: "sidebar-button" - %li#login-name.hide - %li.divider - %li#sign-up-link= link_to t(:label_signup), "#signup", id: "sidebarSignUpButton", class: "sidebar-button" - %li#sign-out-link.hide= link_to "Sign Out", "/logout" -- else - %li#login-link.hide= link_to t(:label_login), "#sidebar", id: "sidebarLoginButton", class: "sidebar-button" - %li#login-name= link_to "#{spree_current_user.email}", "#" - %li.divider - %li#sign-up-link.hide= link_to t(:label_signup), "#" - %li#sign-out-link= link_to t(:label_logout), "/logout" From 04da148af02ee6dbbcee6e4fb6e0710a76a00a26 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 16 Jan 2022 13:19:39 +0000 Subject: [PATCH 11/51] Decouple login modal opening from Angular --- app/views/checkout/_authentication.html.haml | 10 +++++----- app/views/shared/menu/_signed_out.html.haml | 4 ++-- app/webpacker/controllers/login_modal_controller.js | 8 ++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 app/webpacker/controllers/login_modal_controller.js diff --git a/app/views/checkout/_authentication.html.haml b/app/views/checkout/_authentication.html.haml index d157901059..d3362107a8 100644 --- a/app/views/checkout/_authentication.html.haml +++ b/app/views/checkout/_authentication.html.haml @@ -3,17 +3,17 @@ .small-12.columns.text-center %h3.pad-top = t :checkout_headline - .row.pad-top - -if guest_checkout_allowed? + .row.pad-top{ "data-controller": "login-modal" } + - if guest_checkout_allowed? .small-5.columns.text-center - %button.primary.expand{"auth" => "login"} + %button.primary.expand{ "data-action": "click->login-modal#call" } = t :label_login .small-2.columns.text-center %p.pad-top= "#{t :action_or}" .small-5.columns.text-center %button.neutral-btn.dark.expand{"ng-click" => "enabled = true"} = t :checkout_as_guest - -else + - else .small-6.columns.small-centered - %button.primary.expand{"auth" => "login"} + %button.primary.expand{ "data-action": "click->login-modal#call" } = t :label_login diff --git a/app/views/shared/menu/_signed_out.html.haml b/app/views/shared/menu/_signed_out.html.haml index a5d527632a..570c707b31 100644 --- a/app/views/shared/menu/_signed_out.html.haml +++ b/app/views/shared/menu/_signed_out.html.haml @@ -1,5 +1,5 @@ -%li#login-link - %a{"auth" => "login"} +%li#login-link{ "data-controller": "login-modal" } + %a{"auth": "login", "data-action": "click->login-modal#call" } %img{ src: image_pack_path("menu/icn-login.svg") } %span = t 'label_login' diff --git a/app/webpacker/controllers/login_modal_controller.js b/app/webpacker/controllers/login_modal_controller.js new file mode 100644 index 0000000000..34ca4b92ab --- /dev/null +++ b/app/webpacker/controllers/login_modal_controller.js @@ -0,0 +1,8 @@ +import { Controller } from "stimulus" + +export default class extends Controller { + call(event) { + event.preventDefault() + window.dispatchEvent(new Event("login:modal:open")) + } +} From 8a18a4de6658bcc62f75bd12bff78ae0a47b8c30 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 18:30:44 +0000 Subject: [PATCH 12/51] Clear up redirecting logic and path building --- app/controllers/application_controller.rb | 20 +++++++-------- .../payment_gateways/stripe_controller.rb | 2 +- app/controllers/payments_controller.rb | 6 +++-- app/controllers/registration_controller.rb | 2 +- app/controllers/spree/orders_controller.rb | 4 ++- .../spree/user_sessions_controller.rb | 5 ---- .../user_confirmations_controller.rb | 25 +++++++++++-------- app/controllers/user_passwords_controller.rb | 6 ----- lib/spree/core/controller_helpers/auth.rb | 8 +++--- .../registration_controller_spec.rb | 2 +- .../spree/admin/base_controller_spec.rb | 2 +- .../spree/orders_controller_spec.rb | 2 +- .../user_confirmations_controller_spec.rb | 14 ++++++----- .../user_passwords_controller_spec.rb | 2 +- spec/system/consumer/authentication_spec.rb | 4 +-- 15 files changed, 51 insertions(+), 53 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0b8b45d19f..b28bdad774 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -38,6 +38,7 @@ class ApplicationController < ActionController::Base include Spree::Core::ControllerHelpers::Common before_action :set_cache_headers # prevent cart emptying via cache when using back button #1213 + before_action :set_after_login_url include RawParams include EnterprisesHelper @@ -61,15 +62,10 @@ class ApplicationController < ActionController::Base end def set_checkout_redirect - referer_path = OpenFoodNetwork::RefererParser.path(request.referer) - if referer_path - is_checkout_path_the_referer = [main_app.checkout_path].include?(referer_path) - session["spree_user_return_to"] = if is_checkout_path_the_referer - referer_path - else - main_app.root_path - end - end + return unless (referer_path = URI(request.referer.to_s).path) + return unless referer_path == main_app.checkout_path + + session["spree_user_return_to"] = referer_path end def shopfront_session @@ -102,6 +98,10 @@ class ApplicationController < ActionController::Base private + def set_after_login_url + store_location_for(:spree_user, params[:after_login]) if params[:after_login] + end + def shopfront_redirect session[:shopfront_redirect] end @@ -111,7 +111,7 @@ class ApplicationController < ActionController::Base end def require_distributor_chosen - unless @distributor = current_distributor + unless (@distributor = current_distributor) redirect_to main_app.root_path false end diff --git a/app/controllers/payment_gateways/stripe_controller.rb b/app/controllers/payment_gateways/stripe_controller.rb index fc9cb1dd93..e81eb9aa9e 100644 --- a/app/controllers/payment_gateways/stripe_controller.rb +++ b/app/controllers/payment_gateways/stripe_controller.rb @@ -46,7 +46,7 @@ module PaymentGateways return if session[:access_token] || params[:order_token] || spree_current_user flash[:error] = I18n.t("spree.orders.edit.login_to_view_order") - redirect_to root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}") + redirect_to root_path(anchor: "login", after_login: request.original_fullpath) end def validate_stock diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb index e232574b63..92e39715a8 100644 --- a/app/controllers/payments_controller.rb +++ b/app/controllers/payments_controller.rb @@ -9,7 +9,7 @@ class PaymentsController < BaseController @payment = Spree::Payment.find(params[:id]) authorize! :show, @payment.order - if url = @payment.cvv_response_message + if (url = @payment.cvv_response_message) redirect_to url else redirect_to order_url(@payment.order) @@ -21,7 +21,9 @@ class PaymentsController < BaseController def require_logged_in return if session[:access_token] || spree_current_user + store_location_for :spree_user, request.original_fullpath + flash[:error] = I18n.t("spree.orders.edit.login_to_view_order") - redirect_to main_app.root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}") + redirect_to main_app.root_path(anchor: "/login", after_login: request.original_fullpath) end end diff --git a/app/controllers/registration_controller.rb b/app/controllers/registration_controller.rb index 29b523289e..7352786e74 100644 --- a/app/controllers/registration_controller.rb +++ b/app/controllers/registration_controller.rb @@ -19,7 +19,7 @@ class RegistrationController < BaseController def check_user if spree_current_user.nil? - redirect_to registration_auth_path(anchor: "signup?after_login=#{request.env['PATH_INFO']}") + redirect_to registration_auth_path(anchor: "/signup", after_login: request.original_fullpath) elsif !spree_current_user.can_own_more_enterprises? render :limit_reached end diff --git a/app/controllers/spree/orders_controller.rb b/app/controllers/spree/orders_controller.rb index 1e522e0eca..f467dbd196 100644 --- a/app/controllers/spree/orders_controller.rb +++ b/app/controllers/spree/orders_controller.rb @@ -139,8 +139,10 @@ module Spree def require_order_authentication return if session[:access_token] || params[:order_token] || spree_current_user + store_location_for :spree_user, request.original_fullpath + flash[:error] = I18n.t("spree.orders.edit.login_to_view_order") - redirect_to main_app.root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}") + redirect_to main_app.root_path(anchor: "/login", after_login: request.original_fullpath) end def order_to_update diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb index 6de8e67b30..5b82788528 100644 --- a/app/controllers/spree/user_sessions_controller.rb +++ b/app/controllers/spree/user_sessions_controller.rb @@ -57,11 +57,6 @@ module Spree Spree.t(:login) end - def redirect_back_or_default(default) - redirect_to(session["spree_user_return_to"] || default) - session["spree_user_return_to"] = nil - end - def ensure_valid_locale_persisted # When creating a new user session we have to wait until after a successful # login to be able to persist a selected locale on the current user diff --git a/app/controllers/user_confirmations_controller.rb b/app/controllers/user_confirmations_controller.rb index b024504345..0fbe3e1af6 100644 --- a/app/controllers/user_confirmations_controller.rb +++ b/app/controllers/user_confirmations_controller.rb @@ -39,22 +39,25 @@ class UserConfirmationsController < DeviseController end def after_confirmation_path_for(resource) - result = - if resource.errors.empty? - 'confirmed' - else - 'not_confirmed' - end + result = resource.errors.empty? ? "confirmed" : "not_confirmed" if result == 'confirmed' && resource.reset_password_token.present? - raw_reset_password_token = resource.regenerate_reset_password_token return spree.edit_spree_user_password_path( - reset_password_token: raw_reset_password_token + reset_password_token: resource.regenerate_reset_password_token ) end - path = (session[:confirmation_return_url] || login_path).to_s - path += path.include?('?') ? '&' : '?' - path + "validation=#{result}" + path = session[:confirmation_return_url] || root_path(anchor: "/login") + append_query_to_url(path, "validation", result) + end + + private + + def append_query_to_url(url, key, value) + uri = URI.parse(url.to_s) + query = URI.decode_www_form(uri.query || "") << [key, value] + uri.query = URI.encode_www_form(query) + + uri.to_s end end diff --git a/app/controllers/user_passwords_controller.rb b/app/controllers/user_passwords_controller.rb index c33a1716f3..a94800445d 100644 --- a/app/controllers/user_passwords_controller.rb +++ b/app/controllers/user_passwords_controller.rb @@ -3,8 +3,6 @@ class UserPasswordsController < Spree::UserPasswordsController layout 'darkswarm' - before_action :set_admin_redirect, only: :edit - def create render_unconfirmed_response && return if user_unconfirmed? @@ -27,10 +25,6 @@ class UserPasswordsController < Spree::UserPasswordsController private - def set_admin_redirect - session["spree_user_return_to"] = params[:return_to] if params[:return_to] - end - def render_unconfirmed_response render json: { error: t('email_unconfirmed') }, status: :unauthorized end diff --git a/lib/spree/core/controller_helpers/auth.rb b/lib/spree/core/controller_helpers/auth.rb index 85c4e91095..98b1aa70b5 100644 --- a/lib/spree/core/controller_helpers/auth.rb +++ b/lib/spree/core/controller_helpers/auth.rb @@ -29,7 +29,8 @@ module Spree redirect_to '/unauthorized' else store_location - redirect_to main_app.root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}") + + redirect_to main_app.root_path(anchor: "/login", after_login: request.original_fullpath) end end @@ -49,9 +50,8 @@ module Spree session['spree_user_return_to'] = request.fullpath.gsub('//', '/') end - def redirect_back_or_default(default) - redirect_to(session["spree_user_return_to"] || default) - session["spree_user_return_to"] = nil + def return_url_or_default(default) + session.delete("spree_user_return_to") || default end # Need to generate an API key for a user due to some actions potentially diff --git a/spec/controllers/registration_controller_spec.rb b/spec/controllers/registration_controller_spec.rb index 29af1c0e91..363b77704d 100644 --- a/spec/controllers/registration_controller_spec.rb +++ b/spec/controllers/registration_controller_spec.rb @@ -6,7 +6,7 @@ describe RegistrationController, type: :controller do describe "redirecting when user not logged in" do it "index" do get :index - expect(response).to redirect_to registration_auth_path(anchor: "signup?after_login=/register") + expect(response).to redirect_to registration_auth_path(anchor: "/signup", after_login: "/register") end end diff --git a/spec/controllers/spree/admin/base_controller_spec.rb b/spec/controllers/spree/admin/base_controller_spec.rb index 887118b665..7e53deb55e 100644 --- a/spec/controllers/spree/admin/base_controller_spec.rb +++ b/spec/controllers/spree/admin/base_controller_spec.rb @@ -12,7 +12,7 @@ describe Spree::Admin::BaseController, type: :controller do it "redirects to Angular login" do spree_get :index - expect(response).to redirect_to root_path(anchor: "login?after_login=/spree/admin/base") + expect(response).to redirect_to root_path(anchor: "/login", after_login: "/spree/admin/base") end describe "rendering as json ActiveModelSerializer" do diff --git a/spec/controllers/spree/orders_controller_spec.rb b/spec/controllers/spree/orders_controller_spec.rb index 91307e6d7b..ef221178c7 100644 --- a/spec/controllers/spree/orders_controller_spec.rb +++ b/spec/controllers/spree/orders_controller_spec.rb @@ -77,7 +77,7 @@ describe Spree::OrdersController, type: :controller do it "redirects to unauthorized" do get :show, params: { id: order.number } - expect(response).to redirect_to(root_path(anchor: "login?after_login=#{order_path(order)}")) + expect(response).to redirect_to(root_path(anchor: "/login", after_login: order_path(order))) expect(flash[:error]).to eq("Please log in to view your order.") end end diff --git a/spec/controllers/user_confirmations_controller_spec.rb b/spec/controllers/user_confirmations_controller_spec.rb index fd78ef500e..fd32ca2a37 100644 --- a/spec/controllers/user_confirmations_controller_spec.rb +++ b/spec/controllers/user_confirmations_controller_spec.rb @@ -22,7 +22,7 @@ describe UserConfirmationsController, type: :controller do end it "redirects the user to login" do - expect(response).to redirect_to login_path(validation: 'not_confirmed') + expect(response).to redirect_to root_path(anchor: "/login", validation: "not_confirmed") end end @@ -34,19 +34,21 @@ describe UserConfirmationsController, type: :controller do it "redirects the user to #/login by default" do spree_get :show, confirmation_token: unconfirmed_user.confirmation_token - expect(response).to redirect_to login_path(validation: 'confirmed') + expect(response).to redirect_to root_path(anchor: "/login", validation: "confirmed") end it "redirects to previous url, if present" do - session[:confirmation_return_url] = producers_path + '#/login' + session[:confirmation_return_url] = producers_path(anchor: "#/login") spree_get :show, confirmation_token: unconfirmed_user.confirmation_token - expect(response).to redirect_to producers_path + '#/login?validation=confirmed' + expect(response).to redirect_to producers_path(anchor: "#/login", validation: "confirmed") end it "redirects to previous url on /register path" do - session[:confirmation_return_url] = registration_path + '#/signup?after_login=%2Fregister' + session[:confirmation_return_url] = registration_path(anchor: "#/signup", after_login: "/register") spree_get :show, confirmation_token: unconfirmed_user.confirmation_token - expect(response).to redirect_to registration_path + '#/signup?after_login=%2Fregister&validation=confirmed' + expect(response). + to redirect_to registration_path(anchor: "#/signup", + after_login: "/register", validation: "confirmed") end it "redirects to set password page, if user needs to reset their password" do diff --git a/spec/controllers/user_passwords_controller_spec.rb b/spec/controllers/user_passwords_controller_spec.rb index c90a2a3917..3920aef980 100644 --- a/spec/controllers/user_passwords_controller_spec.rb +++ b/spec/controllers/user_passwords_controller_spec.rb @@ -28,7 +28,7 @@ describe UserPasswordsController, type: :controller do describe "edit" do context "when given a redirect" do it "stores the redirect path in 'spree_user_return_to'" do - spree_post :edit, reset_password_token: "token", return_to: "/return_path" + spree_post :edit, reset_password_token: "token", after_login: "/return_path" expect(session["spree_user_return_to"]).to eq "/return_path" end end diff --git a/spec/system/consumer/authentication_spec.rb b/spec/system/consumer/authentication_spec.rb index b1137a3bf4..6844dd19e7 100644 --- a/spec/system/consumer/authentication_spec.rb +++ b/spec/system/consumer/authentication_spec.rb @@ -12,7 +12,7 @@ describe "Authentication", js: true do describe "With redirects" do it "logging in with a redirect set" do - visit groups_path(anchor: "login?after_login=#{producers_path}") + visit groups_path(anchor: "/login", after_login: producers_path) fill_in "Email", with: user.email fill_in "Password", with: user.password click_login_button @@ -161,7 +161,7 @@ describe "Authentication", js: true do describe "after following email confirmation link" do it "shows confirmed message in modal" do - visit '/#/login?validation=confirmed' + visit root_path(anchor: "/login", validation: "confirmed") expect(page).to have_login_modal expect(page).to have_content I18n.t('devise.confirmations.confirmed') end From 0577b46f3f5d5cd9521611c97b51b0b6fa5c26f3 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 18:39:15 +0000 Subject: [PATCH 13/51] Create simpler non-Angular login modal --- .../darkswarm/directives/auth.js.coffee | 11 ---- app/views/layouts/_alert.html.haml | 5 ++ app/views/layouts/_forgot_tab.html.haml | 12 ++++ app/views/layouts/_login_modal.html.haml | 24 +++++++ app/views/layouts/_login_tab.html.haml | 24 +++++++ app/views/layouts/_signup_tab.html.haml | 25 +++++++ app/views/layouts/darkswarm.html.haml | 2 + .../controllers/login_modal_controller.js | 66 +++++++++++++++++++ app/webpacker/controllers/tabs_controller.js | 27 ++++++++ .../css/darkswarm/pages/login_modal.scss | 15 +++++ spec/support/request/ui_component_helper.rb | 6 +- 11 files changed, 203 insertions(+), 14 deletions(-) delete mode 100644 app/assets/javascripts/darkswarm/directives/auth.js.coffee create mode 100644 app/views/layouts/_alert.html.haml create mode 100644 app/views/layouts/_forgot_tab.html.haml create mode 100644 app/views/layouts/_login_modal.html.haml create mode 100644 app/views/layouts/_login_tab.html.haml create mode 100644 app/views/layouts/_signup_tab.html.haml create mode 100644 app/webpacker/controllers/tabs_controller.js diff --git a/app/assets/javascripts/darkswarm/directives/auth.js.coffee b/app/assets/javascripts/darkswarm/directives/auth.js.coffee deleted file mode 100644 index aaa8be0def..0000000000 --- a/app/assets/javascripts/darkswarm/directives/auth.js.coffee +++ /dev/null @@ -1,11 +0,0 @@ -angular.module('Darkswarm').directive 'auth', (AuthenticationService) -> - restrict: 'A' - link: (scope, elem, attrs) -> - elem.bind "click", -> - AuthenticationService.open '/' + attrs.auth - - window.addEventListener "login:modal:open", -> - AuthenticationService.open '/login' - - scope.$on "$destroy", -> - window.removeEventListener "login:modal:open" diff --git a/app/views/layouts/_alert.html.haml b/app/views/layouts/_alert.html.haml new file mode 100644 index 0000000000..539031e1fd --- /dev/null +++ b/app/views/layouts/_alert.html.haml @@ -0,0 +1,5 @@ +.alert-box{ class: "#{type}" } + = message + - if local_assigns[:unconfirmed] + %a{ "data-action": "login-modal#resend_confirmation" } + = t('devise.confirmations.resend_confirmation_email') \ No newline at end of file diff --git a/app/views/layouts/_forgot_tab.html.haml b/app/views/layouts/_forgot_tab.html.haml new file mode 100644 index 0000000000..47ad3c03d2 --- /dev/null +++ b/app/views/layouts/_forgot_tab.html.haml @@ -0,0 +1,12 @@ +#forgot-tab + = form_with url: spree_user_password_path, scope: :spree_user, data: { remote: "true" } do |form| + .row + .large-12.columns#forgot-feedback + + .row + .large-12.columns + = form.label :email, t(:signup_email) + = form.email_field :email, { tabindex: 1, inputmode: "email", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + .row + .large-12.columns + = form.submit t(:reset_password), { class: "button primary", tabindex: 2 } diff --git a/app/views/layouts/_login_modal.html.haml b/app/views/layouts/_login_modal.html.haml new file mode 100644 index 0000000000..b5fda75568 --- /dev/null +++ b/app/views/layouts/_login_modal.html.haml @@ -0,0 +1,24 @@ +%div{"data-controller": "login-modal" } + .reveal-modal-bg.fade{ "data-login-modal-target": "background", "data-action": "click->login-modal#close" } + + .reveal-modal.fade.login-modal.medium{ "data-login-modal-target": "modal" } + %div{ "data-controller": "tabs" } + %dl.tabs + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_login) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_signup) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:forgot_password) + + .tabs-content + .content.active + %div{ data: { "tabs-target": "content" } } + = render "layouts/login_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/signup_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/forgot_tab" + + %a.close-reveal-modal{ "data-action": "click->login-modal#close" } + %i.ofn-i_009-close diff --git a/app/views/layouts/_login_tab.html.haml b/app/views/layouts/_login_tab.html.haml new file mode 100644 index 0000000000..06a09b1d85 --- /dev/null +++ b/app/views/layouts/_login_tab.html.haml @@ -0,0 +1,24 @@ +#login-content + = form_with url: spree.spree_user_session_path, scope: :spree_user, data: { remote: "true" } do |form| + .row + .large-12.columns#login-feedback + - confirmation_result = request.query_parameters[:validation] + - if confirmation_result.in? ["confirmed", "not_confirmed"] + .alert-box{ class: "#{confirmation_result == "confirmed" ? "success" : "alert" }" } + = t("devise.confirmations.#{confirmation_result}") + + .row + .large-12.columns + = form.label :email, t(:email) + = form.email_field :email, { tabindex: 1, inputmode: "email", autocomplete: "off", "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + .row + .large-12.columns + = form.label :password, t(:password) + = form.password_field :password, { tabindex: 2, inputmode: "password" } + .row + .large-12.columns + = form.check_box :remember_me, { tabindex: 3 } + = form.label :remember_me, t(:remember_me) + .row + .large-12.columns + = form.submit t(:label_login), { class: "button primary", tabindex: 4 } diff --git a/app/views/layouts/_signup_tab.html.haml b/app/views/layouts/_signup_tab.html.haml new file mode 100644 index 0000000000..5d2af646e5 --- /dev/null +++ b/app/views/layouts/_signup_tab.html.haml @@ -0,0 +1,25 @@ +- signup_form_user = Spree::User.new if local_assigns[:signup_form_user].nil? + +#signup-tab + = form_with model: signup_form_user, url: spree.account_path, scope: :user, data: { remote: "true" } do |form| + .row + .large-12.columns#signup-feedback + + .row + .large-12.columns + = form.label :email, t(:signup_email) + = form.email_field :email, { tabindex: 1, "data-login-modal-target": "email", "data-action": "input->login-modal#emailOnInput" } + = form.error_message_on :email + .row + .large-12.columns + = form.label :password, t(:choose_password) + = form.password_field :password, { tabindex: 2, autocomplete: "off" } + = form.error_message_on :password + .row + .large-12.columns + = form.label :password_confirmation, t(:confirm_password) + = form.password_field :password_confirmation, { tabindex: 3, autocomplete: "off" } + = form.error_message_on :password_confirmation + .row + .large-12.columns + = form.submit t(:action_signup), { class: "button primary", tabindex: 4 } diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index fedbcdddfc..23a0aeda5e 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -57,3 +57,5 @@ = yield :injection_data = render "layouts/matomo_tag" + + = render "layouts/login_modal" diff --git a/app/webpacker/controllers/login_modal_controller.js b/app/webpacker/controllers/login_modal_controller.js index 34ca4b92ab..ab0643e48d 100644 --- a/app/webpacker/controllers/login_modal_controller.js +++ b/app/webpacker/controllers/login_modal_controller.js @@ -1,8 +1,74 @@ import { Controller } from "stimulus" +import CableReady from "cable_ready" export default class extends Controller { + static targets = ["background", "modal", "email"] + static values = { email: String } + + connect() { + if(this.hasModalTarget) { + window.addEventListener("login:modal:open", this.open) + + if(location.hash.substr(1).includes("/login")) { + this.open() + } + } + } + call(event) { event.preventDefault() window.dispatchEvent(new Event("login:modal:open")) } + + emailOnInput(event) { + this.emailValue = event.currentTarget.value + this.emailTargets.forEach((element) => { + element.value = this.emailValue + }) + } + + open = () => { + if(!location.hash.substr(1).includes("/login")) { + history.pushState({}, "", "#/login") + } + + this.backgroundTarget.style.display = "block" + this.modalTarget.style.display = "block" + + document.querySelector("body").classList.add("modal-open") + + setTimeout(() => { + this.modalTarget.classList.add("in") + this.backgroundTarget.classList.add("in") + }) + } + + close() { + history.pushState({}, "", window.location.pathname + window.location.search) + + this.modalTarget.classList.remove("in") + this.backgroundTarget.classList.remove("in") + + document.querySelector("body").classList.remove("modal-open") + + setTimeout(() => { + this.backgroundTarget.style.display = "none" + this.modalTarget.style.display = "none" + }, 200) + } + + resend_confirmation() { + fetch("/user/spree_user/confirmation", { + method: "POST", + body: JSON.stringify({ + spree_user: { email: this.emailValue } + }) + }).then(data => data.json()).then(CableReady.perform) + } + + disconnect() { + if(this.hasModalTarget) { + window.removeEventListener("login:modal:open", this.open) + } + } } diff --git a/app/webpacker/controllers/tabs_controller.js b/app/webpacker/controllers/tabs_controller.js new file mode 100644 index 0000000000..46f6935c57 --- /dev/null +++ b/app/webpacker/controllers/tabs_controller.js @@ -0,0 +1,27 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + static targets = ["tab", "content"] + + connect() { + this.setCurrentTab() + } + + select(event) { + this.setCurrentTab(this.tabTargets.indexOf(event.currentTarget)) + } + + setCurrentTab(tabIndex = 0) { + this.contentTargets.forEach((element, index) => { + element.hidden = index !== tabIndex + }) + + this.tabTargets.forEach((element, index) => { + if(index === tabIndex) { + element.classList.add("active") + } else { + element.classList.remove("active") + } + }) + } +} diff --git a/app/webpacker/css/darkswarm/pages/login_modal.scss b/app/webpacker/css/darkswarm/pages/login_modal.scss index 98ee4730c7..b72763eb13 100644 --- a/app/webpacker/css/darkswarm/pages/login_modal.scss +++ b/app/webpacker/css/darkswarm/pages/login_modal.scss @@ -5,6 +5,21 @@ .login-modal { background: $modal-background-color; + visibility: visible; + position: fixed; + top: 3em; + + a.active { + background-color: white; + + &:hover { + background-color: white; + } + } + + span.formError { + @extend .error; + } .tabs-content { background: $modal-content-background-color; diff --git a/spec/support/request/ui_component_helper.rb b/spec/support/request/ui_component_helper.rb index b48cfe16e0..f6bf0e41b2 100644 --- a/spec/support/request/ui_component_helper.rb +++ b/spec/support/request/ui_component_helper.rb @@ -111,8 +111,8 @@ module UIComponentHelper end def fill_in_using_keyboard - page.find('#email').send_keys(user.email, :tab, user.password, :tab, :space) - expect(page.find('#remember_me')).to be_checked - page.find('#remember_me').send_keys(:tab, :enter) + page.find('#spree_user_email').send_keys(user.email, :tab, user.password, :tab, :space) + expect(page.find('#spree_user_remember_me')).to be_checked + page.find('#spree_user_remember_me').send_keys(:tab, :enter) end end From 89e692c6c86be5204948c54d884af6dd9056cf74 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 19:32:13 +0000 Subject: [PATCH 14/51] Switch to CableCar for login responses --- .../spree/user_sessions_controller.rb | 32 +++++++------------ app/controllers/spree/users_controller.rb | 12 +++++-- .../user_confirmations_controller.rb | 7 ++++ app/controllers/user_passwords_controller.rb | 28 +++++++++------- 4 files changed, 45 insertions(+), 34 deletions(-) diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb index 5b82788528..6bd55bef6e 100644 --- a/app/controllers/spree/user_sessions_controller.rb +++ b/app/controllers/spree/user_sessions_controller.rb @@ -6,11 +6,12 @@ require "spree/core/controller_helpers/order" module Spree class UserSessionsController < Devise::SessionsController - helper 'spree/base' - include Spree::Core::ControllerHelpers::Auth include Spree::Core::ControllerHelpers::Common include Spree::Core::ControllerHelpers::Order + include CablecarResponses + + helper 'spree/base' before_action :set_checkout_redirect, only: :create after_action :ensure_valid_locale_persisted, only: :create @@ -19,25 +20,16 @@ module Spree authenticate_spree_user! if spree_user_signed_in? - respond_to do |format| - format.html { - flash[:success] = t('devise.success.logged_in_succesfully') - redirect_back_or_default(after_sign_in_path_for(spree_current_user)) - } - format.js { - render json: { email: spree_current_user.login }, status: :ok - } - end + flash[:success] = t('devise.success.logged_in_succesfully') + + render operations: cable_car.redirect_to( + url: URI(return_url_or_default(after_sign_in_path_for(spree_current_user))) + ) else - respond_to do |format| - format.html { - flash.now[:error] = t('devise.failure.invalid') - render :new - } - format.js { - render json: { message: t('devise.failure.invalid') }, status: :unauthorized - } - end + render status: :unauthorized, operations: cable_car.inner_html( + "#login-feedback", + partial("layouts/alert", locals: { type: "alert", message: t('devise.failure.invalid') }) + ) end end diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb index 0b4ded410a..70189a3815 100644 --- a/app/controllers/spree/users_controller.rb +++ b/app/controllers/spree/users_controller.rb @@ -4,6 +4,7 @@ module Spree class UsersController < ::BaseController include Spree::Core::ControllerHelpers include I18nHelper + include CablecarResponses layout 'darkswarm' @@ -32,10 +33,17 @@ module Spree def create @user = Spree::User.new(user_params) + if @user.save - redirect_back_or_default(main_app.root_url) + render operations: cable_car.inner_html( + "#signup-feedback", + partial("layouts/alert", locals: { type: "success", message: t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') }) + ) else - render :new + render status: :unprocessable_entity, operations: cable_car.morph( + "#signup-tab", + partial("layouts/signup_tab", locals: { signup_form_user: @user }) + ) end end diff --git a/app/controllers/user_confirmations_controller.rb b/app/controllers/user_confirmations_controller.rb index 0fbe3e1af6..5575c4eee7 100644 --- a/app/controllers/user_confirmations_controller.rb +++ b/app/controllers/user_confirmations_controller.rb @@ -3,6 +3,7 @@ class UserConfirmationsController < DeviseController # Needed for access to current_ability, so we can authorize! actions include Spree::Core::ControllerHelpers::Auth + include CablecarResponses # GET /resource/confirmation/new def new @@ -20,6 +21,12 @@ class UserConfirmationsController < DeviseController else set_flash_message(:error, :confirmation_not_sent) end + else + render operations: cable_car.inner_html( + "#forgot-feedback", + partial("layouts/alert", locals: { type: "success", message: t("devise.confirmations.send_instructions") }) + ) + return end respond_with_navigational(resource){ redirect_to login_path } diff --git a/app/controllers/user_passwords_controller.rb b/app/controllers/user_passwords_controller.rb index a94800445d..d87b293478 100644 --- a/app/controllers/user_passwords_controller.rb +++ b/app/controllers/user_passwords_controller.rb @@ -1,32 +1,36 @@ # frozen_string_literal: true class UserPasswordsController < Spree::UserPasswordsController + include CablecarResponses + layout 'darkswarm' def create - render_unconfirmed_response && return if user_unconfirmed? + return render_unconfirmed_response if user_unconfirmed? self.resource = resource_class.send_reset_password_instructions(raw_params[resource_name]) if resource.errors.empty? - set_flash_message(:success, :send_instructions) if is_navigational_format? - respond_with resource, location: main_app.login_path + render operations: cable_car.inner_html( + "#forgot-feedback", + partial("layouts/alert", locals: { type: "success", message: t(:password_reset_sent) }) + ) else - respond_to do |format| - format.html do - respond_with_navigational(resource) { render :new } - end - format.js do - render json: { error: t('email_not_found') }, status: :not_found - end - end + render status: :not_found, operations: cable_car.inner_html( + "#forgot-feedback", + partial("layouts/alert", locals: { type: "alert", message: t(:email_not_found) }) + ) end end private def render_unconfirmed_response - render json: { error: t('email_unconfirmed') }, status: :unauthorized + render status: :unauthorized, operations: cable_car.inner_html( + "#forgot-feedback", + partial("layouts/alert", + locals: { type: "alert", message: t(:email_unconfirmed), unconfirmed: true }) + ) end def user_unconfirmed? From 50389a864a03ac3b4851fdfdfd2b5cfe2876e33c Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 19:28:55 +0000 Subject: [PATCH 15/51] Improve dynamic Angular Bootstrapping --- app/assets/javascripts/darkswarm/all.js.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/darkswarm/all.js.coffee b/app/assets/javascripts/darkswarm/all.js.coffee index 700ca28181..dfaf65a185 100644 --- a/app/assets/javascripts/darkswarm/all.js.coffee +++ b/app/assets/javascripts/darkswarm/all.js.coffee @@ -56,7 +56,8 @@ #= require_tree . document.addEventListener "turbo:load", -> - window.injector = angular.bootstrap document.body, ["Darkswarm"] + try + window.injector = angular.bootstrap document.body, ["Darkswarm"] true document.addEventListener "turbo:before-render", -> From 6116fd88817975fb3152d2297182727bbb7363cd Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 19:29:28 +0000 Subject: [PATCH 16/51] Improve inaccurate specs --- spec/support/request/authentication_helper.rb | 4 ++-- spec/system/consumer/authentication_spec.rb | 23 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/spec/support/request/authentication_helper.rb b/spec/support/request/authentication_helper.rb index 147e7ff631..813121f49a 100644 --- a/spec/support/request/authentication_helper.rb +++ b/spec/support/request/authentication_helper.rb @@ -24,8 +24,8 @@ module AuthenticationHelper end def fill_in_and_submit_login_form(user) - fill_in "email", with: user.email - fill_in "password", with: user.password + fill_in "Email", with: user.email + fill_in "Password", with: user.password click_button "Login" end diff --git a/spec/system/consumer/authentication_spec.rb b/spec/system/consumer/authentication_spec.rb index 6844dd19e7..dc2a8930ba 100644 --- a/spec/system/consumer/authentication_spec.rb +++ b/spec/system/consumer/authentication_spec.rb @@ -61,38 +61,35 @@ describe "Authentication", js: true do end it "Failing to sign up because password is too short" do - fill_in "Email", with: "test@foo.com" + fill_in "Your email", with: "test@foo.com" fill_in "Choose a password", with: "short" click_signup_button expect(page).to have_content "too short" end it "Failing to sign up because email is already registered" do - fill_in "Email", with: user.email + fill_in "Your email", with: user.email fill_in "Choose a password", with: "foobarino" click_signup_button expect(page).to have_content "There's already an account for this email." end it "Failing to sign up because password confirmation doesn't match or is blank" do - fill_in "Email", with: user.email + fill_in "Your email", with: user.email fill_in "Choose a password", with: "ForgotToRetype" click_signup_button expect(page).to have_content "doesn't match" end it "Signing up successfully" do - performing_deliveries do - setup_email - fill_in "Email", with: "test@foo.com" - fill_in "Choose a password", with: "test12345" - fill_in "Confirm password", with: "test12345" + fill_in "Your email", with: "test@foo.com" + fill_in "Choose a password", with: "test12345" + fill_in "Confirm password", with: "test12345" - expect do - click_signup_button - expect(page).to have_content I18n.t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') - end.to enqueue_job ActionMailer::MailDeliveryJob - end + expect do + click_signup_button + expect(page).to have_content I18n.t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') + end.to enqueue_job ActionMailer::MailDeliveryJob end end From a522e597e1794e5c5d8d15b727b2dd189f4a410e Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 12:53:08 +0000 Subject: [PATCH 17/51] Add Matamo event --- app/webpacker/controllers/login_modal_controller.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/webpacker/controllers/login_modal_controller.js b/app/webpacker/controllers/login_modal_controller.js index ab0643e48d..98dbabac1a 100644 --- a/app/webpacker/controllers/login_modal_controller.js +++ b/app/webpacker/controllers/login_modal_controller.js @@ -41,6 +41,8 @@ export default class extends Controller { this.modalTarget.classList.add("in") this.backgroundTarget.classList.add("in") }) + + window._paq?.push(['trackEvent', 'Signin/Signup', 'Login Modal View', window.location.href]) } close() { From 77d8e7da907feed3244e8527763a516d5d867861 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 14:25:00 +0000 Subject: [PATCH 18/51] Use non-Angular login modal in /registration pages --- app/views/registration/authenticate.html.haml | 29 ++++++++++++++++++- .../controllers/login_modal_controller.js | 4 +++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/app/views/registration/authenticate.html.haml b/app/views/registration/authenticate.html.haml index 2b65757a5d..4b62d71c7c 100644 --- a/app/views/registration/authenticate.html.haml +++ b/app/views/registration/authenticate.html.haml @@ -1 +1,28 @@ -%div{"ng-controller" => "AuthenticationCtrl"} \ No newline at end of file +%div{"data-controller": "login-modal" } + .reveal-modal-bg.fade.in{ "data-login-modal-target": "background", "data-action": "click->login-modal#returnHome", style: "display: block;" } + + .reveal-modal.fade.login-modal.medium.in{ "data-login-modal-target": "modal", style: "display: block;" } + .row.modal-centered + %h2= t('js.registration.welcome_to_ofn') + %h5= t('js.registration.signup_or_login') + + %div{ "data-controller": "tabs" } + %dl.tabs + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_signup) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:label_login) + %dd + %a{ data: { "tabs-target": "tab", "action": "tabs#select" } }= t(:forgot_password) + + .tabs-content + .content.active + %div{ data: { "tabs-target": "content" } } + = render "layouts/signup_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/login_tab" + %div{ data: { "tabs-target": "content" } } + = render "layouts/forgot_tab" + + %a.close-reveal-modal{ "data-action": "click->login-modal#returnHome" } + %i.ofn-i_009-close diff --git a/app/webpacker/controllers/login_modal_controller.js b/app/webpacker/controllers/login_modal_controller.js index 98dbabac1a..e29b547406 100644 --- a/app/webpacker/controllers/login_modal_controller.js +++ b/app/webpacker/controllers/login_modal_controller.js @@ -68,6 +68,10 @@ export default class extends Controller { }).then(data => data.json()).then(CableReady.perform) } + returnHome() { + window.location = "/" + } + disconnect() { if(this.hasModalTarget) { window.removeEventListener("login:modal:open", this.open) From 13a7fb79cf84cbd3441cb2f615d2c0ed968b510e Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 14:33:32 +0000 Subject: [PATCH 19/51] Move more login handling out of Angular --- .../checkout/checkout_controller.js.coffee | 15 +++++---------- .../checkout/details_controller.js.coffee | 2 +- app/controllers/spree/users_controller.rb | 14 ++++++++++++-- app/webpacker/packs/application.js | 1 + spec/controllers/spree/users_controller_spec.rb | 8 ++++---- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee index c3e07f8c68..294a0c4d10 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/checkout_controller.js.coffee @@ -1,4 +1,4 @@ -angular.module('Darkswarm').controller "CheckoutCtrl", ($scope, localStorageService, Checkout, CurrentUser, CurrentHub, AuthenticationService, SpreeUser, $http) -> +angular.module('Darkswarm').controller "CheckoutCtrl", ($scope, localStorageService, Checkout, CurrentUser, CurrentHub, $http) -> $scope.Checkout = Checkout $scope.submitted = false @@ -35,14 +35,9 @@ angular.module('Darkswarm').controller "CheckoutCtrl", ($scope, localStorageServ $scope.$broadcast 'purchaseFormInvalid', $scope.formdata $scope.ensureUserIsGuest = (callback = null) -> - $http.post("/user/registered_email", {email: $scope.order.email}).then (response)-> - if response.data.registered == true - $scope.promptLogin() - else + $http.post("/user/registered_email", {email: $scope.order.email}) + .then (response)-> + window.CableReady.perform(response.data) + .catch -> $scope.validateForm() if $scope.submitted callback() if callback - - $scope.promptLogin = -> - SpreeUser.spree_user.email = $scope.order.email - AuthenticationService.pushMessage t('devise.failure.already_registered') - AuthenticationService.open '/login' diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee index a163923597..26bc783743 100644 --- a/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee @@ -1,4 +1,4 @@ -angular.module('Darkswarm').controller "DetailsCtrl", ($scope, $timeout, $http, CurrentUser, AuthenticationService, SpreeUser, $controller) -> +angular.module('Darkswarm').controller "DetailsCtrl", ($scope, $timeout, $http, CurrentUser, SpreeUser, $controller) -> angular.extend this, $controller('FieldsetMixin', {$scope: $scope}) $scope.name = "details" diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb index 70189a3815..cf87ba49da 100644 --- a/app/controllers/spree/users_controller.rb +++ b/app/controllers/spree/users_controller.rb @@ -27,8 +27,18 @@ module Spree # Endpoint for queries to check if a user is already registered def registered_email - user = Spree::User.find_by email: params[:email] - render json: { registered: user.present? } + registered = Spree::User.find_by(email: params[:email]).present? + + if registered + render status: :ok, operations: cable_car. + inner_html( + "#login-feedback", + partial("layouts/alert", locals: { type: "alert", message: t('devise.failure.already_registered') }) + ). + dispatch_event(name: "login:modal:open") + else + head :not_found + end end def create diff --git a/app/webpacker/packs/application.js b/app/webpacker/packs/application.js index 2610d9bee3..2d04d92039 100644 --- a/app/webpacker/packs/application.js +++ b/app/webpacker/packs/application.js @@ -14,6 +14,7 @@ import { CableCar } from "mrujs/plugins" import * as Turbo from "@hotwired/turbo" window.Turbo = Turbo +window.CableReady = CableReady mrujs.start({ plugins: [ new CableCar(CableReady) diff --git a/spec/controllers/spree/users_controller_spec.rb b/spec/controllers/spree/users_controller_spec.rb index a1855cea11..9a0e4298fa 100644 --- a/spec/controllers/spree/users_controller_spec.rb +++ b/spec/controllers/spree/users_controller_spec.rb @@ -60,14 +60,14 @@ describe Spree::UsersController, type: :controller do let!(:user) { create(:user) } - it "returns true if email corresponds to a registered user" do + it "returns ok (200) if email corresponds to a registered user" do post :registered_email, params: { email: user.email } - expect(json_response['registered']).to eq true + expect(response).to have_http_status(:ok) end - it "returns false if email does not correspond to a registered user" do + it "returns not_found (404) if email does not correspond to a registered user" do post :registered_email, params: { email: 'nonregistereduser@example.com' } - expect(json_response['registered']).to eq false + expect(response).to have_http_status(:not_found) end end From 794e0e03260fb646f5fff41ccc3ca4ecaa7adc7d Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 14:33:15 +0000 Subject: [PATCH 20/51] Delete old login modal code --- .../forgot_controller.js.coffee | 19 ------- .../authentication/login_controller.js.coffee | 36 ------------ .../signup_controller.js.coffee | 17 ------ .../authentication_controller.js.coffee | 12 ---- .../services/authentication_service.js.coffee | 57 ------------------- .../darkswarm/services/redirections.js.coffee | 3 - .../templates/authentication.html.haml | 7 --- .../javascripts/templates/forgot.html.haml | 31 ---------- .../javascripts/templates/login.html.haml | 44 -------------- .../registration_authentication.html.haml | 17 ------ .../javascripts/templates/signup.html.haml | 51 ----------------- .../cookies_banner_service.js.coffee | 3 +- 12 files changed, 1 insertion(+), 296 deletions(-) delete mode 100644 app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee delete mode 100644 app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee delete mode 100644 app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee delete mode 100644 app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee delete mode 100644 app/assets/javascripts/darkswarm/services/authentication_service.js.coffee delete mode 100644 app/assets/javascripts/darkswarm/services/redirections.js.coffee delete mode 100644 app/assets/javascripts/templates/authentication.html.haml delete mode 100644 app/assets/javascripts/templates/forgot.html.haml delete mode 100644 app/assets/javascripts/templates/login.html.haml delete mode 100644 app/assets/javascripts/templates/registration_authentication.html.haml delete mode 100644 app/assets/javascripts/templates/signup.html.haml diff --git a/app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee deleted file mode 100644 index 8a0a2121de..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication/forgot_controller.js.coffee +++ /dev/null @@ -1,19 +0,0 @@ -angular.module('Darkswarm').controller "ForgotCtrl", ($scope, $http, $location, AuthenticationService) -> - $scope.path = "/forgot" - $scope.sent = false - - $scope.submit = -> - if $scope.spree_user.email != null - $http.post("/user/spree_user/password", {spree_user: $scope.spree_user}).then (response)-> - $scope.sent = true - .catch (response) -> - $scope.errors = response.data.error - $scope.user_unconfirmed = (response.status == 401) - else - $scope.errors = t 'email_required' - - $scope.resend_confirmation = -> - $http.post("/user/spree_user/confirmation", {spree_user: $scope.spree_user, return_url: $location.absUrl()}).then (response)-> - $scope.messages = t('devise.confirmations.send_instructions') - .catch (response) -> - $scope.errors = t('devise.confirmations.failed_to_send') diff --git a/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee deleted file mode 100644 index 63dfb719b4..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication/login_controller.js.coffee +++ /dev/null @@ -1,36 +0,0 @@ -angular.module('Darkswarm').controller "LoginCtrl", ($scope, $timeout, $location, $http, $window, AuthenticationService, Redirections, Loading) -> - $scope.path = "/login" - - $scope.modalMessage = null - - $scope.$watch (-> - AuthenticationService.modalMessage - ), (newValue) -> - $scope.errors = newValue - - $scope.submit = -> - Loading.message = t 'logging_in' - $http.post("/user/spree_user/sign_in", {spree_user: $scope.spree_user}).then (response)-> - if window._paq - window._paq.push(['trackEvent', 'Signin/Signup', 'Login Submit Success', $location.absUrl()]); - if Redirections.after_login - $window.location.href = $window.location.origin + Redirections.after_login - else - $window.location.href = $window.location.origin + $window.location.pathname # Strips out hash fragments - .catch (response) -> - Loading.clear() - $scope.errors = response.data.message || response.data.error - $scope.user_unconfirmed = (response.data.error == t('devise.failure.unconfirmed')) - - $scope.resend_confirmation = -> - $http.post("/user/spree_user/confirmation", {spree_user: $scope.spree_user, return_url: $location.absUrl()}).then (response)-> - $scope.messages = t('devise.confirmations.send_instructions') - .catch (response) -> - $scope.errors = t('devise.confirmations.failed_to_send') - - $timeout -> - if angular.isDefined($location.search()['validation']) - if $location.search()['validation'] == 'confirmed' - $scope.messages = t('devise.confirmations.confirmed') - if $location.search()['validation'] == 'not_confirmed' - $scope.errors = t('devise.confirmations.not_confirmed') diff --git a/app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee deleted file mode 100644 index 7c742b91f8..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication/signup_controller.js.coffee +++ /dev/null @@ -1,17 +0,0 @@ -angular.module('Darkswarm').controller "SignupCtrl", ($scope, $http, $window, $location, Redirections, AuthenticationService) -> - $scope.path = "/signup" - - $scope.spree_user.password_confirmation = '' - - $scope.errors = - email: null - password: null - - $scope.submit = -> - $http.post("/user/spree_user", {spree_user: $scope.spree_user, return_url: $location.absUrl()}).then (response)-> - $scope.errors = {email: null, password: null} - $scope.messages = t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') - if window._paq - window._paq.push(['trackEvent', 'Signin/Signup', 'Signup Submit Success', $location.absUrl()]); - .catch (response) -> - $scope.errors = response.data diff --git a/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee deleted file mode 100644 index 689048722d..0000000000 --- a/app/assets/javascripts/darkswarm/controllers/authentication_controller.js.coffee +++ /dev/null @@ -1,12 +0,0 @@ -angular.module('Darkswarm').controller "AuthenticationCtrl", ($scope, AuthenticationService, SpreeUser)-> - $scope.open = AuthenticationService.open - $scope.toggle = AuthenticationService.toggle - - $scope.spree_user = SpreeUser.spree_user - $scope.isActive = AuthenticationService.isActive - $scope.select = AuthenticationService.select - - $scope.tabs = - login: { active: $scope.isActive('/login') } - signup: { active: $scope.isActive('/signup') } - forgot: { active: $scope.isActive('/forgot') } diff --git a/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee b/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee deleted file mode 100644 index 7c5711d992..0000000000 --- a/app/assets/javascripts/darkswarm/services/authentication_service.js.coffee +++ /dev/null @@ -1,57 +0,0 @@ -# This class deals with displaying things in the login modal. It chooses -# the modal tab templates and deals with switching tabs and passing data -# between the tabs. It has direct access to the instance of the login modal, -# and provides that access to other controllers as a service. - -angular.module('Darkswarm').factory "AuthenticationService", (Navigation, $modal, $location, Redirections, Loading)-> - - new class AuthenticationService - selectedPath: "/login" - modalMessage: null - - constructor: -> - if $location.path() in ["/login", "/signup", "/forgot"] || location.pathname is '/register/auth' - @open @initialTab(), @initialTemplate() - - open: (path = false, template = 'authentication.html') => - @modalInstance = $modal.open - templateUrl: template - windowClass: "login-modal medium" - @modalInstance.result.then @close, @close - @selectedPath = path || @selectedPath - Navigation.navigate @selectedPath - - if window._paq - window._paq.push(['trackEvent', 'Signin/Signup', 'Login Modal View', window.location.href]) - - # Opens the /login tab if returning from email confirmation, - # the /signup tab if opened from the enterprise registration page, - # otherwise opens whichever tab is selected in the URL params ('/login', '/signup', or '/forgot') - initialTab: -> - if angular.isDefined($location.search()['validation']) - '/login' - else if location.pathname is '/register/auth' - '/signup' - else - $location.path() - - # Loads the registration page modal when needed, otherwise the default modal - initialTemplate: -> - if location.pathname is '/register/auth' - 'registration_authentication.html' - else - 'authentication.html' - pushMessage: (message) -> - @modalMessage = String(message) - - select: (path)=> - @selectedPath = path - Navigation.navigate @selectedPath - - isActive: Navigation.isActive - - close: -> - if location.pathname in ["/register", "/register/auth"] - Loading.message = t 'going_back_to_home_page' - location.hash = "" - location.pathname = "/" diff --git a/app/assets/javascripts/darkswarm/services/redirections.js.coffee b/app/assets/javascripts/darkswarm/services/redirections.js.coffee deleted file mode 100644 index a2950b123a..0000000000 --- a/app/assets/javascripts/darkswarm/services/redirections.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -angular.module('Darkswarm').factory "Redirections", ($location)-> - new class Redirections - after_login: $location.search().after_login diff --git a/app/assets/javascripts/templates/authentication.html.haml b/app/assets/javascripts/templates/authentication.html.haml deleted file mode 100644 index db1b5ecd7d..0000000000 --- a/app/assets/javascripts/templates/authentication.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -%div{"ng-controller" => "AuthenticationCtrl"} - %tabset - %ng-include{src: "'login.html'"} - %ng-include{src: "'signup.html'"} - %ng-include{src: "'forgot.html'"} -%a.close-reveal-modal{"ng-click" => "$close()"} - %i.ofn-i_009-close diff --git a/app/assets/javascripts/templates/forgot.html.haml b/app/assets/javascripts/templates/forgot.html.haml deleted file mode 100644 index 94e85af2bc..0000000000 --- a/app/assets/javascripts/templates/forgot.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -%tab#forgot{ heading: "{{'forgot_password' | t}}", active: "tabs.forgot.active", select: "select(path)"} - %form{ ng: { controller: "ForgotCtrl", submit: "submit()" } } - .row - .large-12.columns - .alert-box.success{"ng-show" => "sent"} - {{ 'password_reset_sent' | t }} - - .alert-box.success{"ng-show" => "messages != null"} - {{ messages }} - - .alert-box.alert{"ng-show" => "errors != null"} - {{ errors }} - %a{ng: {show: 'user_unconfirmed', click: 'resend_confirmation()'}} - = t('devise.confirmations.resend_confirmation_email') - - .row - .large-12.columns - %label{for: "email"} {{'signup_email' | t}} - %input.title.input-text{name: "email", - type: "email", - id: "email", - tabindex: 1, - inputmode: "email", - "ng-model" => "spree_user.email"} - .row - .large-12.columns - %input.button.primary{name: "commit", - tabindex: "3", - type: "submit", - value: "{{'reset_password' | t}}"} - diff --git a/app/assets/javascripts/templates/login.html.haml b/app/assets/javascripts/templates/login.html.haml deleted file mode 100644 index 7ca17bfbe9..0000000000 --- a/app/assets/javascripts/templates/login.html.haml +++ /dev/null @@ -1,44 +0,0 @@ -%tab#login-content{ heading: "{{'label_login' | t}}", active: "tabs.login.active", select: "select(path)"} - %form{ ng: { controller: "LoginCtrl", submit: "submit()" } } - .row - .large-12.columns - .alert-box.alert{"ng-show" => "errors != null"} - {{ errors }} - %a{ng: {show: 'user_unconfirmed', click: 'resend_confirmation()'}} - = t('devise.confirmations.resend_confirmation_email') - .alert-box.success{ng: {show: 'messages != null'}} - {{ messages }} - .row - .large-12.columns - %label{for: "email"} {{'email' | t}} - %input.title.input-text{name: "email", - type: "email", - id: "email", - tabindex: "1", - inputmode: "email", - "ng-model" => "spree_user.email"} - .row - .large-12.columns - %label{for: "password"} {{'password' | t}} - %input.title.input-text{name: "password", - type: "password", - id: "password", - autocomplete: "off", - tabindex: "2", - inputmode: "password", - "ng-model" => "spree_user.password"} - .row - .large-12.columns - %input{name: "remember_me", - type: "checkbox", - id: "remember_me", - value: "1", - tabindex: "3", - "ng-model" => "spree_user.remember_me"} - %label{for: "remember_me"} {{'remember_me' | t}} - .row - .large-12.columns - %input.button.primary{name: "commit", - tabindex: "4", - type: "submit", - value: "{{'label_login' | t}}"} diff --git a/app/assets/javascripts/templates/registration_authentication.html.haml b/app/assets/javascripts/templates/registration_authentication.html.haml deleted file mode 100644 index b5a525c3f2..0000000000 --- a/app/assets/javascripts/templates/registration_authentication.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -.container - .row.modal-centered - %h2 {{'js.registration.welcome_to_ofn' | t}} - %h5 {{'js.registration.signup_or_login' | t}}: - %div{"ng-controller" => "AuthenticationCtrl"} - %tabset - %ng-include{src: "'signup.html'"} - %ng-include{src: "'login.html'"} - %ng-include{src: "'forgot.html'"} - %div{ ng: { show: "active('/signup')"} } - %hr - {{'js.registration.have_an_account' | t}} - %a{ href: "", ng: { click: "select('/login')"}} - {{'js.registration.action_login' | t}} - -%a.close-reveal-modal{"ng-click" => "$close()"} - %i.ofn-i_009-close diff --git a/app/assets/javascripts/templates/signup.html.haml b/app/assets/javascripts/templates/signup.html.haml deleted file mode 100644 index 4ee026adb5..0000000000 --- a/app/assets/javascripts/templates/signup.html.haml +++ /dev/null @@ -1,51 +0,0 @@ -%tab#sign-up-content{ heading: "{{'label_signup' | t}}", active: 'tabs.signup.active', select: "select(path)"} - %form{ ng: { controller: "SignupCtrl", submit: "submit()" } } - .row - .large-12.columns - .alert-box.success{ng: {show: 'messages != null'}} - {{ messages }} - .large-12.columns - .alert-box.alert{ng: {show: 'errors.message != null'}} - {{ errors.message }} - .row - .large-12.columns - %label{for: "email"} {{'signup_email' | t}} - %input.title.input-text{name: "email", - type: "email", - id: "email", - tabindex: 1, - inputmode: "email", - "ng-model" => "spree_user.email"} - %span.error{"ng-show" => "errors.email != null"} - {{ errors.email.join(' ') }} - .row - .large-12.columns - %label{for: "password"} {{'choose_password' | t}} - %input.title.input-text{name: "password", - type: "password", - id: "password", - autocomplete: "off", - tabindex: 2, - inputmode: "password", - "ng-model" => "spree_user.password"} - %span.error{"ng-show" => "errors.password != null"} - {{ errors.password.join(' ') }} - .row - .large-12.columns - %label{for: "password_confirmation"} {{'confirm_password' | t}} - %input.title.input-text{name: "password_confirmation", - type: "password", - id: "password_confirmation", - autocomplete: "off", - tabindex: 2, - inputmode: "password", - "ng-model" => "spree_user.password_confirmation"} - %span.error{"ng-show" => "errors.password_confirmation != null"} - {{ errors.password_confirmation.join(' ') }} - .row - .large-12.columns - %input.button.primary{name: "commit", - tabindex: "3", - type: "submit", - value: "{{'action_signup' | t}}"} - diff --git a/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_service.js.coffee b/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_service.js.coffee index 2fd9fbb4c7..079d3206c8 100644 --- a/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_service.js.coffee +++ b/engines/web/app/assets/javascripts/web/cookies_banner/cookies_banner_service.js.coffee @@ -1,5 +1,4 @@ -angular.module('Darkswarm').factory "CookiesBannerService", (Navigation, $modal, $location, Redirections, Loading)-> - +angular.module('Darkswarm').factory "CookiesBannerService", (Navigation, $modal, $location, Loading)-> new class CookiesBannerService modalMessage: null isEnabled: false From 8b59ef20dbe4127cc96b78ad520e9e0f2d113294 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 21 Jan 2022 20:37:49 +0000 Subject: [PATCH 21/51] Improve controller tests --- app/controllers/user_passwords_controller.rb | 2 +- .../spree/user_sessions_controller_spec.rb | 27 +++++++++---- .../user_passwords_controller_spec.rb | 38 +++++++------------ spec/system/consumer/user_password_spec.rb | 14 +++++++ 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/app/controllers/user_passwords_controller.rb b/app/controllers/user_passwords_controller.rb index d87b293478..604e4a113d 100644 --- a/app/controllers/user_passwords_controller.rb +++ b/app/controllers/user_passwords_controller.rb @@ -26,7 +26,7 @@ class UserPasswordsController < Spree::UserPasswordsController private def render_unconfirmed_response - render status: :unauthorized, operations: cable_car.inner_html( + render status: :unprocessable_entity, operations: cable_car.inner_html( "#forgot-feedback", partial("layouts/alert", locals: { type: "alert", message: t(:email_unconfirmed), unconfirmed: true }) diff --git a/spec/controllers/spree/user_sessions_controller_spec.rb b/spec/controllers/spree/user_sessions_controller_spec.rb index 2885f53fc3..34053783b7 100644 --- a/spec/controllers/spree/user_sessions_controller_spec.rb +++ b/spec/controllers/spree/user_sessions_controller_spec.rb @@ -10,12 +10,13 @@ describe Spree::UserSessionsController, type: :controller do end describe "create" do - context "succeed" do + context "success" do context "when referer is not '/checkout'" do it "redirects to root" do - spree_post :create, spree_user: { email: user.email, password: user.password }, - use_route: :spree - expect(response).to redirect_to root_path + spree_post :create, spree_user: { email: user.email, password: user.password } + + expect(response).to have_http_status(:ok) + expect(response.body).to match(root_path).and match("redirect") end end @@ -23,12 +24,24 @@ describe Spree::UserSessionsController, type: :controller do before { @request.env['HTTP_REFERER'] = 'http://test.com/checkout' } it "redirects to checkout" do - spree_post :create, spree_user: { email: user.email, password: user.password }, - use_route: :spree - expect(response).to redirect_to checkout_path + spree_post :create, spree_user: { email: user.email, password: user.password } + + expect(response).to have_http_status(:ok) + expect(response.body).to match(checkout_path).and match("redirect") end end end + + context "failing to log in" do + render_views + + it "returns an error" do + spree_post :create, spree_user: { email: user.email, password: "wrong" } + + expect(response).to have_http_status(:unauthorized) + expect(response.body).to include "Invalid email or password" + end + end end describe "destroy" do diff --git a/spec/controllers/user_passwords_controller_spec.rb b/spec/controllers/user_passwords_controller_spec.rb index 3920aef980..a2e5861455 100644 --- a/spec/controllers/user_passwords_controller_spec.rb +++ b/spec/controllers/user_passwords_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe UserPasswordsController, type: :controller do - include OpenFoodNetwork::EmailHelper + render_views let(:user) { create(:user) } let(:unconfirmed_user) { create(:user, confirmed_at: nil) } @@ -13,15 +13,22 @@ describe UserPasswordsController, type: :controller do end describe "create" do - it "returns errors" do - spree_post :create, spree_user: {} - expect(response.status).to eq 200 - expect(response).to render_template "spree/user_passwords/new" + it "returns 404 if user is not found" do + spree_post :create, spree_user: { email: "xxxxxxxxxx@example.com" } + expect(response.status).to eq 404 + expect(response.body).to match I18n.t(:email_not_found) end - it "redirects to login when data is valid" do + it "returns 422 if user is registered but not confirmed" do + spree_post :create, spree_user: { email: unconfirmed_user.email } + expect(response.status).to eq 422 + expect(response.body).to match I18n.t(:email_unconfirmed) + end + + it "returns 200 when password reset was successful" do spree_post :create, spree_user: { email: user.email } - expect(response).to be_redirect + expect(response.status).to eq 200 + expect(response.body).to match I18n.t(:password_reset_sent) end end @@ -35,8 +42,6 @@ describe UserPasswordsController, type: :controller do end it "renders Darkswarm" do - setup_email - user.send_reset_password_instructions user.reload @@ -44,19 +49,4 @@ describe UserPasswordsController, type: :controller do expect(response).to render_template "user_passwords/edit" end - - describe "via ajax" do - it "returns error when email not found" do - post :create, xhr: true, params: { spree_user: {}, use_route: :spree } - expect(response.status).to eq 404 - expect(json_response).to eq 'error' => I18n.t('email_not_found') - end - - it "returns error when user is unconfirmed" do - post :create, xhr: true, - params: { spree_user: { email: unconfirmed_user.email }, use_route: :spree } - expect(response.status).to eq 401 - expect(json_response).to eq 'error' => I18n.t('email_unconfirmed') - end - end end diff --git a/spec/system/consumer/user_password_spec.rb b/spec/system/consumer/user_password_spec.rb index 93ff772369..a55140b813 100644 --- a/spec/system/consumer/user_password_spec.rb +++ b/spec/system/consumer/user_password_spec.rb @@ -29,6 +29,20 @@ describe "User password confirm/reset page" do expect(page).to have_no_text "Reset password token has expired" expect(page).to be_logged_in_as user end + + it "shows an error if password is empty" do + visit spree.spree_user_confirmation_path(confirmation_token: user.confirmation_token) + + expect(user.reload.confirmed?).to be true + expect(page).to have_text I18n.t(:change_my_password) + + fill_in "Password", with: "" + fill_in "Password Confirmation", with: "" + click_button + + expect(page).to have_text "User password cannot be blank. Please enter a password." + expect(page).to_not be_logged_in_as user + end end describe "can reset its own password" do From f3792acf5524020b14e06958c7c98204c362ab94 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sat, 29 Jan 2022 10:11:53 +0000 Subject: [PATCH 22/51] Drop workaround previously required to avoid a bug caused by the stringex gem --- app/controllers/split_checkout_controller.rb | 2 +- app/controllers/spree/user_sessions_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/split_checkout_controller.rb b/app/controllers/split_checkout_controller.rb index 63ca43a42b..adc0c69a17 100644 --- a/app/controllers/split_checkout_controller.rb +++ b/app/controllers/split_checkout_controller.rb @@ -58,7 +58,7 @@ class SplitCheckoutController < ::BaseController return unless selected_payment_method&.external_gateway? return unless (redirect_url = selected_payment_method.external_payment_url(order: @order)) - render operations: cable_car.redirect_to(url: URI(redirect_url)) + render operations: cable_car.redirect_to(url: redirect_url) true end diff --git a/app/controllers/spree/user_sessions_controller.rb b/app/controllers/spree/user_sessions_controller.rb index 6bd55bef6e..342b5dddc9 100644 --- a/app/controllers/spree/user_sessions_controller.rb +++ b/app/controllers/spree/user_sessions_controller.rb @@ -23,7 +23,7 @@ module Spree flash[:success] = t('devise.success.logged_in_succesfully') render operations: cable_car.redirect_to( - url: URI(return_url_or_default(after_sign_in_path_for(spree_current_user))) + url: return_url_or_default(after_sign_in_path_for(spree_current_user)) ) else render status: :unauthorized, operations: cable_car.inner_html( From f4fdc8740e6c6f41eeed0d1d18d473896aaf7083 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sat, 29 Jan 2022 10:17:44 +0000 Subject: [PATCH 23/51] Disable test that depends on missing Transifex keys --- spec/system/admin/product_import_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/admin/product_import_spec.rb b/spec/system/admin/product_import_spec.rb index 350956ac74..8de92c0ede 100644 --- a/spec/system/admin/product_import_spec.rb +++ b/spec/system/admin/product_import_spec.rb @@ -575,7 +575,7 @@ describe "Product Import", js: true do I18n.default_locale = original_default_locale end - it 'returns the header in selected language' do + xit 'returns the header in selected language' do csv_data = CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "shipping_category"] From 7e62bfcdfb685d40a039dedd65f0d2363f9b2423 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 30 Jan 2022 10:57:40 +0000 Subject: [PATCH 24/51] Add failing test for loading address with state correctly in split checkout --- spec/system/consumer/split_checkout_spec.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/spec/system/consumer/split_checkout_spec.rb b/spec/system/consumer/split_checkout_spec.rb index 91431f0134..eefca9e4a5 100644 --- a/spec/system/consumer/split_checkout_spec.rb +++ b/spec/system/consumer/split_checkout_spec.rb @@ -223,6 +223,25 @@ describe "As a consumer, I want to checkout my order", js: true do end end + context "with a saved address" do + let!(:address_state) do + create(:state, name: "Testville", abbr: "TST", country: DefaultCountry.country ) + end + let(:saved_address) do + create(:bill_address, state: address_state, zipcode: "TST01" ) + end + + before do + user.update_columns bill_address_id: saved_address.id + end + + xit "pre-fills address details" do + visit checkout_path + expect(page).to have_select "order_bill_address_attributes_state_id", selected: "Testville" + expect(page).to have_field "order_bill_address_attributes_zipcode", with: "TST01" + end + end + context "summary step" do let(:order) { create(:order_ready_for_confirmation, distributor: distributor) } From bf4428b688d13869e065149e4e42df6d5153d793 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 30 Jan 2022 09:14:38 +0000 Subject: [PATCH 25/51] Tidy up dependent-select controller --- .../dependant_select_controller.js | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/app/webpacker/controllers/dependant_select_controller.js b/app/webpacker/controllers/dependant_select_controller.js index b58e7c7417..8631121b65 100644 --- a/app/webpacker/controllers/dependant_select_controller.js +++ b/app/webpacker/controllers/dependant_select_controller.js @@ -13,15 +13,25 @@ export default class extends Controller { } populateSelect(sourceId) { - const allOptions = this.optionsValue; - const options = allOptions.find((option) => option[0] === sourceId)[1]; - const selectBox = this.selectTarget; - selectBox.innerHTML = ""; - options.forEach((item) => { - const opt = document.createElement("option"); - opt.value = item[1]; - opt.innerHTML = item[0]; - selectBox.appendChild(opt); + this.removeCurrentOptions() + + this.dependantOptionsFor(sourceId).forEach((item) => { + this.addOption(item[0], item[1]) }); } + + removeCurrentOptions() { + this.selectTarget.innerHTML = "" + } + + addOption(label, value) { + const newOption = document.createElement("option") + newOption.innerHTML = label + newOption.value = value + this.selectTarget.appendChild(newOption) + } + + dependantOptionsFor(sourceId) { + return this.optionsValue.find((option) => option[0] === sourceId)[1] + } } From 370ec17818ef828895f90e2b5b516d77b94867e4 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 30 Jan 2022 09:31:38 +0000 Subject: [PATCH 26/51] Improve countries and states loading --- app/controllers/concerns/checkout_callbacks.rb | 11 +---------- app/helpers/spree/base_helper.rb | 18 ++++++++++++++++++ app/views/split_checkout/_details.html.haml | 14 +++++++++----- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/app/controllers/concerns/checkout_callbacks.rb b/app/controllers/concerns/checkout_callbacks.rb index 991fd8e394..66ad90f69d 100644 --- a/app/controllers/concerns/checkout_callbacks.rb +++ b/app/controllers/concerns/checkout_callbacks.rb @@ -14,7 +14,7 @@ module CheckoutCallbacks prepend_before_action :require_distributor_chosen before_action :load_order, :associate_user, :load_saved_addresses, :load_saved_credit_cards - before_action :load_shipping_methods, :load_countries, if: -> { params[:step] == "details" } + before_action :load_shipping_methods, if: -> { params[:step] == "details" } before_action :ensure_order_not_completed before_action :ensure_checkout_allowed @@ -49,15 +49,6 @@ module CheckoutCallbacks @shipping_methods = Spree::ShippingMethod.for_distributor(@order.distributor).order(:name) end - def load_countries - @countries = available_countries.map { |c| [c.name, c.id] } - @countries_with_states = available_countries.map { |c| - [c.id, c.states.map { |s| - [s.name, s.id] - }] - } - end - def redirect_to_shop? !@order || !@order.checkout_allowed? || diff --git a/app/helpers/spree/base_helper.rb b/app/helpers/spree/base_helper.rb index 11320424b4..92e38aa8a1 100644 --- a/app/helpers/spree/base_helper.rb +++ b/app/helpers/spree/base_helper.rb @@ -17,6 +17,24 @@ module Spree end.sort { |a, b| a.name <=> b.name } end + def countries + available_countries.map { |c| [c.name, c.id] } + end + + def states_for_country(country) + country.states.map do |state| + [state.name, state.id] + end + end + + def countries_with_states + available_countries.map { |c| + [c.id, c.states.map { |s| + [s.name, s.id] + }] + } + end + def pretty_time(time) [I18n.l(time.to_date, format: :long), time.strftime("%l:%M %p")].join(" ") diff --git a/app/views/split_checkout/_details.html.haml b/app/views/split_checkout/_details.html.haml index 6940784684..83762eda6b 100644 --- a/app/views/split_checkout/_details.html.haml +++ b/app/views/split_checkout/_details.html.haml @@ -25,7 +25,7 @@ = bill_address.text_field :phone, { placeholder: t("split_checkout.step1.your_details.phone.placeholder") } = f.error_message_on "bill_address.phone" - %div.checkout-substep{ "data-controller": "dependant-select", "data-dependant-select-options-value": @countries_with_states } + %div.checkout-substep{ "data-controller": "dependant-select", "data-dependant-select-options-value": countries_with_states } -# BILLING ADDRESS %div.checkout-title = t("split_checkout.step1.billing_address.title") @@ -45,9 +45,11 @@ = bill_address.text_field :city, { placeholder: t("split_checkout.step1.address.city.placeholder") } = f.error_message_on "bill_address.city" + - bill_address_country = @order.bill_address.country || DefaultCountry.country + %div.checkout-input = bill_address.label :state_id, t("split_checkout.step1.address.state_id.label") - = bill_address.select :state_id, @countries_with_states, { }, { "data-dependant-select-target": "select" } + = bill_address.select :state_id, states_for_country(bill_address_country), { selected: @order.bill_address&.state_id }, { "data-dependant-select-target": "select" } %div.checkout-input = bill_address.label :zipcode, t("split_checkout.step1.address.zipcode.label") @@ -56,7 +58,7 @@ %div.checkout-input = bill_address.label :country_id, t("split_checkout.step1.address.country_id.label") - = bill_address.select :country_id, @countries, { selected: @order.bill_address.country_id || DefaultCountry.id }, {"data-dependant-select-target": "source", "data-action": "dependant-select#handleSelectChange"} + = bill_address.select :country_id, countries, { selected: bill_address_country.id }, { "data-dependant-select-target": "source", "data-action": "dependant-select#handleSelectChange" } - if spree_current_user||true %div.checkout-input @@ -121,9 +123,11 @@ = ship_address.text_field :city, { placeholder: t("split_checkout.step1.address.city.placeholder") } = f.error_message_on "ship_address.city" + - ship_address_country = @order.ship_address.country || DefaultCountry.country + %div.checkout-input = ship_address.label :state_id, t("split_checkout.step1.address.state_id.label") - = ship_address.select :state_id, @countries_with_states, { }, { "data-dependant-select-target": "select" } + = ship_address.select :state_id, states_for_country(ship_address_country), { selected: @order.ship_address&.state_id }, { "data-dependant-select-target": "select" } %div.checkout-input = ship_address.label :zipcode, t("split_checkout.step1.address.zipcode.label") @@ -132,7 +136,7 @@ %div.checkout-input = ship_address.label :country_id, t("split_checkout.step1.address.country_id.label") - = ship_address.select :country_id, @countries, { selected: @order.ship_address.country_id || DefaultCountry.id }, {"data-dependant-select-target": "source", "data-action": "dependant-select#handleSelectChange"} + = ship_address.select :country_id, countries, { selected: ship_address_country.id }, { "data-dependant-select-target": "source", "data-action": "dependant-select#handleSelectChange" } - if spree_current_user %div.checkout-input{ "data-toggle-target": "content", style: "display: none" } From 908a22bcb627dc49f5cf1683c8dbc78094186084 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 30 Jan 2022 09:43:08 +0000 Subject: [PATCH 27/51] Don't repopulate states select on page load; breaks pre-filling selection from saved address --- app/webpacker/controllers/dependant_select_controller.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/webpacker/controllers/dependant_select_controller.js b/app/webpacker/controllers/dependant_select_controller.js index 8631121b65..f80a686bc6 100644 --- a/app/webpacker/controllers/dependant_select_controller.js +++ b/app/webpacker/controllers/dependant_select_controller.js @@ -4,10 +4,6 @@ export default class extends Controller { static targets = ["source", "select"]; static values = { options: Array }; - connect() { - this.populateSelect(parseInt(this.sourceTarget.value)); - } - handleSelectChange() { this.populateSelect(parseInt(this.sourceTarget.value)); } From 611beb2e902fa1df82ad4a0ee714dc56c2b5dcf3 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 30 Jan 2022 09:40:41 +0000 Subject: [PATCH 28/51] Rearrange controller placement, field order, and nesting --- app/views/split_checkout/_details.html.haml | 40 +++++++++++---------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/app/views/split_checkout/_details.html.haml b/app/views/split_checkout/_details.html.haml index 83762eda6b..22ae7d5031 100644 --- a/app/views/split_checkout/_details.html.haml +++ b/app/views/split_checkout/_details.html.haml @@ -25,7 +25,7 @@ = bill_address.text_field :phone, { placeholder: t("split_checkout.step1.your_details.phone.placeholder") } = f.error_message_on "bill_address.phone" - %div.checkout-substep{ "data-controller": "dependant-select", "data-dependant-select-options-value": countries_with_states } + %div.checkout-substep -# BILLING ADDRESS %div.checkout-title = t("split_checkout.step1.billing_address.title") @@ -45,20 +45,21 @@ = bill_address.text_field :city, { placeholder: t("split_checkout.step1.address.city.placeholder") } = f.error_message_on "bill_address.city" - - bill_address_country = @order.bill_address.country || DefaultCountry.country - - %div.checkout-input - = bill_address.label :state_id, t("split_checkout.step1.address.state_id.label") - = bill_address.select :state_id, states_for_country(bill_address_country), { selected: @order.bill_address&.state_id }, { "data-dependant-select-target": "select" } - %div.checkout-input = bill_address.label :zipcode, t("split_checkout.step1.address.zipcode.label") = bill_address.text_field :zipcode, { placeholder: t("split_checkout.step1.address.zipcode.placeholder") } = f.error_message_on "bill_address.zipcode" - %div.checkout-input - = bill_address.label :country_id, t("split_checkout.step1.address.country_id.label") - = bill_address.select :country_id, countries, { selected: bill_address_country.id }, { "data-dependant-select-target": "source", "data-action": "dependant-select#handleSelectChange" } + %div{ "data-controller": "dependant-select", "data-dependant-select-options-value": countries_with_states } + - bill_address_country = @order.bill_address.country || DefaultCountry.country + + %div.checkout-input + = bill_address.label :country_id, t("split_checkout.step1.address.country_id.label") + = bill_address.select :country_id, countries, { selected: bill_address_country.id }, { "data-dependant-select-target": "source", "data-action": "dependant-select#handleSelectChange" } + + %div.checkout-input + = bill_address.label :state_id, t("split_checkout.step1.address.state_id.label") + = bill_address.select :state_id, states_for_country(bill_address_country), { selected: @order.bill_address&.state_id }, { "data-dependant-select-target": "select" } - if spree_current_user||true %div.checkout-input @@ -123,20 +124,21 @@ = ship_address.text_field :city, { placeholder: t("split_checkout.step1.address.city.placeholder") } = f.error_message_on "ship_address.city" - - ship_address_country = @order.ship_address.country || DefaultCountry.country - - %div.checkout-input - = ship_address.label :state_id, t("split_checkout.step1.address.state_id.label") - = ship_address.select :state_id, states_for_country(ship_address_country), { selected: @order.ship_address&.state_id }, { "data-dependant-select-target": "select" } - %div.checkout-input = ship_address.label :zipcode, t("split_checkout.step1.address.zipcode.label") = ship_address.text_field :zipcode, { placeholder: t("split_checkout.step1.address.zipcode.placeholder") } = f.error_message_on "ship_address.zipcode" - %div.checkout-input - = ship_address.label :country_id, t("split_checkout.step1.address.country_id.label") - = ship_address.select :country_id, countries, { selected: ship_address_country.id }, { "data-dependant-select-target": "source", "data-action": "dependant-select#handleSelectChange" } + %div + - ship_address_country = @order.ship_address.country || DefaultCountry.country + + %div.checkout-input + = ship_address.label :country_id, t("split_checkout.step1.address.country_id.label") + = ship_address.select :country_id, countries, { selected: ship_address_country.id }, { "data-dependant-select-target": "source", "data-action": "dependant-select#handleSelectChange" } + + %div.checkout-input + = ship_address.label :state_id, t("split_checkout.step1.address.state_id.label") + = ship_address.select :state_id, states_for_country(ship_address_country), { selected: @order.ship_address&.state_id }, { "data-dependant-select-target": "select" } - if spree_current_user %div.checkout-input{ "data-toggle-target": "content", style: "display: none" } From 5e321c9f48ddd7e4ac1b067c36872e17818ef7b4 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 30 Jan 2022 09:46:44 +0000 Subject: [PATCH 29/51] Fix country/state selection for shipping address; missing controller and data --- app/views/split_checkout/_details.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/split_checkout/_details.html.haml b/app/views/split_checkout/_details.html.haml index 22ae7d5031..60d6bc626f 100644 --- a/app/views/split_checkout/_details.html.haml +++ b/app/views/split_checkout/_details.html.haml @@ -129,7 +129,7 @@ = ship_address.text_field :zipcode, { placeholder: t("split_checkout.step1.address.zipcode.placeholder") } = f.error_message_on "ship_address.zipcode" - %div + %div{ "data-controller": "dependant-select", "data-dependant-select-options-value": countries_with_states } - ship_address_country = @order.ship_address.country || DefaultCountry.country %div.checkout-input From 0516ec6f15fc8e1dae9297f9562730900a017cc8 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sun, 30 Jan 2022 10:59:58 +0000 Subject: [PATCH 30/51] Enable test for loading address (now passing) --- spec/system/consumer/split_checkout_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/split_checkout_spec.rb b/spec/system/consumer/split_checkout_spec.rb index eefca9e4a5..eeb93e51e5 100644 --- a/spec/system/consumer/split_checkout_spec.rb +++ b/spec/system/consumer/split_checkout_spec.rb @@ -235,7 +235,7 @@ describe "As a consumer, I want to checkout my order", js: true do user.update_columns bill_address_id: saved_address.id end - xit "pre-fills address details" do + it "pre-fills address details" do visit checkout_path expect(page).to have_select "order_bill_address_attributes_state_id", selected: "Testville" expect(page).to have_field "order_bill_address_attributes_zipcode", with: "TST01" From 7c0a631f7f1ceb1a8b91a9152cfa0e0d14f95499 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Mon, 31 Jan 2022 08:40:58 +0000 Subject: [PATCH 31/51] Remove an unnecessary assignment Co-authored-by: Maikel --- app/controllers/application_controller.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b28bdad774..941c346534 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -62,10 +62,9 @@ class ApplicationController < ActionController::Base end def set_checkout_redirect - return unless (referer_path = URI(request.referer.to_s).path) - return unless referer_path == main_app.checkout_path + return unless URI(request.referer.to_s).path == main_app.checkout_path - session["spree_user_return_to"] = referer_path + session["spree_user_return_to"] = main_app.checkout_path end def shopfront_session From 091c04427cca49d3fe38184bd948d098684b97f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jan 2022 09:04:40 +0000 Subject: [PATCH 32/51] Bump @storybook/server from 6.4.14 to 6.4.17 Bumps [@storybook/server](https://github.com/storybookjs/storybook/tree/HEAD/app/server) from 6.4.14 to 6.4.17. - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v6.4.17/app/server) --- updated-dependencies: - dependency-name: "@storybook/server" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 566 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 555 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index 60d19df993..7ae4d22e4d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2206,6 +2206,23 @@ global "^4.4.0" regenerator-runtime "^0.13.7" +"@storybook/addons@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.4.17.tgz#d040db3ddcf72fd9e7df8b8fce2a6dc88578c87e" + integrity sha512-C/hji0Bc7+tssGqaD0JYd/Pz0GM46xbRpdgHSVLInYdhJrb5a9IG6INCbcB8CXeReDKWJCLAaj2+z79Wa96bFQ== + dependencies: + "@storybook/api" "6.4.17" + "@storybook/channels" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/csf" "0.0.2--canary.87bc651.0" + "@storybook/router" "6.4.17" + "@storybook/theming" "6.4.17" + "@types/webpack-env" "^1.16.0" + core-js "^3.8.2" + global "^4.4.0" + regenerator-runtime "^0.13.7" + "@storybook/api@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.4.14.tgz#a477646f7e020a362f044d2e614e3d1a86ba8f6f" @@ -2229,6 +2246,29 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/api@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.4.17.tgz#82c3d756c85a65ecd8a3c3d9ce890e581175003a" + integrity sha512-O0ssHVy40t4QD5CNdNESbJo7uZd86UWYrHCFjgeC2gmxrMgBD+ajO34N4HoQFC/F+/84om2/z8RYAGKu/WpoTA== + dependencies: + "@storybook/channels" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/csf" "0.0.2--canary.87bc651.0" + "@storybook/router" "6.4.17" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.4.17" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + store2 "^2.12.0" + telejson "^5.3.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/builder-webpack4@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.4.14.tgz#77f45d164f5b93776fa154252706c6b73bd0edc5" @@ -2304,6 +2344,81 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.2.2" +"@storybook/builder-webpack4@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.4.17.tgz#ad71aaa0a271941e2efe114d5bf7bc8feaa13dcf" + integrity sha512-jE1JehWj5gjLwafGuvV1OyBFVVhBCvv6ESc3QPm+jrsf4ZyB9xliTsnPt3bDggQhWpTEbxgGw7IkVc83ss4AOw== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-decorators" "^7.12.12" + "@babel/plugin-proposal-export-default-from" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.12" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/preset-env" "^7.12.11" + "@babel/preset-react" "^7.12.10" + "@babel/preset-typescript" "^7.12.7" + "@storybook/addons" "6.4.17" + "@storybook/api" "6.4.17" + "@storybook/channel-postmessage" "6.4.17" + "@storybook/channels" "6.4.17" + "@storybook/client-api" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/components" "6.4.17" + "@storybook/core-common" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/node-logger" "6.4.17" + "@storybook/preview-web" "6.4.17" + "@storybook/router" "6.4.17" + "@storybook/semver" "^7.3.2" + "@storybook/store" "6.4.17" + "@storybook/theming" "6.4.17" + "@storybook/ui" "6.4.17" + "@types/node" "^14.0.10" + "@types/webpack" "^4.41.26" + autoprefixer "^9.8.6" + babel-loader "^8.0.0" + babel-plugin-macros "^2.8.0" + babel-plugin-polyfill-corejs3 "^0.1.0" + case-sensitive-paths-webpack-plugin "^2.3.0" + core-js "^3.8.2" + css-loader "^3.6.0" + file-loader "^6.2.0" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^4.1.6" + glob "^7.1.6" + glob-promise "^3.4.0" + global "^4.4.0" + html-webpack-plugin "^4.0.0" + pnp-webpack-plugin "1.6.4" + postcss "^7.0.36" + postcss-flexbugs-fixes "^4.2.1" + postcss-loader "^4.2.0" + raw-loader "^4.0.2" + stable "^0.1.8" + style-loader "^1.3.0" + terser-webpack-plugin "^4.2.3" + ts-dedent "^2.0.0" + url-loader "^4.1.1" + util-deprecate "^1.0.2" + webpack "4" + webpack-dev-middleware "^3.7.3" + webpack-filter-warnings-plugin "^1.2.1" + webpack-hot-middleware "^2.25.1" + webpack-virtual-modules "^0.2.2" + "@storybook/channel-postmessage@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.4.14.tgz#ce719041768ea8c0d64b7edc32ec7c774fba9b19" @@ -2317,6 +2432,19 @@ qs "^6.10.0" telejson "^5.3.2" +"@storybook/channel-postmessage@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.4.17.tgz#9f439bee440479bfe8f86092701b3b63afc5195a" + integrity sha512-IaVkO/w7bn95Psm1iROlSsc/DHh9RiA7F151VLFD9VTh55qiIfeRssfBXIg3ueGUWm0K+Y9J1jQbcqJoEniMtw== + dependencies: + "@storybook/channels" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/core-events" "6.4.17" + core-js "^3.8.2" + global "^4.4.0" + qs "^6.10.0" + telejson "^5.3.2" + "@storybook/channel-websocket@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-6.4.14.tgz#d71a4c8a4b36e2e89a4a3c56af3e0aa50353e02f" @@ -2328,6 +2456,17 @@ global "^4.4.0" telejson "^5.3.2" +"@storybook/channel-websocket@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-6.4.17.tgz#780cc68bb3a31069196b35a232013764cc2320a3" + integrity sha512-HtApo/3upDvxSl6VU04F/JznMIltUHeyEqaQNlkqJbQ1VQEHky/M/XJZWT4I/b+nGMXCt0+z0P0ikZ6VZKzFsw== + dependencies: + "@storybook/channels" "6.4.17" + "@storybook/client-logger" "6.4.17" + core-js "^3.8.2" + global "^4.4.0" + telejson "^5.3.2" + "@storybook/channels@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.4.14.tgz#f7a5416c971febd26ed7b03a75d99fd819790e48" @@ -2337,6 +2476,15 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/channels@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.4.17.tgz#95d05745a96b6059cea26d45aacca3967c401e26" + integrity sha512-C6ON1olkkHc+FaDerkwL1yYGDL1xtFP+eMlm42ZaO06sIT9qv9EkJZ3GU/PNLTeXYMX4OsZl9kjz2whD4rN7gg== + dependencies: + core-js "^3.8.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/client-api@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.4.14.tgz#d2053511971e06d70bba2accfbd1f6c0f2084e2a" @@ -2363,6 +2511,32 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/client-api@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.4.17.tgz#34476732eb4a698e7dcc774a21feca4529581889" + integrity sha512-qK8Bvsr2KzndAu8RxbBrieNUCltO/ynwtAohJ/29hAg/duf94CZjN0HkuTpQmd4lDip11d9o4Fz5UBWC0zMyOw== + dependencies: + "@storybook/addons" "6.4.17" + "@storybook/channel-postmessage" "6.4.17" + "@storybook/channels" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/csf" "0.0.2--canary.87bc651.0" + "@storybook/store" "6.4.17" + "@types/qs" "^6.9.5" + "@types/webpack-env" "^1.16.0" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + store2 "^2.12.0" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/client-logger@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.4.14.tgz#a7aed982407e4146548f9ac4b3af5eba24cd045e" @@ -2371,6 +2545,14 @@ core-js "^3.8.2" global "^4.4.0" +"@storybook/client-logger@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.4.17.tgz#50652859592c489b671f010455b8ce85d21a1b3d" + integrity sha512-awKBTOWHXHBxAIl8a/Zy/BitIw49A+0RnhPGuf8aFAw2Ym/vKR4bI8lRHVPtlR6RIHFp5rC1g32HmCQfKE22Fw== + dependencies: + core-js "^3.8.2" + global "^4.4.0" + "@storybook/components@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.4.14.tgz#546b34fe3feb09e670b76ff71d889bf5f566f1e4" @@ -2401,6 +2583,36 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/components@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.4.17.tgz#5be383682d9538c35c96463723cb17740f105fb6" + integrity sha512-R6imELCWlHWQiprYMeeXLKgUQK4m698G/jvkc1xUxAThpTxwgROTcpw5qnJA0k+wltjGn4t6MBWKHhheGZc6Hg== + dependencies: + "@popperjs/core" "^2.6.0" + "@storybook/client-logger" "6.4.17" + "@storybook/csf" "0.0.2--canary.87bc651.0" + "@storybook/theming" "6.4.17" + "@types/color-convert" "^2.0.0" + "@types/overlayscrollbars" "^1.12.0" + "@types/react-syntax-highlighter" "11.0.5" + color-convert "^2.0.1" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + markdown-to-jsx "^7.1.3" + memoizerific "^1.11.3" + overlayscrollbars "^1.13.1" + polished "^4.0.5" + prop-types "^15.7.2" + react-colorful "^5.1.2" + react-popper-tooltip "^3.1.1" + react-syntax-highlighter "^13.5.3" + react-textarea-autosize "^8.3.0" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/core-client@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-6.4.14.tgz#8f5dc6fe2295e479225bd396404a43679a15637e" @@ -2427,6 +2639,32 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" +"@storybook/core-client@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-6.4.17.tgz#baff9629a0723f9485d608c00357d45921a78a0d" + integrity sha512-uXO+DW5XI6fWLtQIBIBlBFeYGsy2qZEe3lxxXwBHwIjsDq53/1CmhEPuzC3jAsy5ddeKC2yEEHUdy3d3wkusIQ== + dependencies: + "@storybook/addons" "6.4.17" + "@storybook/channel-postmessage" "6.4.17" + "@storybook/channel-websocket" "6.4.17" + "@storybook/client-api" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/csf" "0.0.2--canary.87bc651.0" + "@storybook/preview-web" "6.4.17" + "@storybook/store" "6.4.17" + "@storybook/ui" "6.4.17" + airbnb-js-shims "^2.2.1" + ansi-to-html "^0.6.11" + core-js "^3.8.2" + global "^4.4.0" + lodash "^4.17.21" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + unfetch "^4.2.0" + util-deprecate "^1.0.2" + "@storybook/core-common@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-6.4.14.tgz#137b935855f0cc785ec55b386312747949e30e99" @@ -2482,6 +2720,61 @@ util-deprecate "^1.0.2" webpack "4" +"@storybook/core-common@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-6.4.17.tgz#bd2b14cfd1473f5f31f40c747afb62ea4a4ada6e" + integrity sha512-aOSG5Yvd8eoZsjvVlk7sS8iRXWT/dleHoHPXtKmHJnGcIZ1dcgr4wZqoOvL8dGhNNoU4Wx9dkJepqHD0+E/UgA== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-decorators" "^7.12.12" + "@babel/plugin-proposal-export-default-from" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.12" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/preset-env" "^7.12.11" + "@babel/preset-react" "^7.12.10" + "@babel/preset-typescript" "^7.12.7" + "@babel/register" "^7.12.1" + "@storybook/node-logger" "6.4.17" + "@storybook/semver" "^7.3.2" + "@types/node" "^14.0.10" + "@types/pretty-hrtime" "^1.0.0" + babel-loader "^8.0.0" + babel-plugin-macros "^3.0.1" + babel-plugin-polyfill-corejs3 "^0.1.0" + chalk "^4.1.0" + core-js "^3.8.2" + express "^4.17.1" + file-system-cache "^1.0.5" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^6.0.4" + fs-extra "^9.0.1" + glob "^7.1.6" + handlebars "^4.7.7" + interpret "^2.2.0" + json5 "^2.1.3" + lazy-universal-dotenv "^3.0.1" + picomatch "^2.3.0" + pkg-dir "^5.0.0" + pretty-hrtime "^1.0.3" + resolve-from "^5.0.0" + slash "^3.0.0" + telejson "^5.3.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + webpack "4" + "@storybook/core-events@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.4.14.tgz#37293c0fce703f2643cec6f24fc6ef7c40e30ded" @@ -2489,6 +2782,13 @@ dependencies: core-js "^3.8.2" +"@storybook/core-events@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.4.17.tgz#ad70c883673a2060f1c7c4aa8f5926fc14119f4a" + integrity sha512-k6wNjQLZZ8A/rt4gLz0M4ebTORKYYz2B9hZ3LvPJftNVqv+bTFAV4KVks6bBlvbJWpJ+eCPEyfeSP9Np2QIFMQ== + dependencies: + core-js "^3.8.2" + "@storybook/core-server@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.4.14.tgz#0bef36e1203eb56e1c9bbf7f02122500c8f7d534" @@ -2537,6 +2837,54 @@ webpack "4" ws "^8.2.3" +"@storybook/core-server@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.4.17.tgz#16f31635565c19248a45a793a7c2150597f3a4cc" + integrity sha512-wXYF4VD2EJ/6uFK+wAo/TgUyfD/lfMzzbAw2gBZAjYp7y7Zwj3svGqUfkFuPQG0/E9gmQfEmlyhTPPZImBFeBg== + dependencies: + "@discoveryjs/json-ext" "^0.5.3" + "@storybook/builder-webpack4" "6.4.17" + "@storybook/core-client" "6.4.17" + "@storybook/core-common" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/csf" "0.0.2--canary.87bc651.0" + "@storybook/csf-tools" "6.4.17" + "@storybook/manager-webpack4" "6.4.17" + "@storybook/node-logger" "6.4.17" + "@storybook/semver" "^7.3.2" + "@storybook/store" "6.4.17" + "@types/node" "^14.0.10" + "@types/node-fetch" "^2.5.7" + "@types/pretty-hrtime" "^1.0.0" + "@types/webpack" "^4.41.26" + better-opn "^2.1.1" + boxen "^5.1.2" + chalk "^4.1.0" + cli-table3 "^0.6.1" + commander "^6.2.1" + compression "^1.7.4" + core-js "^3.8.2" + cpy "^8.1.2" + detect-port "^1.3.0" + express "^4.17.1" + file-system-cache "^1.0.5" + fs-extra "^9.0.1" + globby "^11.0.2" + ip "^1.1.5" + lodash "^4.17.21" + node-fetch "^2.6.1" + pretty-hrtime "^1.0.3" + prompts "^2.4.0" + regenerator-runtime "^0.13.7" + serve-favicon "^2.5.0" + slash "^3.0.0" + telejson "^5.3.3" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + watchpack "^2.2.0" + webpack "4" + ws "^8.2.3" + "@storybook/core@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.4.14.tgz#c20a1432f22603eb2d3523389ff1311fffbba24f" @@ -2545,6 +2893,14 @@ "@storybook/core-client" "6.4.14" "@storybook/core-server" "6.4.14" +"@storybook/core@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.4.17.tgz#61892e2eb484a44fc9d69515c3068b1f64173327" + integrity sha512-wquJcEebw9kXJ7pThcmEsDNK0ykd3ir0uL5tkBzPGNIj7dozpzy24Fo9JSr0rNWHNtE7JczdIAQTcumowLTDig== + dependencies: + "@storybook/core-client" "6.4.17" + "@storybook/core-server" "6.4.17" + "@storybook/csf-tools@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-6.4.14.tgz#c5112e17f07dae4c7b922aefd45dccbbc9e49803" @@ -2568,6 +2924,29 @@ regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" +"@storybook/csf-tools@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-6.4.17.tgz#e7d2b9de95317d706657c294d7beee1d7b307ec4" + integrity sha512-GnaO1dX4wTvMKBthbbHLHcrDTXwZ7PooZmT1fTCeokzaobZzyv1cUtF1hlPQa3zA75kRE5AznJ0jmBVhHe0/9Q== + dependencies: + "@babel/core" "^7.12.10" + "@babel/generator" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/plugin-transform-react-jsx" "^7.12.12" + "@babel/preset-env" "^7.12.11" + "@babel/traverse" "^7.12.11" + "@babel/types" "^7.12.11" + "@mdx-js/mdx" "^1.6.22" + "@storybook/csf" "0.0.2--canary.87bc651.0" + core-js "^3.8.2" + fs-extra "^9.0.1" + global "^4.4.0" + js-string-escape "^1.0.1" + lodash "^4.17.21" + prettier ">=2.2.1 <=2.3.0" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + "@storybook/csf@0.0.2--canary.87bc651.0": version "0.0.2--canary.87bc651.0" resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.0.2--canary.87bc651.0.tgz#c7b99b3a344117ef67b10137b6477a3d2750cf44" @@ -2617,6 +2996,48 @@ webpack-dev-middleware "^3.7.3" webpack-virtual-modules "^0.2.2" +"@storybook/manager-webpack4@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/manager-webpack4/-/manager-webpack4-6.4.17.tgz#8fc6d5dba0587446defe78ced67b7033886c4c47" + integrity sha512-ekHudBR8FVSE475YQZZs9sqwou7YqFv03hNVOcvIJ36cZBgMbSkG8q50cK4uru2xCOedTK15SKIoFZQQ77cmQQ== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/preset-react" "^7.12.10" + "@storybook/addons" "6.4.17" + "@storybook/core-client" "6.4.17" + "@storybook/core-common" "6.4.17" + "@storybook/node-logger" "6.4.17" + "@storybook/theming" "6.4.17" + "@storybook/ui" "6.4.17" + "@types/node" "^14.0.10" + "@types/webpack" "^4.41.26" + babel-loader "^8.0.0" + case-sensitive-paths-webpack-plugin "^2.3.0" + chalk "^4.1.0" + core-js "^3.8.2" + css-loader "^3.6.0" + express "^4.17.1" + file-loader "^6.2.0" + file-system-cache "^1.0.5" + find-up "^5.0.0" + fs-extra "^9.0.1" + html-webpack-plugin "^4.0.0" + node-fetch "^2.6.1" + pnp-webpack-plugin "1.6.4" + read-pkg-up "^7.0.1" + regenerator-runtime "^0.13.7" + resolve-from "^5.0.0" + style-loader "^1.3.0" + telejson "^5.3.2" + terser-webpack-plugin "^4.2.3" + ts-dedent "^2.0.0" + url-loader "^4.1.1" + util-deprecate "^1.0.2" + webpack "4" + webpack-dev-middleware "^3.7.3" + webpack-virtual-modules "^0.2.2" + "@storybook/node-logger@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.4.14.tgz#2e96f4e3e06c78c3d065e59818515209122d9ae4" @@ -2628,6 +3049,17 @@ npmlog "^5.0.1" pretty-hrtime "^1.0.3" +"@storybook/node-logger@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.4.17.tgz#14fe3091b2030413c2f43f0de3e9408b27591d9c" + integrity sha512-gymFKjmOdi9fAJCaM4C8I/5Go4hPsOAcVNixpjAQYsvNQQZ1Yjm2zcSdD+QOuLJ36NTxgOFxT4ESbC2AfSjyqA== + dependencies: + "@types/npmlog" "^4.1.2" + chalk "^4.1.0" + core-js "^3.8.2" + npmlog "^5.0.1" + pretty-hrtime "^1.0.3" + "@storybook/postinstall@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.4.14.tgz#e8f7925529d4955783660f409deee1e907897b2b" @@ -2657,6 +3089,28 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" +"@storybook/preview-web@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/preview-web/-/preview-web-6.4.17.tgz#d29bbfa8f66428ef5e2202c4c364c1892d8cbf7b" + integrity sha512-fJIE/LO7I09w334AH71ojRpIiHLQrBUidkZlIQbjEmHn/GZBTePlf3CevrERA12FbCLoUbeS5nadk2dEg6YnUw== + dependencies: + "@storybook/addons" "6.4.17" + "@storybook/channel-postmessage" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/csf" "0.0.2--canary.87bc651.0" + "@storybook/store" "6.4.17" + ansi-to-html "^0.6.11" + core-js "^3.8.2" + global "^4.4.0" + lodash "^4.17.21" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + unfetch "^4.2.0" + util-deprecate "^1.0.2" + "@storybook/router@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.4.14.tgz#46fd46eadafc0d6b647be13702704c5fcf8f11e3" @@ -2674,6 +3128,23 @@ react-router-dom "^6.0.0" ts-dedent "^2.0.0" +"@storybook/router@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.4.17.tgz#d53c4f9a4ccaa21a7bbe8d875a1a81c9dba2a6f2" + integrity sha512-GLhzth83BB2BbUkM/+ld2JITIbDQtzFLs/CnZZQKq6aR93Kou6VK2epHnIwrPyWbP6rsGavR/8L/UWeBdwwTrQ== + dependencies: + "@storybook/client-logger" "6.4.17" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + history "5.0.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + qs "^6.10.0" + react-router "^6.0.0" + react-router-dom "^6.0.0" + ts-dedent "^2.0.0" + "@storybook/semver@^7.3.2": version "7.3.2" resolved "https://registry.yarnpkg.com/@storybook/semver/-/semver-7.3.2.tgz#f3b9c44a1c9a0b933c04e66d0048fcf2fa10dac0" @@ -2683,19 +3154,19 @@ find-up "^4.1.0" "@storybook/server@^6.4.13": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/server/-/server-6.4.14.tgz#c1f0293fdef084fd63473eaf128fda19351b68fa" - integrity sha512-DfehTFQ5yd9UoGoEj2AnyTg7RupgqQpzusj8gN42DxcKF/5Jpp2tzkN71imw0shzL5SL0KFs36YVvJQMUKXQ4Q== + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/server/-/server-6.4.17.tgz#e30c89d45550b430ad25cfc357b6c8b29525c90a" + integrity sha512-KZ4f/ArfxVQwKsZ8t62zG9LGcbbuI130PAXbr4u9AodUaRlIg2bBPpBZ0P2peR0UJOikgXgFLu7K6p2MLK61fw== dependencies: - "@storybook/addons" "6.4.14" - "@storybook/api" "6.4.14" - "@storybook/client-api" "6.4.14" - "@storybook/core" "6.4.14" - "@storybook/core-common" "6.4.14" + "@storybook/addons" "6.4.17" + "@storybook/api" "6.4.17" + "@storybook/client-api" "6.4.17" + "@storybook/core" "6.4.17" + "@storybook/core-common" "6.4.17" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/node-logger" "6.4.14" - "@storybook/preview-web" "6.4.14" - "@storybook/store" "6.4.14" + "@storybook/node-logger" "6.4.17" + "@storybook/preview-web" "6.4.17" + "@storybook/store" "6.4.17" "@types/webpack-env" "^1.16.0" core-js "^3.8.2" global "^4.4.0" @@ -2744,6 +3215,27 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/store@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/store/-/store-6.4.17.tgz#a68b687628b82f8ca0ef2c74f5d65f5a30e94f86" + integrity sha512-0rWk8u7gtzBOp5NvuIrL6abBHaDxax7e+yBPvU9tR0GZ7X0ALhOhJFRIo+lW9sZTUrcuSinOJ8Acyb0ZvnYCkg== + dependencies: + "@storybook/addons" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/csf" "0.0.2--canary.87bc651.0" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + slash "^3.0.0" + stable "^0.1.8" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/theming@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.4.14.tgz#f034914eb1853a80f588c7c141d47af0595f6d1f" @@ -2762,6 +3254,24 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" +"@storybook/theming@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.4.17.tgz#f0a03d2d3239638ac171e97a8f089ee2656a8287" + integrity sha512-7+U72/VdhoMb00q1URMzdTW3OYHJogro2i2hScgKR+ndL4/dtSmetJ/1z9PuoFxLxHgdLKcwMAV0fZAjEYlhCA== + dependencies: + "@emotion/core" "^10.1.1" + "@emotion/is-prop-valid" "^0.8.6" + "@emotion/styled" "^10.0.27" + "@storybook/client-logger" "6.4.17" + core-js "^3.8.2" + deep-object-diff "^1.1.0" + emotion-theming "^10.0.27" + global "^4.4.0" + memoizerific "^1.11.3" + polished "^4.0.5" + resolve-from "^5.0.0" + ts-dedent "^2.0.0" + "@storybook/ui@6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.4.14.tgz#59f08ac8d8eb782fa13fc9a8dd715222c96bf234" @@ -2796,6 +3306,40 @@ resolve-from "^5.0.0" store2 "^2.12.0" +"@storybook/ui@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.4.17.tgz#926aa1dbb4d3f9a28afe6edd6a0e5cb667be8e19" + integrity sha512-vBYV8PmvhYgMjjTRLtOHIisGqr1nfajAgOC+wfYvGLbF0npVEt5PfDieG1LTRc1OaItWLpKKJcByqSfL/y9Qow== + dependencies: + "@emotion/core" "^10.1.1" + "@storybook/addons" "6.4.17" + "@storybook/api" "6.4.17" + "@storybook/channels" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/components" "6.4.17" + "@storybook/core-events" "6.4.17" + "@storybook/router" "6.4.17" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.4.17" + copy-to-clipboard "^3.3.1" + core-js "^3.8.2" + core-js-pure "^3.8.2" + downshift "^6.0.15" + emotion-theming "^10.0.27" + fuse.js "^3.6.1" + global "^4.4.0" + lodash "^4.17.21" + markdown-to-jsx "^7.1.3" + memoizerific "^1.11.3" + polished "^4.0.5" + qs "^6.10.0" + react-draggable "^4.4.3" + react-helmet-async "^1.0.7" + react-sizeme "^3.0.1" + regenerator-runtime "^0.13.7" + resolve-from "^5.0.0" + store2 "^2.12.0" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" From 5f02ab79d4aac8d256e4e9b30d6b9c7116ee61e4 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Mon, 31 Jan 2022 09:55:14 +0000 Subject: [PATCH 33/51] Adjust animation handling for show/hide --- app/webpacker/controllers/login_modal_controller.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/webpacker/controllers/login_modal_controller.js b/app/webpacker/controllers/login_modal_controller.js index e29b547406..941df160dd 100644 --- a/app/webpacker/controllers/login_modal_controller.js +++ b/app/webpacker/controllers/login_modal_controller.js @@ -35,11 +35,10 @@ export default class extends Controller { this.backgroundTarget.style.display = "block" this.modalTarget.style.display = "block" - document.querySelector("body").classList.add("modal-open") - setTimeout(() => { this.modalTarget.classList.add("in") this.backgroundTarget.classList.add("in") + document.querySelector("body").classList.add("modal-open") }) window._paq?.push(['trackEvent', 'Signin/Signup', 'Login Modal View', window.location.href]) From 3abef1b703aa891b82c1377ae4d8c49ff14b9a9a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bellet Date: Tue, 21 Dec 2021 10:16:46 +0100 Subject: [PATCH 34/51] Specify css for this sticky container with a nice box-shadow. Handle special case for mobile view (ie. max width 700px) --- app/views/split_checkout/_summary.html.haml | 2 +- .../css/darkswarm/split-checkout.scss | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/app/views/split_checkout/_summary.html.haml b/app/views/split_checkout/_summary.html.haml index 75bdb00d36..8932bc1c70 100644 --- a/app/views/split_checkout/_summary.html.haml +++ b/app/views/split_checkout/_summary.html.haml @@ -74,7 +74,7 @@ - if any_terms_required?(@order.distributor) = render partial: "terms_and_conditions", locals: { f: f } -%div.checkout-submit.medium-6 +%div.checkout-submit.medium-6.checkout-step3 = f.submit t("split_checkout.step3.submit"), name: "confirm_order", class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false %a.button.cancel{href: main_app.cart_path} = t("split_checkout.step3.cancel") diff --git a/app/webpacker/css/darkswarm/split-checkout.scss b/app/webpacker/css/darkswarm/split-checkout.scss index 1ede2db116..49e6d18769 100644 --- a/app/webpacker/css/darkswarm/split-checkout.scss +++ b/app/webpacker/css/darkswarm/split-checkout.scss @@ -165,6 +165,38 @@ } } + .checkout-step3 { + padding-left: 15px; + padding-right: 15px; + .checkout-submit { + margin-top: 0; + margin-bottom: 0; + padding-top: 2rem; + } + + &.sticked { + background-color: $white; + box-shadow: 0 -6px 12px -6px rgba(0, 0, 0, 0.33); + border-left: 1px solid $light-grey; + border-right: 1px solid $light-grey; + border-top: 1px solid $light-grey; + } + + @media screen and (max-width: 700px) { + &.sticked { + width: 100%; + width: auto; + box-shadow: 0 0px 10px 0px rgba(0, 0, 0, 0.33); + + .checkout-submit { + width: 100%; + padding-left: 15px; + padding-right: 15px; + } + } + } + } + .checkout-submit { margin-top: 5rem; margin-bottom: 5rem; From 293bc10dde82fc207a7671fe70cfd557b7a7d85d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bellet Date: Tue, 21 Dec 2021 15:43:49 +0100 Subject: [PATCH 35/51] Create a sticky controller that handle the sticky position of an element .. at the bottom And then add the sticked class to this element if the element is actually sticked --- .../controllers/sticky_controller.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 app/webpacker/controllers/sticky_controller.js diff --git a/app/webpacker/controllers/sticky_controller.js b/app/webpacker/controllers/sticky_controller.js new file mode 100644 index 0000000000..4c165bdd86 --- /dev/null +++ b/app/webpacker/controllers/sticky_controller.js @@ -0,0 +1,24 @@ +import { Controller } from "stimulus"; + +// This add a `sticked` class to the element (`container`) when the user scrolls down +// or up until the element is `sticked`. +// The class is then removed once the element is no more `sticked`. +// The element should have a `data-sticky-target` attribute with `container` as value. +// This is only functionnal with a sticked element at the bottom. We could improve that point +// by adding a `data-position` attribute with `top|bottom|left|right` as value and +// modify the code below to handle the different positions. +export default class extends Controller { + static targets = ["container"]; + + connect() { + this.containerTarget.style.position = "sticky"; + this.containerTarget.style.bottom = "-1px"; + const observer = new IntersectionObserver( + ([e]) => { + e.target.classList.toggle("sticked", e.intersectionRatio < 1); + }, + { threshold: [1] } + ); + observer.observe(this.containerTarget); + } +} From d8391aa1d326acb2efd4b23770e5d6f3ad0ffcf7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bellet Date: Tue, 21 Dec 2021 15:44:59 +0100 Subject: [PATCH 36/51] Create a div with a special class (checkout-step3) ... and attach the controller to it Add the T&Cs inside the sicked container with submit buttons --- app/views/split_checkout/_summary.html.haml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/views/split_checkout/_summary.html.haml b/app/views/split_checkout/_summary.html.haml index 8932bc1c70..b29d746714 100644 --- a/app/views/split_checkout/_summary.html.haml +++ b/app/views/split_checkout/_summary.html.haml @@ -71,10 +71,11 @@ = render 'spree/orders/summary', order: @order -- if any_terms_required?(@order.distributor) - = render partial: "terms_and_conditions", locals: { f: f } - -%div.checkout-submit.medium-6.checkout-step3 - = f.submit t("split_checkout.step3.submit"), name: "confirm_order", class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false - %a.button.cancel{href: main_app.cart_path} - = t("split_checkout.step3.cancel") +.checkout-step3{"data-controller": "sticky", "data-sticky-target": "container"} + - if any_terms_required?(@order.distributor) + = render partial: "terms_and_conditions", locals: { f: f } + .medium-6 + .checkout-submit + = f.submit t("split_checkout.step3.submit"), name: "confirm_order", class: "button primary", disabled: @terms_and_conditions_accepted == false || @platform_tos_accepted == false + %a.button.cancel{href: main_app.cart_path} + = t("split_checkout.step3.cancel") From fdeadd0940e8b72abcd23bcd33dc7e954a25d5b7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bellet Date: Tue, 21 Dec 2021 18:13:31 +0100 Subject: [PATCH 37/51] Reduce margin on step3 since the container could be a little too high --- app/webpacker/css/darkswarm/split-checkout.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/webpacker/css/darkswarm/split-checkout.scss b/app/webpacker/css/darkswarm/split-checkout.scss index 49e6d18769..c7f4b0d77c 100644 --- a/app/webpacker/css/darkswarm/split-checkout.scss +++ b/app/webpacker/css/darkswarm/split-checkout.scss @@ -172,6 +172,10 @@ margin-top: 0; margin-bottom: 0; padding-top: 2rem; + + .button { + margin-bottom: 1rem; + } } &.sticked { From ae0a71b29deb478b70b6d1bb2f2f773e37d0669a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bellet Date: Mon, 31 Jan 2022 11:47:21 +0100 Subject: [PATCH 38/51] This `row` adds an extra space on the right of the page which introduce an horizontal scroll: visual regression --- app/views/split_checkout/edit.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/split_checkout/edit.html.haml b/app/views/split_checkout/edit.html.haml index 7043b31543..b9dab1817f 100644 --- a/app/views/split_checkout/edit.html.haml +++ b/app/views/split_checkout/edit.html.haml @@ -19,7 +19,7 @@ .sub-header.show-for-medium-down = render partial: "shopping_shared/order_cycles" - .row{ "data-controller": "guest-checkout", "data-guest-checkout-distributor-value": @order.distributor.id } + %div{ "data-controller": "guest-checkout", "data-guest-checkout-distributor-value": @order.distributor.id } %div{ style: "display: #{spree_current_user ? 'block' : 'none'}", "data-guest-checkout-target": "checkout" } = render partial: "checkout" From da6be441f83e7d4e7c24596607223db2948824f7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bellet Date: Mon, 31 Jan 2022 11:47:35 +0100 Subject: [PATCH 39/51] Make sticky buttons fullwidth on mobile --- app/webpacker/css/darkswarm/split-checkout.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/webpacker/css/darkswarm/split-checkout.scss b/app/webpacker/css/darkswarm/split-checkout.scss index c7f4b0d77c..a653c2187f 100644 --- a/app/webpacker/css/darkswarm/split-checkout.scss +++ b/app/webpacker/css/darkswarm/split-checkout.scss @@ -188,8 +188,9 @@ @media screen and (max-width: 700px) { &.sticked { - width: 100%; width: auto; + margin-left: -15px; + margin-right: -15px; box-shadow: 0 0px 10px 0px rgba(0, 0, 0, 0.33); .checkout-submit { From ddaac654efaa59d886313c9c44057e02ee37a189 Mon Sep 17 00:00:00 2001 From: "Nihal M. Kelanthodika" Date: Thu, 27 Jan 2022 16:11:06 +0530 Subject: [PATCH 40/51] Add specs for conversion of variant weight input into decimal/0.0 --- spec/models/spree/variant_spec.rb | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 548f82e1d8..73a1f79660 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -525,6 +525,38 @@ module Spree expect(product.master).to be_valid end end + + context "when the product's unit is non-weight" do + before do + product.update_attribute :variant_unit, 'volume' + product.reload + variant.reload + end + + it "sets weight to decimal before save if it's integer" do + variant.weight = 1 + variant.save! + expect(variant.weight).to eq 1.0 + end + + it "sets weight to 0.0 before save if it's nil" do + variant.weight = nil + variant.save! + expect(variant.weight).to eq 0.0 + end + + it "sets weight to 0.0 if input is a non numerical string" do + variant.weight = "BANANAS!" + variant.save! + expect(variant.weight).to eq 0.0 + end + + it "sets weight to correct decimal value if input is numerical string" do + variant.weight = "2" + variant.save! + expect(variant.weight).to eq 2.0 + end + end end describe "unit value/description" do From d97381548a4cab9c83c30193150b656cdc6fe1df Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bellet Date: Mon, 31 Jan 2022 15:50:37 +0100 Subject: [PATCH 41/51] Specify a min width for radio --- app/webpacker/css/darkswarm/split-checkout.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/webpacker/css/darkswarm/split-checkout.scss b/app/webpacker/css/darkswarm/split-checkout.scss index 1ede2db116..f51df66f8e 100644 --- a/app/webpacker/css/darkswarm/split-checkout.scss +++ b/app/webpacker/css/darkswarm/split-checkout.scss @@ -136,6 +136,10 @@ display: flex; align-items: center; + input[type=radio] { + min-width: 12px; + } + label { margin-top: 0.3rem; } From 5e6dd1e6e1facc47b5fdf581ea335c6d57530c3a Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sat, 29 Jan 2022 12:10:55 +0000 Subject: [PATCH 42/51] Move #check_order_cycle_expiry method to OrderStockCheck and don't call it from BaseController :before_action callback --- app/controllers/application_controller.rb | 11 ----------- app/controllers/base_controller.rb | 1 - app/controllers/concerns/order_stock_check.rb | 11 +++++++++++ spec/controllers/base_controller_spec.rb | 13 ------------- spec/controllers/checkout_controller_spec.rb | 14 ++++++++++++++ 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0b8b45d19f..d62aa2b9d9 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -139,17 +139,6 @@ class ApplicationController < ActionController::Base !current_distributor.ready_for_checkout? end - def check_order_cycle_expiry - if current_order_cycle&.closed? - Bugsnag.notify("Notice: order cycle closed during checkout completion", order: current_order) - current_order.empty! - current_order.set_order_cycle! nil - flash[:info] = I18n.t('order_cycle_closed') - - redirect_to main_app.shop_path - end - end - # All render calls within the block will be performed with the specified format # Useful for rendering html within a JSON response, particularly if the specified # template or partial then goes on to render further partials without specifying diff --git a/app/controllers/base_controller.rb b/app/controllers/base_controller.rb index beaf68ef28..7816066b8b 100644 --- a/app/controllers/base_controller.rb +++ b/app/controllers/base_controller.rb @@ -12,7 +12,6 @@ class BaseController < ApplicationController include OrderCyclesHelper before_action :set_locale - before_action :check_order_cycle_expiry private diff --git a/app/controllers/concerns/order_stock_check.rb b/app/controllers/concerns/order_stock_check.rb index a3c09d1838..3a46ee9ea0 100644 --- a/app/controllers/concerns/order_stock_check.rb +++ b/app/controllers/concerns/order_stock_check.rb @@ -18,6 +18,17 @@ module OrderStockCheck redirect_to main_app.cart_path end + def check_order_cycle_expiry + if current_order_cycle&.closed? + Bugsnag.notify("Notice: order cycle closed during checkout completion", order: current_order) + current_order.empty! + current_order.set_order_cycle! nil + flash[:info] = I18n.t('order_cycle_closed') + + redirect_to main_app.shop_path + end + end + private def sufficient_stock? diff --git a/spec/controllers/base_controller_spec.rb b/spec/controllers/base_controller_spec.rb index 98d6183ea4..edad99c70b 100644 --- a/spec/controllers/base_controller_spec.rb +++ b/spec/controllers/base_controller_spec.rb @@ -99,17 +99,4 @@ describe BaseController, type: :controller do controller.current_order(true) end end - - it "redirects to shopfront with message if order cycle is expired" do - expect(controller).to receive(:current_order_cycle).and_return(oc) - expect(controller).to receive(:current_order).and_return(order).at_least(:twice) - expect(oc).to receive(:closed?).and_return(true) - expect(order).to receive(:empty!) - expect(order).to receive(:set_order_cycle!).with(nil) - - get :index - - expect(response).to redirect_to shop_url - expect(flash[:info]).to eq I18n.t('order_cycle_closed') - end end diff --git a/spec/controllers/checkout_controller_spec.rb b/spec/controllers/checkout_controller_spec.rb index 844ffac75e..342c6444ee 100644 --- a/spec/controllers/checkout_controller_spec.rb +++ b/spec/controllers/checkout_controller_spec.rb @@ -25,6 +25,20 @@ describe CheckoutController, type: :controller do expect(response).to redirect_to shop_path end + it "redirects to shopfront with message if order cycle is expired" do + allow(controller).to receive(:current_distributor).and_return(distributor) + expect(controller).to receive(:current_order_cycle).and_return(order_cycle).at_least(:once) + expect(controller).to receive(:current_order).and_return(order).at_least(:once) + expect(order_cycle).to receive(:closed?).and_return(true) + expect(order).to receive(:empty!) + expect(order).to receive(:set_order_cycle!).with(nil) + + get :edit + + expect(response).to redirect_to shop_url + expect(flash[:info]).to eq I18n.t('order_cycle_closed') + end + it "redirects home with message if hub is not ready for checkout" do allow(distributor).to receive(:ready_for_checkout?) { false } allow(order).to receive_messages(distributor: distributor, order_cycle: order_cycle) From 11ed1574cae96983dbc51cf414863b91d727242b Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sat, 29 Jan 2022 12:15:30 +0000 Subject: [PATCH 43/51] Call #check_order_cycle_expiry in PaypalController and StripeController, but avoid it on #authorize action The authorize action is used for authorizing off-session payments where the order is *already complete* and the order cycle may have closed (backoffice and subscriptions). They are essentially asynchronous and not coupled to the current open/closed state of the order cycle. --- .../payment_gateways/paypal_controller.rb | 1 + .../payment_gateways/stripe_controller.rb | 1 + .../stripe_controller_spec.rb | 31 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/app/controllers/payment_gateways/paypal_controller.rb b/app/controllers/payment_gateways/paypal_controller.rb index 4519ef74e2..c0c41fd77d 100644 --- a/app/controllers/payment_gateways/paypal_controller.rb +++ b/app/controllers/payment_gateways/paypal_controller.rb @@ -8,6 +8,7 @@ module PaymentGateways before_action :destroy_orphaned_paypal_payments, only: :confirm before_action :load_checkout_order, only: [:express, :confirm] before_action :handle_insufficient_stock, only: [:express, :confirm] + before_action :check_order_cycle_expiry, only: [:express, :confirm] before_action :permit_parameters! after_action :reset_order_when_complete, only: :confirm diff --git a/app/controllers/payment_gateways/stripe_controller.rb b/app/controllers/payment_gateways/stripe_controller.rb index fc9cb1dd93..6cbd3ee871 100644 --- a/app/controllers/payment_gateways/stripe_controller.rb +++ b/app/controllers/payment_gateways/stripe_controller.rb @@ -7,6 +7,7 @@ module PaymentGateways before_action :load_checkout_order, only: :confirm before_action :validate_payment_intent, only: :confirm + before_action :check_order_cycle_expiry, only: :confirm before_action :validate_stock, only: :confirm def confirm diff --git a/spec/controllers/payment_gateways/stripe_controller_spec.rb b/spec/controllers/payment_gateways/stripe_controller_spec.rb index d1819cccfb..fe68206148 100644 --- a/spec/controllers/payment_gateways/stripe_controller_spec.rb +++ b/spec/controllers/payment_gateways/stripe_controller_spec.rb @@ -70,6 +70,22 @@ module PaymentGateways }.to change { Customer.count }.by(1) end + context "when the order cycle has closed" do + it "redirects to shopfront with message if order cycle is expired" do + allow(controller).to receive(:current_distributor).and_return(distributor) + expect(controller).to receive(:current_order_cycle).and_return(order_cycle) + expect(controller).to receive(:current_order).and_return(order).at_least(:once) + expect(order_cycle).to receive(:closed?).and_return(true) + expect(order).to receive(:empty!) + expect(order).to receive(:set_order_cycle!).with(nil) + + get :confirm, params: { payment_intent: "pi_123" } + + expect(response).to redirect_to shop_url + expect(flash[:info]).to eq I18n.t('order_cycle_closed') + end + end + context "using split checkout" do before do allow(Flipper).to receive(:enabled?).with(:split_checkout) { true } @@ -236,6 +252,21 @@ module PaymentGateways expect(payment.cvv_response_message).to be nil end end + + context "when the order cycle has closed" do + it "should still authorize the payment successfully" do + expect(order).to receive(:process_payments!) do + payment.complete! + end + + get :authorize, params: { order_number: order.number, payment_intent: payment_intent } + + expect(response).to redirect_to order_path(order) + payment.reload + expect(payment.state).to eq("completed") + expect(payment.cvv_response_message).to be nil + end + end end context "when the payment intent response has errors" do From 5b434ca7c40f3b793b77597586bda9ba341cc1cb Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Sat, 29 Jan 2022 12:57:51 +0000 Subject: [PATCH 44/51] Replace conditional with a guard clause --- app/controllers/concerns/order_stock_check.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/concerns/order_stock_check.rb b/app/controllers/concerns/order_stock_check.rb index 3a46ee9ea0..bcbb9fb87d 100644 --- a/app/controllers/concerns/order_stock_check.rb +++ b/app/controllers/concerns/order_stock_check.rb @@ -19,14 +19,14 @@ module OrderStockCheck end def check_order_cycle_expiry - if current_order_cycle&.closed? - Bugsnag.notify("Notice: order cycle closed during checkout completion", order: current_order) - current_order.empty! - current_order.set_order_cycle! nil - flash[:info] = I18n.t('order_cycle_closed') + return unless current_order_cycle&.closed? - redirect_to main_app.shop_path - end + Bugsnag.notify("Notice: order cycle closed during checkout completion", order: current_order) + current_order.empty! + current_order.set_order_cycle! nil + + flash[:info] = I18n.t('order_cycle_closed') + redirect_to main_app.shop_path end private From 81f5755e3d53ef827ad55cb08c2b08e8b782f477 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Mon, 31 Jan 2022 16:34:35 +0000 Subject: [PATCH 45/51] Add tests for tabs_controller --- .../stimulus/tabs_controller_test.js | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 spec/javascripts/stimulus/tabs_controller_test.js diff --git a/spec/javascripts/stimulus/tabs_controller_test.js b/spec/javascripts/stimulus/tabs_controller_test.js new file mode 100644 index 0000000000..a67296bd0b --- /dev/null +++ b/spec/javascripts/stimulus/tabs_controller_test.js @@ -0,0 +1,67 @@ +/** + * @jest-environment jsdom + */ + +import { Application } from "stimulus"; +import tabs_controller from "../../../app/webpacker/controllers/tabs_controller"; + +describe("TabsController", () => { + describe("#select", () => { + beforeEach(() => { + document.body.innerHTML = ` +
+ + + + +
+ Dogs content +
+
+ Cats content +
+
+ Birds content +
+
+ `; + + const application = Application.start(); + application.register("tabs", tabs_controller); + }); + + it("shows the corresponding content when a tab button is clicked", () => { + const dogs_button = document.querySelectorAll('button')[0]; + const cats_button = document.querySelectorAll('button')[1]; + const birds_button = document.querySelectorAll('button')[2]; + const dogs_content = document.querySelectorAll('.content-area')[0]; + const cats_content = document.querySelectorAll('.content-area')[1]; + const birds_content = document.querySelectorAll('.content-area')[2]; + + expect(dogs_content.hidden).toBe(false); + expect(cats_content.hidden).toBe(true); + expect(birds_content.hidden).toBe(true); + + expect(document.querySelectorAll('button.active').length).toBe(1); + expect(document.querySelectorAll('button.active')[0]).toBe(dogs_button); + + birds_button.click(); + + expect(dogs_content.hidden).toBe(true); + expect(cats_content.hidden).toBe(true); + expect(birds_content.hidden).toBe(false); + + expect(document.querySelectorAll('button.active').length).toBe(1); + expect(document.querySelectorAll('button.active')[0]).toBe(birds_button); + + cats_button.click(); + + expect(dogs_content.hidden).toBe(true); + expect(cats_content.hidden).toBe(false); + expect(birds_content.hidden).toBe(true); + + expect(document.querySelectorAll('button.active').length).toBe(1); + expect(document.querySelectorAll('button.active')[0]).toBe(cats_button); + }); + }); +}); From 5eb88e020cbd0b2cc680cf6a4d01395254c7a28e Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Mon, 31 Jan 2022 16:35:41 +0000 Subject: [PATCH 46/51] Extract/clarify methods in tabs_controller --- app/webpacker/controllers/tabs_controller.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/app/webpacker/controllers/tabs_controller.js b/app/webpacker/controllers/tabs_controller.js index 46f6935c57..9d9995b94e 100644 --- a/app/webpacker/controllers/tabs_controller.js +++ b/app/webpacker/controllers/tabs_controller.js @@ -3,19 +3,28 @@ import { Controller } from "stimulus"; export default class extends Controller { static targets = ["tab", "content"] - connect() { - this.setCurrentTab() - } - select(event) { this.setCurrentTab(this.tabTargets.indexOf(event.currentTarget)) } + // private + + connect() { + this.setCurrentTab() + } + setCurrentTab(tabIndex = 0) { + this.showSelectedContent(tabIndex) + this.setButtonActiveClass(tabIndex) + } + + showSelectedContent(tabIndex) { this.contentTargets.forEach((element, index) => { element.hidden = index !== tabIndex }) + } + setButtonActiveClass(tabIndex) { this.tabTargets.forEach((element, index) => { if(index === tabIndex) { element.classList.add("active") From f02c79751ce1afdc244cdbad0930ae509e1ef141 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Feb 2022 05:40:34 +0000 Subject: [PATCH 47/51] Bump @storybook/addon-docs from 6.4.14 to 6.4.17 Bumps [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/addons/docs) from 6.4.14 to 6.4.17. - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v6.4.17/addons/docs) --- updated-dependencies: - dependency-name: "@storybook/addon-docs" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 382 ++++-------------------------------------------------- 1 file changed, 27 insertions(+), 355 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7ae4d22e4d..eaaa575107 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2138,9 +2138,9 @@ ts-dedent "^2.0.0" "@storybook/addon-docs@^6.4.13": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.4.14.tgz#0be1faf6d0b4deae93e37a838a2aae197cead74a" - integrity sha512-MIZWfDG80kolo1lOGfMOzQlE3d0I3PBvz04u8v2UMB6k99msC55ZigZcyaKRQs3lwlVM6uUflNVnpTVuTUZNHA== + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.4.17.tgz#d5b78554137379e8761f9ffcaa9fcc64c7e41c2b" + integrity sha512-AyCl4chBJErIpGRUbk+bC/Xkvt57H3+pyrFdN7hOuR8erreBaFeFQBAtKZodxq0X4WlQKCKmHYCNZXxNaQOTvw== dependencies: "@babel/core" "^7.12.10" "@babel/generator" "^7.12.11" @@ -2151,21 +2151,21 @@ "@mdx-js/loader" "^1.6.22" "@mdx-js/mdx" "^1.6.22" "@mdx-js/react" "^1.6.22" - "@storybook/addons" "6.4.14" - "@storybook/api" "6.4.14" - "@storybook/builder-webpack4" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/components" "6.4.14" - "@storybook/core" "6.4.14" - "@storybook/core-events" "6.4.14" + "@storybook/addons" "6.4.17" + "@storybook/api" "6.4.17" + "@storybook/builder-webpack4" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/components" "6.4.17" + "@storybook/core" "6.4.17" + "@storybook/core-events" "6.4.17" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/csf-tools" "6.4.14" - "@storybook/node-logger" "6.4.14" - "@storybook/postinstall" "6.4.14" - "@storybook/preview-web" "6.4.14" - "@storybook/source-loader" "6.4.14" - "@storybook/store" "6.4.14" - "@storybook/theming" "6.4.14" + "@storybook/csf-tools" "6.4.17" + "@storybook/node-logger" "6.4.17" + "@storybook/postinstall" "6.4.17" + "@storybook/preview-web" "6.4.17" + "@storybook/source-loader" "6.4.17" + "@storybook/store" "6.4.17" + "@storybook/theming" "6.4.17" acorn "^7.4.1" acorn-jsx "^5.3.1" acorn-walk "^7.2.0" @@ -2269,81 +2269,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/builder-webpack4@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.4.14.tgz#77f45d164f5b93776fa154252706c6b73bd0edc5" - integrity sha512-hRzwdNNLxuyb0XPpvbTSkQuqG2frhog2SsjgPVXorsSMPr95owo9Nq9hp+TnywpvaR9lrPlESzhhv2sSR3blTw== - dependencies: - "@babel/core" "^7.12.10" - "@babel/plugin-proposal-class-properties" "^7.12.1" - "@babel/plugin-proposal-decorators" "^7.12.12" - "@babel/plugin-proposal-export-default-from" "^7.12.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" - "@babel/plugin-proposal-object-rest-spread" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.12.7" - "@babel/plugin-proposal-private-methods" "^7.12.1" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.12.1" - "@babel/plugin-transform-block-scoping" "^7.12.12" - "@babel/plugin-transform-classes" "^7.12.1" - "@babel/plugin-transform-destructuring" "^7.12.1" - "@babel/plugin-transform-for-of" "^7.12.1" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-transform-shorthand-properties" "^7.12.1" - "@babel/plugin-transform-spread" "^7.12.1" - "@babel/plugin-transform-template-literals" "^7.12.1" - "@babel/preset-env" "^7.12.11" - "@babel/preset-react" "^7.12.10" - "@babel/preset-typescript" "^7.12.7" - "@storybook/addons" "6.4.14" - "@storybook/api" "6.4.14" - "@storybook/channel-postmessage" "6.4.14" - "@storybook/channels" "6.4.14" - "@storybook/client-api" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/components" "6.4.14" - "@storybook/core-common" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/node-logger" "6.4.14" - "@storybook/preview-web" "6.4.14" - "@storybook/router" "6.4.14" - "@storybook/semver" "^7.3.2" - "@storybook/store" "6.4.14" - "@storybook/theming" "6.4.14" - "@storybook/ui" "6.4.14" - "@types/node" "^14.0.10" - "@types/webpack" "^4.41.26" - autoprefixer "^9.8.6" - babel-loader "^8.0.0" - babel-plugin-macros "^2.8.0" - babel-plugin-polyfill-corejs3 "^0.1.0" - case-sensitive-paths-webpack-plugin "^2.3.0" - core-js "^3.8.2" - css-loader "^3.6.0" - file-loader "^6.2.0" - find-up "^5.0.0" - fork-ts-checker-webpack-plugin "^4.1.6" - glob "^7.1.6" - glob-promise "^3.4.0" - global "^4.4.0" - html-webpack-plugin "^4.0.0" - pnp-webpack-plugin "1.6.4" - postcss "^7.0.36" - postcss-flexbugs-fixes "^4.2.1" - postcss-loader "^4.2.0" - raw-loader "^4.0.2" - stable "^0.1.8" - style-loader "^1.3.0" - terser-webpack-plugin "^4.2.3" - ts-dedent "^2.0.0" - url-loader "^4.1.1" - util-deprecate "^1.0.2" - webpack "4" - webpack-dev-middleware "^3.7.3" - webpack-filter-warnings-plugin "^1.2.1" - webpack-hot-middleware "^2.25.1" - webpack-virtual-modules "^0.2.2" - "@storybook/builder-webpack4@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.4.17.tgz#ad71aaa0a271941e2efe114d5bf7bc8feaa13dcf" @@ -2419,19 +2344,6 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.2.2" -"@storybook/channel-postmessage@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.4.14.tgz#ce719041768ea8c0d64b7edc32ec7c774fba9b19" - integrity sha512-z+fBi/eAAswELWOdlIFI9XXNjyxfguKyqKGSQ7qdz3eFyxeuWnxTa9aZsnLIXpPKY9QPydpBSJcIKUCdN6DbIg== - dependencies: - "@storybook/channels" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/core-events" "6.4.14" - core-js "^3.8.2" - global "^4.4.0" - qs "^6.10.0" - telejson "^5.3.2" - "@storybook/channel-postmessage@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.4.17.tgz#9f439bee440479bfe8f86092701b3b63afc5195a" @@ -2445,17 +2357,6 @@ qs "^6.10.0" telejson "^5.3.2" -"@storybook/channel-websocket@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-6.4.14.tgz#d71a4c8a4b36e2e89a4a3c56af3e0aa50353e02f" - integrity sha512-4Y6TDeYLzItGIaYKo3s6xxSmUF11j96dOX7n74ax45zcMhpp/XwG5i0FU1DtGb5PnhPxg+vJmKa1IgizzaWRYg== - dependencies: - "@storybook/channels" "6.4.14" - "@storybook/client-logger" "6.4.14" - core-js "^3.8.2" - global "^4.4.0" - telejson "^5.3.2" - "@storybook/channel-websocket@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-6.4.17.tgz#780cc68bb3a31069196b35a232013764cc2320a3" @@ -2485,32 +2386,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.4.14.tgz#d2053511971e06d70bba2accfbd1f6c0f2084e2a" - integrity sha512-hqdgE0zKVhcqG/8t/veJRgjsOT076LeKxoA+w2Ga4iU+reIGui/GvLsjvyFFTyOMHVeo2Ze4LW63oTYKF/I5iQ== - dependencies: - "@storybook/addons" "6.4.14" - "@storybook/channel-postmessage" "6.4.14" - "@storybook/channels" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/store" "6.4.14" - "@types/qs" "^6.9.5" - "@types/webpack-env" "^1.16.0" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.21" - memoizerific "^1.11.3" - qs "^6.10.0" - regenerator-runtime "^0.13.7" - store2 "^2.12.0" - synchronous-promise "^2.0.15" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/client-api@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.4.17.tgz#34476732eb4a698e7dcc774a21feca4529581889" @@ -2613,32 +2488,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/core-client@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-6.4.14.tgz#8f5dc6fe2295e479225bd396404a43679a15637e" - integrity sha512-e9pzKz52DVhmo8+sUEDvagwGKVqWZ6NQBIt3mBvd79/zXTPkFRnSVitOyYErqhgN1kuwocTg+2BigRr3H0qXaQ== - dependencies: - "@storybook/addons" "6.4.14" - "@storybook/channel-postmessage" "6.4.14" - "@storybook/channel-websocket" "6.4.14" - "@storybook/client-api" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/preview-web" "6.4.14" - "@storybook/store" "6.4.14" - "@storybook/ui" "6.4.14" - airbnb-js-shims "^2.2.1" - ansi-to-html "^0.6.11" - core-js "^3.8.2" - global "^4.4.0" - lodash "^4.17.21" - qs "^6.10.0" - regenerator-runtime "^0.13.7" - ts-dedent "^2.0.0" - unfetch "^4.2.0" - util-deprecate "^1.0.2" - "@storybook/core-client@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-6.4.17.tgz#baff9629a0723f9485d608c00357d45921a78a0d" @@ -2789,54 +2638,6 @@ dependencies: core-js "^3.8.2" -"@storybook/core-server@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.4.14.tgz#0bef36e1203eb56e1c9bbf7f02122500c8f7d534" - integrity sha512-SzO8SaLTZ36Q4PNhJD4XJjlnonbR2Os0gzTknDBbwyIRPUtFUdk6isSG14RM5yYWPM0QQIs9og5ztSPX58YZlw== - dependencies: - "@discoveryjs/json-ext" "^0.5.3" - "@storybook/builder-webpack4" "6.4.14" - "@storybook/core-client" "6.4.14" - "@storybook/core-common" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/csf-tools" "6.4.14" - "@storybook/manager-webpack4" "6.4.14" - "@storybook/node-logger" "6.4.14" - "@storybook/semver" "^7.3.2" - "@storybook/store" "6.4.14" - "@types/node" "^14.0.10" - "@types/node-fetch" "^2.5.7" - "@types/pretty-hrtime" "^1.0.0" - "@types/webpack" "^4.41.26" - better-opn "^2.1.1" - boxen "^5.1.2" - chalk "^4.1.0" - cli-table3 "^0.6.1" - commander "^6.2.1" - compression "^1.7.4" - core-js "^3.8.2" - cpy "^8.1.2" - detect-port "^1.3.0" - express "^4.17.1" - file-system-cache "^1.0.5" - fs-extra "^9.0.1" - globby "^11.0.2" - ip "^1.1.5" - lodash "^4.17.21" - node-fetch "^2.6.1" - pretty-hrtime "^1.0.3" - prompts "^2.4.0" - regenerator-runtime "^0.13.7" - serve-favicon "^2.5.0" - slash "^3.0.0" - telejson "^5.3.3" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - watchpack "^2.2.0" - webpack "4" - ws "^8.2.3" - "@storybook/core-server@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.4.17.tgz#16f31635565c19248a45a793a7c2150597f3a4cc" @@ -2885,14 +2686,6 @@ webpack "4" ws "^8.2.3" -"@storybook/core@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.4.14.tgz#c20a1432f22603eb2d3523389ff1311fffbba24f" - integrity sha512-41WNDXKMZuCKnvbLBBYCd1+ip4uJ4AGeCOhmp/KZK7TgkitJ0JrvyRgnbpXR8bAMiOv2Hh9t9Vmi5D3QZ8COlg== - dependencies: - "@storybook/core-client" "6.4.14" - "@storybook/core-server" "6.4.14" - "@storybook/core@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.4.17.tgz#61892e2eb484a44fc9d69515c3068b1f64173327" @@ -2901,29 +2694,6 @@ "@storybook/core-client" "6.4.17" "@storybook/core-server" "6.4.17" -"@storybook/csf-tools@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-6.4.14.tgz#c5112e17f07dae4c7b922aefd45dccbbc9e49803" - integrity sha512-mRFsIhzFA2JBeUqdvl6+WM6HmHXaWGLbCgalzGqX65i1pSvhmC3jHh0OTTypMj9XneWH6/cHQh7LvivYbjJ8Cg== - dependencies: - "@babel/core" "^7.12.10" - "@babel/generator" "^7.12.11" - "@babel/parser" "^7.12.11" - "@babel/plugin-transform-react-jsx" "^7.12.12" - "@babel/preset-env" "^7.12.11" - "@babel/traverse" "^7.12.11" - "@babel/types" "^7.12.11" - "@mdx-js/mdx" "^1.6.22" - "@storybook/csf" "0.0.2--canary.87bc651.0" - core-js "^3.8.2" - fs-extra "^9.0.1" - global "^4.4.0" - js-string-escape "^1.0.1" - lodash "^4.17.21" - prettier ">=2.2.1 <=2.3.0" - regenerator-runtime "^0.13.7" - ts-dedent "^2.0.0" - "@storybook/csf-tools@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-6.4.17.tgz#e7d2b9de95317d706657c294d7beee1d7b307ec4" @@ -2954,48 +2724,6 @@ dependencies: lodash "^4.17.15" -"@storybook/manager-webpack4@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/manager-webpack4/-/manager-webpack4-6.4.14.tgz#b8ca3a11d0fb18ef6ca3e58e1c36b2eb8226ccbf" - integrity sha512-j565G7vZLBXK60J1hiZhbeZ6K48y8CMMZCcIihqsFv/4jj0kI3Ba4IhCrOkHiqiRM89mRu5/Ga3DnHTBvIYIEA== - dependencies: - "@babel/core" "^7.12.10" - "@babel/plugin-transform-template-literals" "^7.12.1" - "@babel/preset-react" "^7.12.10" - "@storybook/addons" "6.4.14" - "@storybook/core-client" "6.4.14" - "@storybook/core-common" "6.4.14" - "@storybook/node-logger" "6.4.14" - "@storybook/theming" "6.4.14" - "@storybook/ui" "6.4.14" - "@types/node" "^14.0.10" - "@types/webpack" "^4.41.26" - babel-loader "^8.0.0" - case-sensitive-paths-webpack-plugin "^2.3.0" - chalk "^4.1.0" - core-js "^3.8.2" - css-loader "^3.6.0" - express "^4.17.1" - file-loader "^6.2.0" - file-system-cache "^1.0.5" - find-up "^5.0.0" - fs-extra "^9.0.1" - html-webpack-plugin "^4.0.0" - node-fetch "^2.6.1" - pnp-webpack-plugin "1.6.4" - read-pkg-up "^7.0.1" - regenerator-runtime "^0.13.7" - resolve-from "^5.0.0" - style-loader "^1.3.0" - telejson "^5.3.2" - terser-webpack-plugin "^4.2.3" - ts-dedent "^2.0.0" - url-loader "^4.1.1" - util-deprecate "^1.0.2" - webpack "4" - webpack-dev-middleware "^3.7.3" - webpack-virtual-modules "^0.2.2" - "@storybook/manager-webpack4@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/manager-webpack4/-/manager-webpack4-6.4.17.tgz#8fc6d5dba0587446defe78ced67b7033886c4c47" @@ -3060,35 +2788,13 @@ npmlog "^5.0.1" pretty-hrtime "^1.0.3" -"@storybook/postinstall@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.4.14.tgz#e8f7925529d4955783660f409deee1e907897b2b" - integrity sha512-nLHV+BdDKFAZWU1CA/o3zRCNT3+tVWesERqkO9kJLURwqHkfU1yyv5WNILyUsvlwwJCFdDOEdXupC1RR7E6Gkg== +"@storybook/postinstall@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.4.17.tgz#f8a858b45e39d012ceb2054c1a8417f66dbb73e8" + integrity sha512-KHjhb3yRrATgYrVNeU/rdMRWXzXxFVFHtrtTo63D8LAoogX2g02DzLmtgqcoddp/JnSeHRtwEIbXnAExGYwb3Q== dependencies: core-js "^3.8.2" -"@storybook/preview-web@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/preview-web/-/preview-web-6.4.14.tgz#4d7035d5aa0e8c41c9a2ff21c2a3b3cbae9f3688" - integrity sha512-3E++OYz+OCyJBIchkNCJRtxEU7XNDBdIvKRTCx48X+Uv5qoLeCpXiXOSK/42LlraWZkfBs56yHv9VSqJoQ8VwA== - dependencies: - "@storybook/addons" "6.4.14" - "@storybook/channel-postmessage" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/store" "6.4.14" - ansi-to-html "^0.6.11" - core-js "^3.8.2" - global "^4.4.0" - lodash "^4.17.21" - qs "^6.10.0" - regenerator-runtime "^0.13.7" - synchronous-promise "^2.0.15" - ts-dedent "^2.0.0" - unfetch "^4.2.0" - util-deprecate "^1.0.2" - "@storybook/preview-web@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/preview-web/-/preview-web-6.4.17.tgz#d29bbfa8f66428ef5e2202c4c364c1892d8cbf7b" @@ -3178,13 +2884,13 @@ ts-dedent "^2.0.0" yaml-loader "^0.6.0" -"@storybook/source-loader@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-6.4.14.tgz#d1e6c2df0918e4867b3e4b5ce748685938f77d87" - integrity sha512-3hqVTK5+rQFK7Jf6/jYO/24daYIMn9L1vCAo9xSFgy999OMw7967ZmVMGMgVkOh7GQSZmzt3kMonv4bDmIGJMw== +"@storybook/source-loader@6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-6.4.17.tgz#d17e73f88f8c2a714fe129bf66ad692b4d4e0c97" + integrity sha512-OAETI21mL/jwmb9e/JtFDIsLWoOOWOAIm3Cj89XHQz/5VkYljZxdh2icb6xDHR8PtEaXj4+sBWQUG3L+a/a9QQ== dependencies: - "@storybook/addons" "6.4.14" - "@storybook/client-logger" "6.4.14" + "@storybook/addons" "6.4.17" + "@storybook/client-logger" "6.4.17" "@storybook/csf" "0.0.2--canary.87bc651.0" core-js "^3.8.2" estraverse "^5.2.0" @@ -3272,40 +2978,6 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" -"@storybook/ui@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.4.14.tgz#59f08ac8d8eb782fa13fc9a8dd715222c96bf234" - integrity sha512-nZsd8GXzYwmmTjZUB7pJMh+Q1fST0d2lFkhDHakxLaPLwumibw9NHJ7bRWYHFlAVYpD0c2+POP3FpOW5Bjby1A== - dependencies: - "@emotion/core" "^10.1.1" - "@storybook/addons" "6.4.14" - "@storybook/api" "6.4.14" - "@storybook/channels" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/components" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/router" "6.4.14" - "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.4.14" - copy-to-clipboard "^3.3.1" - core-js "^3.8.2" - core-js-pure "^3.8.2" - downshift "^6.0.15" - emotion-theming "^10.0.27" - fuse.js "^3.6.1" - global "^4.4.0" - lodash "^4.17.21" - markdown-to-jsx "^7.1.3" - memoizerific "^1.11.3" - polished "^4.0.5" - qs "^6.10.0" - react-draggable "^4.4.3" - react-helmet-async "^1.0.7" - react-sizeme "^3.0.1" - regenerator-runtime "^0.13.7" - resolve-from "^5.0.0" - store2 "^2.12.0" - "@storybook/ui@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.4.17.tgz#926aa1dbb4d3f9a28afe6edd6a0e5cb667be8e19" From 031258e1ee5c4b5ce8cadefcee8f381409239ffc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Feb 2022 06:06:09 +0000 Subject: [PATCH 48/51] Bump @storybook/addon-controls from 6.4.14 to 6.4.17 Bumps [@storybook/addon-controls](https://github.com/storybookjs/storybook/tree/HEAD/addons/controls) from 6.4.14 to 6.4.17. - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v6.4.17/addons/controls) --- updated-dependencies: - dependency-name: "@storybook/addon-controls" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 238 +++--------------------------------------------------- 1 file changed, 11 insertions(+), 227 deletions(-) diff --git a/yarn.lock b/yarn.lock index eaaa575107..e205a25593 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2120,19 +2120,19 @@ "@sinonjs/commons" "^1.7.0" "@storybook/addon-controls@^6.4.13": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-6.4.14.tgz#05a2d58175bf5af00d408386f18bcb2f62da431b" - integrity sha512-12d0Bw0TsueyaQOKMzWTm+G4d78yKXRdX7NP6q6h0HWdqGFdcsuZ60QcQh+GExR9z/M2laDSIijTBZtEJggWGQ== + version "6.4.17" + resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-6.4.17.tgz#8d3ac4a71b6c0cd7e863cb813ccc7184fd4c6cdc" + integrity sha512-THUzl+iTBi+joESO09mKbCe3063EVDysDGRHa/f7f6pND8306gLlcVDlFjYDX7F39V6h+1UpdDeNDdBL7yiGjQ== dependencies: - "@storybook/addons" "6.4.14" - "@storybook/api" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/components" "6.4.14" - "@storybook/core-common" "6.4.14" + "@storybook/addons" "6.4.17" + "@storybook/api" "6.4.17" + "@storybook/client-logger" "6.4.17" + "@storybook/components" "6.4.17" + "@storybook/core-common" "6.4.17" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/node-logger" "6.4.14" - "@storybook/store" "6.4.14" - "@storybook/theming" "6.4.14" + "@storybook/node-logger" "6.4.17" + "@storybook/store" "6.4.17" + "@storybook/theming" "6.4.17" core-js "^3.8.2" lodash "^4.17.21" ts-dedent "^2.0.0" @@ -2189,23 +2189,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addons@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.4.14.tgz#45d6937bc2ece33ceadc5358b2a2298d2a0d1e95" - integrity sha512-Snu42ejLyBAh6PWdlrdI72HKN1oKY7q0R9qEID2wk953WrqgGu4URakp14YLxghJCyKTSfGPs6LNZRRI6H5xgA== - dependencies: - "@storybook/api" "6.4.14" - "@storybook/channels" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/router" "6.4.14" - "@storybook/theming" "6.4.14" - "@types/webpack-env" "^1.16.0" - core-js "^3.8.2" - global "^4.4.0" - regenerator-runtime "^0.13.7" - "@storybook/addons@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.4.17.tgz#d040db3ddcf72fd9e7df8b8fce2a6dc88578c87e" @@ -2223,29 +2206,6 @@ global "^4.4.0" regenerator-runtime "^0.13.7" -"@storybook/api@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.4.14.tgz#a477646f7e020a362f044d2e614e3d1a86ba8f6f" - integrity sha512-GGGwB5+EquoausTXYx4dnLBBk2sOiS1Z58mDj0swBXCZdjfyUfLyxjxvvb/hl65ltufWP3IdmlKKaLiuARXNtw== - dependencies: - "@storybook/channels" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/router" "6.4.14" - "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.4.14" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.21" - memoizerific "^1.11.3" - regenerator-runtime "^0.13.7" - store2 "^2.12.0" - telejson "^5.3.2" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/api@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.4.17.tgz#82c3d756c85a65ecd8a3c3d9ce890e581175003a" @@ -2368,15 +2328,6 @@ global "^4.4.0" telejson "^5.3.2" -"@storybook/channels@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.4.14.tgz#f7a5416c971febd26ed7b03a75d99fd819790e48" - integrity sha512-3QOVxFG6ZAxDXCta1ie4SUPQ3s50yHeuZzVg6uPp+DcC1FrXeDFYBcU9t0j/jrSgbeKcnFHWxmRHNy1BRyWv/A== - dependencies: - core-js "^3.8.2" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/channels@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.4.17.tgz#95d05745a96b6059cea26d45aacca3967c401e26" @@ -2412,14 +2363,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-logger@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.4.14.tgz#a7aed982407e4146548f9ac4b3af5eba24cd045e" - integrity sha512-4VmFWZxhpeiG5fDhfqAyQbCfXZSBKS4fNKf35ABWiHStZRDndxml8K5WFtmOmMvVzjrGQx8HesenYMawK6xo/Q== - dependencies: - core-js "^3.8.2" - global "^4.4.0" - "@storybook/client-logger@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.4.17.tgz#50652859592c489b671f010455b8ce85d21a1b3d" @@ -2428,36 +2371,6 @@ core-js "^3.8.2" global "^4.4.0" -"@storybook/components@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.4.14.tgz#546b34fe3feb09e670b76ff71d889bf5f566f1e4" - integrity sha512-M7unerbOnvg+UN7qPxBCBWzK/boVdSSQxRiPAr1OL3M4OyEU8+TNPdQeAG0aF4zqtU0BrsDf4E85EznoMXUiFQ== - dependencies: - "@popperjs/core" "^2.6.0" - "@storybook/client-logger" "6.4.14" - "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/theming" "6.4.14" - "@types/color-convert" "^2.0.0" - "@types/overlayscrollbars" "^1.12.0" - "@types/react-syntax-highlighter" "11.0.5" - color-convert "^2.0.1" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.21" - markdown-to-jsx "^7.1.3" - memoizerific "^1.11.3" - overlayscrollbars "^1.13.1" - polished "^4.0.5" - prop-types "^15.7.2" - react-colorful "^5.1.2" - react-popper-tooltip "^3.1.1" - react-syntax-highlighter "^13.5.3" - react-textarea-autosize "^8.3.0" - regenerator-runtime "^0.13.7" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/components@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.4.17.tgz#5be383682d9538c35c96463723cb17740f105fb6" @@ -2514,61 +2427,6 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" -"@storybook/core-common@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-6.4.14.tgz#137b935855f0cc785ec55b386312747949e30e99" - integrity sha512-7NRmtcY2INmobsmUUX4afO78RHpyQMO8vboy6H8HRtfcw6fy4zaHoCb7gZZfvvn8gtBWNmwip8I9XK5BpRrh3Q== - dependencies: - "@babel/core" "^7.12.10" - "@babel/plugin-proposal-class-properties" "^7.12.1" - "@babel/plugin-proposal-decorators" "^7.12.12" - "@babel/plugin-proposal-export-default-from" "^7.12.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" - "@babel/plugin-proposal-object-rest-spread" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.12.7" - "@babel/plugin-proposal-private-methods" "^7.12.1" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.12.1" - "@babel/plugin-transform-block-scoping" "^7.12.12" - "@babel/plugin-transform-classes" "^7.12.1" - "@babel/plugin-transform-destructuring" "^7.12.1" - "@babel/plugin-transform-for-of" "^7.12.1" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-transform-shorthand-properties" "^7.12.1" - "@babel/plugin-transform-spread" "^7.12.1" - "@babel/preset-env" "^7.12.11" - "@babel/preset-react" "^7.12.10" - "@babel/preset-typescript" "^7.12.7" - "@babel/register" "^7.12.1" - "@storybook/node-logger" "6.4.14" - "@storybook/semver" "^7.3.2" - "@types/node" "^14.0.10" - "@types/pretty-hrtime" "^1.0.0" - babel-loader "^8.0.0" - babel-plugin-macros "^3.0.1" - babel-plugin-polyfill-corejs3 "^0.1.0" - chalk "^4.1.0" - core-js "^3.8.2" - express "^4.17.1" - file-system-cache "^1.0.5" - find-up "^5.0.0" - fork-ts-checker-webpack-plugin "^6.0.4" - fs-extra "^9.0.1" - glob "^7.1.6" - handlebars "^4.7.7" - interpret "^2.2.0" - json5 "^2.1.3" - lazy-universal-dotenv "^3.0.1" - picomatch "^2.3.0" - pkg-dir "^5.0.0" - pretty-hrtime "^1.0.3" - resolve-from "^5.0.0" - slash "^3.0.0" - telejson "^5.3.2" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - webpack "4" - "@storybook/core-common@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-6.4.17.tgz#bd2b14cfd1473f5f31f40c747afb62ea4a4ada6e" @@ -2624,13 +2482,6 @@ util-deprecate "^1.0.2" webpack "4" -"@storybook/core-events@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.4.14.tgz#37293c0fce703f2643cec6f24fc6ef7c40e30ded" - integrity sha512-9QFltg2mxTDjMBfmVtFHtrAEPY/i0oVp2kVdTWo6g05cPffYKAjNUnUVjUl7yiqcQmdEcdqUUQ0ut3xgmcYi/A== - dependencies: - core-js "^3.8.2" - "@storybook/core-events@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.4.17.tgz#ad70c883673a2060f1c7c4aa8f5926fc14119f4a" @@ -2766,17 +2617,6 @@ webpack-dev-middleware "^3.7.3" webpack-virtual-modules "^0.2.2" -"@storybook/node-logger@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.4.14.tgz#2e96f4e3e06c78c3d065e59818515209122d9ae4" - integrity sha512-mowC0adx4hLtCqGMQKRfNmiRYAL2PYdk3ojc91qzIKNrjSYnE4U8d9qlw5WLx1PKEnZVji3+QiYfNHpA/8PoKw== - dependencies: - "@types/npmlog" "^4.1.2" - chalk "^4.1.0" - core-js "^3.8.2" - npmlog "^5.0.1" - pretty-hrtime "^1.0.3" - "@storybook/node-logger@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.4.17.tgz#14fe3091b2030413c2f43f0de3e9408b27591d9c" @@ -2817,23 +2657,6 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" -"@storybook/router@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.4.14.tgz#46fd46eadafc0d6b647be13702704c5fcf8f11e3" - integrity sha512-5+tePyINtwPYm4izgOBZ2sX2ViWtfmmO2vwOAPlWWEGzsRosVQsGMdZv1R8rk4Jl/TotMjlTmd8I1/BufEeIeQ== - dependencies: - "@storybook/client-logger" "6.4.14" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - history "5.0.0" - lodash "^4.17.21" - memoizerific "^1.11.3" - qs "^6.10.0" - react-router "^6.0.0" - react-router-dom "^6.0.0" - ts-dedent "^2.0.0" - "@storybook/router@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.4.17.tgz#d53c4f9a4ccaa21a7bbe8d875a1a81c9dba2a6f2" @@ -2900,27 +2723,6 @@ prettier ">=2.2.1 <=2.3.0" regenerator-runtime "^0.13.7" -"@storybook/store@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/store/-/store-6.4.14.tgz#2ec5601e1c40a27f164b570d4c2b84c57d3a4115" - integrity sha512-D9KoJuNvwb9mEQD60GTPYSbQuXWZQHE8RBxCq7d7Qu46mrhlsNTOwt09lIgmuM3jAVto3FxnXY4U81RwJza7tg== - dependencies: - "@storybook/addons" "6.4.14" - "@storybook/client-logger" "6.4.14" - "@storybook/core-events" "6.4.14" - "@storybook/csf" "0.0.2--canary.87bc651.0" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.21" - memoizerific "^1.11.3" - regenerator-runtime "^0.13.7" - slash "^3.0.0" - stable "^0.1.8" - synchronous-promise "^2.0.15" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/store@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/store/-/store-6.4.17.tgz#a68b687628b82f8ca0ef2c74f5d65f5a30e94f86" @@ -2942,24 +2744,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/theming@6.4.14": - version "6.4.14" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.4.14.tgz#f034914eb1853a80f588c7c141d47af0595f6d1f" - integrity sha512-kqmXNnIoOSAS4cgr9PitMgVrOps725O99eTsJNxB6J1Ide0CsA5v2tV6AmQn/scnpCQNr8uSjZerNlEcl/ensg== - dependencies: - "@emotion/core" "^10.1.1" - "@emotion/is-prop-valid" "^0.8.6" - "@emotion/styled" "^10.0.27" - "@storybook/client-logger" "6.4.14" - core-js "^3.8.2" - deep-object-diff "^1.1.0" - emotion-theming "^10.0.27" - global "^4.4.0" - memoizerific "^1.11.3" - polished "^4.0.5" - resolve-from "^5.0.0" - ts-dedent "^2.0.0" - "@storybook/theming@6.4.17": version "6.4.17" resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.4.17.tgz#f0a03d2d3239638ac171e97a8f089ee2656a8287" From bbf10a71984b30fbc0a280ffaa040fddce538804 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Feb 2022 09:04:04 +0000 Subject: [PATCH 49/51] Bump karma from 6.3.12 to 6.3.13 Bumps [karma](https://github.com/karma-runner/karma) from 6.3.12 to 6.3.13. - [Release notes](https://github.com/karma-runner/karma/releases) - [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md) - [Commits](https://github.com/karma-runner/karma/compare/v6.3.12...v6.3.13) --- updated-dependencies: - dependency-name: karma dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index e205a25593..c518bcbd96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8227,9 +8227,9 @@ karma-jasmine@~0.3.8: integrity sha1-W2RXeRrZuJqhc/B54+vhuMgFI2w= karma@~6.3.11: - version "6.3.12" - resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.12.tgz#fe6347f027385fc16da1a9bb87d766e2d25981c6" - integrity sha512-qwIG+oB2YmHx4hjvYSRMNzL3YWAJ9baHaLAxiP7biFNkfpwYTUTtPck0joFpucalNLzMr+7z/FX1uY/kl8DV9A== + version "6.3.13" + resolved "https://registry.yarnpkg.com/karma/-/karma-6.3.13.tgz#ff58622c4f913508dbf86506a5fc614be0e98137" + integrity sha512-64lbtHBnM/sG7XKvitSQVlImKYNugyjw4K2e8cZYrlZm0GwoWrfsrkzgS/KWY/r3+fVM/2xvT/JN6MyfdttxLw== dependencies: body-parser "^1.19.0" braces "^3.0.2" @@ -8243,7 +8243,7 @@ karma@~6.3.11: http-proxy "^1.18.1" isbinaryfile "^4.0.8" lodash "^4.17.21" - log4js "^6.3.0" + log4js "^6.4.1" mime "^2.5.2" minimatch "^3.0.4" qjobs "^1.2.0" @@ -8413,10 +8413,10 @@ lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log4js@^6.3.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.4.0.tgz#3f63ccfc8033c83cd617a4d2d50e48be5944eae9" - integrity sha512-ysc/XUecZJuN8NoKOssk3V0cQ29xY4fra6fnigZa5VwxFsCsvdqsdnEuAxNN89LlHpbE4KUD3zGcn+kFqonSVQ== +log4js@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.4.1.tgz#9d3a8bf2c31c1e213fe3fc398a6053f7a2bc53e8" + integrity sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg== dependencies: date-format "^4.0.3" debug "^4.3.3" From 6468b7d98d00cb1129e4f43d272e13d5141e9540 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 3 Feb 2022 11:25:16 +1100 Subject: [PATCH 50/51] Spec image upload The use of AWS S3 was untested before and it failed after upgrading to Ruby 3. --- spec/models/spree/image_spec.rb | 74 +++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 spec/models/spree/image_spec.rb diff --git a/spec/models/spree/image_spec.rb b/spec/models/spree/image_spec.rb new file mode 100644 index 0000000000..75096792a8 --- /dev/null +++ b/spec/models/spree/image_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: false + +require 'spec_helper' + +module Spree + describe Image do + include FileHelper + + let(:file) { Rack::Test::UploadedFile.new(black_logo_file, 'image/png') } + let(:product) { create(:product) } + + describe "using local storage" do + it "stores a new image" do + image = Spree::Image.create!( + attachment: file, + viewable: product.master, + ) + + attachment = image.attachment + expect(attachment.exists?).to eq true + expect(attachment.file?).to eq true + expect(attachment.url).to match /logo-black\.png\?[0-9]+$/ + end + end + + describe "using AWS S3" do + let(:s3_config) { + { + url: ":s3_alias_url", + storage: :s3, + s3_credentials: { + access_key_id: "A...A", + secret_access_key: "H...H", + }, + s3_headers: { "Cache-Control" => "max-age=31557600" }, + bucket: "ofn", + s3_protocol: "https", + s3_host_alias: "ofn.s3.us-east-1.amazonaws.com", + + # This is for easier testing: + path: "/:id/:style/:basename.:extension", + } + } + around do |example| + original_config = Spree::Image.attachment_definitions + test_config = original_config.dup + test_config[:attachment].merge!(s3_config) + Spree::Image.attachment_definitions = test_config + + example.run + + Spree::Image.attachment_definitions = original_config + end + + it "saves a new image when none is present" do + pending "patch for aws-sdk to encode URIs" + + stub_request(:put, %r"https://ofn.s3.amazonaws.com/[0-9]+/(original|mini|small|product|large)/logo-black.png"). + to_return(status: 200, body: "", headers: {}) + stub_request(:head, %r"https://ofn.s3.amazonaws.com/[0-9]+/product/logo-black.png"). + to_return(status: 200, body: "", headers: {}) + image = Spree::Image.create!( + attachment: file, + viewable: product.master, + ) + + attachment = image.attachment + expect(attachment.exists?).to eq true + expect(attachment.file?).to eq true + expect(attachment.url).to match /logo-black\.png\?[0-9]+$/ + end + end + end +end From 2e6d8c12161d918940d02c8800b0ac41757b2a47 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 3 Feb 2022 11:26:34 +1100 Subject: [PATCH 51/51] Provide aws-sdk with working URI.encode method The S3 class is calling URI.encode which is removed in Ruby 3. By providing a URI module within the S3 class makes the S3 code call that module instead. --- config/initializers/aws_sdk.rb | 20 ++++++++++++++++++++ spec/models/spree/image_spec.rb | 28 +++++++++++++--------------- 2 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 config/initializers/aws_sdk.rb diff --git a/config/initializers/aws_sdk.rb b/config/initializers/aws_sdk.rb new file mode 100644 index 0000000000..cf49dc9bb5 --- /dev/null +++ b/config/initializers/aws_sdk.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: false + +if AWS::VERSION == "1.67.0" + module AWS + module Core + module Signers + # @api private + class S3 + module URI + def self.escape(string) + ::URI::RFC2396_Parser.new.escape(string) + end + end + end + end + end + end +else + Rails.logger.warn "The aws-sdk patch needs updating or removing." +end diff --git a/spec/models/spree/image_spec.rb b/spec/models/spree/image_spec.rb index 75096792a8..eba817048b 100644 --- a/spec/models/spree/image_spec.rb +++ b/spec/models/spree/image_spec.rb @@ -19,7 +19,7 @@ module Spree attachment = image.attachment expect(attachment.exists?).to eq true expect(attachment.file?).to eq true - expect(attachment.url).to match /logo-black\.png\?[0-9]+$/ + expect(attachment.url).to match %r"^/spree/products/[0-9]+/product/logo-black\.png\?[0-9]+$" end end @@ -41,24 +41,22 @@ module Spree path: "/:id/:style/:basename.:extension", } } - around do |example| - original_config = Spree::Image.attachment_definitions - test_config = original_config.dup - test_config[:attachment].merge!(s3_config) - Spree::Image.attachment_definitions = test_config - example.run - - Spree::Image.attachment_definitions = original_config + before do + attachment_definition = Spree::Image.attachment_definitions[:attachment] + allow(Spree::Image).to receive(:attachment_definitions).and_return( + attachment: attachment_definition.merge(s3_config) + ) end it "saves a new image when none is present" do - pending "patch for aws-sdk to encode URIs" + upload_pattern = %r"^https://ofn.s3.amazonaws.com/[0-9]+/(original|mini|small|product|large)/logo-black.png$" + download_pattern = %r"^https://ofn.s3.amazonaws.com/[0-9]+/product/logo-black.png$" + public_url_pattern = %r"^https://ofn.s3.us-east-1.amazonaws.com/[0-9]+/product/logo-black.png\?[0-9]+$" + + stub_request(:put, upload_pattern).to_return(status: 200, body: "", headers: {}) + stub_request(:head, download_pattern).to_return(status: 200, body: "", headers: {}) - stub_request(:put, %r"https://ofn.s3.amazonaws.com/[0-9]+/(original|mini|small|product|large)/logo-black.png"). - to_return(status: 200, body: "", headers: {}) - stub_request(:head, %r"https://ofn.s3.amazonaws.com/[0-9]+/product/logo-black.png"). - to_return(status: 200, body: "", headers: {}) image = Spree::Image.create!( attachment: file, viewable: product.master, @@ -67,7 +65,7 @@ module Spree attachment = image.attachment expect(attachment.exists?).to eq true expect(attachment.file?).to eq true - expect(attachment.url).to match /logo-black\.png\?[0-9]+$/ + expect(attachment.url).to match public_url_pattern end end end