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
@@ -3,19 +3,46 @@ require 'digest'
3
3
  module Spree
4
4
  module NavigationHelper
5
5
  def spree_navigation_data
6
- SpreeStorefrontConfig.dig(current_store.code, :navigation) || SpreeStorefrontConfig.dig(:default, :navigation) || []
6
+ Spree::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')
14
- base_cache_key + [current_store, spree_navigation_data_cache_key, Spree::Config[:logo], section]
23
+ Spree::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
+
28
+ @spree_nav_cache_key = begin
29
+ keys = base_cache_key + [current_store, spree_navigation_data_cache_key, stores&.cache_key_with_version, section]
30
+ Digest::MD5.hexdigest(keys.join('-'))
31
+ end
32
+ end
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('-'))
15
42
  end
16
43
 
17
44
  def main_nav_image(image_path, title = '')
18
- image_url = asset_path(asset_exists?(image_path) ? image_path : 'noimage/plp.png')
45
+ image_url = asset_path(asset_exists?(image_path) ? image_path : 'noimage/plp.svg')
19
46
 
20
47
  lazy_image(
21
48
  src: image_url,
@@ -25,6 +52,56 @@ module Spree
25
52
  )
26
53
  end
27
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::Product', 'Spree::Taxon', 'Spree::CmsPage'].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
+
79
+ def should_render_internationalization_dropdown?
80
+ (defined?(should_render_locale_dropdown?) && should_render_locale_dropdown?) ||
81
+ (defined?(should_render_currency_dropdown?) && should_render_currency_dropdown?)
82
+ end
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
+
28
105
  private
29
106
 
30
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.presentation, 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
@@ -0,0 +1,41 @@
1
+ module Spree
2
+ module StoreHelper
3
+ include LocaleHelper
4
+
5
+ def store_country_iso(store = nil)
6
+ store ||= current_store if defined?(current_store)
7
+
8
+ store&.default_country&.iso&.downcase
9
+ end
10
+
11
+ def stores
12
+ @stores ||= Spree::Store.includes(:default_country).order(:id)
13
+ end
14
+
15
+ def store_currency_symbol(store = nil)
16
+ store ||= current_store if defined?(current_store)
17
+ return unless store&.default_currency
18
+
19
+ ::Money::Currency.find(store.default_currency).symbol
20
+ end
21
+
22
+ def store_locale_name(store = nil)
23
+ store ||= current_store if defined?(current_store)
24
+ return unless store
25
+ return store.name if store.default_locale.blank?
26
+
27
+ locale_full_name(store.default_locale)
28
+ end
29
+
30
+ def should_render_store_chooser?
31
+ Spree::Frontend::Config[:show_store_selector] && stores.size > 1
32
+ end
33
+
34
+ def store_link(store = nil, html_opts = {})
35
+ store ||= current_store if defined?(current_store)
36
+ return unless store
37
+
38
+ link_to "#{store_locale_name(store)} (#{store_currency_symbol(store)})", store.formatted_url, **html_opts
39
+ end
40
+ end
41
+ end
@@ -22,10 +22,10 @@ module Spree
22
22
  name: product.name,
23
23
  image: structured_images(product),
24
24
  description: product.description,
