solidus_frontend 2.6.5 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of solidus_frontend might be problematic. Click here for more details.

Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -5
  3. data/app/assets/images/favicon.ico +0 -0
  4. data/app/assets/javascripts/spree/frontend/checkout/coupon-code.js +2 -1
  5. data/app/assets/stylesheets/spree/frontend/screen.css.scss +39 -1
  6. data/app/controllers/spree/checkout_controller.rb +61 -3
  7. data/app/controllers/spree/coupon_codes_controller.rb +35 -0
  8. data/app/controllers/spree/locale_controller.rb +1 -1
  9. data/app/controllers/spree/orders_controller.rb +27 -12
  10. data/app/controllers/spree/store_controller.rb +0 -18
  11. data/app/controllers/spree/taxons_controller.rb +6 -3
  12. data/app/views/spree/checkout/_coupon_code.html.erb +12 -0
  13. data/app/views/spree/checkout/_delivery.html.erb +6 -2
  14. data/app/views/spree/checkout/_payment.html.erb +0 -10
  15. data/app/views/spree/checkout/_summary.html.erb +4 -0
  16. data/app/views/spree/checkout/payment/_gateway.html.erb +6 -5
  17. data/app/views/spree/coupon_codes/new.html.erb +6 -0
  18. data/app/views/spree/orders/_form.html.erb +1 -1
  19. data/app/views/spree/orders/_line_item.html.erb +3 -5
  20. data/app/views/spree/orders/edit.html.erb +5 -6
  21. data/app/views/spree/products/_image.html.erb +4 -1
  22. data/app/views/spree/products/_thumbnails.html.erb +10 -8
  23. data/app/views/spree/shared/_image.html.erb +4 -4
  24. data/app/views/spree/shared/_locale_selector.html.erb +1 -1
  25. data/app/views/spree/shared/_order_details.html.erb +3 -5
  26. data/app/views/spree/shared/_products.html.erb +1 -1
  27. data/config/routes.rb +1 -0
  28. data/lib/spree/frontend.rb +1 -1
  29. data/solidus_frontend.gemspec +1 -1
  30. data/spec/controllers/spree/checkout_controller_spec.rb +109 -9
  31. data/spec/controllers/spree/checkout_controller_with_views_spec.rb +1 -1
  32. data/spec/controllers/spree/home_controller_spec.rb +1 -1
  33. data/spec/controllers/spree/orders_controller_ability_spec.rb +11 -30
  34. data/spec/controllers/spree/orders_controller_spec.rb +54 -3
  35. data/spec/controllers/spree/products_controller_spec.rb +3 -3
  36. data/spec/controllers/spree/taxons_controller_spec.rb +1 -1
  37. data/spec/features/address_spec.rb +1 -1
  38. data/spec/features/automatic_promotion_adjustments_spec.rb +2 -2
  39. data/spec/features/caching/taxons_spec.rb +1 -1
  40. data/spec/features/checkout_confirm_insufficient_stock_spec.rb +71 -0
  41. data/spec/features/checkout_spec.rb +34 -25
  42. data/spec/features/coupon_code_spec.rb +96 -56
  43. data/spec/features/currency_spec.rb +1 -1
  44. data/spec/features/first_order_promotion_spec.rb +59 -0
  45. data/spec/features/free_shipping_promotions_spec.rb +2 -2
  46. data/spec/features/products_spec.rb +8 -8
  47. data/spec/features/promotion_code_invalidation_spec.rb +2 -2
  48. data/spec/features/quantity_promotions_spec.rb +9 -9
  49. data/spec/spec_helper.rb +1 -1
  50. metadata +14 -9
  51. data/spec/support/features/fill_in_with_force.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0afc7f4b4eedf6436cc5522b2dafda85c15464cbd604fdfc44c0cebaa1f26359
4
- data.tar.gz: cfec130241aaeeea4bb874778801e6fe04fc631a25f235a4e2ef82797168961f
3
+ metadata.gz: '021429976db5161133e0b99d6fe493da794d0b8c1a54062a3fe1f0dec420fb41'
4
+ data.tar.gz: 89e3e0326e2aced1f9d1107442816b64a2c554c719f883e408cfc0cb4597b820
5
5
  SHA512:
