spree_core 4.2.0.rc5 → 4.2.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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/spree.js +16 -0
- data/app/finders/spree/products/find.rb +3 -3
- data/app/helpers/spree/base_helper.rb +2 -1
- data/app/helpers/spree/currency_helper.rb +24 -0
- data/app/helpers/spree/locale_helper.rb +15 -3
- data/app/models/concerns/spree/product_scopes.rb +1 -1
- data/app/models/spree/app_configuration.rb +1 -1
- data/app/models/spree/app_dependencies.rb +3 -1
- data/app/models/spree/credit_card.rb +4 -0
- data/app/models/spree/price.rb +1 -1
- data/app/models/spree/product.rb +17 -0
- data/app/models/spree/store.rb +19 -2
- data/app/models/spree/variant.rb +1 -1
- data/app/paginators/spree/shared/paginate.rb +8 -1
- data/app/services/spree/build_localized_redirect_url.rb +101 -0
- data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +13 -0
- data/app/views/spree/shared/_purchased_items_table.html.erb +15 -6
- data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +2 -2
- data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +1 -1
- data/config/locales/en.yml +7 -6
- data/db/migrate/20191017121054_add_supported_currencies_to_store.rb +1 -0
- data/db/migrate/20201012091259_add_filterable_column_to_spree_option_types.rb +6 -2
- data/db/migrate/20210205211040_add_supported_locales_to_spree_stores.rb +11 -0
- data/db/migrate/20210215202602_migrate_spree_i18n_globalize_config.rb +22 -0
- data/lib/generators/spree/install/install_generator.rb +9 -6
- data/lib/spree/core/controller_helpers/currency.rb +8 -6
- data/lib/spree/core/controller_helpers/locale.rb +13 -12
- data/lib/spree/core/controller_helpers/search.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/i18n.rb +12 -0
- data/lib/spree/permitted_attributes.rb +1 -1
- data/lib/spree/service_module.rb +2 -2
- data/lib/spree/testing_support/common_rake.rb +1 -1
- data/lib/spree/testing_support/controller_requests.rb +10 -10
- data/lib/spree/testing_support/factories/store_factory.rb +1 -0
- data/lib/spree/testing_support/flatpickr_capybara.rb +101 -0
- data/lib/spree/testing_support/locale_helpers.rb +71 -0
- data/lib/spree/testing_support/next_instance_of.rb +38 -0
- metadata +11 -6
- data/lib/generators/spree/install/templates/config/initializers/spree_storefront.rb +0 -1
- data/lib/generators/spree/install/templates/config/spree_storefront.yml +0 -67
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a59c1e362e580d2884f8c82e1c15d2cdf057e21b1efc66e1ede10ef4e41883a8
|
4
|
+
data.tar.gz: cfe5bc95ed8d23c91c0c19dace8fe3d96b015cbcd97af1c38524b73c94797cac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 420dbd7fdd44e2a4fa1d68d4d9e78a2fc42062757fc9470e57277bb7599fc3883b9e01a8052e5d0c34fb784361a5bc2b1b0b8e0e7bd7342860412e09e5799e70
|
7
|
+
data.tar.gz: 6b45c3c66e49701c0830b59e51ecb1776563abf078fc0728080479799dbbda443b4191c5f3af934cb663cdda6e824564b5891ec805950e87f949f0011b34430c
|
@@ -17,9 +17,25 @@ Spree.adminPath = function () {
|
|
17
17
|
|
18
18
|
Spree.pathFor = function (path) {
|
19
19
|
var locationOrigin = (window.location.protocol + '//' + window.location.hostname) + (window.location.port ? ':' + window.location.port : '')
|
20
|
+
|
20
21
|
return this.url('' + locationOrigin + (this.mountedAt()) + path, this.url_params).toString()
|
21
22
|
}
|
22
23
|
|
24
|
+
Spree.localizedPathFor = function(path) {
|
25
|
+
if (typeof (SPREE_LOCALE) !== 'undefined') {
|
26
|
+
if (path.match(/api\/v/)) {
|
27
|
+
if (path.match(/\?/)) {
|
28
|
+
path = path + '&locale=' + SPREE_LOCALE
|
29
|
+
} else {
|
30
|
+
path = path + '?locale=' + SPREE_LOCALE
|
31
|
+
}
|
32
|
+
} else {
|
33
|
+
path = SPREE_LOCALE + '/' + path
|
34
|
+
}
|
35
|
+
}
|
36
|
+
return Spree.pathFor(path)
|
37
|
+
}
|
38
|
+
|
23
39
|
Spree.adminPathFor = function (path) {
|
24
40
|
return this.pathFor('' + (this.adminPath()) + path)
|
25
41
|
}
|
@@ -7,7 +7,7 @@ module Spree
|
|
7
7
|
@ids = String(params.dig(:filter, :ids)).split(',')
|
8
8
|
@skus = String(params.dig(:filter, :skus)).split(',')
|
9
9
|
@price = String(params.dig(:filter, :price)).split(',').map(&:to_f)
|
10
|
-
@currency =
|
10
|
+
@currency = current_currency
|
11
11
|
@taxons = taxon_ids(params.dig(:filter, :taxons))
|
12
12
|
@concat_taxons = taxon_ids(params.dig(:filter, :concat_taxons))
|
13
13
|
@name = params.dig(:filter, :name)
|
@@ -103,7 +103,7 @@ module Spree
|
|
103
103
|
where(
|
104
104
|
spree_prices: {
|
105
105
|
amount: price.min..price.max,
|
106
|
-
currency: currency
|
106
|
+
currency: currency&.upcase
|
107
107
|
}
|
108
108
|
)
|
109
109
|
end
|
@@ -111,7 +111,7 @@ module Spree
|
|
111
111
|
def by_currency(products)
|
112
112
|
return products unless currency?
|
113
113
|
|
114
|
-
products.joins(master: :prices).where(spree_prices: { currency: currency })
|
114
|
+
products.joins(master: :prices).where(spree_prices: { currency: currency.upcase })
|
115
115
|
end
|
116
116
|
|
117
117
|
def by_taxons(products)
|
@@ -134,7 +134,8 @@ module Spree
|
|
134
134
|
[I18n.l(date.to_date, format: :long)].join(' ')
|
135
135
|
end
|
136
136
|
|
137
|
-
def seo_url(taxon, options =
|
137
|
+
def seo_url(taxon, options = {})
|
138
|
+
options.merge(locale: locale_param)
|
138
139
|
spree.nested_taxons_path(taxon.permalink, options)
|
139
140
|
end
|
140
141
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Spree
|
2
|
+
module CurrencyHelper
|
3
|
+
def currency_options(selected_value = nil)
|
4
|
+
selected_value ||= Spree::Config[:currency]
|
5
|
+
currencies = ::Money::Currency.table.map do |_code, details|
|
6
|
+
iso = details[:iso_code]
|
7
|
+
[iso, "#{details[:name]} (#{iso})"]
|
8
|
+
end
|
9
|
+
options_from_collection_for_select(currencies, :first, :last, selected_value)
|
10
|
+
end
|
11
|
+
|
12
|
+
def supported_currency_options
|
13
|
+
return if current_store.nil?
|
14
|
+
|
15
|
+
current_store.supported_currencies_list.map(&:iso_code)
|
16
|
+
end
|
17
|
+
|
18
|
+
def should_render_currency_dropdown?
|
19
|
+
return false if current_store.nil?
|
20
|
+
|
21
|
+
current_store.supported_currencies_list.size > 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -8,12 +8,24 @@ module Spree
|
|
8
8
|
available_locales.map { |locale| locale_presentation(locale) }
|
9
9
|
end
|
10
10
|
|
11
|
+
def supported_locales_options
|
12
|
+
return if current_store.nil?
|
13
|
+
|
14
|
+
current_store.supported_locales_list.map { |locale| locale_presentation(locale) }
|
15
|
+
end
|
16
|
+
|
11
17
|
def locale_presentation(locale)
|
12
|
-
if
|
13
|
-
[Spree.t('i18n.this_file_language', locale: locale), locale]
|
18
|
+
if I18n.exists?('spree.i18n.this_file_language', locale: locale)
|
19
|
+
[Spree.t('i18n.this_file_language', locale: locale), locale.to_s]
|
14
20
|
else
|
15
|
-
locale.to_s == 'en' ? ['English (US)',
|
21
|
+
locale.to_s == 'en' ? ['English (US)', 'en'] : [locale, locale.to_s]
|
16
22
|
end
|
17
23
|
end
|
24
|
+
|
25
|
+
def should_render_locale_dropdown?
|
26
|
+
return false if current_store.nil?
|
27
|
+
|
28
|
+
current_store.supported_locales_list.size > 1
|
29
|
+
end
|
18
30
|
end
|
19
31
|
end
|
@@ -69,7 +69,7 @@ module Spree
|
|
69
69
|
preference :credit_to_new_allocation, :boolean, default: false
|
70
70
|
|
71
71
|
# Multi store configurations
|
72
|
-
preference :show_store_selector, :boolean, default:
|
72
|
+
preference :show_store_selector, :boolean, default: false
|
73
73
|
|
74
74
|
# searcher_class allows spree extension writers to provide their own Search class
|
75
75
|
def searcher_class
|
@@ -13,7 +13,7 @@ module Spree
|
|
13
13
|
:completed_order_finder, :order_sorter, :cart_compare_line_items_service, :collection_paginator, :products_sorter,
|
14
14
|
:products_finder, :taxon_finder, :line_item_by_variant_finder, :cart_estimate_shipping_rates_service,
|
15
15
|
:account_create_address_service, :account_update_address_service, :address_finder,
|
16
|
-
:collection_sorter
|
16
|
+
:collection_sorter, :error_handler
|
17
17
|
].freeze
|
18
18
|
|
19
19
|
attr_accessor *INJECTION_POINTS
|
@@ -66,6 +66,8 @@ module Spree
|
|
66
66
|
# account
|
67
67
|
@account_create_address_service = 'Spree::Account::Addresses::Create'
|
68
68
|
@account_update_address_service = 'Spree::Account::Addresses::Update'
|
69
|
+
|
70
|
+
@error_handler = 'Spree::ErrorReporter'
|
69
71
|
end
|
70
72
|
|
71
73
|
def set_default_finders
|
data/app/models/spree/price.rb
CHANGED
data/app/models/spree/product.rb
CHANGED
@@ -90,6 +90,10 @@ module Spree
|
|
90
90
|
after_save :reset_nested_changes
|
91
91
|
after_touch :touch_taxons
|
92
92
|
|
93
|
+
# reset cache on save inside trasaction and transaction commit
|
94
|
+
after_save :reset_memoized_data
|
95
|
+
after_commit :reset_memoized_data
|
96
|
+
|
93
97
|
before_validation :normalize_slug, on: :update
|
94
98
|
before_validation :validate_master
|
95
99
|
|
@@ -127,6 +131,13 @@ module Spree
|
|
127
131
|
|
128
132
|
alias master_images images
|
129
133
|
|
134
|
+
def reload
|
135
|
+
%w(total_on_hand taxonomy_ids taxon_and_ancestors category category default_variant_id tax_category default_variant).each do |v|
|
136
|
+
instance_variable_set(:"@#{v}", nil)
|
137
|
+
end
|
138
|
+
super
|
139
|
+
end
|
140
|
+
|
130
141
|
# Cant use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
|
131
142
|
def purchasable?
|
132
143
|
variants_including_master.any?(&:purchasable?)
|
@@ -468,5 +479,11 @@ module Spree
|
|
468
479
|
errors.add(:discontinue_on, :invalid_date_range)
|
469
480
|
end
|
470
481
|
end
|
482
|
+
|
483
|
+
def reset_memoized_data
|
484
|
+
%w(total_on_hand taxonomy_ids taxon_and_ancestors category default_variant_id tax_category default_variant).each do |v|
|
485
|
+
instance_variable_set(:"@#{v}", nil)
|
486
|
+
end
|
487
|
+
end
|
471
488
|
end
|
472
489
|
end
|
data/app/models/spree/store.rb
CHANGED
@@ -24,6 +24,7 @@ module Spree
|
|
24
24
|
validates :mailer_logo, content_type: ['image/png', 'image/jpg', 'image/jpeg']
|
25
25
|
|
26
26
|
before_save :ensure_default_exists_and_is_unique
|
27
|
+
before_save :ensure_supported_currencies, :ensure_supported_locales
|
27
28
|
before_destroy :validate_not_default
|
28
29
|
|
29
30
|
scope :by_url, ->(url) { where('url like ?', "%#{url}%") }
|
@@ -50,14 +51,14 @@ module Spree
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def supported_currencies_list
|
53
|
-
@supported_currencies_list ||= (read_attribute(:supported_currencies).to_s.split(',') << default_currency).map(&:to_s).map do |code|
|
54
|
+
@supported_currencies_list ||= (read_attribute(:supported_currencies).to_s.split(',') << default_currency).sort.map(&:to_s).map do |code|
|
54
55
|
::Money::Currency.find(code.strip)
|
55
56
|
end.uniq.compact
|
56
57
|
end
|
57
58
|
|
58
59
|
def supported_locales_list
|
59
60
|
# TODO: add support of multiple supported languages to a single Store
|
60
|
-
@supported_locales_list ||=
|
61
|
+
@supported_locales_list ||= (read_attribute(:supported_locales).to_s.split(',') << default_locale).compact.uniq.sort
|
61
62
|
end
|
62
63
|
|
63
64
|
def unique_name
|
@@ -96,6 +97,22 @@ module Spree
|
|
96
97
|
end
|
97
98
|
end
|
98
99
|
|
100
|
+
def ensure_supported_locales
|
101
|
+
return unless attributes.keys.include?('supported_locales')
|
102
|
+
return if supported_locales.present?
|
103
|
+
return if default_locale.blank?
|
104
|
+
|
105
|
+
self.supported_locales = default_locale
|
106
|
+
end
|
107
|
+
|
108
|
+
def ensure_supported_currencies
|
109
|
+
return unless attributes.keys.include?('supported_currencies')
|
110
|
+
return if supported_currencies.present?
|
111
|
+
return if default_currency.blank?
|
112
|
+
|
113
|
+
self.supported_currencies = default_currency
|
114
|
+
end
|
115
|
+
|
99
116
|
def validate_not_default
|
100
117
|
if default
|
101
118
|
errors.add(:base, :cannot_destroy_default_store)
|
data/app/models/spree/variant.rb
CHANGED
@@ -192,7 +192,7 @@ module Spree
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def price_in(currency)
|
195
|
-
prices.detect { |price| price.currency == currency } || prices.build(currency: currency)
|
195
|
+
prices.detect { |price| price.currency == currency&.upcase } || prices.build(currency: currency&.upcase)
|
196
196
|
end
|
197
197
|
|
198
198
|
def amount_in(currency)
|
@@ -4,7 +4,14 @@ module Spree
|
|
4
4
|
def initialize(collection, params)
|
5
5
|
@collection = collection
|
6
6
|
@page = params[:page]
|
7
|
-
|
7
|
+
|
8
|
+
per_page_limit = Spree::Api::Config[:api_v2_per_page_limit]
|
9
|
+
|
10
|
+
@per_page = if params[:per_page].to_i.between?(1, per_page_limit)
|
11
|
+
params[:per_page]
|
12
|
+
else
|
13
|
+
Kaminari.config.default_per_page
|
14
|
+
end
|
8
15
|
end
|
9
16
|
|
10
17
|
def call
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Spree
|
4
|
+
class BuildLocalizedRedirectUrl
|
5
|
+
prepend Spree::ServiceModule::Base
|
6
|
+
|
7
|
+
LOCALE_REGEX = /^\/[A-Za-z]{2}\/|^\/[A-Za-z]{2}-[A-Za-z]{2}\/|^\/[A-Za-z]{2}$|^\/[A-Za-z]{2}-[A-Za-z]{2}$/.freeze
|
8
|
+
|
9
|
+
SUPPORTED_PATHS_REGEX = /\/(products|t\/|cart|checkout|addresses|content)/.freeze
|
10
|
+
|
11
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
12
|
+
def call(url:, locale:, default_locale: nil)
|
13
|
+
run :initialize_url_object
|
14
|
+
run :generate_new_path
|
15
|
+
run :append_locale_param
|
16
|
+
run :build_url
|
17
|
+
end
|
18
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def initialize_url_object(url:, locale:, default_locale:)
|
23
|
+
success(
|
24
|
+
url: URI(url),
|
25
|
+
locale: locale,
|
26
|
+
default_locale_supplied: default_locale_supplied?(locale, default_locale)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_new_path(url:, locale:, default_locale_supplied:)
|
31
|
+
unless supported_path?(url.path)
|
32
|
+
return success(
|
33
|
+
url: url,
|
34
|
+
locale: locale,
|
35
|
+
path: cleanup_path(url.path),
|
36
|
+
default_locale_supplied: default_locale_supplied,
|
37
|
+
locale_added_to_path: false
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
new_path = if default_locale_supplied
|
42
|
+
maches_locale_regex?(url.path) ? url.path.gsub(LOCALE_REGEX, '/') : url.path
|
43
|
+
else
|
44
|
+
maches_locale_regex?(url.path) ? url.path.gsub(LOCALE_REGEX, "/#{locale}/") : "/#{locale}#{url.path}"
|
45
|
+
end
|
46
|
+
|
47
|
+
success(
|
48
|
+
url: url,
|
49
|
+
locale: locale,
|
50
|
+
path: cleanup_path(new_path),
|
51
|
+
default_locale_supplied: default_locale_supplied,
|
52
|
+
locale_added_to_path: true
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
def append_locale_param(url:, locale:, path:, default_locale_supplied:, locale_added_to_path:)
|
57
|
+
return success(url: url, path: path, query: url.query) if locale_added_to_path
|
58
|
+
|
59
|
+
query_params = Rack::Utils.parse_nested_query(url.query)
|
60
|
+
|
61
|
+
if default_locale_supplied
|
62
|
+
query_params.delete('locale')
|
63
|
+
else
|
64
|
+
query_params.merge!('locale' => locale)
|
65
|
+
end
|
66
|
+
|
67
|
+
query_string = query_params.any? ? query_params.to_query : nil
|
68
|
+
|
69
|
+
success(url: url, path: path, query: query_string)
|
70
|
+
end
|
71
|
+
|
72
|
+
def build_url(url:, path:, query:)
|
73
|
+
localized_url = builder_class(url).build(host: url.host, port: url.port, path: path, query: query).to_s
|
74
|
+
success(localized_url)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def supported_path?(path)
|
80
|
+
return true if path.blank? || path == '/' || maches_locale_regex?(path)
|
81
|
+
|
82
|
+
path.match(SUPPORTED_PATHS_REGEX)
|
83
|
+
end
|
84
|
+
|
85
|
+
def maches_locale_regex?(path)
|
86
|
+
path.match(LOCALE_REGEX)[0].gsub('/', '') if path.match(LOCALE_REGEX)
|
87
|
+
end
|
88
|
+
|
89
|
+
def default_locale_supplied?(locale, default_locale)
|
90
|
+
default_locale.present? && default_locale.to_s == locale.to_s
|
91
|
+
end
|
92
|
+
|
93
|
+
def cleanup_path(path)
|
94
|
+
path.chomp('/').gsub('//', '/')
|
95
|
+
end
|
96
|
+
|
97
|
+
def builder_class(url)
|
98
|
+
url.scheme == 'http' ? URI::HTTP : URI::HTTPS
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -287,10 +287,20 @@
|
|
287
287
|
color: #333333;
|
288
288
|
}
|
289
289
|
|
290
|
+
.purchase_total--name {
|
291
|
+
margin: 0;
|
292
|
+
text-align: right;
|
293
|
+
color: #333333;
|
294
|
+
}
|
295
|
+
|
290
296
|
.purchase_total--label {
|
291
297
|
padding: 0 15px 0 0;
|
292
298
|
}
|
293
299
|
|
300
|
+
.purchase_total-col {
|
301
|
+
vertical-align: bottom;
|
302
|
+
}
|
303
|
+
|
294
304
|
body {
|
295
305
|
background-color: #F2F4F6;
|
296
306
|
color: #51545E;
|
@@ -400,6 +410,9 @@
|
|
400
410
|
.email-footer {
|
401
411
|
width: 100% !important;
|
402
412
|
}
|
413
|
+
.content-cell {
|
414
|
+
padding: 40px 15px !important;
|
415
|
+
}
|
403
416
|
}
|
404
417
|
|
405
418
|
@media (prefers-color-scheme: dark) {
|
@@ -8,10 +8,13 @@
|
|
8
8
|
<td></td>
|
9
9
|
<td>
|
10
10
|
<p class="f-fallback purchase_total purchase_total--label">
|
11
|
-
<%= Spree.t(:promotion)
|
11
|
+
<%= Spree.t(:promotion) %>:
|
12
|
+
</p>
|
13
|
+
<p class="f-fallback purchase_total--name purchase_total--label">
|
14
|
+
<%= label %>
|
12
15
|
</p>
|
13
16
|
</td>
|
14
|
-
<td>
|
17
|
+
<td class="purchase_total-col">
|
15
18
|
<p class="f-fallback purchase_total">
|
16
19
|
<%= Spree::Money.new(adjustments.sum(&:amount), currency: order.currency) %>
|
17
20
|
</p>
|
@@ -25,10 +28,13 @@
|
|
25
28
|
<td></td>
|
26
29
|
<td>
|
27
30
|
<p class="f-fallback purchase_total purchase_total--label">
|
28
|
-
<%= Spree.t(:shipping)
|
31
|
+
<%= Spree.t(:shipping) %>:
|
32
|
+
</p>
|
33
|
+
<p class="f-fallback purchase_total--name purchase_total--label">
|
34
|
+
<%= name %>
|
29
35
|
</p>
|
30
36
|
</td>
|
31
|
-
<td>
|
37
|
+
<td class="purchase_total-col">
|
32
38
|
<p class="f-fallback purchase_total">
|
33
39
|
<%= Spree::Money.new(shipments.sum(&:discounted_cost), currency: order.currency) %>
|
34
40
|
</p>
|
@@ -41,10 +47,13 @@
|
|
41
47
|
<td></td>
|
42
48
|
<td>
|
43
49
|
<p class="f-fallback purchase_total purchase_total--label">
|
44
|
-
<%= Spree.t(:tax)
|
50
|
+
<%= Spree.t(:tax) %>:
|
51
|
+
</p>
|
52
|
+
<p class="f-fallback purchase_total--name purchase_total--label">
|
53
|
+
<%= label %>
|
45
54
|
</p>
|
46
55
|
</td>
|
47
|
-
<td>
|
56
|
+
<td class="purchase_total-col">
|
48
57
|
<p class="f-fallback purchase_total">
|
49
58
|
<%= Spree::Money.new(adjustments.sum(&:amount), currency: order.currency) %>
|
50
59
|
</p>
|