workarea-package_products 3.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) 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 +15 -0
  7. data/CHANGELOG.md +343 -0
  8. data/CODE_OF_CONDUCT.md +3 -0
  9. data/CONTRIBUTING.md +3 -0
  10. data/Gemfile +16 -0
  11. data/LICENSE +52 -0
  12. data/README.md +40 -0
  13. data/Rakefile +52 -0
  14. data/app/assets/javascripts/workarea/storefront/package_products/modules/family_product_add_to_cart.js +83 -0
  15. data/app/assets/javascripts/workarea/storefront/package_products/templates/family_add_to_cart_checkbox.jst.ejs +1 -0
  16. data/app/assets/stylesheets/workarea/admin/package_products/components/_product_cards.scss +7 -0
  17. data/app/assets/stylesheets/workarea/storefront/package_products/components/_product_detail_packaged_products.scss +11 -0
  18. data/app/controllers/workarea/admin/create_catalog_package_products_controller.rb +150 -0
  19. data/app/controllers/workarea/admin/create_catalog_products_controller.decorator +25 -0
  20. data/app/controllers/workarea/storefront/cart_items_controller.decorator +29 -0
  21. data/app/controllers/workarea/storefront/products_controller.decorator +8 -0
  22. data/app/models/workarea/catalog/product.decorator +44 -0
  23. data/app/models/workarea/search/admin/catalog_product.decorator +20 -0
  24. data/app/models/workarea/search/storefront/package_product.rb +40 -0
  25. data/app/queries/workarea/search/product_entries.decorator +8 -0
  26. data/app/seeds/workarea/package_product_seeds.rb +41 -0
  27. data/app/services/workarea/add_package_to_cart.rb +79 -0
  28. data/app/view_models/workarea/admin/product_view_model.decorator +35 -0
  29. data/app/view_models/workarea/storefront/product_templates/family_view_model.rb +6 -0
  30. data/app/view_models/workarea/storefront/product_templates/package_view_model.rb +33 -0
  31. data/app/view_models/workarea/storefront/product_view_model.decorator +13 -0
  32. data/app/views/workarea/admin/catalog_products/_create_package_button.html.haml +1 -0
  33. data/app/views/workarea/admin/catalog_products/_packaged_products_card.html.haml +26 -0
  34. data/app/views/workarea/admin/create_catalog_package_products/categorization.html.haml +64 -0
  35. data/app/views/workarea/admin/create_catalog_package_products/content.html.haml +54 -0
  36. data/app/views/workarea/admin/create_catalog_package_products/details.html.haml +87 -0
  37. data/app/views/workarea/admin/create_catalog_package_products/images.html.haml +57 -0
  38. data/app/views/workarea/admin/create_catalog_package_products/packaged_products.html.haml +79 -0
  39. data/app/views/workarea/admin/create_catalog_package_products/publish.html.haml +61 -0
  40. data/app/views/workarea/admin/create_catalog_package_products/setup.html.haml +68 -0
  41. data/app/views/workarea/admin/create_catalog_products/select.html.haml +34 -0
  42. data/app/views/workarea/storefront/cart_items/package.html.haml +59 -0
  43. data/app/views/workarea/storefront/products/package_show.html.haml +49 -0
  44. data/app/views/workarea/storefront/products/templates/_family.html.haml +42 -0
  45. data/app/views/workarea/storefront/products/templates/_package.html.haml +36 -0
  46. data/app/workers/workarea/update_package_products.rb +21 -0
  47. data/bin/rails +16 -0
  48. data/config/initializers/appends.rb +31 -0
  49. data/config/initializers/configuration.rb +6 -0
  50. data/config/initializers/seeds.rb +1 -0
  51. data/config/locales/en.yml +45 -0
  52. data/config/routes.rb +30 -0
  53. data/lib/tasks/sample_data.rake +16 -0
  54. data/lib/workarea/package_products.rb +10 -0
  55. data/lib/workarea/package_products/engine.rb +8 -0
  56. data/lib/workarea/package_products/version.rb +5 -0
  57. data/test/dummy/Rakefile +6 -0
  58. data/test/dummy/app/assets/config/manifest.js +4 -0
  59. data/test/dummy/app/assets/images/.keep +0 -0
  60. data/test/dummy/app/assets/javascripts/application.js +13 -0
  61. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  62. data/test/dummy/app/controllers/application_controller.rb +3 -0
  63. data/test/dummy/app/controllers/concerns/.keep +0 -0
  64. data/test/dummy/app/helpers/application_helper.rb +2 -0
  65. data/test/dummy/app/jobs/application_job.rb +2 -0
  66. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  67. data/test/dummy/app/models/concerns/.keep +0 -0
  68. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  69. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  70. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  71. data/test/dummy/bin/bundle +3 -0
  72. data/test/dummy/bin/rails +4 -0
  73. data/test/dummy/bin/rake +4 -0
  74. data/test/dummy/bin/setup +34 -0
  75. data/test/dummy/bin/update +29 -0
  76. data/test/dummy/config.ru +5 -0
  77. data/test/dummy/config/application.rb +18 -0
  78. data/test/dummy/config/boot.rb +5 -0
  79. data/test/dummy/config/cable.yml +9 -0
  80. data/test/dummy/config/environment.rb +5 -0
  81. data/test/dummy/config/environments/development.rb +54 -0
  82. data/test/dummy/config/environments/production.rb +83 -0
  83. data/test/dummy/config/environments/test.rb +43 -0
  84. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  85. data/test/dummy/config/initializers/assets.rb +11 -0
  86. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  87. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  88. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  89. data/test/dummy/config/initializers/inflections.rb +16 -0
  90. data/test/dummy/config/initializers/mime_types.rb +4 -0
  91. data/test/dummy/config/initializers/session_store.rb +3 -0
  92. data/test/dummy/config/initializers/workarea.rb +5 -0
  93. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  94. data/test/dummy/config/locales/en.yml +23 -0
  95. data/test/dummy/config/puma.rb +47 -0
  96. data/test/dummy/config/routes.rb +5 -0
  97. data/test/dummy/config/secrets.yml +22 -0
  98. data/test/dummy/db/seeds.rb +2 -0
  99. data/test/dummy/lib/assets/.keep +0 -0
  100. data/test/dummy/log/.keep +0 -0
  101. data/test/dummy/public/404.html +67 -0
  102. data/test/dummy/public/422.html +67 -0
  103. data/test/dummy/public/500.html +66 -0
  104. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  105. data/test/dummy/public/apple-touch-icon.png +0 -0
  106. data/test/dummy/public/favicon.ico +1 -0
  107. data/test/integration/workarea/admin/create_catalog_package_products_integration_test.rb +139 -0
  108. data/test/integration/workarea/storefront/package_cart_items_integration_test.rb +47 -0
  109. data/test/integration/workarea/storefront/products_integration_test.decorator +19 -0
  110. data/test/models/workarea/catalog/package_product_test.rb +68 -0
  111. data/test/models/workarea/search/storefront/package_product_test.rb +44 -0
  112. data/test/queries/workarea/search/product_entries_test.decorator +15 -0
  113. data/test/services/workarea/add_package_to_cart_test.rb +46 -0
  114. data/test/system/workarea/admin/activity_system_test.decorator +53 -0
  115. data/test/system/workarea/admin/package_product_copy_system_test.rb +27 -0
  116. data/test/system/workarea/admin/package_products_system_test.rb +101 -0
  117. data/test/system/workarea/admin/product_copy_system_test.decorator +28 -0
  118. data/test/system/workarea/admin/products_system_test.decorator +69 -0
  119. data/test/system/workarea/storefront/categories_with_packages_system_test.rb +172 -0
  120. data/test/system/workarea/storefront/family_product_system_test.rb +58 -0
  121. data/test/system/workarea/storefront/package_product_system_test.rb +42 -0
  122. data/test/test_helper.rb +10 -0
  123. data/test/view_models/workarea/admin/package_product_view_model_test.rb +41 -0
  124. data/test/view_models/workarea/storefront/package_product_view_model_test.rb +27 -0
  125. data/test/view_models/workarea/storefront/package_templates/package_view_model_test.rb +34 -0
  126. data/test/workers/workarea/update_package_products_test.rb +27 -0
  127. data/workarea-package_products.gemspec +24 -0
  128. metadata +189 -0
