spree_frontend 4.1.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (314) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +120 -0
  3. data/.codeclimate.yml +36 -0
  4. data/.deepsource.toml +19 -0
  5. data/.editorconfig +22 -0
  6. data/.eslintignore +7 -0
  7. data/.eslintrc +36 -0
  8. data/.gem_release.yml +7 -0
  9. data/.github/CONTRIBUTING.md +1 -0
  10. data/.github/ISSUE_TEMPLATE/bug_report.md +47 -0
  11. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  12. data/.github/ISSUE_TEMPLATE.md +39 -0
  13. data/.github/dependabot.yml +32 -0
  14. data/.gitignore +58 -0
  15. data/.rubocop.yml +197 -0
  16. data/.solargraph.yml +20 -0
  17. data/.stylelintignore +4 -0
  18. data/.stylelintrc +6 -0
  19. data/CODE_OF_CONDUCT.md +22 -0
  20. data/Gemfile +57 -3
  21. data/LICENSE +1 -1
  22. data/README.md +89 -0
  23. data/Rakefile +1 -1
  24. data/SECURITY.md +1 -0
  25. data/app/assets/config/spree_frontend_manifest.js +5 -0
  26. data/app/assets/images/arrow-down.svg +12 -0
  27. data/app/assets/images/arrow-right-circle-fill.svg +3 -0
  28. data/app/assets/images/card-image.svg +4 -0
  29. data/app/assets/images/edit.svg +1 -1
  30. data/app/assets/images/favicon.ico +0 -0
  31. data/app/assets/images/file-image.svg +4 -0
  32. data/app/assets/images/global.svg +1 -0
  33. data/app/assets/images/image.svg +4 -0
  34. data/app/assets/images/info.svg +7 -0
  35. data/app/assets/images/logo/spree_50.png +0 -0
  36. data/app/assets/images/logo-spree.png +0 -0
  37. data/app/assets/images/logo.png +0 -0
  38. data/app/assets/images/logo.svg +10 -1
  39. data/app/assets/images/logo@2x.png +0 -0
  40. data/app/assets/images/logo@3x.png +0 -0
  41. data/app/assets/images/noimage/large.png +0 -0
  42. data/app/assets/images/noimage/mini.png +0 -0
  43. data/app/assets/images/noimage/plp.png +0 -0
  44. data/app/assets/images/noimage/plp.svg +16 -0
  45. data/app/assets/images/noimage/product.png +0 -0
  46. data/app/assets/images/noimage/small.png +0 -0
  47. data/app/assets/images/pagination-arrow-right.svg +3 -10
  48. data/app/assets/images/pagination-double-arrow-right.svg +6 -13
  49. data/app/assets/images/plus.svg +1 -1
  50. data/app/assets/images/search.svg +1 -1
  51. data/app/assets/javascripts/spree/frontend/account.js +1 -1
  52. data/app/assets/javascripts/spree/frontend/api/main.js +36 -0
  53. data/app/assets/javascripts/spree/frontend/api/storefront/cart.js +49 -0
  54. data/app/assets/javascripts/spree/frontend/cart.js +24 -2
  55. data/app/assets/javascripts/spree/frontend/checkout/address.js +78 -52
  56. data/app/assets/javascripts/spree/frontend/checkout/address_book.js +38 -40
  57. data/app/assets/javascripts/spree/frontend/checkout/payment.js +63 -23
  58. data/app/assets/javascripts/spree/frontend/checkout/shipment.js +15 -2
  59. data/app/assets/javascripts/spree/frontend/checkout.js +17 -1
  60. data/app/assets/javascripts/spree/frontend/coupon_manager.js +1 -1
  61. data/app/assets/javascripts/spree/frontend/currency.js +44 -0
  62. data/app/assets/javascripts/spree/frontend/locale.es6 +12 -0
  63. data/app/assets/javascripts/spree/frontend/login.js +5 -0
  64. data/app/assets/javascripts/spree/frontend/main.js +78 -0
  65. data/app/assets/javascripts/spree/frontend/main_nav_bar.js +86 -0
  66. data/app/assets/javascripts/spree/frontend/{turbolinks_scroll_fix.js → turbo_scroll_fix.js} +3 -3
  67. data/app/assets/javascripts/spree/frontend/views/spree/home/product_carousels.js +4 -4
  68. data/app/assets/javascripts/spree/frontend/views/spree/product/related.js +3 -3
  69. data/app/assets/javascripts/spree/frontend/views/spree/products/cart_form.js +67 -18
  70. data/app/assets/javascripts/spree/frontend/views/spree/products/description.js +1 -1
  71. data/app/assets/javascripts/spree/frontend/views/spree/products/index.js +76 -15
  72. data/app/assets/javascripts/spree/frontend/views/spree/products/price_filters.es6 +46 -0
  73. data/app/assets/javascripts/spree/frontend/views/spree/shared/mobile_navigation.js +9 -10
  74. data/app/assets/javascripts/spree/frontend/views/spree/shared/product_added_modal.js +7 -0
  75. data/app/assets/javascripts/spree/frontend/views/spree/shared/variant_select.js +93 -0
  76. data/app/assets/javascripts/spree/frontend.js +68 -11
  77. data/app/assets/stylesheets/spree/frontend/application.scss +5 -2
  78. data/app/assets/stylesheets/spree/frontend/components-bootstrap/button.scss +8 -0
  79. data/app/assets/stylesheets/spree/frontend/components-bootstrap/carousel.scss +4 -0
  80. data/app/assets/stylesheets/spree/frontend/components-custom/inputs.scss +80 -1
  81. data/app/assets/stylesheets/spree/frontend/flags/_flag-icon-base.scss +23 -0
  82. data/app/assets/stylesheets/spree/frontend/flags/_flag-icon-list.scss +265 -0
  83. data/app/assets/stylesheets/spree/frontend/flags/_variables.scss +2 -0
  84. data/app/assets/stylesheets/spree/frontend/flags/flag-icon.scss +3 -0
  85. data/app/assets/stylesheets/spree/frontend/functions.scss +1 -0
  86. data/app/assets/stylesheets/spree/frontend/helpers/spree/frontend_helper.scss +48 -0
  87. data/app/assets/stylesheets/spree/frontend/variables/bootstrap-overrides.scss +2 -2
  88. data/app/assets/stylesheets/spree/frontend/variables/helper-variables.scss +1 -0
  89. data/app/assets/stylesheets/spree/frontend/variables/variables.scss +54 -0
  90. data/app/assets/stylesheets/spree/frontend/views/spree/checkout/confirm.scss +27 -26
  91. data/app/assets/stylesheets/spree/frontend/views/spree/checkout/delivery.scss +6 -0
  92. data/app/assets/stylesheets/spree/frontend/views/spree/checkout/edit.scss +24 -10
  93. data/app/assets/stylesheets/spree/frontend/views/spree/cms_sections/_index.scss +1 -0
  94. data/app/assets/stylesheets/spree/frontend/views/spree/cms_sections/product_buy_bar.scss +20 -0
  95. data/app/assets/stylesheets/spree/frontend/views/spree/home/index.scss +54 -67
  96. data/app/assets/stylesheets/spree/frontend/views/spree/orders/edit.scss +4 -3
  97. data/app/assets/stylesheets/spree/frontend/views/spree/orders/show.scss +3 -0
  98. data/app/assets/stylesheets/spree/frontend/views/spree/products/cart_form.scss +8 -0
  99. data/app/assets/stylesheets/spree/frontend/views/spree/products/gallery_modal.scss +7 -0
  100. data/app/assets/stylesheets/spree/frontend/views/spree/products/index.scss +55 -26
  101. data/app/assets/stylesheets/spree/frontend/views/spree/products/show.scss +7 -0
  102. data/app/assets/stylesheets/spree/frontend/views/spree/shared/_color_select.scss +10 -9
  103. data/app/assets/stylesheets/spree/frontend/views/spree/shared/carousel/single.scss +1 -1
  104. data/app/assets/stylesheets/spree/frontend/views/spree/shared/carousel/thumbnails.scss +1 -0
  105. data/app/assets/stylesheets/spree/frontend/views/spree/shared/cart.scss +9 -4
  106. data/app/assets/stylesheets/spree/frontend/views/spree/shared/category_nav_bar.scss +3 -3
  107. data/app/assets/stylesheets/spree/frontend/views/spree/shared/change_store.scss +7 -0
  108. data/app/assets/stylesheets/spree/frontend/views/spree/shared/footer.scss +4 -0
  109. data/app/assets/stylesheets/spree/frontend/views/spree/shared/main_nav_bar.scss +42 -26
  110. data/app/assets/stylesheets/spree/frontend/views/spree/shared/mobile_navigation.scss +34 -3
  111. data/app/assets/stylesheets/spree/frontend/views/spree/shared/nav_bar.scss +24 -7
  112. data/app/assets/stylesheets/spree/frontend/views/spree/shared/quantity_select.scss +9 -12
  113. data/app/assets/stylesheets/spree/frontend/views/spree/shared/search_form.scss +12 -0
  114. data/app/assets/stylesheets/spree/frontend/views/spree/users/show.scss +7 -13
  115. data/app/assets/stylesheets/spree/frontend.css +0 -1
  116. data/app/controllers/concerns/spree/checkout/address_book.rb +9 -7
  117. data/app/controllers/concerns/spree/locale_urls.rb +21 -0
  118. data/app/controllers/spree/addresses_controller.rb +16 -33
  119. data/app/controllers/spree/checkout_controller.rb +15 -13
  120. data/app/controllers/spree/cms_pages_controller.rb +29 -0
  121. data/app/controllers/spree/content_controller.rb +0 -2
  122. data/app/controllers/spree/currency_controller.rb +17 -0
  123. data/app/controllers/spree/errors_controller.rb +11 -0
  124. data/app/controllers/spree/home_controller.rb +38 -1
  125. data/app/controllers/spree/locale_controller.rb +35 -6
  126. data/app/controllers/spree/orders_controller.rb +12 -10
  127. data/app/controllers/spree/products_controller.rb +46 -28
  128. data/app/controllers/spree/store_controller.rb +77 -12
  129. data/app/controllers/spree/taxons_controller.rb +16 -8
  130. data/app/helpers/spree/addresses_helper.rb +64 -12
  131. data/app/helpers/spree/cache_helper.rb +7 -0
  132. data/app/helpers/spree/cms_pages_helper.rb +23 -0
  133. data/app/helpers/spree/frontend_helper.rb +170 -18
  134. data/app/helpers/spree/navigation_helper.rb +81 -4
  135. data/app/helpers/spree/products_filters_helper.rb +168 -0
  136. data/app/helpers/spree/store_helper.rb +41 -0
  137. data/app/helpers/spree/structured_data_helper.rb +6 -2
  138. data/app/helpers/spree/taxons_helper.rb +2 -2
  139. data/app/services/spree/build_localized_redirect_url.rb +141 -0
  140. data/app/views/kaminari/twitter-bootstrap-4/_first_page.html.erb +3 -3
  141. data/app/views/kaminari/twitter-bootstrap-4/_gap.html.erb +2 -2
  142. data/app/views/kaminari/twitter-bootstrap-4/_last_page.html.erb +3 -3
  143. data/app/views/kaminari/twitter-bootstrap-4/_next_page.html.erb +3 -3
  144. data/app/views/kaminari/twitter-bootstrap-4/_page.html.erb +2 -2
  145. data/app/views/kaminari/twitter-bootstrap-4/_paginator.html.erb +2 -2
  146. data/app/views/kaminari/twitter-bootstrap-4/_prev_page.html.erb +3 -3
  147. data/app/views/spree/address/_form.html.erb +26 -27
  148. data/app/views/spree/addresses/_form.html.erb +15 -6
  149. data/app/views/spree/addresses/edit.html.erb +13 -8
  150. data/app/views/spree/addresses/new.html.erb +8 -4
  151. data/app/views/spree/checkout/_address.html.erb +19 -23
  152. data/app/views/spree/checkout/_confirm.html.erb +1 -75
  153. data/app/views/spree/checkout/_credit_card.html.erb +3 -2
  154. data/app/views/spree/checkout/_delivery.html.erb +11 -4
  155. data/app/views/spree/checkout/_delivery_informations.html.erb +51 -0
  156. data/app/views/spree/checkout/_payment.html.erb +5 -24
  157. data/app/views/spree/checkout/_payment_sources.html.erb +17 -0
  158. data/app/views/spree/checkout/_summary.html.erb +22 -19
  159. data/app/views/spree/checkout/edit.html.erb +22 -2
  160. data/app/views/spree/checkout/payment/_gateway.html.erb +2 -2
  161. data/app/views/spree/checkout/registration.html.erb +3 -3
  162. data/app/views/spree/cms_pages/show.html.erb +16 -0
  163. data/app/views/spree/errors/not_found.html.erb +2 -2
  164. data/app/views/spree/home/index.html.erb +17 -123
  165. data/app/views/spree/layouts/checkout.html.erb +3 -1
  166. data/app/views/spree/layouts/spree_application.html.erb +3 -2
  167. data/app/views/spree/locale/index.html.erb +1 -0
  168. data/app/views/spree/orders/_coupon_code.html.erb +3 -4
  169. data/app/views/spree/orders/_line_item.html.erb +4 -4
  170. data/app/views/spree/orders/_line_item_data.html.erb +3 -3
  171. data/app/views/spree/orders/edit.html.erb +2 -3
  172. data/app/views/spree/orders/show.html.erb +2 -72
  173. data/app/views/spree/products/_cart_form.html.erb +5 -2
  174. data/app/views/spree/products/_color_option_type.html.erb +14 -14
  175. data/app/views/spree/products/_description.html.erb +19 -14
  176. data/app/views/spree/products/_filters_desktop.html.erb +80 -40
  177. data/app/views/spree/products/_filters_mobile.html.erb +47 -15
  178. data/app/views/spree/products/_gallery.html.erb +4 -6
  179. data/app/views/spree/products/_gallery_modal.html.erb +4 -6
  180. data/app/views/spree/products/_option_type.html.erb +1 -3
  181. data/app/views/spree/products/_product.html.erb +1 -1
  182. data/app/views/spree/products/_properties.html.erb +6 -4
  183. data/app/views/spree/products/_sort_desktop.html.erb +20 -14
  184. data/app/views/spree/products/_sort_mobile.html.erb +24 -8
  185. data/app/views/spree/products/_thumbnails.html.erb +2 -2
  186. data/app/views/spree/products/index.html.erb +7 -4
  187. data/app/views/spree/products/related.html.erb +11 -5
  188. data/app/views/spree/products/show.html.erb +2 -3
  189. data/app/views/spree/shared/_breadcrumbs.html.erb +2 -2
  190. data/app/views/spree/shared/_carousel_4_products.html.erb +14 -20
  191. data/app/views/spree/shared/_cart.html.erb +1 -1
  192. data/app/views/spree/shared/_checkout_header.html.erb +22 -21
  193. data/app/views/spree/shared/_color_select.html.erb +3 -3
  194. data/app/views/spree/shared/_copyright.html.erb +1 -10
  195. data/app/views/spree/shared/_currency_dropdown.html.erb +13 -0
  196. data/app/views/spree/shared/_delete_address_popup.html.erb +1 -2
  197. data/app/views/spree/shared/_error_messages.html.erb +2 -2
  198. data/app/views/spree/shared/_footer.html.erb +31 -21
  199. data/app/views/spree/shared/_get_started.html.erb +32 -0
  200. data/app/views/spree/shared/_head.html.erb +8 -5
  201. data/app/views/spree/shared/_header.html.erb +4 -4
  202. data/app/views/spree/shared/_internationalization_options.html.erb +31 -0
  203. data/app/views/spree/shared/_line_item.html.erb +3 -3
  204. data/app/views/spree/shared/_link_to_account.html.erb +7 -4
  205. data/app/views/spree/shared/_link_to_cart.html.erb +1 -2
  206. data/app/views/spree/shared/_locale_and_currency.html.erb +6 -0
  207. data/app/views/spree/shared/_locale_dropdown.html.erb +13 -0
  208. data/app/views/spree/shared/_login.html.erb +5 -5
  209. data/app/views/spree/shared/_main_nav_bar.html.erb +69 -45
  210. data/app/views/spree/shared/_mobile_internationalization_options.html.erb +37 -0
  211. data/app/views/spree/shared/_mobile_navigation.html.erb +48 -63
  212. data/app/views/spree/shared/_nav_bar.html.erb +9 -19
  213. data/app/views/spree/shared/_no_product_available.html.erb +1 -1
  214. data/app/views/spree/shared/_option_values.html.erb +2 -21
  215. data/app/views/spree/shared/_order_details.html.erb +117 -174
  216. data/app/views/spree/shared/_paths.html.erb +8 -0
  217. data/app/views/spree/shared/_payment.html.erb +2 -2
  218. data/app/views/spree/shared/_payment_sources.html.erb +2 -2
  219. data/app/views/spree/shared/_product_added_modal.html.erb +3 -3
  220. data/app/views/spree/shared/_properties.html.erb +4 -0
  221. data/app/views/spree/shared/_quantity_select.html.erb +2 -2
  222. data/app/views/spree/shared/_search.html.erb +9 -13
  223. data/app/views/spree/shared/_translations.html.erb +8 -7
  224. data/app/views/spree/shared/carousel/_single.html.erb +9 -14
  225. data/app/views/spree/shared/carousel/_thumbnails.html.erb +35 -39
  226. data/app/views/spree/shared/cms/pages/_edit_mode.html.erb +13 -0
  227. data/app/views/spree/shared/cms/sections/_featured_article.html.erb +27 -0
  228. data/app/views/spree/shared/cms/sections/_hero_image.html.erb +60 -0
  229. data/app/views/spree/shared/cms/sections/_image_gallery.html.erb +171 -0
  230. data/app/views/spree/shared/cms/sections/_product_carousel.html.erb +5 -0
  231. data/app/views/spree/shared/cms/sections/_rich_text_content.html.erb +3 -0
  232. data/app/views/spree/shared/cms/sections/_side_by_side_images.html.erb +118 -0
  233. data/app/views/spree/taxons/_header.html.erb +7 -2
  234. data/app/views/spree/users/_address.html.erb +16 -24
  235. data/app/views/spree/users/_address_controls.html.erb +10 -0
  236. data/app/views/spree/users/show.html.erb +21 -16
  237. data/config/initializers/admin_actions.rb +18 -0
  238. data/config/initializers/assets.rb +4 -13
  239. data/config/initializers/canonical_rails.rb +1 -1
  240. data/config/routes.rb +30 -26
  241. data/lib/generators/spree/frontend/copy_storefront/copy_storefront_generator.rb +1 -7
  242. data/lib/generators/spree/frontend/install/install_generator.rb +34 -0
  243. data/lib/generators/spree/frontend/install/templates/app/assets/config/manifest.js +2 -0
  244. data/lib/generators/spree/frontend/install/templates/vendor/assets/javascripts/spree/frontend/all.js +8 -0
  245. data/lib/generators/spree/frontend/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +9 -0
  246. data/lib/spree/frontend/configuration.rb +18 -0
  247. data/lib/spree/frontend/engine.rb +3 -1
  248. data/lib/spree/frontend/version.rb +9 -0
  249. data/lib/spree/frontend.rb +8 -4
  250. data/license.md +13 -0
  251. data/spec/fixtures/files/store_favicon.ico +0 -0
  252. data/spree_frontend.gemspec +26 -14
  253. data/vendor/assets/javascripts/cleave.js +8 -0
  254. data/vendor/assets/javascripts/fetch.umd.js +531 -0
  255. data/vendor/assets/javascripts/jquery.payment.js +652 -0
  256. data/vendor/assets/javascripts/jsuri.js +458 -0
  257. data/vendor/assets/javascripts/polyfill.min.js +1 -0
  258. metadata +224 -86
  259. data/app/assets/images/homepage/big_category_banner.jpg +0 -0
  260. data/app/assets/images/homepage/big_category_banner_mobile.jpg +0 -0
  261. data/app/assets/images/homepage/big_category_banner_tablet_landscape.jpg +0 -0
  262. data/app/assets/images/homepage/big_category_banner_tablet_portrait.jpg +0 -0
  263. data/app/assets/images/homepage/category_banner_lower.jpg +0 -0
  264. data/app/assets/images/homepage/category_banner_lower_mobile.jpg +0 -0
  265. data/app/assets/images/homepage/category_banner_lower_tablet_landscape.jpg +0 -0
  266. data/app/assets/images/homepage/category_banner_lower_tablet_portrait.jpg +0 -0
  267. data/app/assets/images/homepage/category_banner_upper.jpg +0 -0
  268. data/app/assets/images/homepage/category_banner_upper_mobile.jpg +0 -0
  269. data/app/assets/images/homepage/category_banner_upper_tablet_landscape.jpg +0 -0
  270. data/app/assets/images/homepage/category_banner_upper_tablet_portrait.jpg +0 -0
  271. data/app/assets/images/homepage/main_banner.jpg +0 -0
  272. data/app/assets/images/homepage/main_banner_mobile.jpg +0 -0
  273. data/app/assets/images/homepage/main_banner_tablet_landscape.jpg +0 -0
  274. data/app/assets/images/homepage/main_banner_tablet_portrait.jpg +0 -0
  275. data/app/assets/images/homepage/promo_banner_left.jpg +0 -0
  276. data/app/assets/images/homepage/promo_banner_left_mobile.jpg +0 -0
  277. data/app/assets/images/homepage/promo_banner_left_tablet_landscape.jpg +0 -0
  278. data/app/assets/images/homepage/promo_banner_left_tablet_portrait.jpg +0 -0
  279. data/app/assets/images/homepage/promo_banner_right.jpg +0 -0
  280. data/app/assets/images/homepage/promo_banner_right_mobile.jpg +0 -0
  281. data/app/assets/images/homepage/promo_banner_right_tablet_landscape.jpg +0 -0
  282. data/app/assets/images/homepage/promo_banner_right_tablet_portrait.jpg +0 -0
  283. data/app/assets/images/meganav/promo_banner_left-first-category.jpg +0 -0
  284. data/app/assets/images/meganav/promo_banner_left-second-category.jpg +0 -0
  285. data/app/assets/images/meganav/promo_banner_left-third-category.jpg +0 -0
  286. data/app/assets/images/meganav/promo_banner_right-first-category.jpg +0 -0
  287. data/app/assets/images/meganav/promo_banner_right-second-category.jpg +0 -0
  288. data/app/assets/images/meganav/promo_banner_right-third-category.jpg +0 -0
  289. data/app/assets/images/noimage/big_category_banner.jpg +0 -0
  290. data/app/assets/images/noimage/big_category_banner_mobile.jpg +0 -0
  291. data/app/assets/images/noimage/big_category_banner_tablet_landscape.jpg +0 -0
  292. data/app/assets/images/noimage/big_category_banner_tablet_portrait.jpg +0 -0
  293. data/app/assets/images/noimage/category_banner.jpg +0 -0
  294. data/app/assets/images/noimage/category_banner_mobile.jpg +0 -0
  295. data/app/assets/images/noimage/category_banner_plp.jpg +0 -0
  296. data/app/assets/images/noimage/category_banner_tablet_landscape.jpg +0 -0
  297. data/app/assets/images/noimage/category_banner_tablet_portrait.jpg +0 -0
  298. data/app/assets/images/noimage/main_banner.jpg +0 -0
  299. data/app/assets/images/noimage/main_banner_mobile.jpg +0 -0
  300. data/app/assets/images/noimage/main_banner_tablet_landscape.jpg +0 -0
  301. data/app/assets/images/noimage/main_banner_tablet_portrait.jpg +0 -0
  302. data/app/assets/images/noimage/product_photo.jpg +0 -0
  303. data/app/assets/images/noimage/promo_banner.jpg +0 -0
  304. data/app/assets/images/noimage/promo_banner_megamenu.jpg +0 -0
  305. data/app/assets/images/noimage/promo_banner_mobile.jpg +0 -0
  306. data/app/assets/images/noimage/promo_banner_tablet_landscape.jpg +0 -0
  307. data/app/assets/images/noimage/promo_banner_tablet_portrait.jpg +0 -0
  308. data/app/assets/images/spark-logo@3x.png +0 -0
  309. data/app/assets/stylesheets/spree/frontend/_glyphicons_urls_fix.scss +0 -10
  310. data/app/assets/stylesheets/spree/frontend/address_book.scss +0 -8
  311. data/app/models/spree/frontend_configuration.rb +0 -7
  312. data/app/views/spree/shared/_taxonomies.html.erb +0 -16
  313. /data/app/views/spree/{shared → errors}/forbidden.html.erb +0 -0
  314. /data/app/views/spree/{shared → errors}/unauthorized.html.erb +0 -0
