workarea-swatches 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  4. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.gitignore +21 -0
  7. data/CHANGELOG.md +121 -0
  8. data/CODE_OF_CONDUCT.md +3 -0
  9. data/CONTRIBUTING.md +3 -0
  10. data/Gemfile +17 -0
  11. data/LICENSE +52 -0
  12. data/README.md +40 -0
  13. data/Rakefile +60 -0
  14. data/app/assets/javascripts/workarea/storefront/swatches/modules/product_summary_swatches.js +63 -0
  15. data/app/assets/stylesheets/workarea/storefront/swatches/components/_option_button.scss +17 -0
  16. data/app/assets/stylesheets/workarea/storefront/swatches/components/_swatch_facet.scss +25 -0
  17. data/app/assets/stylesheets/workarea/storefront/swatches/components/_swatch_options.scss +54 -0
  18. data/app/controllers/workarea/admin/catalog_product_swatches_controller.rb +47 -0
  19. data/app/controllers/workarea/admin/catalog_swatches_controller.rb +48 -0
  20. data/app/controllers/workarea/storefront/products_controller.decorator +12 -0
  21. data/app/helpers/workarea/storefront/swatches_helper.rb +84 -0
  22. data/app/models/workarea/catalog/product.decorator +7 -0
  23. data/app/models/workarea/catalog/product_swatch.rb +10 -0
  24. data/app/models/workarea/catalog/swatch.rb +37 -0
  25. data/app/models/workarea/search/settings.decorator +8 -0
  26. data/app/queries/workarea/search/category_browse.decorator +7 -0
  27. data/app/queries/workarea/search/product_search.decorator +7 -0
  28. data/app/queries/workarea/search/swatched_facets.rb +19 -0
  29. data/app/queries/workarea/search/swatches_facet.rb +13 -0
  30. data/app/seeds/workarea/swatches_seeds.rb +37 -0
  31. data/app/view_models/workarea/storefront/product_templates/swatches_view_model.rb +57 -0
  32. data/app/views/workarea/admin/activities/_catalog_product_swatch_create.html.haml +10 -0
  33. data/app/views/workarea/admin/activities/_catalog_product_swatch_destroy.html.haml +10 -0
  34. data/app/views/workarea/admin/activities/_catalog_swatch_create.html.haml +12 -0
  35. data/app/views/workarea/admin/activities/_catalog_swatch_destroy.html.haml +10 -0
  36. data/app/views/workarea/admin/catalog_product_swatches/edit.html.haml +52 -0
  37. data/app/views/workarea/admin/catalog_product_swatches/index.html.haml +65 -0
  38. data/app/views/workarea/admin/catalog_products/_swatches_card.html.haml +27 -0
  39. data/app/views/workarea/admin/catalog_swatches/_primary_navigation.html.haml +1 -0
  40. data/app/views/workarea/admin/catalog_swatches/index.html.haml +78 -0
  41. data/app/views/workarea/api/storefront/facets/_swatches.json.jbuilder +17 -0
  42. data/app/views/workarea/storefront/facets/_swatches.html.haml +14 -0
  43. data/app/views/workarea/storefront/products/_swatch_summary.html.haml +17 -0
  44. data/app/views/workarea/storefront/products/templates/_swatches.html.haml +79 -0
  45. data/bin/rails +19 -0
  46. data/config/initializers/dragonfly.rb +11 -0
  47. data/config/initializers/workarea.rb +40 -0
  48. data/config/locales/en.yml +52 -0
  49. data/config/routes.rb +15 -0
  50. data/lib/tasks/swatches_tasks.rake +4 -0
  51. data/lib/workarea/swatches.rb +11 -0
  52. data/lib/workarea/swatches/engine.rb +12 -0
  53. data/lib/workarea/swatches/version.rb +5 -0
  54. data/test/dummy/Rakefile +6 -0
  55. data/test/dummy/app/assets/config/manifest.js +4 -0
  56. data/test/dummy/app/assets/javascripts/application.js +13 -0
  57. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  58. data/test/dummy/app/controllers/application_controller.rb +3 -0
  59. data/test/dummy/app/helpers/application_helper.rb +2 -0
  60. data/test/dummy/app/jobs/application_job.rb +2 -0
  61. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  62. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  63. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  64. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  65. data/test/dummy/bin/bundle +3 -0
  66. data/test/dummy/bin/rails +4 -0
  67. data/test/dummy/bin/rake +4 -0
  68. data/test/dummy/bin/setup +30 -0
  69. data/test/dummy/bin/update +26 -0
  70. data/test/dummy/bin/yarn +11 -0
  71. data/test/dummy/config.ru +5 -0
  72. data/test/dummy/config/application.rb +30 -0
  73. data/test/dummy/config/boot.rb +5 -0
  74. data/test/dummy/config/cable.yml +10 -0
  75. data/test/dummy/config/environment.rb +5 -0
  76. data/test/dummy/config/environments/development.rb +51 -0
  77. data/test/dummy/config/environments/production.rb +88 -0
  78. data/test/dummy/config/environments/test.rb +44 -0
  79. data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
  80. data/test/dummy/config/initializers/assets.rb +14 -0
  81. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  82. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  83. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  84. data/test/dummy/config/initializers/inflections.rb +16 -0
  85. data/test/dummy/config/initializers/mime_types.rb +4 -0
  86. data/test/dummy/config/initializers/workarea.rb +5 -0
  87. data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
  88. data/test/dummy/config/locales/en.yml +33 -0
  89. data/test/dummy/config/puma.rb +56 -0
  90. data/test/dummy/config/routes.rb +5 -0
  91. data/test/dummy/config/secrets.yml +32 -0
  92. data/test/dummy/config/spring.rb +6 -0
  93. data/test/dummy/db/seeds.rb +2 -0
  94. data/test/dummy/log/.keep +0 -0
  95. data/test/factories/workarea/swatches.rb +14 -0
  96. data/test/integration/workarea/admin/product_swatches_integration_test.rb +43 -0
  97. data/test/integration/workarea/admin/swatches_integration_test.rb +37 -0
  98. data/test/integration/workarea/storefront/swatches_integration_test.rb +72 -0
  99. data/test/system/workarea/admin/swatches_system_test.rb +58 -0
  100. data/test/system/workarea/storefront/browse_swatches_system_test.rb +50 -0
  101. data/test/system/workarea/storefront/swatches_system_test.rb +101 -0
  102. data/test/teaspoon_env.rb +6 -0
  103. data/test/test_helper.rb +10 -0
  104. data/test/view_models/workarea/storefront/product_templates/swatches_view_model_test.rb +74 -0
  105. data/workarea-swatches.gemspec +19 -0
  106. metadata +147 -0