6
- metadata.gz: 88de1ce45b86e5a00d00c6ee8b900b0f0e9af70fae5bcfd4e375f43bac130ff67d57fe569d4f207ad647e8fe575dd99828032c25ea0d4dc72502fa632cbbf209
7
- data.tar.gz: b2a5c4a1514cc2254c0cba837929fade6773140f537d0a37f8228249cc678afcb3a6e4230bdcacf456fdae531e8f961c920f2f8434abad98396189ff03626cc9
6
+ metadata.gz: 274a3dceabef1220e03a11f56081ecfb9501076ef83b7a85b5efb7eaa1ee8858612dbcb516aa73451d89141f195dcfa55a64ef4a7601adedb77762ff7047655e
7
+ data.tar.gz: 53f65dd4e588101f31592f22401617e8cf871fa58c6e3ff1d025e9af0c533890e39cffe65d8e5cde3f8fdd60da845a027bf95ed6a462d209e03c71bd4a07666b
data/README.md CHANGED
@@ -11,19 +11,19 @@ Solidus provides a generator to help with copying the right view into your host
11
11
 
12
12
  Simply call the generator to copy all views into your host app.
13
13
 
14
- ```shell
14
+ ```bash
15
15
  $ bundle exec rails g solidus:views:override
16
16
  ```
17
17
 
18
18
  If you only want to copy certain views into your host app, you can provide the `--only` argument:
19
19
 
20
- ```shell
20
+ ```bash
21
21
  $ bundle exec rails g solidus:views:override --only products/show
22
22
  ```
23
23
 
24
24
  The argument to `--only` can also be a substring of the name of the view from the `app/views/spree` folder:
25
25
 
26
- ```shell
26
+ ```bash
27
27
  $ bundle exec rails g solidus:views:override --only product
28
28
  ```
29
29
 
@@ -31,10 +31,12 @@ This will copy all views whose directory or filename contains the string "produc
31
31
 
32
32
  ### Handle upgrades
33
33
 
34
- After upgrading solidus to a new version run the generator again and follow on screen instructions.
34
+ After upgrading Solidus to a new version run the generator again and follow on screen instructions.
35
35
 
36
36
  ## Testing
37
37
 
38
38
  Run the tests
39
39
 
40
- bundle exec rspec
40
+ ```bash
41
+ bundle exec rspec
42
+ ```
Binary file
@@ -1,4 +1,5 @@
1
1
  Spree.onCouponCodeApply = function(e) {
2
+ e.preventDefault();
2
3
  var couponCodeField = $("#order_coupon_code");
3
4
  var couponCode = $.trim(couponCodeField.val());
4
5
  if (couponCode === "") {
@@ -13,7 +14,7 @@ Spree.onCouponCodeApply = function(e) {
13
14
  coupon_code: couponCode
14
15
  };
15
16
  var req = Spree.ajax({
16
- method: "PUT",
17
+ method: 'POST',
17
18
  url: Spree.routes.apply_coupon_code(Spree.current_order_id),
18
19
  data: JSON.stringify(data),
19
20
  contentType: "application/json"
@@ -948,9 +948,35 @@ p[data-hook="use_billing"] {
948
948
  padding: 5px;
949
949
  }
950
950
 
951
+ .coupon-code {
952
+ margin-top: 20px;
953
+ padding: 10px;
954
+
955
+ form {
956
+ display: flex;
957
+ flex-flow: row wrap;
958
+ }
959
+
960
+ label {
961
+ flex: 1 100%;
962
+ text-align: left;
963
+ }
964
+
965
+ input[type="text"] {
966
+ flex: 3 0;
967
+ width: 100%;
968
+ margin-right: 5px;
969
+ }
970
+
971
+ &-apply-button {
972
+ white-space: nowrap;
973
+ }
974
+ }
975
+
951
976
  #coupon_status {
977
+ margin-top: 10px;
952
978
  font-weight: bold;
953
- font-size: 125%;
979
+ font-size: 100%;
954
980
  &.success {
955
981
  color: $c_green;
956
982
  }
@@ -1066,6 +1092,9 @@ div[data-hook="inside_cart_form"] {
1066
1092
  /*--------------------------------------*/
1067
1093
  #order_summary {
1068
1094
  margin-top: 0;
1095
+ h1 {
1096
+ padding-left: 10px;
1097
+ }
1069
1098
  }
1070
1099
  #order {
1071
1100
  p[data-hook="links"] {
@@ -1236,6 +1265,15 @@ table.order-summary {
1236
1265
 
1237
1266
  }
1238
1267
 
1268
+ // # Logo
1269
+ #logo {
1270
+ padding: 20px 0;
1271
+
1272
+ > a {
1273
+ display: inline-block;
1274
+ }
1275
+ }
1276
+
1239
1277
  @media only screen and (max-width: 767px) {
1240
1278
  #empty-cart {
1241
1279
  clear: both;
@@ -24,6 +24,7 @@ module Spree
24
24
  helper 'spree/orders'
25
25
 
26
26
  rescue_from Spree::Core::GatewayError, with: :rescue_from_spree_gateway_error
27
+ rescue_from Spree::Order::InsufficientStock, with: :insufficient_stock_error
27
28
 
28
29
  # Updates the order and advances to the next state (when possible.)
29
30
  def update
@@ -166,6 +167,24 @@ module Spree
166
167
  spree.order_path(@order)
167
168
  end
168
169
 
170
+ def apply_coupon_code
171
+ if update_params[:coupon_code].present?
172
+ Spree::Deprecation.warn('This endpoint is deprecated. Please use `Spree::CouponCodesController#create` endpoint instead.')
173
+ @order.coupon_code = update_params[:coupon_code]
174
+
175
+ handler = PromotionHandler::Coupon.new(@order).apply
176
+
177
+ if handler.error.present?
178
+ flash.now[:error] = handler.error
179
+ elsif handler.success
180
+ flash[:success] = handler.success
181
+ end
182
+
183
+ setup_for_current_state
184
+ respond_with(@order) { |format| format.html { render :edit } } && return
185
+ end
186
+ end
187
+
169
188
  def setup_for_current_state