@@ -1,25 +1,38 @@
1
1
  module Spree
2
- class StoreController < Spree::BaseController
2
+ class StoreController < ApplicationController
3
+ include Spree::Core::ControllerHelpers::Auth
4
+ include Spree::Core::ControllerHelpers::Search
5
+ include Spree::Core::ControllerHelpers::Store
6
+ include Spree::Core::ControllerHelpers::StrongParameters
7
+ include Spree::Core::ControllerHelpers::Locale
8
+ include Spree::Core::ControllerHelpers::Currency
3
9
  include Spree::Core::ControllerHelpers::Order
10
+ include Spree::LocaleUrls
4
11
 
5
- skip_before_action :verify_authenticity_token, only: :ensure_cart, raise: false
12
+ respond_to :html
6
13
 
7
- def forbidden
8
- render 'spree/shared/forbidden', layout: Spree::Config[:layout], status: 403
9
- end
14
+ layout :get_layout
10
15
 
11
- def unauthorized
12
- render 'spree/shared/unauthorized', layout: Spree::Config[:layout], status: 401
13
- end
16
+ helper 'spree/base'
17
+ helper 'spree/locale'
18
+ helper 'spree/currency'
19
+
20
+ helper_method :title
21
+ helper_method :title=
22
+ helper_method :accurate_title
23
+
24
+ skip_before_action :verify_authenticity_token, only: :ensure_cart, raise: false
25
+
26
+ before_action :redirect_to_default_locale
14
27
 
