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.
- checksums.yaml +4 -4
- data/README.md +7 -5
- data/app/assets/images/favicon.ico +0 -0
- data/app/assets/javascripts/spree/frontend/checkout/coupon-code.js +2 -1
- data/app/assets/stylesheets/spree/frontend/screen.css.scss +39 -1
- data/app/controllers/spree/checkout_controller.rb +61 -3
- data/app/controllers/spree/coupon_codes_controller.rb +35 -0
- data/app/controllers/spree/locale_controller.rb +1 -1
- data/app/controllers/spree/orders_controller.rb +27 -12
- data/app/controllers/spree/store_controller.rb +0 -18
- data/app/controllers/spree/taxons_controller.rb +6 -3
- data/app/views/spree/checkout/_coupon_code.html.erb +12 -0
- data/app/views/spree/checkout/_delivery.html.erb +6 -2
- data/app/views/spree/checkout/_payment.html.erb +0 -10
- data/app/views/spree/checkout/_summary.html.erb +4 -0
- data/app/views/spree/checkout/payment/_gateway.html.erb +6 -5
- data/app/views/spree/coupon_codes/new.html.erb +6 -0
- data/app/views/spree/orders/_form.html.erb +1 -1
- data/app/views/spree/orders/_line_item.html.erb +3 -5
- data/app/views/spree/orders/edit.html.erb +5 -6
- data/app/views/spree/products/_image.html.erb +4 -1
- data/app/views/spree/products/_thumbnails.html.erb +10 -8
- data/app/views/spree/shared/_image.html.erb +4 -4
- data/app/views/spree/shared/_locale_selector.html.erb +1 -1
- data/app/views/spree/shared/_order_details.html.erb +3 -5
- data/app/views/spree/shared/_products.html.erb +1 -1
- data/config/routes.rb +1 -0
- data/lib/spree/frontend.rb +1 -1
- data/solidus_frontend.gemspec +1 -1
- data/spec/controllers/spree/checkout_controller_spec.rb +109 -9
- data/spec/controllers/spree/checkout_controller_with_views_spec.rb +1 -1
- data/spec/controllers/spree/home_controller_spec.rb +1 -1
- data/spec/controllers/spree/orders_controller_ability_spec.rb +11 -30
- data/spec/controllers/spree/orders_controller_spec.rb +54 -3
- data/spec/controllers/spree/products_controller_spec.rb +3 -3
- data/spec/controllers/spree/taxons_controller_spec.rb +1 -1
- data/spec/features/address_spec.rb +1 -1
- data/spec/features/automatic_promotion_adjustments_spec.rb +2 -2
- data/spec/features/caching/taxons_spec.rb +1 -1
- data/spec/features/checkout_confirm_insufficient_stock_spec.rb +71 -0
- data/spec/features/checkout_spec.rb +34 -25
- data/spec/features/coupon_code_spec.rb +96 -56
- data/spec/features/currency_spec.rb +1 -1
- data/spec/features/first_order_promotion_spec.rb +59 -0
- data/spec/features/free_shipping_promotions_spec.rb +2 -2
- data/spec/features/products_spec.rb +8 -8
- data/spec/features/promotion_code_invalidation_spec.rb +2 -2
- data/spec/features/quantity_promotions_spec.rb +9 -9
- data/spec/spec_helper.rb +1 -1
- metadata +14 -9
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '021429976db5161133e0b99d6fe493da794d0b8c1a54062a3fe1f0dec420fb41'
|
4
|
+
data.tar.gz: 89e3e0326e2aced1f9d1107442816b64a2c554c719f883e408cfc0cb4597b820
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
```
|
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
|
-
```
|
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
|
-
```
|
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
|
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
|
-
|
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:
|
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:
|
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
|
-
|
204
|
-
|
205
|
-
|
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[
|
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
|
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
|
-
|
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
|
-
|
100
|
-
|
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',
|
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',
|
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>
|