25
- sku: product.sku,
25
+ sku: structured_sku(product),
26
26
  offers: {
27
27
  '@type': 'Offer',
28
- price: product.price_in(current_currency).amount,
28
+ price: product.default_variant.price_in(current_currency).amount,
29
29
  priceCurrency: current_currency,
30
30
  availability: product.in_stock? ? 'InStock' : 'OutOfStock',
31
31
  url: spree.product_url(product),
@@ -35,6 +35,10 @@ module Spree
35
35
  end
36
36
  end
37
37
 
38
+ def structured_sku(product)
39
+ product.default_variant.sku? ? product.default_variant.sku : product.sku
40
+ end
41
+
38
42
  def structured_images(product)
39
43
  image = default_image_for_product_or_variant(product)
40
44
 
@@ -4,8 +4,8 @@ module Spree
4
4
  # that we can use configurations as well as make it easier for end users to override this determination. One idea is
5
5
  # to show the most popular products for a particular taxon (that is an exercise left to the developer.)
6
6
  def taxon_preview(taxon, max = 4)
7
- ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
8
- TaxonsHelper is deprecated and will be removed in Spree 4.2.
7
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
8
+ TaxonsHelper is deprecated and will be removed in Spree 5.0.
9
9
  Please remove any `helper 'spree/taxons'` from your controllers.
10
10
  DEPRECATION
11
11
  products = taxon.active_products.distinct.select('spree_products.*, spree_products_taxons.position').limit(max)
@@ -0,0 +1,141 @@
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|pages|login|account|logout|signup|users)/.freeze
10
+
11
+ PRODUCT_PATH_REGEX = /\/products\/(\S+)/.freeze
12
+ TAXON_PATH_REGEX = /\/t\/(\S+)/.freeze
13
+
14
+ # rubocop:disable Lint/UnusedMethodArgument
15
+ def call(url:, locale:, default_locale: nil)
16
+ run :initialize_url_object
17
+ run :generate_new_path
18
+ run :append_locale_param
19
+ run :build_url
20
+ end
21
+ # rubocop:enable Lint/UnusedMethodArgument
22
+
23
+ protected
24
+
25
+ def initialize_url_object(url:, locale:, default_locale:)
26
+ success(
27
+ url: URI(url),
28
+ locale: locale,
29
+ default_locale: default_locale,
30
+ default_locale_supplied: default_locale_supplied?(locale, default_locale)
31
+ )
32
+ end
33
+
34
+ def generate_new_path(url:, locale:, default_locale:, default_locale_supplied:)
35
+ unless supported_path?(url.path)
36
+ return success(
37
+ url: url,
38
+ locale: locale,
39
+ path: cleanup_path(url.path),
40
+ default_locale_supplied: default_locale_supplied,
41
+ locale_added_to_path: false
42
+ )
43
+ end
44
+
45
+
46
+ locale_url_match = url.path.match(LOCALE_REGEX)
47
+ previous_locale = locale_url_match ? locale_url_match[1] || default_locale : default_locale
48
+
49
+ product_path_match = url.path.match(PRODUCT_PATH_REGEX)
50
+ taxon_path_match = url.path.match(TAXON_PATH_REGEX)
51
+
52
+ if product_path_match
53
+ new_path = generate_product_path(product_path_match, previous_locale, locale, default_locale, default_locale_supplied)
54
+ elsif url.path.match(TAXON_PATH_REGEX)
55
+ new_path = generate_taxon_path(taxon_path_match, previous_locale, locale, default_locale, default_locale_supplied)
56
+ else
57
+ new_path = generate_regular_page_path(default_locale_supplied, url, locale)
58
+ end
59
+
60
+ success(
61
+ url: url,
62
+ locale: locale,
63
+ path: cleanup_path(new_path),
64
+ default_locale_supplied: default_locale_supplied,
65
+ locale_added_to_path: true
66
+ )
67
+ end
68
+
69
+ def append_locale_param(url:, locale:, path:, default_locale_supplied:, locale_added_to_path:)
70
+ return success(url: url, path: path, query: url.query) if locale_added_to_path
71
+
72
+ query_params = Rack::Utils.parse_nested_query(url.query)
73
+
74
+ if default_locale_supplied
75
+ query_params.delete('locale')
76
+ else
77
+ query_params.merge!('locale' => locale)
78
+ end
79
+
80
+ query_string = query_params.any? ? query_params.to_query : nil
81
+
82
+ success(url: url, path: path, query: query_string)
83
+ end
84
+
85
+ def build_url(url:, path:, query:)
86
+ localized_url = builder_class(url).build(host: url.host, port: url.port, path: path, query: query).to_s
87
+ success(localized_url)
88
+ end
89
+
90
+ private
91
+
92
+ def supported_path?(path)
93
+ return true if path.blank? || path == '/' || maches_locale_regex?(path)
94
+
95
+ path.match(SUPPORTED_PATHS_REGEX)
96
+ end
97
+
98
+ def maches_locale_regex?(path)
99
+ path.match(LOCALE_REGEX)[0].gsub('/', '') if path.match(LOCALE_REGEX)
100
+ end
101
+
102
+ def default_locale_supplied?(locale, default_locale)
103
+ default_locale.present? && default_locale.to_s == locale.to_s
104
+ end
105
+
106
+ def cleanup_path(path)
107
+ path.chomp('/').gsub('//', '/')
108
+ end
109
+
110
+ def builder_class(url)
111
+ url.scheme == 'http' ? URI::HTTP : URI::HTTPS
112
+ end
113
+
114
+ def generate_product_path(product_path_match, previous_locale, locale, default_locale, default_locale_supplied)
115
+ product = begin
116
+ Mobility.with_locale(previous_locale) { Spree::Product.friendly.find(product_path_match[1]) }
117
+ rescue ActiveRecord::RecordNotFound
118
+ Mobility.with_locale(default_locale) { Spree::Product.friendly.find(product_path_match[1]) }
119
+ end
120
+
121
+ new_slug = product.slug(locale: locale) || product.slug(locale: default_locale)
122
+ new_path_slug = "/products/#{new_slug}"
123
+ default_locale_supplied ? new_path_slug : "/#{locale}/#{new_path_slug}"
124
+ end
125
+
126
+ def generate_taxon_path(taxon_path_match, previous_locale, locale, default_locale, default_locale_supplied)
127
+ taxon = Mobility.with_locale(previous_locale) { Spree::Taxon.friendly.find(taxon_path_match[1]) }
128
+ new_slug = taxon.permalink(locale: locale) || taxon.permalink(locale: default_locale)
129
+ new_path_slug = "/t/#{new_slug}"
130
+ default_locale_supplied ? new_path_slug : "/#{locale}/#{new_path_slug}"
131
+ end
132
+
133
+ def generate_regular_page_path(default_locale_supplied, url, locale)
134
+ if default_locale_supplied
135
+ maches_locale_regex?(url.path) ? url.path.gsub(LOCALE_REGEX, '/') : url.path
136
+ else
137
+ maches_locale_regex?(url.path) ? url.path.gsub(LOCALE_REGEX, "/#{locale}/") : "/#{locale}#{url.path}"
138
+ end
139
+ end
140
+ end
141
+ end
@@ -4,10 +4,10 @@
4
4
  current_page: a page object for the currently displayed page
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
- remote: data-remote
8
- -%>
7
+ remote: data-remote -%>
8
+
9
9
  <% unless current_page.first? %>