15
28
  def account_link
16
29
  render partial: 'spree/shared/link_to_account'
17
- fresh_when(try_spree_current_user)
30
+ fresh_when(etag: [try_spree_current_user, I18n.locale])
18
31
  end
19
32
 
20
33
  def cart_link
21
34
  render partial: 'spree/shared/link_to_cart'
22
- fresh_when(simple_current_order)
35
+ fresh_when(etag: [simple_current_order, I18n.locale])
23
36
  end
24
37
 
25
38
  def api_tokens
@@ -35,20 +48,72 @@ module Spree
35
48
 
36
49
  protected
37
50
 
51
+ # can be used in views as well as controllers.
52
+ # e.g. <% self.title = 'This is a custom title for this view' %>
53
+ attr_writer :title
54
+
55
+ def title
56
+ title_string = @title.present? ? @title : accurate_title
57
+ if title_string.present?
58
+ if Spree::Frontend::Config[:always_put_site_name_in_title] && !title_string.include?(default_title)
59
+ [title_string, default_title].join(" #{Spree::Frontend::Config[:title_site_name_separator]} ")
60
+ else
61
+ title_string
62
+ end
63
+ else
64
+ default_title
65
+ end
66
+ end
67
+
68
+ def default_title
69
+ current_store.name
70
+ end
71
+
72
+ # this is a hook for subclasses to provide title
73
+ def accurate_title
74
+ current_store.seo_title
75
+ end
76
+
38
77
  def config_locale
