spree_frontend 4.2.6 → 4.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/app/assets/config/spree_frontend_manifest.js +4 -0
- data/app/assets/images/card-image.svg +4 -0
- data/app/assets/images/file-image.svg +4 -0
- data/app/assets/images/image.svg +4 -0
- data/app/assets/images/noimage/large.png +0 -0
- data/app/assets/images/noimage/mini.png +0 -0
- data/app/assets/images/noimage/plp.svg +23 -0
- data/app/assets/images/noimage/product.png +0 -0
- data/app/assets/images/noimage/small.png +0 -0
- data/app/assets/javascripts/spree/api/main.js +36 -0
- data/app/assets/javascripts/spree/api/storefront/cart.js +49 -0
- data/app/assets/javascripts/spree/frontend/checkout/payment.js +18 -5
- data/app/assets/javascripts/spree/frontend/checkout.js +16 -0
- data/app/assets/javascripts/spree/frontend/locale.es6 +13 -0
- data/app/assets/javascripts/spree/frontend/views/spree/home/product_carousels.js +3 -3
- data/app/assets/javascripts/spree/frontend/views/spree/products/index.js +0 -9
- data/app/assets/javascripts/spree/frontend/views/spree/products/price_filters.es6 +46 -0
- data/app/assets/javascripts/spree/frontend.js +3 -0
- data/app/assets/javascripts/spree.js +78 -0
- data/app/assets/stylesheets/spree/frontend/application.scss +1 -0
- data/app/assets/stylesheets/spree/frontend/components-bootstrap/button.scss +8 -0
- data/app/assets/stylesheets/spree/frontend/helpers/spree/frontend_helper.scss +41 -0
- data/app/assets/stylesheets/spree/frontend/variables/variables.scss +2 -2
- data/app/assets/stylesheets/spree/frontend/views/spree/checkout/edit.scss +17 -5
- data/app/assets/stylesheets/spree/frontend/views/spree/cms_sections/_index.scss +1 -0
- data/app/assets/stylesheets/spree/frontend/views/spree/cms_sections/product_buy_bar.scss +20 -0
- data/app/assets/stylesheets/spree/frontend/views/spree/home/index.scss +54 -67
- data/app/assets/stylesheets/spree/frontend/views/spree/shared/category_nav_bar.scss +3 -3
- data/app/assets/stylesheets/spree/frontend/views/spree/shared/footer.scss +4 -0
- data/app/assets/stylesheets/spree/frontend/views/spree/shared/main_nav_bar.scss +12 -1
- data/app/controllers/spree/addresses_controller.rb +14 -19
- data/app/controllers/spree/checkout_controller.rb +5 -3
- data/app/controllers/spree/cms_pages_controller.rb +29 -0
- data/app/controllers/spree/content_controller.rb +0 -2
- data/app/controllers/spree/errors_controller.rb +11 -0
- data/app/controllers/spree/home_controller.rb +34 -1
- data/app/controllers/spree/locale_controller.rb +7 -1
- data/app/controllers/spree/orders_controller.rb +9 -7
- data/app/controllers/spree/products_controller.rb +14 -13
- data/app/controllers/spree/store_controller.rb +25 -1
- data/app/controllers/spree/taxons_controller.rb +12 -5
- data/app/helpers/spree/addresses_helper.rb +9 -4
- data/app/helpers/spree/cms_pages_helper.rb +23 -0
- data/app/helpers/spree/frontend_helper.rb +109 -10
- data/app/helpers/spree/navigation_helper.rb +73 -4
- data/app/helpers/spree/products_filters_helper.rb +168 -0
- data/app/helpers/spree/store_helper.rb +3 -1
- data/app/views/spree/checkout/_address.html.erb +1 -1
- data/app/views/spree/checkout/_credit_card.html.erb +1 -0
- data/app/views/spree/cms_pages/show.html.erb +16 -0
- data/app/views/spree/errors/forbidden.html.erb +0 -0
- data/app/views/spree/errors/unauthorized.html.erb +0 -0
- data/app/views/spree/home/index.html.erb +19 -118
- data/app/views/spree/layouts/spree_application.html.erb +1 -1
- data/app/views/spree/products/_description.html.erb +16 -19
- data/app/views/spree/products/_filters_desktop.html.erb +50 -15
- data/app/views/spree/products/_filters_mobile.html.erb +38 -10
- data/app/views/spree/products/_sort_desktop.html.erb +17 -11
- data/app/views/spree/products/_sort_mobile.html.erb +16 -0
- data/app/views/spree/products/index.html.erb +1 -1
- data/app/views/spree/shared/_carousel_4_products.html.erb +2 -2
- data/app/views/spree/shared/_checkout_header.html.erb +22 -21
- data/app/views/spree/shared/_copyright.html.erb +1 -1
- data/app/views/spree/shared/_footer.html.erb +15 -9
- data/app/views/spree/shared/_head.html.erb +1 -1
- data/app/views/spree/shared/_header.html.erb +3 -3
- data/app/views/spree/shared/_main_nav_bar.html.erb +61 -43
- data/app/views/spree/shared/_mobile_navigation.html.erb +30 -19
- data/app/views/spree/shared/_nav_bar.html.erb +1 -1
- data/app/views/spree/shared/_option_values.html.erb +2 -21
- data/app/views/spree/shared/_order_details.html.erb +1 -1
- data/app/views/spree/shared/_paths.html.erb +8 -0
- data/app/views/spree/shared/_properties.html.erb +4 -0
- data/app/views/spree/shared/_translations.html.erb +2 -1
- data/app/views/spree/shared/carousel/_single.html.erb +1 -1
- data/app/views/spree/shared/carousel/_thumbnails.html.erb +1 -1
- data/app/views/spree/shared/cms/pages/_edit_mode.html.erb +13 -0
- data/app/views/spree/shared/cms/sections/_featured_article.html.erb +27 -0
- data/app/views/spree/shared/cms/sections/_hero_image.html.erb +60 -0
- data/app/views/spree/shared/cms/sections/_image_gallery.html.erb +171 -0
- data/app/views/spree/shared/cms/sections/_product_carousel.html.erb +5 -0
- data/app/views/spree/shared/cms/sections/_rich_text_content.html.erb +3 -0
- data/app/views/spree/shared/cms/sections/_side_by_side_images.html.erb +118 -0
- data/app/views/spree/taxons/_header.html.erb +6 -1
- data/app/views/spree/users/show.html.erb +1 -1
- data/config/initializers/assets.rb +4 -13
- data/config/routes.rb +9 -3
- data/lib/generators/spree/frontend/install/install_generator.rb +5 -5
- data/lib/generators/spree/frontend/install/templates/app/assets/config/manifest.js +2 -0
- data/lib/generators/spree/frontend/install/templates/vendor/assets/javascripts/spree/frontend/all.js +8 -0
- data/lib/generators/spree/frontend/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +9 -0
- data/lib/spree/frontend/engine.rb +6 -0
- data/lib/spree/frontend.rb +6 -3
- data/spec/fixtures/files/store_favicon.ico +0 -0
- data/spree_frontend.gemspec +7 -3
- data/vendor/assets/javascripts/cleave.js +8 -0
- data/vendor/assets/javascripts/fetch.umd.js +531 -0
- data/vendor/assets/javascripts/jquery.payment.js +652 -0
- data/vendor/assets/javascripts/jsuri.js +458 -0
- data/vendor/assets/javascripts/polyfill.min.js +1 -0
- metadata +116 -70
- data/app/assets/images/homepage/big_category_banner.jpg +0 -0
- data/app/assets/images/homepage/big_category_banner_mobile.jpg +0 -0
- data/app/assets/images/homepage/big_category_banner_tablet_landscape.jpg +0 -0
- data/app/assets/images/homepage/big_category_banner_tablet_portrait.jpg +0 -0
- data/app/assets/images/homepage/category_banner_lower.jpg +0 -0
- data/app/assets/images/homepage/category_banner_lower_mobile.jpg +0 -0
- data/app/assets/images/homepage/category_banner_lower_tablet_landscape.jpg +0 -0
- data/app/assets/images/homepage/category_banner_lower_tablet_portrait.jpg +0 -0
- data/app/assets/images/homepage/category_banner_upper.jpg +0 -0
- data/app/assets/images/homepage/category_banner_upper_mobile.jpg +0 -0
- data/app/assets/images/homepage/category_banner_upper_tablet_landscape.jpg +0 -0
- data/app/assets/images/homepage/category_banner_upper_tablet_portrait.jpg +0 -0
- data/app/assets/images/homepage/main_banner.jpg +0 -0
- data/app/assets/images/homepage/main_banner_mobile.jpg +0 -0
- data/app/assets/images/homepage/main_banner_tablet_landscape.jpg +0 -0
- data/app/assets/images/homepage/main_banner_tablet_portrait.jpg +0 -0
- data/app/assets/images/homepage/promo_banner_left.jpg +0 -0
- data/app/assets/images/homepage/promo_banner_left_mobile.jpg +0 -0
- data/app/assets/images/homepage/promo_banner_left_tablet_landscape.jpg +0 -0
- data/app/assets/images/homepage/promo_banner_left_tablet_portrait.jpg +0 -0
- data/app/assets/images/homepage/promo_banner_right.jpg +0 -0
- data/app/assets/images/homepage/promo_banner_right_mobile.jpg +0 -0
- data/app/assets/images/homepage/promo_banner_right_tablet_landscape.jpg +0 -0
- data/app/assets/images/homepage/promo_banner_right_tablet_portrait.jpg +0 -0
- data/app/assets/images/meganav/promo_banner_left-first-category.jpg +0 -0
- data/app/assets/images/meganav/promo_banner_left-second-category.jpg +0 -0
- data/app/assets/images/meganav/promo_banner_left-third-category.jpg +0 -0
- data/app/assets/images/meganav/promo_banner_right-first-category.jpg +0 -0
- data/app/assets/images/meganav/promo_banner_right-second-category.jpg +0 -0
- data/app/assets/images/meganav/promo_banner_right-third-category.jpg +0 -0
- data/app/assets/images/noimage/big_category_banner.jpg +0 -0
- data/app/assets/images/noimage/big_category_banner_mobile.jpg +0 -0
- data/app/assets/images/noimage/big_category_banner_tablet_landscape.jpg +0 -0
- data/app/assets/images/noimage/big_category_banner_tablet_portrait.jpg +0 -0
- data/app/assets/images/noimage/category_banner.jpg +0 -0
- data/app/assets/images/noimage/category_banner_mobile.jpg +0 -0
- data/app/assets/images/noimage/category_banner_plp.jpg +0 -0
- data/app/assets/images/noimage/category_banner_tablet_landscape.jpg +0 -0
- data/app/assets/images/noimage/category_banner_tablet_portrait.jpg +0 -0
- data/app/assets/images/noimage/main_banner.jpg +0 -0
- data/app/assets/images/noimage/main_banner_mobile.jpg +0 -0
- data/app/assets/images/noimage/main_banner_tablet_landscape.jpg +0 -0
- data/app/assets/images/noimage/main_banner_tablet_portrait.jpg +0 -0
- data/app/assets/images/noimage/product_photo.jpg +0 -0
- data/app/assets/images/noimage/promo_banner.jpg +0 -0
- data/app/assets/images/noimage/promo_banner_megamenu.jpg +0 -0
- data/app/assets/images/noimage/promo_banner_mobile.jpg +0 -0
- data/app/assets/images/noimage/promo_banner_tablet_landscape.jpg +0 -0
- data/app/assets/images/noimage/promo_banner_tablet_portrait.jpg +0 -0
- data/app/assets/javascripts/spree/frontend/locale.js +0 -13
- data/app/assets/javascripts/spree/frontend/multi_currency.js +0 -13
- data/lib/generators/spree/frontend/install/templates/config/initializers/spree_storefront.rb +0 -1
- data/lib/generators/spree/frontend/install/templates/config/spree_storefront.yml +0 -99
@@ -22,7 +22,7 @@ module Spree
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def address_zipcode(form, country, address_id = 'b')
|
25
|
-
country ||=
|
25
|
+
country ||= address_default_country
|
26
26
|
is_required = country.zipcode_required?
|
27
27
|
method_name = Spree.t(:zipcode)
|
28
28
|
required = Spree.t(:required)
|
@@ -38,7 +38,7 @@ module Spree
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def address_state(form, country, address_id = 'b')
|
41
|
-
country ||=
|
41
|
+
country ||= address_default_country
|
42
42
|
have_states = country.states.any?
|
43
43
|
state_elements = [
|
44
44
|
form.collection_select(:state_id, checkout_zone_applicable_states_for(country).sort_by(&:name),
|
@@ -60,8 +60,9 @@ module Spree
|
|
60
60
|
class: [!have_states ? 'hidden' : nil, 'position-absolute spree-flat-select-arrow'].compact)
|
61
61
|
].join.tr('"', "'").delete("\n")
|
62
62
|
|
63
|
-
content_tag
|
64
|
-
|
63
|
+
content_tag :span, class: 'd-block position-relative' do
|
64
|
+
state_elements.html_safe
|
65
|
+
end
|
65
66
|
end
|
66
67
|
|
67
68
|
def user_available_addresses
|
@@ -80,5 +81,9 @@ module Spree
|
|
80
81
|
def checkout_zone_applicable_states_for(country)
|
81
82
|
current_store.states_available_for_checkout(country)
|
82
83
|
end
|
84
|
+
|
85
|
+
def address_default_country
|
86
|
+
@address_default_country ||= current_store.default_country
|
87
|
+
end
|
83
88
|
end
|
84
89
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Spree
|
2
|
+
module CmsPagesHelper
|
3
|
+
def simple_page?(page)
|
4
|
+
page.content.present? && !page.sections?
|
5
|
+
end
|
6
|
+
|
7
|
+
def section_tags(section, &block)
|
8
|
+
inner_content = content_tag(:div, class: section.css_classes, &block)
|
9
|
+
|
10
|
+
if section.fullscreen?
|
11
|
+
inner_content
|
12
|
+
else
|
13
|
+
content_tag(:div, inner_content, class: 'container')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def build_section(section)
|
18
|
+
section_tags(section) do
|
19
|
+
render "spree/shared/cms/sections/#{spree_resource_path(section)}", section: section
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module Spree
|
2
2
|
module FrontendHelper
|
3
|
+
include BaseHelper
|
3
4
|
include InlineSvg::ActionView::Helpers
|
4
5
|
|
5
6
|
def body_class
|
@@ -7,6 +8,22 @@ module Spree
|
|
7
8
|
@body_class
|
8
9
|
end
|
9
10
|
|
11
|
+
def logo(image_path = nil, options = {})
|
12
|
+
image_path ||= if current_store.logo.attached? && current_store.logo.variable?
|
13
|
+
main_app.url_for(current_store.logo.variant(resize: '244x104>'))
|
14
|
+
elsif current_store.logo.attached? && current_store.logo.image?
|
15
|
+
main_app.url_for(current_store.logo)
|
16
|
+
else
|
17
|
+
Spree::Config[:logo]
|
18
|
+
end
|
19
|
+
|
20
|
+
path = spree.respond_to?(:root_path) ? spree.root_path : main_app.root_path
|
21
|
+
|
22
|
+
link_to path, 'aria-label': current_store.name, method: options[:method] do
|
23
|
+
image_tag image_path, alt: current_store.name, title: current_store.name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
10
27
|
def spree_breadcrumbs(taxon, _separator = '', product = nil)
|
11
28
|
return '' if current_page?('/') || taxon.nil?
|
12
29
|
|
@@ -137,10 +154,10 @@ module Spree
|
|
137
154
|
end
|
138
155
|
|
139
156
|
def asset_exists?(path)
|
140
|
-
if Rails.
|
141
|
-
Rails.application.
|
157
|
+
if Rails.configuration.assets.compile
|
158
|
+
Rails.application.precompiled_assets.include? path
|
142
159
|
else
|
143
|
-
Rails.application.assets
|
160
|
+
Rails.application.assets_manifest.assets[path].present?
|
144
161
|
end
|
145
162
|
end
|
146
163
|
|
@@ -150,7 +167,7 @@ module Spree
|
|
150
167
|
image_url = if image.present?
|
151
168
|
main_app.url_for(image.url('plp'))
|
152
169
|
else
|
153
|
-
asset_path('noimage/plp.
|
170
|
+
asset_path('noimage/plp.svg')
|
154
171
|
end
|
155
172
|
|
156
173
|
image_style = image&.style(:plp)
|
@@ -228,6 +245,11 @@ module Spree
|
|
228
245
|
end
|
229
246
|
|
230
247
|
def price_filter_values
|
248
|
+
ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
|
249
|
+
`FrontendHelper#price_filter_values` is deprecated and will be removed in Spree 5.0.
|
250
|
+
Please use `ProductsFiltersHelper#price_filters` method
|
251
|
+
DEPRECATION
|
252
|
+
|
231
253
|
@price_filter_values ||= [
|
232
254
|
"#{I18n.t('activerecord.attributes.spree/product.less_than')} #{formatted_price(50)}",
|
233
255
|
"#{formatted_price(50)} - #{formatted_price(100)}",
|
@@ -250,18 +272,81 @@ module Spree
|
|
250
272
|
end
|
251
273
|
|
252
274
|
def filtering_params_cache_key
|
253
|
-
@filtering_params_cache_key ||=
|
275
|
+
@filtering_params_cache_key ||= begin
|
276
|
+
cache_key_parts = []
|
277
|
+
|
278
|
+
permitted_products_params.each do |key, value|
|
279
|
+
next if value.blank?
|
280
|
+
|
281
|
+
if value.is_a?(String)
|
282
|
+
cache_key_parts << [key, value].join('-')
|
283
|
+
else
|
284
|
+
value.each do |part_key, part_value|
|
285
|
+
next if part_value.blank?
|
286
|
+
|
287
|
+
cache_key_parts << [part_key, part_value].join('-')
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
cache_key_parts.join('-').parameterize
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def filters_cache_key(kind)
|
297
|
+
base_cache_key + [
|
298
|
+
kind,
|
299
|
+
available_option_types_cache_key,
|
300
|
+
available_properties_cache_key,
|
301
|
+
filtering_params_cache_key,
|
302
|
+
@taxon&.id,
|
303
|
+
params[:menu_open]
|
304
|
+
].flatten
|
305
|
+
end
|
306
|
+
|
307
|
+
def permitted_products_params
|
308
|
+
@permitted_products_params ||= begin
|
309
|
+
params.permit(*filtering_params, properties: available_properties.map(&:filter_param))
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
def option_type_cache_key(option_type)
|
314
|
+
filter_param = option_type.filter_param
|
315
|
+
filtered_params = params[filter_param]
|
316
|
+
|
317
|
+
[
|
318
|
+
available_option_types_cache_key,
|
319
|
+
filter_param,
|
320
|
+
filtered_params
|
321
|
+
]
|
254
322
|
end
|
255
323
|
|
256
324
|
def available_option_types_cache_key
|
257
|
-
@available_option_types_cache_key ||=
|
325
|
+
@available_option_types_cache_key ||= [
|
326
|
+
Spree::OptionType.filterable.maximum(:updated_at).to_f,
|
327
|
+
products_for_filters_cache_key
|
328
|
+
].flatten.join('/')
|
258
329
|
end
|
259
330
|
|
260
331
|
def available_option_types
|
261
332
|
@available_option_types ||= Rails.cache.fetch("available-option-types/#{available_option_types_cache_key}") do
|
262
|
-
|
333
|
+
option_values = OptionValues::FindAvailable.new(products_scope: products_for_filters).execute
|
334
|
+
Filters::OptionsPresenter.new(option_values_scope: option_values).to_a
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def available_properties_cache_key
|
339
|
+
@available_properties_cache_key ||= [
|
340
|
+
Spree::Property.filterable.maximum(:updated_at).to_f,
|
341
|
+
products_for_filters_cache_key
|
342
|
+
].flatten.join('/')
|
343
|
+
end
|
344
|
+
|
345
|
+
def available_properties
|
346
|
+
@available_properties ||= Rails.cache.fetch("available-properties/#{available_properties_cache_key}") do
|
347
|
+
product_properties = ProductProperties::FindAvailable.new(products_scope: products_for_filters).execute
|
348
|
+
Filters::PropertiesPresenter.new(product_properties_scope: product_properties).to_a
|
263
349
|
end
|
264
|
-
@available_option_types
|
265
350
|
end
|
266
351
|
|
267
352
|
def spree_social_link(service)
|
@@ -275,7 +360,7 @@ module Spree
|
|
275
360
|
end
|
276
361
|
|
277
362
|
def checkout_available_payment_methods
|
278
|
-
@checkout_available_payment_methods ||= @order.available_payment_methods
|
363
|
+
@checkout_available_payment_methods ||= @order.available_payment_methods
|
279
364
|
end
|
280
365
|
|
281
366
|
def color_option_type_name
|
@@ -305,7 +390,7 @@ module Spree
|
|
305
390
|
end
|
306
391
|
|
307
392
|
def checkout_edit_link(step = 'address', order = @order)
|
308
|
-
return if order.
|
393
|
+
return if order.uneditable?
|
309
394
|
|
310
395
|
classes = 'align-text-bottom checkout-confirm-delivery-informations-link'
|
311
396
|
|
@@ -313,5 +398,19 @@ module Spree
|
|
313
398
|
inline_svg_tag 'edit.svg'
|
314
399
|
end
|
315
400
|
end
|
401
|
+
|
402
|
+
def products_for_filters
|
403
|
+
@products_for_filters ||= current_store.products.for_filters(current_currency, taxon: @taxon)
|
404
|
+
end
|
405
|
+
|
406
|
+
def products_for_filters_cache_key
|
407
|
+
@products_for_filters_cache_key ||= begin
|
408
|
+
[
|
409
|
+
products_for_filters.maximum(:updated_at).to_f,
|
410
|
+
base_cache_key,
|
411
|
+
@taxon&.permalink
|
412
|
+
].flatten.compact
|
413
|
+
end
|
414
|
+
end
|
316
415
|
end
|
317
416
|
end
|
@@ -3,22 +3,46 @@ require 'digest'
|
|
3
3
|
module Spree
|
4
4
|
module NavigationHelper
|
5
5
|
def spree_navigation_data
|
6
|
-
|
6
|
+
ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
|
7
|
+
NavigationHelper#spree_navigation_data is deprecated and will be removed in Spree 5.0.
|
8
|
+
Please migrate to the new navigation cms system.
|
9
|
+
DEPRECATION
|
10
|
+
|
11
|
+
@spree_navigation_data ||= SpreeStorefrontConfig.dig(I18n.locale,
|
12
|
+
:navigation) || SpreeStorefrontConfig.dig(current_store.code,
|
13
|
+
:navigation) || SpreeStorefrontConfig.dig(
|
14
|
+
:default, :navigation
|
15
|
+
) || []
|
7
16
|
# safeguard for older Spree installs that don't have spree_navigation initializer
|
8
17
|
# or spree.yml file present
|
9
|
-
rescue
|
18
|
+
rescue StandardError
|
10
19
|
[]
|
11
20
|
end
|
12
21
|
|
13
22
|
def spree_nav_cache_key(section = 'header')
|
23
|
+
ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
|
24
|
+
NavigationHelper#spree_nav_cache_key is deprecated and will be removed in Spree 5.0.
|
25
|
+
Please migrate to the new navigation cms system.
|
26
|
+
DEPRECATION
|
27
|
+
|
14
28
|
@spree_nav_cache_key = begin
|
15
|
-
keys = base_cache_key + [current_store, spree_navigation_data_cache_key, Spree::Config[:logo], stores&.
|
29
|
+
keys = base_cache_key + [current_store, spree_navigation_data_cache_key, Spree::Config[:logo], stores&.cache_key_with_version, section]
|
16
30
|
Digest::MD5.hexdigest(keys.join('-'))
|
17
31
|
end
|
18
32
|
end
|
19
33
|
|
34
|
+
def spree_menu_cache_key(section = 'header')
|
35
|
+
keys = base_cache_key + [
|
36
|
+
current_store.cache_key_with_version,
|
37
|
+
spree_menu(section)&.cache_key_with_version,
|
38
|
+
stores&.maximum(:updated_at),
|
39
|
+
section
|
40
|
+
]
|
41
|
+
Digest::MD5.hexdigest(keys.join('-'))
|
42
|
+
end
|
43
|
+
|
20
44
|
def main_nav_image(image_path, title = '')
|
21
|
-
image_url = asset_path(asset_exists?(image_path) ? image_path : 'noimage/plp.
|
45
|
+
image_url = asset_path(asset_exists?(image_path) ? image_path : 'noimage/plp.svg')
|
22
46
|
|
23
47
|
lazy_image(
|
24
48
|
src: image_url,
|
@@ -28,11 +52,56 @@ module Spree
|
|
28
52
|
)
|
29
53
|
end
|
30
54
|
|
55
|
+
def spree_menu(location = 'header')
|
56
|
+
method_name = "for_#{location}"
|
57
|
+
|
58
|
+
if available_menus.respond_to?(method_name) && Spree::Menu::MENU_LOCATIONS_PARAMETERIZED.include?(location)
|
59
|
+
available_menus.send(method_name, I18n.locale) || current_store.default_menu(location)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def spree_localized_link(item)
|
64
|
+
return if item.link.nil?
|
65
|
+
|
66
|
+
output_locale = if locale_param
|
67
|
+
"/#{I18n.locale}"
|
68
|
+
end
|
69
|
+
|
70
|
+
if Spree::MenuItem::DYNAMIC_RESOURCE_TYPE.include? item.linked_resource_type
|
71
|
+
output_locale.to_s + item.link
|
72
|
+
elsif item.linked_resource_type == 'Home Page'
|
73
|
+
"/#{locale_param}"
|
74
|
+
else
|
75
|
+
item.link
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
31
79
|
def should_render_internationalization_dropdown?
|
32
80
|
(defined?(should_render_locale_dropdown?) && should_render_locale_dropdown?) ||
|
33
81
|
(defined?(should_render_currency_dropdown?) && should_render_currency_dropdown?)
|
34
82
|
end
|
35
83
|
|
84
|
+
def spree_nav_link_tag(item, opts = {}, &block)
|
85
|
+
if item.new_window
|
86
|
+
target = opts[:target] || '_blank'
|
87
|
+
rel = opts[:rel] || 'noopener noreferrer'
|
88
|
+
end
|
89
|
+
|
90
|
+
active_class = if request && current_page?(spree_localized_link(item))
|
91
|
+
"active #{opts[:class]}"
|
92
|
+
else
|
93
|
+
opts[:class]
|
94
|
+
end
|
95
|
+
|
96
|
+
link_opts = { target: target, rel: rel, class: active_class, id: opts[:id], data: opts[:data], aria: opts[:aria] }
|
97
|
+
|
98
|
+
if block_given?
|
99
|
+
link_to spree_localized_link(item), link_opts, &block
|
100
|
+
else
|
101
|
+
link_to item.name, spree_localized_link(item), link_opts
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
36
105
|
private
|
37
106
|
|
38
107
|
def spree_navigation_data_cache_key
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module Spree
|
2
|
+
module ProductsFiltersHelper
|
3
|
+
PRICE_FILTER_NAME = 'price'.freeze
|
4
|
+
|
5
|
+
FILTER_LINK_CSS_CLASSES = 'd-inline-block text-uppercase py-1 px-2 m-1 plp-overlay-card-item'.freeze
|
6
|
+
ACTIVE_FILTER_LINK_CSS_CLASSES = 'plp-overlay-card-item--selected'.freeze
|
7
|
+
|
8
|
+
CLEAR_ALL_FILTERS_LINK_CSS_CLASSES = 'btn spree-btn btn-outline-primary w-100 mb-4'.freeze
|
9
|
+
|
10
|
+
def price_filters
|
11
|
+
@price_filters ||= [
|
12
|
+
filters_less_than_price_range(50),
|
13
|
+
filters_price_range(50, 100),
|
14
|
+
filters_price_range(101, 150),
|
15
|
+
filters_price_range(151, 200),
|
16
|
+
filters_price_range(201, 300),
|
17
|
+
filters_more_than_price_range(300)
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
def min_price_filter_input(**html_options)
|
22
|
+
price_filter_input(
|
23
|
+
name: :min_price,
|
24
|
+
value: filters_price_range_from_param.min_price.to_i,
|
25
|
+
placeholder: "#{currency_symbol(current_currency)} #{Spree.t(:min)}",
|
26
|
+
**html_options
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def max_price_filter_input(**html_options)
|
31
|
+
price_filter_input(
|
32
|
+
name: :max_price,
|
33
|
+
value: filters_price_range_from_param.max_price.to_i,
|
34
|
+
placeholder: "#{currency_symbol(current_currency)} #{Spree.t(:max)}",
|
35
|
+
**html_options
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def price_filter_input(name:, value:, placeholder:, **html_options)
|
40
|
+
price_value = value&.zero? ? '' : value
|
41
|
+
style_class = "spree-flat-input #{html_options[:class]}"
|
42
|
+
|
43
|
+
number_field_tag(
|
44
|
+
name, price_value,
|
45
|
+
id: name,
|
46
|
+
class: style_class,
|
47
|
+
min: 0, step: 1, placeholder: placeholder,
|
48
|
+
**html_options.except(:class)
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def option_value_filter_link(option_value, permitted_params, opts = {})
|
53
|
+
id = option_value.id
|
54
|
+
ot_downcase_name = option_value.option_type.filter_param
|
55
|
+
selected_option_values = params[ot_downcase_name]&.split(',')&.map(&:to_i) || []
|
56
|
+
is_selected = selected_option_values.include?(id)
|
57
|
+
option_value_param = (is_selected ? selected_option_values - [id] : selected_option_values + [id]).join(',')
|
58
|
+
new_params = permitted_params.merge(ot_downcase_name => option_value_param, menu_open: 1)
|
59
|
+
|
60
|
+
link_to new_params, data: { params: new_params, id: id, filter_name: ot_downcase_name, multiselect: true } do
|
61
|
+
# TODO: refactor this
|
62
|
+
if color_option_type_name.present? && color_option_type_name.downcase == ot_downcase_name
|
63
|
+
content_tag :span, class: 'd-inline-block mb-1' do
|
64
|
+
render partial: 'spree/shared/color_select', locals: {
|
65
|
+
color: option_value.presentation,
|
66
|
+
selected: is_selected
|
67
|
+
}
|
68
|
+
end
|
69
|
+
else
|
70
|
+
filter_content_tag(option_value.name, opts.merge(is_selected: is_selected))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def property_value_filter_link(property, value, permitted_params, opts = {})
|
76
|
+
id = value.first
|
77
|
+
name = value.last
|
78
|
+
|
79
|
+
selected_properties = params.dig(:properties, property.filter_param)&.split(',') || []
|
80
|
+
is_selected = selected_properties.include?(id)
|
81
|
+
property_values = (is_selected ? selected_properties - [id] : selected_properties + [id])
|
82
|
+
url = permitted_params.merge(properties: { property.filter_param => property_values }, menu_open: 1)
|
83
|
+
filter_name = "properties[#{property.filter_param}]"
|
84
|
+
new_params = permitted_params.merge(filter_name => property_values, menu_open: 1)
|
85
|
+
|
86
|
+
base_filter_link(url, name, opts.merge(params: new_params, is_selected: is_selected, filter_name: filter_name, id: id, multiselect: true))
|
87
|
+
end
|
88
|
+
|
89
|
+
def price_filter_link(price_range, permitted_params, opts = {})
|
90
|
+
is_selected = params[:price] == price_range.to_param
|
91
|
+
price_param = is_selected ? '' : price_range.to_param
|
92
|
+
url = permitted_params.merge(price: price_param, menu_open: 1)
|
93
|
+
|
94
|
+
opts[:is_selected] ||= is_selected
|
95
|
+
|
96
|
+
content_tag :div do
|
97
|
+
base_filter_link(url, price_range, opts.merge(is_selected: is_selected, filter_name: PRICE_FILTER_NAME, id: price_param))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def product_filters_present?(permitted_params)
|
102
|
+
properties = permitted_params.fetch(:properties, {}).to_unsafe_h
|
103
|
+
flatten_params = permitted_params.to_h.merge(properties)
|
104
|
+
|
105
|
+
flatten_params.any? { |name, value| product_filter_present?(name, value) }
|
106
|
+
end
|
107
|
+
|
108
|
+
def clear_all_filters_link(permitted_params, opts = {})
|
109
|
+
opts[:css_class] ||= CLEAR_ALL_FILTERS_LINK_CSS_CLASSES
|
110
|
+
sort_by_param = permitted_params.slice(:sort_by)
|
111
|
+
|
112
|
+
link_to Spree.t('plp.clear_all'), sort_by_param, class: opts[:css_class], data: { params: sort_by_param }
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def product_filter_present?(filter_param, filter_value)
|
118
|
+
filter_param.in?(product_filters_params) && filter_value.present?
|
119
|
+
end
|
120
|
+
|
121
|
+
def product_filters_params
|
122
|
+
options_filter_params = OptionType.filterable.map(&:filter_param)
|
123
|
+
properties_filter_params = Property.filterable.pluck(:filter_param)
|
124
|
+
|
125
|
+
options_filter_params + properties_filter_params + [PRICE_FILTER_NAME]
|
126
|
+
end
|
127
|
+
|
128
|
+
def base_filter_link(url, label, opts = {})
|
129
|
+
opts[:params] ||= url
|
130
|
+
|
131
|
+
link_to url, data: { filter_name: opts[:filter_name], id: opts[:id], params: opts[:params], multiselect: opts[:multiselect] } do
|
132
|
+
filter_content_tag(label, opts)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def filter_content_tag(label, opts = {})
|
137
|
+
opts[:css_class] ||= FILTER_LINK_CSS_CLASSES
|
138
|
+
opts[:css_active_class] ||= ACTIVE_FILTER_LINK_CSS_CLASSES
|
139
|
+
|
140
|
+
content_tag :div, class: "#{opts[:css_class]} #{opts[:css_active_class] if opts[:is_selected]}" do
|
141
|
+
label.to_s
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def filters_price_range_from_param
|
146
|
+
Filters::PriceRangePresenter.from_param(params[:price].to_s, currency: current_currency)
|
147
|
+
end
|
148
|
+
|
149
|
+
def filters_price_range(min_amount, max_amount)
|
150
|
+
Filters::PriceRangePresenter.new(
|
151
|
+
min_price: filters_price(min_amount),
|
152
|
+
max_price: filters_price(max_amount)
|
153
|
+
)
|
154
|
+
end
|
155
|
+
|
156
|
+
def filters_less_than_price_range(amount)
|
157
|
+
Filters::QuantifiedPriceRangePresenter.new(price: filters_price(amount), quantifier: :less_than)
|
158
|
+
end
|
159
|
+
|
160
|
+
def filters_more_than_price_range(amount)
|
161
|
+
Filters::QuantifiedPriceRangePresenter.new(price: filters_price(amount), quantifier: :more_than)
|
162
|
+
end
|
163
|
+
|
164
|
+
def filters_price(amount)
|
165
|
+
Filters::PricePresenter.new(amount: amount, currency: current_currency)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Spree
|
2
2
|
module StoreHelper
|
3
|
+
include LocaleHelper
|
4
|
+
|
3
5
|
def store_country_iso(store = nil)
|
4
6
|
store ||= current_store if defined?(current_store)
|
5
7
|
|
@@ -22,7 +24,7 @@ module Spree
|
|
22
24
|
return unless store
|
23
25
|
return store.name if store.default_locale.blank?
|
24
26
|
|
25
|
-
|
27
|
+
locale_full_name(store.default_locale)
|
26
28
|
end
|
27
29
|
|
28
30
|
def should_render_store_chooser?
|
@@ -5,5 +5,6 @@
|
|
5
5
|
<%= credit_card_icon(card.cc_type) %>
|
6
6
|
<span>****<%= card.last_digits %>, </span>
|
7
7
|
<span><%= card.name %></span>
|
8
|
+
<%= button_tag Spree.t(:remove), type: 'button', class: 'btn text-left d-block p-0 js-remove-credit-card', data: { id: card.id } %>
|
8
9
|
</label>
|
9
10
|
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% if @cms_page %>
|
2
|
+
<% if simple_page?(@cms_page) %>
|
3
|
+
<div class="container">
|
4
|
+
<div class="row my-5">
|
5
|
+
<div class="col-12">
|
6
|
+
<%= @cms_page.content.html_safe %>
|
7
|
+
</div>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
<% else %>
|
11
|
+
<% @cms_page.cms_sections.each do |section| %>
|
12
|
+
<%= build_section(section) %>
|
13
|
+
<% end %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
<%= render "spree/shared/cms/pages/edit_mode", edit_mode: @edit_mode %>
|
File without changes
|
File without changes
|