solidus_frontend 2.6.5 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.

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>