39
78
  Spree::Frontend::Config[:locale]
40
79
  end
41
80
 
81
+ # Returns which layout to render.
82
+ #
83
+ # You can set the layout you want to render inside your Spree configuration with the +:layout+ option.
84
+ #
85
+ # Default layout is: +app/views/spree/layouts/spree_application+
86
+ #
87
+ def get_layout
88
+ layout ||= Spree::Frontend::Config[:layout]
89
+ end
90
+
42
91
  def store_etag
43
92
  [
44
93
  current_store,
45
94
  current_currency,
46
- config_locale
47
- ]
95
+ I18n.locale,
96
+ try_spree_current_user.present?,
97
+ try_spree_current_user.try(:has_spree_role?, 'admin')
98
+ ].compact
48
99
  end
49
100
 
50
101
  def store_last_modified
51
102
  (current_store.updated_at || Time.current).utc
52
103
  end
104
+
105
+ def redirect_unauthorized_access
106
+ if try_spree_current_user
107
+ flash[:error] = Spree.t(:authorization_failure)
108
+ redirect_to spree.forbidden_path
109
+ else
110
+ store_location
111
+ if respond_to?(:spree_login_path)
112
+ redirect_to spree_login_path
113
+ else
114
+ redirect_to spree.root_path
115
+ end
116
+ end
117
+ end
53
118
  end