170
189
  method_name = :"before_#{@order.state}"
171
190
  send(method_name) if respond_to?(method_name, true)
@@ -200,9 +219,14 @@ module Spree
200
219
  @wallet_payment_sources = try_spree_current_user.wallet.wallet_payment_sources
201
220
  @default_wallet_payment_source = @wallet_payment_sources.detect(&:default) ||
202
221
  @wallet_payment_sources.first
203
- # TODO: How can we deprecate this instance variable? We could try
204
- # wrapping it in a delegating object that produces deprecation warnings.
205
- @payment_sources = try_spree_current_user.wallet.wallet_payment_sources.map(&:payment_source).select { |ps| ps.is_a?(Spree::CreditCard) }
222
+
223
+ @payment_sources = Spree::DeprecatedInstanceVariableProxy.new(
224
+ self,
225
+ :deprecated_payment_sources,
226
+ :@payment_sources,
227
+ Spree::Deprecation,
228
+ "Please, do not use @payment_sources anymore, use @wallet_payment_sources instead."
229
+ )
206
230
  end
207
231
  end
208
232
 
@@ -215,5 +239,39 @@ module Spree
215
239
  def check_authorization
216
240
  authorize!(:edit, current_order, cookies.signed[:guest_token])
217
241
  end
242
+
243
+ def insufficient_stock_error
244
+ packages = @order.shipments.map(&:to_package)
245
+ if packages.empty?
246
+ flash[:error] = I18n.t('spree.insufficient_stock_for_order')
247
+ redirect_to cart_path
248
+ else
249
+ availability_validator = Spree::Stock::AvailabilityValidator.new
250
+ unavailable_items = @order.line_items.reject { |line_item| availability_validator.validate(line_item) }
251
+ if unavailable_items.any?
252
+ item_names = unavailable_items.map(&:name).to_sentence
253
+ flash[:error] = t('spree.inventory_error_flash_for_insufficient_shipment_quantity', unavailable_items: item_names)
254
+ @order.restart_checkout_flow
255
+ redirect_to spree.checkout_state_path(@order.state)
256
+ end
257
+ end
258
+ end
259
+
260
+ # This method returns payment sources of the current user. It is no more
261
+ # used into our frontend. We used to assign the content of this method
262
+ # into an ivar (@payment_sources) into the checkout payment step. This
263
+ # method is here only to be able to deprecate this ivar and will be removed.
264
+ #
265
+ # DO NOT USE THIS METHOD!
266
+ #
267
+ # @return [Array<Spree::PaymentSource>] Payment sources connected to
268
+ # current user wallet.
269
+ # @deprecated This method has been added to deprecate @payment_sources
270
+ # ivar and will be removed. Use @wallet_payment_sources instead.
271
+ def deprecated_payment_sources
272
+ try_spree_current_user.wallet.wallet_payment_sources
273
+ .map(&:payment_source)
274
+ .select { |ps| ps.is_a?(Spree::CreditCard) }
275
+ end
218
276
  end