@@ -0,0 +1,29 @@
1
+ module Workarea
2
+ decorate Storefront::CartItemsController, with: :package_products do
3
+
4
+ decorated do
5
+ skip_before_action :verify_authenticity_token, only: [:create, :package]
6
+ after_action :check_inventory, except: [:create, :package]
7
+ end
8
+
9
+ def package
10
+ add_to_cart = AddPackageToCart.new(current_order, params)
11
+
12
+ if add_to_cart.save
13
+ check_inventory
14
+ Pricing.perform(current_order, current_shipping)
15
+
16
+ order_items = add_to_cart.items.map do |item|
17
+ current_order.items.find_existing(
18
+ item.item_params[:sku],
19
+ item.item_params[:customizations]
20
+ )
21
+ end.compact
22
+
23
+ @items = order_items.map do |item|
24
+ Storefront::OrderItemViewModel.wrap(item, view_model_options)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,8 @@
1
+ module Workarea
2
+ decorate Storefront::ProductsController, with: :package_products do
3
+ def show
4
+ super
5
+ render 'package_show' and return if @product.package? && !request.xhr?
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,44 @@
1
+ module Workarea
2
+ decorate Catalog::Product, with: :package_products do
3
+ decorated do
4
+ include FeaturedProducts
5
+
6
+ scope :packages_containing, ->(id) { where('product_ids' => id) }
7
+
8
+ # For all products that have the given SKU return an Array containing:
9
+ # * the matching product
10
+ # * the package products that contain the matching product
11
+ #
12
+ # @param sku [String]
13
+ # @return [Array<Catalog::Product>]
14
+ #
15
+ def self.find_for_update_by_sku(sku)
16
+ where('variants.sku' => sku).flat_map do |product|
17
+ [product] + packages_containing(product.id)
18
+ end
19
+ end
20
+ end
21
+
22
+ def package?
23
+ template == 'package' || product_ids.present?
24
+ end
25
+
26
+ def family?
27
+ template == 'family'
28
+ end
29
+
30
+ def active?
31
+ attribute = if Workarea.config.localized_active_fields
32
+ read_attribute(:active)[I18n.locale.to_s]
33
+ else
34
+ read_attribute(:active)
35
+ end
36
+
37
+ attribute && (variants.active.any? || product_ids.present?)
38
+ end
39
+
40
+ def purchasable?
41
+ super && !package?
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,20 @@
1
+ module Workarea
2
+ decorate Search::Admin::CatalogProduct, with: :package_products do
3
+ def search_text
4
+ super.tap do |text|
5
+ text << 'package' if model.package?
6
+ text << 'family' if model.family?
7
+ end
8
+ end
9
+
10
+ def issues
11
+ super.tap do |issues|
12
+ if model.package?
13
+ # issues << 'No Packaged Products' if model.product_ids.blank?
14
+ issues.delete('No Variants')
15
+ issues.delete('SKU missing price')
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ module Workarea
2
+ module Search
3
+ class Storefront
4
+ class PackageProduct < Product
5
+ def skus
6
+ packaged_products.flat_map(&:skus)
7
+ end
8
+
9
+ def variant_count
10
+ packaged_products.sum(&:variant_count)
11
+ end
12
+
13
+ def orders_score
14
+ return 0 unless packaged_products.present?
15
+ packaged_products.sum(&:orders_score) / packaged_products.size
16
+ end
17
+
18
+ def variant_details_text
19
+ @variant_details_text ||= packaged_products_variants.map do |variant|
20
+ "#{variant.name} #{HashText.new(variant.details).text}"
21
+ end.join(' ')
22
+ end
23
+
24
+ private
25
+
26
+ def packaged_products
27
+ return @packaged_products if defined?(@packaged_products)
28
+
29
+ products = Catalog::Product.find_ordered(model.product_ids)
30
+ @packaged_products ||= products.map { |p| Product.new(p) }
31
+ end
32
+
33
+ def packaged_products_variants
34
+ @package_products_variants ||=
35
+ packaged_products.map(&:model).flat_map { |p| p.variants.active }
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,8 @@
1
+ module Workarea
2
+ decorate Search::ProductEntries, with: :package_products do
3
+ def index_entries_for(product)
4
+ return Search::Storefront::PackageProduct.new(product) if product.package?
5
+ super
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,41 @@
1
+ module Workarea
2
+ class PackageProductSeeds
3
+ def perform
4
+ puts 'Adding package products...'
5
+
6
+ 10.times do
7
+ package = create_product
8
+
9
+ category = Workarea::Catalog::Category.sample
10
+ category.product_ids.push(package.id)
11
+ category.save!
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def create_product
18
+ Sidekiq::Callbacks.disable do
19
+ model = Workarea::Catalog::Product.new
20
+ packaged_products =
21
+ Workarea::Catalog::Product.sample(4).reject(&:package?)
22
+
23
+ model.id = rand(1_000_000)
24
+ model.name = "Package Product #{rand(100_000)}"
25
+ model.template = Workarea.config.package_product_templates.sample
26
+ model.product_ids = packaged_products.map(&:id)
27
+
28
+ model.filters = packaged_products.each_with_object({}) do |product, package_filters|
29
+ product.filters.each do |filter_name, values|
30
+ package_filters[filter_name] ||= []
31
+ package_filters[filter_name].concat(Array(values)).uniq!
32
+ end
33
+ end
34
+
35
+ model.description = Faker::Lorem.paragraph
36
+ model.save!
37
+ model
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,79 @@
1
+ module Workarea
2
+ class AddPackageToCart
3
+ attr_reader :items
4
+
5
+ def initialize(order, params)
6
+ @items = []
7
+
8
+ # ActionController::Parameters has no #map
9
+ params[:items].each do |_, item|
10
+ @items << Item.new(order, item)
11
+ end
12
+ end
13
+
14
+ def save
15
+ items.all?(&:save)
16
+ end
17
+
18
+ def errors
19
+ items.flat_map(&:errors)
20
+ end
21
+
22
+ class Item
23
+ attr_reader :order, :params
24
+
25
+ def initialize(order, params)
26
+ @order = order
27
+ @params = params
28
+ end
29
+
30
+ def errors
31
+ @errors ||= []
32
+ end
33
+
34
+ def valid?
35
+ (!customizations.present? || customizations.valid?).tap do |valid|
36
+ customizations.errors.full_messages unless valid
37
+ end
38
+ end
39
+
40
+ def save
41
+ return false unless valid?
42
+ order.add_item(item_params)
43
+ end
44
+
45
+ def item_params
46
+ params
47
+ .permit(:product_id, :sku, :quantity)
48
+ .merge(customizations: customizations)
49
+ .merge(item_details)
50
+ end
51
+
52
+ private
53
+
54
+ def product_id
55
+ @product_id ||= if params[:product_id].present?
56
+ params[:product_id]
57
+ elsif params[:sku].present?
58
+ Catalog::Product.find_by_sku(params[:sku]).id
59
+ end
60
+ end
61
+
62
+ def customizations
63
+ @customizations ||= Catalog::Customizations.find(product_id, params)
64
+ end
65
+
66
+ def customization_params
67
+ ActionController::Parameters.new(
68
+ customizations.try(:to_h) || {}
69
+ )
70
+ end
71
+
72
+ def item_details
73
+ ActionController::Parameters.new(
74
+ OrderItemDetails.find!(params[:sku]).to_h
75
+ ).permit!
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,35 @@
1
+ module Workarea
2
+ decorate Admin::ProductViewModel, with: :package_products do
3
+ decorated do
4
+ include Admin::FeaturedProductsViewModel
5
+ end
6
+
7
+ def packaged_products
8
+ @packaged_products ||=
9
+ begin
10
+ models = Catalog::Product.find_ordered_for_display(
11
+ model.product_ids
12
+ )
13
+ Admin::ProductViewModel.wrap(models)
14
+ end
15
+ end
16
+
17
+ def package_templates
18
+ Workarea.config.package_product_templates
19
+ .map(&:to_s)
20
+ .map do |template_name|
21
+ [template_name.titleize, template_name.optionize]
22
+ end
23
+ end
24
+
25
+ def templates
26
+ return super unless model.present?
27
+
28
+ if package?
29
+ package_templates
30
+ else
31
+ super.reject { |o| o.in?(package_templates) }
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,6 @@
1
+ module Workarea
2
+ module Storefront
3
+ class ProductTemplates::FamilyViewModel < ProductTemplates::PackageViewModel
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,33 @@
1
+ module Workarea
2
+ module Storefront
3
+ class ProductTemplates::PackageViewModel < ProductViewModel
4
+ delegate :has_price_range?, :price, :display_min_price,
5
+ :display_max_price, :display_price, :has_msrp_range?,
6
+ :msrp?, :msrp, :msrp_min, :msrp_max, :sale_starts_at,
7
+ :sale_ends_at, to: :pricing
8
+
9
+ def primary_image
10
+ product_image = super
11
+ return product_image unless product_image.placeholder?
12
+
13
+ @primary_image ||=
14
+ packaged_products
15
+ .map(&:images)
16
+ .flatten
17
+ .reject(&:placeholder?)
18
+ .first ||
19
+ Catalog::ProductPlaceholderImage.cached
20
+ end
21
+
22
+ def show_panel?
23
+ false
24
+ end
25
+
26
+ def pricing
27
+ @pricing ||=
28
+ options[:pricing] ||
29
+ Pricing::Collection.new(packaged_products.map(&:skus).flatten)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ module Workarea
2
+ decorate Storefront::ProductViewModel, with: :package_products do
3
+ def packaged_products
4
+ @packaged_products ||= begin
5
+ return [] if product_ids.blank?
6
+
7
+ models = Catalog::Product.find_ordered_for_display(product_ids)
8
+ models.map { |p| Storefront::ProductViewModel.wrap(p, options) }
9
+ .select { |p| p.variants.any? }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ .grid__cell= link_to t('workarea.admin.catalog_products.index.add_new_package_product'), create_catalog_package_products_path, id: 'add_product', class: 'workflow-bar__button workflow-bar__button--create'
@@ -0,0 +1,26 @@
1
+ - if model.package? || model.family?
2
+ .grid__cell
3
+ .card{ class: card_classes(:featured_products, local_assigns[:active]) }
4
+ = link_to select_featured_product_path(model.to_global_id), class: 'card__header' do
5
+ %span.card__header-text= t('workarea.admin.catalog_products.cards.packaged_products.title')
6
+ = inline_svg 'workarea/admin/icons/featured_products.svg', class: 'card__icon'
7
+
8
+ - if local_assigns[:active].blank?
9
+ .card__body
10
+ - if model.packaged_products.empty?
11
+ .card__empty-note
12
+ %p= t('workarea.admin.catalog_products.cards.packaged_products.empty')
13
+ %p= t('workarea.admin.catalog_products.cards.packaged_products.description')
14
+ = link_to select_featured_product_path(model.to_global_id), class: 'card__button' do
15
+ %span.button.button--small= t('workarea.admin.catalog_products.cards.packaged_products.empty_button')
16
+ - else
17
+ %ol.grid
18
+ - model.packaged_products.take(4).each_with_index do |product, i|
19
+ %li.grid__cell.grid__cell--50
20
+ .card__photo-box
21
+ - if i == 3 && model.packaged_products.size > 4
22
+ %span.card__photo +#{model.packaged_products.size - i}
23
+ - else
24
+ = image_tag product_image_url(product.primary_image, :medium), alt: product.name, class: 'card__photo'
25
+ = link_to edit_featured_product_path(model.to_global_id), class: 'card__button' do
26
+ %span.button.button--small= t('workarea.admin.catalog_products.cards.packaged_products.button')
@@ -0,0 +1,64 @@
1
+ - @page_title = t('workarea.admin.create_catalog_products.categorization.page_title', product_name: @product.name)
2
+
3
+ .view
4
+ .view__header
5
+ .view__heading
6
+ %h1.heading.heading--no-margin= t('workarea.admin.create_catalog_products.categorization.categorize', product_name: @product.name)
7
+ %p= link_to t('workarea.admin.create_catalog_products.categorization.or_skip_this'), publish_create_catalog_package_product_path(@product)
8
+
9
+ .view__container.view__container--narrow
10
+ .grid.grid--center.grid--huge
11
+ .grid__cell.grid__cell--50-at-medium
12
+ %h2.align-center= t('workarea.admin.create_catalog_products.categorization.by_matching_category_rules')
13
+
14
+ - if @product.rules_categories.blank?
15
+ %p.align-center= t('workarea.admin.create_catalog_products.categorization.doesnt_match_any_categorys_rules')
16
+ - else
17
+ %ul.list-reset.align-center
18
+ - @product.rules_categories.each do |category|
19
+ %li
20
+ %strong= link_to category.name, catalog_category_path(category)
21
+
22
+ .grid__cell.grid__cell--50-at-medium
23
+ %h2.align-center= t('workarea.admin.create_catalog_products.categorization.by_being_featured')
24
+
25
+ - if @product.featured_categories.blank?
26
+ %p.align-center= t('workarea.admin.create_catalog_products.categorization.not_featured_in_any_categories_yet')
27
+ - else
28
+ %ul.list-reset.align-center
29
+ - @product.featured_categories.each do |category|
30
+ %li
31
+ %strong= link_to category.name, catalog_category_path(category)
32
+ = link_to catalog_product_categorization_path(@product, category), data: { remote: true, method: 'delete', dom_remove: 'li' } do
33
+ = inline_svg('workarea/admin/icons/delete.svg', class: 'svg-icon svg-icon--small svg-icon--red', title: t('workarea.admin.actions.remove'))
34
+
35
+ .section
36
+ = form_tag save_categorization_create_catalog_package_product_path(@product), method: 'post', class: 'align-center' do
37
+ = select_tag 'category_ids[]', nil, multiple: true, data: { remote_select: { source: catalog_categories_path, options: { placeholder: 'Feature in categories...' } }.to_json }
38
+ = button_tag t('workarea.admin.create_catalog_products.categorization.save'), value: 'add_categories', class: 'button button--small'
39
+
40
+ .workflow-bar
41
+ .grid.grid--middle
42
+ .grid__cell.grid__cell--20
43
+ = link_to t('workarea.admin.create_catalog_products.categorization.cancel'), catalog_product_path(@product), class: 'workflow-bar__button workflow-bar__button--delete', data: { method: 'delete', confirm: t('workarea.admin.create_catalog_products.are_you_sure_all_work_on_this_product_will_be_lost') }
44
+
45
+ .grid__cell.grid__cell--60
46
+ %ol.workflow-bar__steps
47
+ %li.workflow-bar__step
48
+ 1) #{link_to t('workarea.admin.create_catalog_products.steps.setup'), edit_create_catalog_package_product_path(@product)}
49
+ %li.workflow-bar__step
50
+ 2) #{link_to t('workarea.admin.create_catalog_package_products.steps.packaged_products'), packaged_products_create_catalog_package_product_path(@product)}
51
+ %li.workflow-bar__step
52
+ 3) #{link_to t('workarea.admin.create_catalog_products.steps.images'), images_create_catalog_package_product_path(@product)}
53
+ %li.workflow-bar__step
54
+ 4) #{link_to t('workarea.admin.create_catalog_products.steps.details'), details_create_catalog_package_product_path(@product)}
55
+ %li.workflow-bar__step
56
+ 5) #{link_to t('workarea.admin.create_catalog_products.steps.content'), content_create_catalog_package_product_path(@product)}
57
+ %li.workflow-bar__step
58
+ %strong 6) #{t('workarea.admin.create_catalog_products.steps.categorization')}
59
+ %li.workflow-bar__step
60
+ 7) #{t('workarea.admin.create_catalog_products.steps.publish')}
61
+
62
+ .grid__cell.grid__cell--20
63
+ .grid.grid--auto.grid--right.grid--middle
64
+ .grid__cell= link_to "#{t('workarea.admin.create_catalog_products.categorization.continue_to_publish')} →", publish_create_catalog_package_product_path(@product), class: 'workflow-bar__button'