54
119
  end
@@ -1,22 +1,21 @@
1
1
  module Spree
2
2
  class TaxonsController < Spree::StoreController
3
3
  include Spree::FrontendHelper
4
+ include Spree::CacheHelper
4
5
  helper 'spree/products'
5
6
 
6
7
  before_action :load_taxon
7
8
 
8
- respond_to :html
9
-
10
9
  def show
11
- if stale?(etag: etag, last_modified: last_modified, public: true)
10
+ if !http_cache_enabled? || stale?(etag: etag, last_modified: last_modified, public: true)
12
11
  load_products
13
12
  end
14
13
  end
15
14
 
16
15
  def product_carousel
17
- if stale?(etag: carousel_etag, last_modified: last_modified, public: true)
16
+ if !http_cache_enabled? || stale?(etag: carousel_etag, last_modified: last_modified, public: true)
18
17
  load_products
19
- if @products.any?
18
+ if @products.reload.any?
20
19
  render template: 'spree/taxons/product_carousel', layout: false
21
20
  else
22
21
  head :no_content
@@ -31,11 +30,17 @@ module Spree
31
30
  end
32
31
 
33
32
  def load_taxon
34
- @taxon = Spree::Taxon.friendly.find(params[:id])
33
+ @taxon = find_with_fallback_default_locale { current_store.taxons.friendly.find(params[:id]) }
35
34
  end