219
277
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ class CouponCodesController < Spree::StoreController
5
+ before_action :load_order, only: :create
6
+ around_action :lock_order, only: :create
7
+
8
+ def create
9
+ authorize! :update, @order, cookies.signed[:guest_token]
10
+
11
+ if params[:coupon_code].present?
12
+ @order.coupon_code = params[:coupon_code]
13
+ handler = PromotionHandler::Coupon.new(@order).apply
14
+
15
+ respond_with(@order) do |format|
16
+ format.html do
17
+ if handler.successful?
18
+ flash[:success] = handler.success
19
+ redirect_to cart_path
20
+ else
21
+ flash.now[:error] = handler.error
22
+ render 'spree/coupon_codes/new'
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def load_order
32
+ @order = current_order
33
+ end
34
+ end
35
+ end
@@ -7,7 +7,7 @@ module Spree
7
7
  requested_locale = params[:switch_to_locale] || params[:locale]
8
8
 
9
9
  if requested_locale && available_locales.map(&:to_s).include?(requested_locale)
10
- session[:locale] = requested_locale
10
+ session[set_user_language_locale_key] = requested_locale
11
11
  I18n.locale = requested_locale
12
12
  flash.notice = t('spree.locale_changed')
13
13
  else
@@ -2,11 +2,11 @@
2
2
 
3
3
  module Spree
4
4
  class OrdersController < Spree::StoreController
5
- before_action :check_authorization
6
5
  helper 'spree/products', 'spree/orders'
7
6
 
8
7
  respond_to :html
9
8
 
9
+ before_action :store_guest_token
10
10
  before_action :assign_order, only: :update
11
11
  # note: do not lock the #edit action because that's where we redirect when we fail to acquire a lock
12
12
  around_action :lock_order, only: :update
@@ -15,9 +15,11 @@ module Spree
15
15
 
16
16
  def show
17
17
  @order = Spree::Order.find_by!(number: params[:id])
18
+ authorize! :read, @order, cookies.signed[:guest_token]
18
19
  end
19
20
 
20
21
  def update
22
+ authorize! :update, @order, cookies.signed[:guest_token]
21
23
  if @order.contents.update_cart(order_params)
22
24
  @order.next if params.key?(:checkout) && @order.cart?
23
25
 
@@ -38,12 +40,15 @@ module Spree
38
40
  # Shows the current incomplete order from the session
39
41
  def edit
40
42
  @order = current_order || Spree::Order.incomplete.find_or_initialize_by(guest_token: cookies.signed[:guest_token])
43
+ authorize! :read, @order, cookies.signed[:guest_token]
41
44
  associate_user
42
45
  end
43
46
 
44
47
  # Adds a new item to the order (creating a new order if none already exists)
45
48
  def populate
46
- @order = current_order(create_order_if_necessary: true)
49
+ @order = current_order(create_order_if_necessary: true)
50
+ authorize! :update, @order, cookies.signed[:guest_token]
51
+
47
52
  variant = Spree::Variant.find(params[:variant_id])
48
53
  quantity = params[:quantity].present? ? params[:quantity].to_i : 1
49
54
 
@@ -78,6 +83,7 @@ module Spree
78
83
 
79
84
  def empty
80
85
  if @order = current_order
86
+ authorize! :update, @order, cookies.signed[:guest_token]
81
87
  @order.empty!
82
88
  end
83
89
 
@@ -92,19 +98,12 @@ module Spree
92
98
  end
93
99
  end
94
100
 
95
- def check_authorization
96
- cookies.permanent.signed[:guest_token] = params[:token] if params[:token]
97
- order = Spree::Order.find_by(number: params[:id]) || current_order
101
+ private
98
102
 
99
- if order
100
- authorize! :edit, order, cookies.signed[:guest_token]
101
- else
102
- authorize! :create, Spree::Order
103
- end
103
+ def store_guest_token
104
+ cookies.permanent.signed[:guest_token] = params[:token] if params[:token]
104
105
  end
105
106
 
106
- private
107
-
108
107
  def order_params
109
108
  if params[:order]
110
109
  params[:order].permit(*permitted_order_attributes)