10
10
  <li class="first page-item">
11
- <%= link_to_unless current_page.first?, inline_svg_tag('pagination-double-arrow-right.svg', size: '13px*16px', class: 'spree-icon-arrow-left'), url, remote: remote, class: 'page-link' %>
11
+ <%= link_to_unless current_page.first?, inline_svg_tag('pagination-double-arrow-right.svg', size: '13px*16px', class: 'spree-icon-arrow-left'), url, remote: remote, class: 'page-link', 'aria-label': 'First page' %>
12
12
  </li>
13
13
  <% end %>
@@ -3,8 +3,8 @@
3
3
  current_page: a page object for the currently displayed page
4
4
  total_pages: total number of pages
5
5
  per_page: number of items to fetch per page
6
- remote: data-remote
7
- -%>
6
+ remote: data-remote -%>
7
+
8
8
  <li class="page gap disabled page-item d-none d-lg-flex">
9
9
  <a href="#" onclick="return false;" class="page-link">
10
10
  <%= raw(t 'views.pagination.truncate') %>
@@ -4,10 +4,10 @@
4
4
  current_page: a page object for the currently displayed page
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
- remote: data-remote
8
- -%>
7
+ remote: data-remote -%>
8
+
9
9
  <% unless current_page.last? %>
10
10
  <li class="last next page-item"><%# "next" class present for border styling in twitter bootstrap %>
11
- <%= link_to_unless current_page.last?, inline_svg_tag('pagination-double-arrow-right.svg', size: '13px*16px'), url, remote: remote, class: 'page-link' %>
11
+ <%= link_to_unless current_page.last?, inline_svg_tag('pagination-double-arrow-right.svg', size: '13px*16px'), url, remote: remote, class: 'page-link', 'aria-label': 'Last page' %>
12
12
  </li>
13
13
  <% end %>
@@ -4,10 +4,10 @@
4
4
  current_page: a page object for the currently displayed page
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
- remote: data-remote
8
- -%>
7
+ remote: data-remote -%>
8
+
9
9
  <% unless current_page.last? %>
10
10
  <li class="next_page page-item">
11
- <%= link_to_unless current_page.last?, inline_svg_tag('pagination-arrow-right.svg', size: '13px*16px'), url, rel: 'next', remote: remote, class: 'page-link' %>
11
+ <%= link_to_unless current_page.last?, inline_svg_tag('pagination-arrow-right.svg', size: '13px*16px'), url, rel: 'next', remote: remote, class: 'page-link', 'aria-label': 'Next page' %>
12
12
  </li>
13
13
  <% end %>
@@ -5,8 +5,8 @@
5
5
  current_page: a page object for the currently displayed page
6
6
  total_pages: total number of pages
7
7
  per_page: number of items to fetch per page
8
- remote: data-remote
9
- -%>
8
+ remote: data-remote -%>
9
+
10
10
  <li class="page<%= ' active' if page.current? %> page-item">
11
11
  <%= link_to page,
12
12
  url,
@@ -4,8 +4,8 @@
4
4
  total_pages: total number of pages
5
5
  per_page: number of items to fetch per page
6
6
  remote: data-remote
7
- paginator: the paginator that renders the pagination tags inside
8
- -%>
7
+ paginator: the paginator that renders the pagination tags inside -%>
8
+
9
9
  <% pagination_class ||= '' %>
10
10
 
11
11
  <%= paginator.render do %>
@@ -4,10 +4,10 @@
4
4
  current_page: a page object for the currently displayed page
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
- remote: data-remote
8
- -%>
7
+ remote: data-remote -%>
8
+
9
9
  <% unless current_page.first? %>
10
10
  <li class="prev page-item">
11
- <%= link_to_unless current_page.first?, inline_svg_tag('pagination-arrow-right.svg', size: '13px*16px', class: 'spree-icon-arrow-left'), url, rel: 'prev', remote: remote, class: 'page-link' %>
11
+ <%= link_to_unless current_page.first?, inline_svg_tag('pagination-arrow-right.svg', size: '13px*16px', class: 'spree-icon-arrow-left'), url, rel: 'prev', remote: remote, class: 'page-link', 'aria-label': 'Previous page' %>
12
12
  </li>
13
13
  <% end %>