36
35
 
37
36
  def load_products
38
- @searcher = build_searcher(params.merge(taxon: @taxon.id, include_images: true))
37
+ search_params = params.merge(
38
+ current_store: current_store,
39
+ taxon: @taxon,
40
+ include_images: true
41
+ )
42
+
43
+ @searcher = build_searcher(search_params)
39
44
  @products = @searcher.retrieve_products
40
45
  end
41
46
 
@@ -56,7 +61,10 @@ module Spree
56
61
  end
57
62
 
58
63
  def last_modified
59
- @taxon.updated_at&.utc
64
+ taxon_last_modified = @taxon&.updated_at&.utc
65
+ current_store_last_modified = current_store.updated_at.utc
66
+
67
+ [taxon_last_modified, current_store_last_modified].compact.max
60
68
  end
61
69
  end
62
70
  end
@@ -2,7 +2,7 @@
2
2
  module Spree
3
3
  module AddressesHelper
4
4
  def address_field(form, method, address_id = 'b', &handler)
5
- content_tag :p, id: [address_id, method].join, class: 'form-group checkout-content-inner-field' do
5
+ content_tag :div, id: [address_id, method].join, class: 'form-group checkout-content-inner-field has-float-label' do
6
6
  if handler
7
7
  yield
8
8
  else
@@ -10,28 +10,80 @@ module Spree
10
10
  method_name = I18n.t("activerecord.attributes.spree/address.#{method}")
11
11
  required = Spree.t(:required)
12
12
  form.text_field(method,
13
- class: [is_required ? 'required' : nil, 'spree-flat-input'].compact,
13
+ class: ['spree-flat-input'].compact,
14
14
  required: is_required,
15
- placeholder: is_required ? "#{method_name} #{required}" : method_name)
15
+ placeholder: is_required ? "#{method_name} #{required}" : method_name,
16
+ aria: { label: method_name }) +
17
+ form.label(method_name,
18
+ is_required ? "#{method_name} #{required}" : method_name,
19
+ class: 'text-uppercase')
16
20
  end
17
21
  end
18
22
  end
19
23
 
20
- def address_state(form, country, _address_id = 'b')
21
- country ||= Spree::Country.find(Spree::Config[:default_country_id])
24
+ def address_zipcode(form, country, address_id = 'b')
25
+ country ||= address_default_country
26
+ is_required = country.zipcode_required?
27
+ method_name = Spree.t(:zipcode)
28
+ required = Spree.t(:required)
29
+ form.text_field(:zipcode,
30
+ class: ['spree-flat-input'].compact,
31
+ required: is_required,
32
+ placeholder: is_required ? "#{method_name} #{required}" : method_name,
33
+ aria: { label: Spree.t(:zipcode) }) +
34
+ form.label(:zipcode,
35
+ is_required ? "#{method_name} #{required}" : method_name,
36
+ class: 'text-uppercase',
37
+ id: address_id + '_zipcode_label')
38
+ end
39
+
40
+ def address_state(form, country, address_id = 'b')
41
+ country ||= address_default_country
22
42
  have_states = country.states.any?
23
43
  state_elements = [
24
- form.collection_select(:state_id, country.states.order(:name),
44
+ form.collection_select(:state_id, checkout_zone_applicable_states_for(country).sort_by(&:name),
25
45
  :id, :name,
26
- { prompt: Spree.t(:state).upcase },
27
- class: have_states ? 'required form-control spree-flat-select' : 'hidden',
46
+ { prompt: Spree.t(:state) },
47
+ class: ['spree-flat-select'].compact,
48
+ aria: { label: Spree.t(:state) },
28
49
  disabled: !have_states) +
29
- form.text_field(:state_name, class: !have_states ? 'required' : 'hidden', disabled: have_states) +
30
- image_tag('arrow.svg', class: 'position-absolute spree-flat-select-arrow')
50
+ form.text_field(:state_name,
51
+ class: ['spree-flat-input'].compact,
52
+ aria: { label: Spree.t(:state) },
53
+ disabled: have_states,
54
+ placeholder: Spree.t(:state) + " #{Spree.t(:required)}") +
55
+ form.label(Spree.t(:state).downcase,
56
+ raw(Spree.t(:state) + content_tag(:abbr, " #{Spree.t(:required)}")),
57
+ class: [have_states ? 'state-select-label' : nil, ' text-uppercase'].compact,
58
+ id: address_id + '_state_label') +
59
+ image_tag('arrow.svg',
60
+ class: [!have_states ? 'hidden' : nil, 'position-absolute spree-flat-select-arrow'].compact)
31
61
  ].join.tr('"', "'").delete("\n")
32
62
 
33
- content_tag(:noscript, form.text_field(:state_name, class: 'required')) +
34
- javascript_tag("document.write(\"<span class='d-block position-relative'>#{state_elements.html_safe}</span>\");")
63
+ content_tag :span, class: 'd-block position-relative' do
64
+ state_elements.html_safe
65
+ end
66
+ end
67
+
68
+ def user_available_addresses
69
+ @user_available_addresses ||= begin
70
+ return [] unless try_spree_current_user
71
+
72
+ states = current_store.countries_available_for_checkout.each_with_object([]) do |country, memo|
73
+ memo << current_store.states_available_for_checkout(country)
74
+ end.flatten
75
+
76
+ try_spree_current_user.addresses.
77
+ where(country_id: states.pluck(:country_id).uniq)
78
+ end
79
+ end
80
+
81
+ def checkout_zone_applicable_states_for(country)
82
+ current_store.states_available_for_checkout(country)
83
+ end
84
+
85
+ def address_default_country
86
+ @address_default_country ||= current_store.default_country
35
87
  end
36
88
  end
37
89
  end
@@ -0,0 +1,7 @@
1
+ module Spree
2
+ module CacheHelper
3
+ def http_cache_enabled?
4
+ @http_cache_enabled ||= Spree::Frontend::Config[:http_cache_enabled]
5
+ end
6
+ end
7
+ 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,28 @@ module Spree
7
8
  @body_class
8
9
  end
9
10
 
11
+ def logo(image_path = nil, options = {})
12
+ logo_attachment = if defined?(Spree::StoreLogo) && current_store.logo.is_a?(Spree::StoreLogo)
13
+ current_store.logo.attachment # Spree v5
14
+ else
15
+ current_store.logo # Spree 4.x
16
+ end
17
+
18
+ image_path ||= if logo_attachment&.attached? && logo_attachment&.variable?
19
+ main_app.cdn_image_url(logo_attachment.variant(resize: '244x104>'))
20
+ elsif logo_attachment&.attached? && logo_attachment&.image?
21
+ main_app.cdn_image_url(logo_attachment)
22
+ else
23
+ asset_path('logo/spree_50.png')
24
+ end
25
+
26
+ path = spree.respond_to?(:root_path) ? spree.root_path : main_app.root_path
27
+
28
+ link_to path, 'aria-label': current_store.name, method: options[:method] do
29
+ image_tag image_path, alt: current_store.name, title: current_store.name
30
+ end
31
+ end
32
+
10
33
  def spree_breadcrumbs(taxon, _separator = '', product = nil)
11
34
  return '' if current_page?('/') || taxon.nil?
12
35
 
@@ -51,7 +74,7 @@ module Spree
51
74
  ) << content_tag(:meta, nil, itemprop: 'position', content: '1'), class: 'active', itemscope: 'itemscope', itemtype: 'https://schema.org/ListItem', itemprop: 'itemListElement')