@@ -0,0 +1,57 @@
1
+ module Workarea
2
+ module Storefront
3
+ class ProductTemplates::SwatchesViewModel < ProductViewModel
4
+ include OptionSetViewModel
5
+
6
+ def images_by_option
7
+ @images_by_option ||= model
8
+ .images
9
+ .reject { |i| i.option.blank? }
10
+ .group_by { |i| i.option.optionize }
11
+ .with_indifferent_access
12
+ .transform_keys(&:optionize)
13
+ end
14
+
15
+ def swatches_by_option
16
+ @swatches_by_option ||= Hash[swatches_with_overrides.map { |s| [s.id, s] }]
17
+ end
18
+
19
+ def browse_link_options
20
+ return super unless current_browse_selection.present?
21
+ super.merge(browse_swatch_option.slug => current_browse_selection)
22
+ end
23
+
24
+ def browse_swatch_option
25
+ @browse_swatch_option ||=
26
+ Workarea.config.browse_swatch_option.call(self, options_for_selection)
27
+ end
28
+
29
+ def display_browse_swatches?
30
+ return false if model.try(:browse_option).present?
31
+ browse_swatch_option.present?
32
+ end
33
+
34
+ def current_browse_selection
35
+ return if browse_swatch_option.blank?
36
+ options[browse_swatch_option.slug]
37
+ end
38
+
39
+ def current_browse_selection?(selection)
40
+ current_browse_selection == selection
41
+ end
42
+
43
+ private
44
+
45
+ def swatches_with_overrides
46
+ (global_swatches + model.swatches).map do |swatch|
47
+ override_swatch = model.swatches.detect { |s| s.id == swatch.id }
48
+ override_swatch || swatch
49
+ end
50
+ end
51
+
52
+ def global_swatches
53
+ @global_swatches ||= Catalog::Swatch.all.to_a
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,10 @@
1
+ .activity
2
+ .activity__header
3
+ .activity__avatar
4
+ = link_to_modifier(entry) do
5
+ = avatar_for entry.modifier
6
+ %h3.activity__name= link_to_modifier(entry)
7
+ %p.activity__time= activity_time(entry.created_at)
8
+ .activity__message
9
+ - name = entry.root.blank? ? t('workarea.admin.activities.a_product') : link_to(entry.root.name, catalog_product_path(entry.root))
10
+ = t('workarea.admin.activities.catalog_product_swatch_create_html', name: name)
@@ -0,0 +1,10 @@
1
+ .activity
2
+ .activity__header
3
+ .activity__avatar
4
+ = link_to_modifier(entry) do
5
+ = avatar_for entry.modifier
6
+ %h3.activity__name= link_to_modifier(entry)
7
+ %p.activity__time= activity_time(entry.created_at)
8
+ .activity__message
9
+ - name = entry.root.blank? ? t('workarea.admin.activities.a_product') : link_to(entry.root.name, catalog_product_path(entry.root))
10
+ = t('workarea.admin.activities.catalog_product_swatch_destroy_html', name: name)
@@ -0,0 +1,12 @@
1
+ .activity
2
+ .activity__header
3
+ .activity__avatar
4
+ = link_to_modifier(entry) do
5
+ = avatar_for entry.modifier
6
+ %h3.activity__name= link_to_modifier(entry)
7
+ %p.activity__time= activity_time(entry.created_at)
8
+ .activity__message
9
+ - if entry.audited.present?
10
+ = t('workarea.admin.activities.catalog_swatch_create_html', name: link_to(entry.audited.name, catalog_swatch_path(entry.audited)))
11
+ - else
12
+ = t('workarea.admin.activities.catalog_swatch_create_html', name: entry.model_name)
@@ -0,0 +1,10 @@
1
+ .activity
2
+ .activity__header
3
+ .activity__avatar
4
+ = link_to_modifier(entry) do
5
+ = avatar_for entry.modifier
6
+ %h3.activity__name= link_to_modifier(entry)
7
+ %p.activity__time= activity_time(entry.created_at)
8
+ .activity__message
9
+ = t('workarea.admin.activities.catalog_swatch_destroy_html', name: entry.model_name)
10
+ = link_to_restore_for(entry)
@@ -0,0 +1,52 @@
1
+ - @page_title = t('workarea.admin.catalog_product_swatches.edit.edit_swatch_for', product: @product.name)
2
+
3
+ .product-images.view
4
+ .view__header
5
+ .grid.grid--middle
6
+ .grid__cell.grid__cell--25
7
+ = render 'workarea/admin/releases/select'
8
+ .grid__cell.grid__cell--50
9
+ .view__heading
10
+ = link_to_index_for(@product)
11
+ %h1= link_to @product.name, url_for(@product)
12
+ .grid__cell.grid__cell--25
13
+ = render_aux_navigation_for(@product)
14
+
15
+ .view__container
16
+ = render_cards_for(@product, :swatches)
17
+
18
+ .view__container.view__container--narrow
19
+ .section
20
+ .product-images__option-group
21
+ .product-images__option
22
+ .product-images__option-header
23
+ .product-images__option-title= @swatch.option.present? ? "#{@swatch.option.titleize} #{t('workarea.admin.catalog_product_swatches.edit.swatch')}" : t('workarea.admin.catalog_product_swatches.edit.without_options')
24
+
25
+ .product-images__image-group
26
+ .product-images__image
27
+ .product-images__image-summary
28
+ .product-images__image-summary-container= image_tag @swatch.image.process(:swatch).url, alt: "#{@swatch.option} #{t('workarea.admin.catalog_product_swatches.edit.swatch')}", id: @swatch.option.parameterize, class: 'product-images__image-summary-image'
29
+
30
+ .section
31
+ %h2= t('workarea.admin.catalog_product_swatches.edit.edit_swatch')
32
+
33
+ = form_tag catalog_product_swatch_path(@product, @swatch), method: :patch, multipart: true do
34
+ .property
35
+ = label_tag 'swatch_image', t('workarea.admin.fields.image'), class: 'property__name'
36
+ = file_field_tag 'swatch[image]', value: @swatch.url
37
+
38
+ .property
39
+ = label_tag 'swatch_option', t('workarea.admin.fields.option'), class: 'property__name'
40
+ = text_field_tag 'swatch[option]', @swatch.option, class: 'text-box text-box--medium', data: { autocomplete_field: options_catalog_product_images_path(@product) }
41
+
42
+ = append_partials('admin.product_swatch_fields')
43
+
44
+ = append_partials('admin.product_swatches', product: @product)
45
+
46
+ .workflow-bar
47
+ .grid.grid--right.grid--middle
48
+ .grid__cell.grid__cell--20
49
+ = link_to t('workarea.admin.form.cancel'), catalog_product_swatches_path(@product), class: 'workflow-bar__button workflow-bar__button--delete'
50
+ .grid__cell.grid__cell--80
51
+ .grid.grid--auto.grid--right.grid--middle
52
+ .grid__cell= button_tag t('workarea.admin.form.save_changes'), value: 'save_product_image', class: 'workflow-bar__button workflow-bar__button--update'
@@ -0,0 +1,65 @@
1
+ - @page_title = t('workarea.admin.catalog_product_swatches.index.swatches_for', product: @product.name)
2
+ .product-images.view
3
+ .view__header
4
+ .grid.grid--middle
5
+ .grid__cell.grid__cell--25
6
+ = render 'workarea/admin/releases/select'
7
+ .grid__cell.grid__cell--50
8
+ .view__heading
9
+ = link_to_index_for(@product)
10
+ %h1= link_to @product.name, url_for(@product)
11
+ .grid__cell.grid__cell--25
12
+ = render_aux_navigation_for(@product)
13
+
14
+ .view__container
15
+ = render_cards_for(@product, :swatches)
16
+
17
+ .view__container.view__container--narrow
18
+ .section
19
+ - if @product.swatches.blank?
20
+ %h2.align-center= t('workarea.admin.catalog_swatches.index.no_swatches')
21
+ - else
22
+ %table.index-table
23
+ %thead
24
+ %tr
25
+ %th= t('workarea.admin.fields.name')
26
+ %th= t('workarea.admin.fields.color')
27
+ %th= t('workarea.admin.fields.image')
28
+ %th= t('workarea.admin.actions.remove')
29
+ %tbody
30
+ - @product.swatches.each do |swatch|
31
+ %tr.index-table__row
32
+ %td= swatch.name
33
+ %td
34
+ = form_tag catalog_product_swatch_path(@product, swatch), method: 'patch' do
35
+ = color_field_tag 'swatch[hex]', swatch.hex, class: 'color-picker__input', data: { form_submitting_control: '' }, id: nil
36
+ %td
37
+ = form_tag catalog_product_swatch_path(@product, swatch), method: 'patch', multipart: true do
38
+ = image_tag swatch.image.process(:small).url if swatch.image.present?
39
+ = file_field_tag 'swatch[image]', class: 'text-box', data: { form_submitting_control: '' }, id: nil
40
+ %td
41
+ = form_tag catalog_product_swatch_path(@product, swatch), method: 'delete', class: 'text-button text-button--destroy' do
42
+ = button_tag value: 'remove_swatch', class: 'text-button text-button--destroy' do
43
+ = inline_svg('workarea/admin/icons/delete.svg', class: 'text-button__icon', title: t('workarea.admin.actions.delete'))
44
+
45
+ .section
46
+ .grid.grid--center
47
+ .grid__cell.grid__cell--50
48
+ %h2.align-center= t('workarea.admin.catalog_swatches.index.add_new')
49
+
50
+ = form_tag catalog_product_swatches_path(@product), method: 'post', multipart: true do
51
+ .grid.grid--auto
52
+ .grid__cell
53
+ .property.property--required
54
+ = label_tag 'swatch_name', t('workarea.admin.fields.name'), class: 'property__name'
55
+ = text_field_tag 'swatch[name]', params.dig(:swatch, :name), class: 'text-box text-box--medium', required: true, id: nil
56
+ .grid__cell
57
+ .property
58
+ = label_tag 'swatch_hex', t('workarea.admin.fields.color'), class: 'property__name'
59
+ = color_field_tag 'swatch[hex]', params.dig(:swatch, :hex), class: 'color-picker__input', id: nil
60
+ .grid__cell
61
+ .property
62
+ = label_tag 'swatch_image', t('workarea.admin.fields.image'), class: 'property__name'
63
+ = file_field_tag 'swatch[image]', class: 'text-box text-box--large', id: nil
64
+
65
+ = button_tag t('workarea.admin.actions.save'), value: 'save_new_swatch', class: 'button'
@@ -0,0 +1,27 @@
1
+ .grid__cell
2
+ .card{ class: card_classes(:swatches, local_assigns[:active]) }
3
+ = link_to catalog_product_swatches_path(model), class: 'card__header' do
4
+ %span.card__header-text= t('workarea.admin.catalog_products.cards.swatches.title')
5
+ = inline_svg 'workarea/admin/icons/images.svg', class: 'card__icon'
6
+
7
+ - if local_assigns[:active].blank?
8
+ .card__body
9
+ - if model.swatches.empty?
10
+ %p= t('workarea.admin.catalog_products.cards.swatches.description')
11
+ = link_to catalog_product_swatches_path(model), class: 'card__button' do
12
+ %span.button.button--small= t('workarea.admin.catalog_products.cards.swatches.add_swatches')
13
+ - else
14
+ %ul.grid
15
+ - model.swatches.take(4).each_with_index do |swatch, i|
16
+ %li.grid__cell.grid__cell--50
17
+ - if i == 3 && model.swatches.size > 4
18
+ .card__photo-box
19
+ %span.card__photo +#{model.swatches.size - i}
20
+ - elsif swatch.image.present?
21
+ .card__photo-box
22
+ = image_tag swatch.image.process(:small_thumb).url, alt: swatch.name, class: 'card__photo'
23
+ - else
24
+ .card__photo-box{ style: "background-color: #{swatch.hex};" }
25
+
26
+ = link_to catalog_product_swatches_path(model), class: 'card__button' do
27
+ %span.button.button--small= t('workarea.admin.catalog_products.cards.swatches.manage_swatches')
@@ -0,0 +1 @@
1
+ %li{ class: "primary-nav__item" }= link_to t('workarea.admin.catalog_swatches.primary_navigation.swatches'), catalog_swatches_path, class: navigation_link_classes(catalog_swatches_path)
@@ -0,0 +1,78 @@
1
+ - @page_title= t('workarea.admin.catalog_swatches.index.page_title')
2
+
3
+ .view
4
+ .view__header
5
+ .grid.grid--center
6
+ .grid__cell.grid__cell--50
7
+ .view__heading
8
+ = link_to "↑ #{t('workarea.admin.catalog.dashboard_link')}", catalog_dashboards_path, class: 'view__dashboard-button'
9
+ %h1.heading--no-margin= t('workarea.admin.catalog_swatches.index.page_title')
10
+ %p= t('workarea.admin.catalog_swatches.index.description')
11
+
12
+ .view__container.view__container--narrow
13
+ .section
14
+ - if @swatches.blank?
15
+ %h2= t('workarea.admin.catalog_swatches.index.no_swatches')
16
+ - else
17
+ %table.index-table
18
+ %thead
19
+ %tr
20
+ %th= t('workarea.admin.fields.name')
21
+ %th= t('workarea.admin.fields.color')
22
+ %th= t('workarea.admin.fields.image')
23
+ %th= t('workarea.admin.actions.remove')
24
+ %tbody
25
+ - @swatches.each do |swatch|
26
+ %tr.index-table__row
27
+ %td= swatch.name
28
+ %td
29
+ = form_tag catalog_swatch_path(swatch), method: 'patch' do
30
+ = color_field_tag 'swatch[hex]', swatch.hex, class: 'color-picker__input', data: { form_submitting_control: '' }, id: nil
31
+ %td
32
+ = form_tag catalog_swatch_path(swatch), method: 'patch', multipart: true do
33
+ = image_tag swatch.image.process(:small).url if swatch.image.present?
34
+ = file_field_tag 'swatch[image]', class: 'text-box', data: { form_submitting_control: '' }, id: nil
35
+ %td
36
+ = form_tag catalog_swatch_path(swatch), method: 'delete', class: 'text-button text-button--destroy' do
37
+ = button_tag value: 'remove_swatch', class: 'text-button text-button--destroy' do
38
+ = inline_svg('workarea/admin/icons/delete.svg', class: 'text-button__icon', title: t('workarea.admin.actions.delete'))
39
+
40
+ .section
41
+ .grid
42
+ .grid__cell.grid__cell--50
43
+ %h2= t('workarea.admin.catalog_swatches.index.add_new')
44
+
45
+ = form_tag catalog_swatches_path, method: 'post', multipart: true do
46
+ .grid.grid--auto
47
+ .grid__cell
48
+ .property.property--required
49
+ = label_tag 'swatch_name', t('workarea.admin.fields.name'), class: 'property__name'
50
+ = text_field_tag 'swatch[name]', params.dig(:swatch, :name), class: 'text-box text-box--medium', required: true, id: nil
51
+ .grid__cell
52
+ .property
53
+ = label_tag 'swatch_hex', t('workarea.admin.fields.color'), class: 'property__name'
54
+ = color_field_tag 'swatch[hex]', params.dig(:swatch, :hex), class: 'color-picker__input', id: nil
55
+ .grid__cell
56
+ .property
57
+ = label_tag 'swatch_image', t('workarea.admin.fields.image'), class: 'property__name'
58
+ = file_field_tag 'swatch[image]', class: 'text-box text-box--large', id: nil
59
+
60
+ = button_tag t('workarea.admin.actions.save'), value: 'save_new_swatch', class: 'button'
61
+
62
+ .grid__cell.grid__cell--50
63
+ %h2= t('workarea.admin.catalog_swatches.index.manage_filters')
64
+
65
+ = form_tag search_settings_path, method: 'patch', data: { unsaved_changes: '' } do
66
+ = hidden_field_tag :return_to, catalog_swatches_path
67
+ .property
68
+ = label_tag 'swatch_facets_list', class: 'property__name' do
69
+ = t('workarea.admin.catalog_swatches.index.swatch_filters')
70
+ = link_to '#swatch-facets-info', data: { tooltip: '' } do
71
+ = inline_svg('workarea/admin/icons/help.svg', class: 'svg-icon svg-icon--small svg-icon--blue', title: t('workarea.admin.catalog_swatches.index.swatch_filters'))
72
+
73
+ = text_field_tag 'settings[swatch_facets_list]', @search_settings.swatch_facets_list, class: 'text-box'
74
+ %span.property__note= t('workarea.admin.form.csv_field_note')
75
+ #swatch-facets-info.tooltip-content
76
+ %p= t('workarea.admin.catalog_swatches.index.swatch_facets_info')
77
+
78
+ = button_tag t('workarea.admin.actions.save'), value: 'save_settings', class: 'button'
@@ -0,0 +1,17 @@
1
+ json.type facet.type
2
+ json.name facet.name
3
+ json.display_name facet.display_name
4
+
5
+ json.results facet.results do |name, count|
6
+ json.name name
7
+ json.count count
8
+
9
+ @swatches_cache ||= Workarea::Catalog::Swatch.all.to_a
10
+ swatch = @swatches_cache.detect { |s| s.id == name.systemize }
11
+
12
+ if swatch&.image?
13
+ json.swatch_image swatch.image.process(:facet_swatch).url
14
+ elsif swatch&.hex?
15
+ json.swatch_hex swatch.hex
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ %div{ class: "result-filters__section result-filters__section--#{facet.system_name}" }
2
+ %h2= t('workarea.storefront.products.filter_title', name: facet.display_name)
3
+ %ul.result-filters__group
4
+ - facet.results.each do |value_name, count|
5
+ %li.result-filters__filter{ class: facet.selected?(value_name) ? 'result-filters__filter--selected' : nil }
6
+ = link_to render_swatch_facet(value_name), facet_path(facet, value_name), rel: 'nofollow', class: 'results-filters__swatch-link'
7
+
8
+ = link_to facet_path(facet, value_name), rel: 'nofollow', class: 'result-filters__link' do
9
+ = value_name.titleize
10
+
11
+ - if facet.selected?(value_name)
12
+ %strong.result-filters__remove= t('workarea.storefront.products.remove_filter')
13
+ -else
14
+ %span.result-filters__count (#{count})
@@ -0,0 +1,17 @@
1
+ - if product.try(:display_browse_swatches?)
2
+ .swatch-options.swatch-options--small
3
+ %ul.swatch-options__group
4
+ - product.browse_swatch_option.selections.each do |selection|
5
+ - swatch = product.swatches_by_option[selection.optionize]
6
+ - swatch_content = render_browse_swatch(selection, swatch)
7
+
8
+ - if product.current_browse_selection?(selection)
9
+ %li.swatch-options__swatch.swatch-options__swatch--selected>
10
+ = swatch_content
11
+ - else
12
+ %li.swatch-options__swatch>
13
+ - selection_options = option_selection_url_for(product, product.browse_swatch_option, selection)
14
+ - product_path = product_path(product, product.browse_link_options.merge(selection_options))
15
+
16
+ = link_to product_path, title: selection, class: 'swatch-options__swatch-button', data: { product_summary_swatch: { url: summary_product_path(product, selection_options) }.to_json } do
17
+ = swatch_content
@@ -0,0 +1,79 @@
1
+ .grid.grid--rev
2
+ .grid__cell.grid__cell--60-at-medium
3
+
4
+ .product-details__name
5
+ %h1.product-details__heading{ itemprop: 'name' }= product.name
6
+
7
+ %p.product-details__id
8
+ %span{ itemprop: 'productID' }= product.id
9
+
10
+ .product-prices.product-prices--details{ itemprop: 'offers', itemscope: true, itemtype: 'http://schema.org/Offer' }
11
+ = render 'workarea/storefront/products/pricing', product: product
12
+
13
+ = append_partials('storefront.product_pricing_details', product: product)
14
+
15
+ - if product.description.present?
16
+ .product-details__description
17
+ %p= truncated_product_description(product, t('workarea.storefront.products.read_more'))
18
+
19
+ = form_tag cart_items_path, method: 'post', class: 'product-details__add-to-cart-form', data: { dialog_form: { dialogOptions: { closeAll: true, initModules: true } }, analytics: add_to_cart_analytics_data(product).to_json } do
20
+ = hidden_field_tag :product_id, product.id, id: dom_id(product, 'product_id')
21
+ = hidden_field_tag :sku, product.current_sku
22
+ = hidden_field_tag :via, params[:via], id: dom_id(product, 'via')
23
+
24
+ - product.options_for_selection.each do |option|
25
+ .property
26
+ = label_tag option.slug, nil, class: 'property__name', for: "#{option.slug}_#{dom_id(product)}" do
27
+ %span.property__text= option_label(option)
28
+ .value
29
+ - option.selections.each do |selection|
30
+ = radio_button_tag option.slug, selection, option.current == selection, required: true, title: selection, class: 'visually-hidden', id: nil
31
+ = link_to option_selection_url_for(product, option, selection), title: selection, class: "option-button option-button--#{selection.downcase.dasherize}#{' option-button--active' if option.current == selection}", data: { option_button: '' } do
32
+ - swatch_content = render_swatch_option(selection, product.swatches_by_option[selection.optionize])
33
+
34
+ - if swatch_content.present?
35
+ = swatch_content
36
+ - elsif product.images_by_option[selection.optionize].present?
37
+ = image_tag(product_image_url(product.images_by_option[selection.optionize].first, :small_thumb), alt: selection, class: 'option-button__image')
38
+ - else
39
+ %span.option-button__text= selection
40
+
41
+ - unless product.currently_selected_options.blank?
42
+ = link_to t('workarea.storefront.products.clear_selections'), product_path(product), data: { option_button: '' }
43
+
44
+ = append_partials('storefront.add_to_cart_form', product: product)
45
+
46
+ - if product.purchasable?
47
+ .product-details__quantity
48
+ .property
49
+ = label_tag :quantity, nil, class: 'property__name', for: "quantity#{dom_id(product)}" do
50
+ %span.property__text= t('workarea.storefront.products.quantity')
51
+ .value
52
+ = number_field_tag :quantity, params[:quantity] || 1, class: 'text-box text-box--x-small', required: true, min: 1, id: "quantity#{dom_id(product)}"
53
+ - if product.current_sku.present?
54
+ .value__note= product.inventory_status
55
+
56
+ %p.product-details__add-to-cart-action= button_tag t('workarea.storefront.products.add_to_cart'), value: 'add_to_cart', class: 'button button--large'
57
+
58
+ - else
59
+ = hidden_field_tag :quantity, params[:quantity] || 1, id: "quantity#{dom_id(product)}"
60
+ %p.product-details__unavailable= t('workarea.storefront.products.unavailable')
61
+
62
+ = append_partials('storefront.product_details', product: product)
63
+
64
+ %p.product-details__full-details=link_to t('workarea.storefront.products.view_full_details'), product_path(product, color: params[:color]), class: 'text-button', itemprop: 'url'
65
+
66
+ .grid__cell.grid__cell--40-at-medium
67
+
68
+ .product-details__primary-image
69
+ = link_to(product_image_url(product.primary_image, :zoom), target: '_blank', rel: 'noopener', class: 'product-details__primary-image-link', data: { dialog_button: '' }) do
70
+ = image_tag product_image_url(product.primary_image, :detail), alt: t('workarea.storefront.products.image_alt_attribute', name: product.name), itemprop: 'image', class: 'product-details__primary-image-link-image'
71
+
72
+ - if product.images.length > 1
73
+ .product-details__alt-images
74
+ .grid.grid--auto
75
+ - product.images.each_with_index do |image, index|
76
+ .grid__cell
77
+ .product-details__alt-image
78
+ - button_class = index == 0 ? 'product-details__alt-image-link product-details__alt-image-link--selected' : 'product-details__alt-image-link'
79
+ = link_to(image_tag(product_image_url(image, :small_thumb), alt: t('workarea.storefront.products.zoom')), product_image_url(image, :zoom), class: button_class, target: '_blank', rel: 'noopener', data: { alternate_image_button: { src: product_image_url(image, :detail) }.to_json })