@@ -120,5 +119,21 @@ module Spree
120
119
  redirect_to(root_path) && return
121
120
  end
122
121
  end
122
+
123
+ def apply_coupon_code
124
+ if order_params[:coupon_code].present?
125
+ Spree::Deprecation.warn('This endpoint is deprecated. Please use `Spree::CouponCodesController#create` endpoint instead.')
126
+ @order.coupon_code = order_params[:coupon_code]
127
+
128
+ handler = PromotionHandler::Coupon.new(@order).apply
129
+
130
+ if handler.error.present?
131
+ flash.now[:error] = handler.error
132
+ respond_with(@order) { |format| format.html { render :edit } } && return
133
+ elsif handler.success
134
+ flash[:success] = handler.success
135
+ end
136
+ end
137
+ end
123
138
  end
124
139
  end
@@ -16,24 +16,6 @@ module Spree
16
16
 
17
17
  private
18
18
 
19
- # This method is placed here so that the CheckoutController
20
- # and OrdersController can both reference it (or any other controller
21
- # which needs it)
22
- def apply_coupon_code
23
- if params[:order] && params[:order][:coupon_code]
24
- @order.coupon_code = params[:order][:coupon_code]
25
-
26
- handler = PromotionHandler::Coupon.new(@order).apply
27
-
28
- if handler.error.present?
29
- flash.now[:error] = handler.error
30
- respond_with(@order) { |format| format.html { render :edit } } && return
31
- elsif handler.success
32
- flash[:success] = handler.success
33
- end
34
- end
35
- end
36
-
37
19
  def config_locale
38
20
  Spree::Frontend::Config[:locale]
39
21
  end
@@ -4,12 +4,11 @@ module Spree
4
4
  class TaxonsController < Spree::StoreController
5
5
  helper 'spree/products', 'spree/taxon_filters'
6
6
 
7
+ before_action :load_taxon, only: [:show]
8
+
7
9
  respond_to :html
8
10
 
9
11
  def show
10
- @taxon = Spree::Taxon.find_by!(permalink: params[:id])
11
- return unless @taxon
12
-
13
12
  @searcher = build_searcher(params.merge(taxon: @taxon.id, include_images: true))
14
13
  @products = @searcher.retrieve_products
15
14
  @taxonomies = Spree::Taxonomy.includes(root: :children)
@@ -17,6 +16,10 @@ module Spree
17
16
 
18
17
  private
19
18
 
19
+ def load_taxon
20
+ @taxon = Spree::Taxon.find_by!(permalink: params[:id])
21
+ end
22
+
20
23
  def accurate_title
21
24
  if @taxon
22
25
  @taxon.seo_title
@@ -0,0 +1,12 @@
1
+ <div class="coupon-code" data-hook='coupon_code'>
2
+ <%= form_for order, url: update_checkout_path(order.state) do |form| %>
3
+ <%= form.label :coupon_code %>
4
+ <%= form.text_field :coupon_code, placeholder: true %>
5
+
6
+ <button type="submit" class="button coupon-code-apply-button" id="coupon-code-apply-button">
7
+ <%= t('spree.apply_code') %>
8
+ </button>
9
+ <% end %>
10
+
11
+ <div id='coupon_status'></div>
12
+ </div>
@@ -27,7 +27,9 @@
27
27
  <% ship_form.object.manifest.each do |item| %>
28
28
  <tr class="stock-item">
29
29
  <td class="item-image">
30
- <%= render 'spree/shared/image', image: item.variant.display_image, size: :mini %>
30
+ <%= render 'spree/shared/image',
31
+ image: (item.variant.gallery.images.first || item.variant.product.gallery.images.first),
32
+ size: :mini %>
31
33
  </td>
32
34
  <td class="item-name"><%= item.variant.name %></td>
33
35
  <td class="item-qty"><%= item.quantity %></td>
@@ -75,7 +77,9 @@
75
77
  <% @differentiator.missing.each do |variant, quantity| %>
76
78
  <tr class="stock-item">
77
79
  <td class="item-image">
78
- <%= render 'spree/shared/image', image: variant.display_image, size: :mini %>
80
+ <%= render 'spree/shared/image',
81
+ image: (variant.gallery.images.first || variant.product.gallery.images.first),
82
+ size: :mini %>
79
83
  </td>
80
84
  <td class="item-name"><%= variant.name %></td>
81
85
  <td class="item-qty"><%= quantity %></td>