52
75
  end
53
76
  crumb_list = content_tag(:ol, raw(crumbs.flatten.map(&:mb_chars).join), class: 'breadcrumb', itemscope: 'itemscope', itemtype: 'https://schema.org/BreadcrumbList')
54
- content_tag(:nav, crumb_list, id: 'breadcrumbs', class: 'col-12 mt-1 mt-sm-3 mt-lg-4', aria: { label: 'breadcrumb' })
77
+ content_tag(:nav, crumb_list, id: 'breadcrumbs', class: 'col-12 mt-1 mt-sm-3 mt-lg-4', aria: { label: Spree.t(:breadcrumbs) })
55
78
  end
56
79
 
57
80
  def class_for(flash_type)
@@ -101,7 +124,8 @@ module Spree
101
124
  end
102
125
  end
103
126
  content = content_tag('ul', raw(items.join("\n")), class: 'nav justify-content-between checkout-progress-steps', id: "checkout-step-#{@order.state}")
104
- content << content_tag('div', raw('<hr /><hr /><hr />'), class: "checkout-progress-steps-line state-#{@order.state}")
127
+ hrs = '<hr />' * (states.length - 1)
128
+ content << content_tag('div', raw(hrs), class: "checkout-progress-steps-line state-#{@order.state}")
105
129
  end
106
130
 
107
131
  def flash_messages(opts = {})
@@ -136,16 +160,22 @@ module Spree
136
160
  end
137
161
 
138
162
  def asset_exists?(path)
139
- if Rails.env.production?
140
- Rails.application.assets_manifest.find_sources(path).present?
163
+ if Rails.configuration.assets.compile
164
+ Rails.application.precompiled_assets.include? path
141
165
  else
142
- Rails.application.assets.find_asset(path).present?
166
+ Rails.application.assets_manifest.assets[path].present?
143
167
  end
144
168
  end
145
169
 
146
170
  def plp_and_carousel_image(product, image_class = '')
147
171
  image = default_image_for_product_or_variant(product)
148
- image_url = image&.plp_url || asset_path('noimage/plp.png')
172
+
173
+ image_url = if image.present?
174
+ main_app.cdn_image_url(image.url('plp'))
175
+ else
176
+ asset_path('noimage/plp.svg')
177
+ end
178
+
149
179
  image_style = image&.style(:plp)
150
180
 
151
181
  lazy_image(
@@ -176,7 +206,7 @@ module Spree
176
206
  widths = { lg: 1200, md: 992, sm: 768, xs: 576 }
177
207
  set = []
178
208
  widths.each do |key, value|
179
- file = main_app.url_for(image.url("plp_and_carousel_#{key}"))
209
+ file = main_app.cdn_image_url(image.url("plp_and_carousel_#{key}"))
180
210
 
181
211
  set << "#{file} #{value}w"
182
212
  end
@@ -221,7 +251,12 @@ module Spree
221
251
  end
222
252
 
223
253
  def price_filter_values
224
- [
254
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
255
+ `FrontendHelper#price_filter_values` is deprecated and will be removed in Spree 5.0.
256
+ Please use `ProductsFiltersHelper#price_filters` method
257
+ DEPRECATION
258
+
259
+ @price_filter_values ||= [
225
260
  "#{I18n.t('activerecord.attributes.spree/product.less_than')} #{formatted_price(50)}",
226
261
  "#{formatted_price(50)} - #{formatted_price(100)}",
227
262
  "#{formatted_price(101)} - #{formatted_price(150)}",
@@ -230,37 +265,138 @@ module Spree
230
265
  ]
231
266
  end
232
267
 
233
- def filtering_params
234
- static_filters = %w(keywords price sort_by)
268
+ def static_filters
269
+ @static_filters ||= Spree::Frontend::Config[:products_filters]
270
+ end
271
+
272
+ def additional_filters_partials
273
+ @additional_filters_partials ||= Spree::Frontend::Config[:additional_filters_partials]
274
+ end
235
275
 
236
- available_option_types.map(&:filter_param).concat(static_filters)
276
+ def filtering_params
277
+ @filtering_params ||= available_option_types.map(&:filter_param).concat(static_filters)
237
278
  end
238
279
 
239
280
  def filtering_params_cache_key
240
- params.permit(*filtering_params)&.reject { |_, v| v.blank? }&.to_s
281
+ @filtering_params_cache_key ||= begin
282
+ cache_key_parts = []
283
+
284
+ permitted_products_params.each do |key, value|
285
+ next if value.blank?
286
+
287
+ if value.is_a?(String)
288
+ cache_key_parts << [key, value].join('-')
289
+ else
290
+ value.each do |part_key, part_value|
291
+ next if part_value.blank?
292
+
293
+ cache_key_parts << [part_key, part_value].join('-')
294
+ end
295
+ end
296
+ end
297
+
298
+ cache_key_parts.join('-').parameterize
299
+ end
300
+ end
301
+
302
+ def filters_cache_key(kind)
303
+ base_cache_key + [
304
+ kind,
305
+ available_option_types_cache_key,
306
+ available_properties_cache_key,
307
+ filtering_params_cache_key,
308
+ @taxon&.id,
309
+ params[:menu_open]
310
+ ].flatten
311
+ end
312
+
313
+ def permitted_products_params
314
+ @permitted_products_params ||= begin
315
+ params.permit(*filtering_params, properties: available_properties.map(&:filter_param))
316
+ end
317
+ end
318
+
319
+ def option_type_cache_key(option_type)
320
+ filter_param = option_type.filter_param
321
+ filtered_params = params[filter_param]
322
+
323
+ [
324
+ available_option_types_cache_key,
325
+ filter_param,
326
+ filtered_params
327
+ ]
241
328
  end
242
329
 
243
330
  def available_option_types_cache_key
244
- @available_option_types_cache_key ||= Spree::OptionType.maximum(:updated_at)&.utc&.to_i
331
+ @available_option_types_cache_key ||= [
332
+ Spree::OptionType.filterable.maximum(:updated_at).to_f,
333
+ products_for_filters_cache_key
334
+ ].flatten.join('/')
245
335
  end
246
336
 
247
337
  def available_option_types
248
338
  @available_option_types ||= Rails.cache.fetch("available-option-types/#{available_option_types_cache_key}") do
249
- Spree::OptionType.includes(:option_values).to_a
339
+ option_values = OptionValues::FindAvailable.new(products_scope: products_for_filters).execute
340
+ Filters::OptionsPresenter.new(option_values_scope: option_values).to_a
341
+ end
342
+ end
343
+
344
+ def available_properties_cache_key
345
+ @available_properties_cache_key ||= [
346
+ Spree::Property.filterable.maximum(:updated_at).to_f,
347
+ products_for_filters_cache_key
348
+ ].flatten.join('/')
349
+ end
350
+
351
+ def available_properties
352
+ @available_properties ||= Rails.cache.fetch("available-properties/#{available_properties_cache_key}") do
353
+ product_properties = ProductProperties::FindAvailable.new(products_scope: products_for_filters).execute
354
+ Filters::PropertiesPresenter.new(product_properties_scope: product_properties).to_a
250
355
  end
251
- @available_option_types
252
356
  end
253
357
 
254
358
  def spree_social_link(service)
255
359
  return '' if current_store.send(service).blank?
256
360
 
257
- link_to "https://#{service}.com/#{current_store.send(service)}", target: :blank, rel: 'nofollow noopener' do
258
- content_tag :gigure, id: service, class: 'px-2' do
361
+ link_to "https://#{service}.com/#{current_store.send(service)}", target: '_blank', rel: 'nofollow noopener', 'aria-label': service do
362
+ content_tag :figure, id: service, class: 'px-2' do
259
363
  icon(name: service, width: 22, height: 22)
260
364
  end
261
365
  end
262
366
  end
263
367
 
368
+ def checkout_available_payment_methods
369
+ @checkout_available_payment_methods ||= @order.available_payment_methods
370
+ end
371
+
372
+ def color_option_type_name
373
+ @color_option_type_name ||= Spree::OptionType.color&.name
374
+ end
375
+
376
+ def country_flag_icon(country_iso_code = nil)
377
+ return if country_iso_code.blank?
378
+
379
+ content_tag :span, nil, class: "flag-icon flag-icon-#{country_iso_code.downcase}"
380
+ end
381
+
382
+ def product_wysiwyg_editor_enabled?
383
+ defined?(Spree::Backend) && Spree::Backend::Config[:product_wysiwyg_editor_enabled]
384
+ end
385
+
386
+ def taxon_wysiwyg_editor_enabled?
387
+ defined?(Spree::Backend) && Spree::Backend::Config[:taxon_wysiwyg_editor_enabled]
388
+ end
389
+
390
+ # converts line breaks in product description into <p> tags (for html display purposes)
391
+ def product_description(product)
392
+ description = if Spree::Frontend::Config[:show_raw_product_description] || product_wysiwyg_editor_enabled?
393
+ product.description
394
+ else
395
+ product.description.to_s.gsub(/(.*?)\r?\n\r?\n/m, '<p>\1</p>')
396
+ end
397
+ description.blank? ? Spree.t(:product_has_no_description) : description
398
+ end
399
+
264
400
  private
265
401
 
266
402
  def formatted_price(value)
@@ -277,12 +413,28 @@ module Spree
277
413
  end
278
414
  end
279
415
 
280
- def checkout_edit_link(step = 'address')
416
+ def checkout_edit_link(step = 'address', order = @order)
417
+ return if order.uneditable?
418
+
281
419
  classes = 'align-text-bottom checkout-confirm-delivery-informations-link'
282
420
 
283
421
  link_to spree.checkout_state_path(step), class: classes, method: :get do
284
422
  inline_svg_tag 'edit.svg'
285
423
  end
286
424
  end
425
+
426
+ def products_for_filters
427
+ @products_for_filters ||= current_store.products.for_filters(current_currency, taxon: @taxon)
428
+ end
429
+
430
+ def products_for_filters_cache_key
431
+ @products_for_filters_cache_key ||= begin
432
+ [
433
+ products_for_filters.maximum(:updated_at).to_f,
434
+ base_cache_key,
435
+ @taxon&.permalink
436
+ ].flatten.compact
437
+ end
438
+ end
287
439
  end
288
440
  end