stall 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -21
  3. data/app/assets/javascripts/para/stall/inputs/variants-matrix/input.coffee +8 -1
  4. data/app/assets/javascripts/para/stall/inputs/variants-matrix/variant.coffee +9 -0
  5. data/app/assets/javascripts/stall.coffee +7 -1
  6. data/app/assets/javascripts/stall/add-to-cart-form.coffee +1 -4
  7. data/app/assets/javascripts/stall/products-filters.coffee +29 -0
  8. data/app/assets/stylesheets/para/stall.sass +5 -0
  9. data/app/assets/stylesheets/stall.sass +0 -0
  10. data/app/controllers/stall/checkout/steps_controller.rb +6 -5
  11. data/app/controllers/stall/checkout_base_controller.rb +14 -0
  12. data/app/controllers/stall/checkouts_controller.rb +7 -4
  13. data/app/controllers/stall/curated_product_lists_controller.rb +10 -0
  14. data/app/controllers/stall/line_items_controller.rb +1 -5
  15. data/app/controllers/stall/manufacturers_controller.rb +12 -0
  16. data/app/controllers/stall/omniauth_callbacks_controller.rb +49 -0
  17. data/app/controllers/stall/product_categories_controller.rb +13 -0
  18. data/app/controllers/stall/products_breadcrumbs.rb +16 -0
  19. data/app/controllers/stall/products_controller.rb +20 -0
  20. data/app/controllers/stall/products_search.rb +11 -0
  21. data/app/helpers/stall/customers_helper.rb +0 -10
  22. data/app/helpers/stall/omniauth_helper.rb +7 -0
  23. data/app/helpers/stall/prices_helper.rb +12 -0
  24. data/app/helpers/stall/products_filters_helper.rb +34 -0
  25. data/app/mailers/stall/customer_mailer.rb +4 -3
  26. data/app/models/curated_list_product.rb +3 -0
  27. data/app/models/curated_product_list.rb +3 -0
  28. data/app/models/image.rb +3 -0
  29. data/app/models/product_suggestion.rb +3 -0
  30. data/app/models/stall/models/curated_list_product.rb +15 -0
  31. data/app/models/stall/models/curated_product_list.rb +22 -0
  32. data/app/models/stall/models/customer.rb +5 -8
  33. data/app/models/stall/models/image.rb +21 -0
  34. data/app/models/stall/models/manufacturer.rb +4 -0
  35. data/app/models/stall/models/product.rb +30 -7
  36. data/app/models/stall/models/product_category.rb +5 -2
  37. data/app/models/stall/models/product_list.rb +1 -1
  38. data/app/models/stall/models/product_suggestion.rb +14 -0
  39. data/app/models/stall/models/shipment.rb +0 -2
  40. data/app/models/stall/models/user.rb +18 -0
  41. data/app/models/stall/models/user_omniauth_account.rb +13 -0
  42. data/app/models/stall/models/variant.rb +11 -11
  43. data/app/models/user.rb +3 -0
  44. data/app/models/user_omniauth_account.rb +3 -0
  45. data/app/services/stall/add_to_cart_service.rb +19 -4
  46. data/app/services/stall/available_stocks_service.rb +11 -0
  47. data/app/services/stall/cart_credit_note_creation_service.rb +4 -0
  48. data/app/services/stall/cart_payment_validation_service.rb +5 -3
  49. data/app/services/stall/credit_usage_service.rb +8 -2
  50. data/app/services/stall/omniauth_user_authentication_service.rb +48 -0
  51. data/app/services/stall/product_list_staleness_handling_service.rb +6 -3
  52. data/app/services/stall/products_search_service.rb +23 -0
  53. data/app/services/stall/shipping_notification_service.rb +1 -1
  54. data/app/views/admin/carts/_filters.html.haml +10 -4
  55. data/app/views/admin/carts/_form.html.haml +9 -9
  56. data/app/views/admin/manufacturers/_form.html.haml +7 -0
  57. data/app/views/admin/manufacturers/_table.html.haml +8 -0
  58. data/app/views/admin/product_categories/_form.html.haml +7 -0
  59. data/app/views/admin/products/_form.html.haml +23 -0
  60. data/app/views/admin/products/_table.html.haml +4 -2
  61. data/app/views/checkout/steps/_informations.html.haml +2 -2
  62. data/app/views/para/admin/resources/_variant_row.html.haml +9 -1
  63. data/app/views/para/admin/resources/_variant_row_header.html.haml +14 -0
  64. data/app/views/para/stall/inputs/_variant_select.html.haml +3 -3
  65. data/app/views/para/stall/inputs/_variants_matrix.html.haml +7 -16
  66. data/app/views/para/stall/inputs/shipping_notes/new.html.haml +22 -0
  67. data/app/views/para/stall/inputs/shipping_notes/sent.html.haml +11 -0
  68. data/app/views/stall/carts/_cart.html.haml +1 -1
  69. data/app/views/stall/credit_note_adjustments/_form.html.haml +1 -1
  70. data/app/views/stall/curated_product_lists/show.html.haml +8 -0
  71. data/app/views/stall/customers/_fields.html.haml +17 -5
  72. data/app/views/stall/customers/_sign_in.html.haml +22 -10
  73. data/app/views/stall/line_items/_form.html.haml +2 -3
  74. data/app/views/stall/manufacturers/show.html.haml +8 -0
  75. data/app/views/stall/product_categories/show.html.haml +8 -0
  76. data/app/views/stall/products/_filters.html.haml +4 -0
  77. data/app/views/stall/products/_list.html.haml +7 -0
  78. data/app/views/stall/products/_product.html.haml +4 -0
  79. data/app/views/stall/products/_product_details.html.haml +13 -0
  80. data/app/views/stall/products/filters/_category_filter.html.haml +2 -0
  81. data/app/views/stall/products/filters/_manufacturer_filter.html.haml +2 -0
  82. data/app/views/stall/products/filters/_price_filter.html.haml +2 -0
  83. data/app/views/stall/products/filters/_property_filter.html.haml +2 -0
  84. data/app/views/stall/products/index.html.haml +8 -0
  85. data/app/views/stall/products/show.html.haml +26 -0
  86. data/config/locales/stall.fr.yml +97 -11
  87. data/db/migrate/20170221094450_add_slug_to_stall_manufacturers.rb +5 -0
  88. data/db/migrate/20170303122616_create_stall_product_suggestions.rb +13 -0
  89. data/db/migrate/20170303151939_add_position_to_stall_manufacturers.rb +5 -0
  90. data/db/migrate/20170308162740_create_stall_curated_product_lists.rb +10 -0
  91. data/db/migrate/20170308163532_create_stall_curated_list_products.rb +14 -0
  92. data/db/migrate/20170317103740_create_stall_users.rb +28 -0
  93. data/db/migrate/20170317104332_create_stall_user_omniauth_accounts.rb +14 -0
  94. data/db/migrate/20170320133513_fix_curated_product_list_bad_foreign_key.rb +6 -0
  95. data/db/migrate/20170321104203_create_stall_images.rb +11 -0
  96. data/db/migrate/20170321112248_remove_image_attachment_to_stall_products.rb +5 -0
  97. data/db/migrate/20170411134756_add_stock_to_stall_variants.rb +5 -0
  98. data/lib/ext/ransack.rb +13 -0
  99. data/lib/generators/stall/install/templates/initializer.rb +50 -15
  100. data/lib/generators/stall/service/service_generator.rb +0 -4
  101. data/lib/generators/stall/view/view_generator.rb +10 -8
  102. data/lib/para/stall/inputs/variant_select_input.rb +11 -1
  103. data/lib/para/stall/inputs/variants_matrix_input.rb +12 -6
  104. data/lib/stall.rb +14 -0
  105. data/lib/stall/addressable.rb +2 -2
  106. data/lib/stall/addresses/copy_source_to_target.rb +7 -3
  107. data/lib/stall/addresses/prefill_target_from_source.rb +4 -2
  108. data/lib/stall/cart_helper.rb +3 -3
  109. data/lib/stall/carts_cleaner.rb +2 -2
  110. data/lib/stall/checkout/informations_checkout_step.rb +2 -2
  111. data/lib/stall/config.rb +29 -9
  112. data/lib/stall/engine.rb +28 -13
  113. data/lib/stall/omniauth_provider.rb +41 -0
  114. data/lib/stall/payable.rb +3 -1
  115. data/lib/stall/product_filters.rb +12 -0
  116. data/lib/stall/product_filters/base_filter.rb +43 -0
  117. data/lib/stall/product_filters/builder.rb +59 -0
  118. data/lib/stall/product_filters/category_filter.rb +28 -0
  119. data/lib/stall/product_filters/manufacturer_filter.rb +19 -0
  120. data/lib/stall/product_filters/price_filter.rb +39 -0
  121. data/lib/stall/product_filters/property_filter.rb +38 -0
  122. data/lib/stall/routes.rb +40 -0
  123. data/lib/stall/shipping/calculator.rb +3 -1
  124. data/lib/stall/version.rb +1 -1
  125. metadata +158 -7
  126. data/app/assets/stylesheets/stall/carts.css +0 -4
@@ -0,0 +1,11 @@
1
+ = modal id: "shipment-modal-#{ @cart.id }", fade: false do |modal|
2
+ = modal.header do
3
+ = t('para.stall.shipping_note.sent')
4
+
5
+ = modal.body do
6
+ %p= t('para.stall.shipping_note.sent_description').html_safe
7
+
8
+ = modal.footer do
9
+ %button.btn.btn-default{ type: 'button', data: { dismiss: 'modal' } }
10
+ = t('stall.shared.close')
11
+
@@ -19,7 +19,7 @@
19
19
  %td= t('stall.carts.recap.subtotal')
20
20
  %td= number_to_currency(cart.subtotal)
21
21
 
22
- - if cart.shipment.try(:persisted?)
22
+ - if cart.shipment.try(:persisted?) && cart.shipment.shipping_method
23
23
  %tr
24
24
  %td
25
25
  = t('stall.carts.recap.total_shipment_price')
@@ -1,4 +1,4 @@
1
- - if stall_user_signed_in? && available_customer_credit_for?(cart) && !cart.paid?
1
+ - if user_signed_in? && available_customer_credit_for?(cart) && !cart.paid?
2
2
  = simple_form_for cart, url: cart_credit_path(cart), method: (credit_used_for?(@cart) ? :delete : :patch), html: { class: 'cart-credit-form', data: { :'cart-credit-form' => true } } do |form|
3
3
  = hidden_field_tag :_return_to, request.fullpath
4
4
 
@@ -0,0 +1,8 @@
1
+ %h1= @curated_product_list.name
2
+
3
+ .row
4
+ .col-md-4
5
+ = render partial: 'stall/products/filters', locals: { search: @search, products: @filterable_products }
6
+
7
+ .col-md-8
8
+ = render partial: 'stall/products/list', locals: { products: @products }
@@ -1,10 +1,10 @@
1
1
  -# When stall a user is signed in, a customer autoatically exist and is assigned
2
2
  -# to the cart, by default, we notify the visitor that he's signed in and will
3
3
  -# order with that account, making customer and user related fields unnecessary
4
- - if stall_user_signed_in?
4
+ - if user_signed_in?
5
5
  .alert.alert-info
6
6
  %i.fa.fa-info-circle
7
- = t('stall.checkout.informations.signed_in_as', email: current_stall_user.email)
7
+ = t('stall.checkout.informations.signed_in_as', email: current_user.email)
8
8
 
9
9
  - else
10
10
  -# The `#with_errors_from_user` helper ensures that user e-mail errors, like
@@ -14,9 +14,21 @@
14
14
 
15
15
  = form.fields_for :customer do |customer_form|
16
16
  = customer_form.fields_for :user, customer_form.object.user_or_default do |user_form|
17
- %fieldset.collapse{ class: ('in' if params[:create_account] == '1'), data: { :'user-fields' => true } }
18
- = user_form.input :password
19
- = user_form.input :password_confirmation
17
+ .collapse{ class: ('in' if params[:create_account] == '1'), data: { :'user-fields' => true } }
18
+ %fieldset
19
+ %legend.password-sign-up= t('stall.checkout.sign_in.password_sign_up')
20
+
21
+ = user_form.input :password
22
+ = user_form.input :password_confirmation
23
+
24
+ - if Stall.config.omniauth_providers.any?
25
+ %fieldset
26
+ %legend.omniauth-sign-up= t('stall.checkout.sign_in.omniauth_sign_up')
27
+
28
+ - Stall.config.omniauth_providers.each do |provider|
29
+ = link_to user_omniauth_redirect_path(provider.name, _redirect_to: request.path), class: 'btn btn-default' do
30
+ = fa_icon provider.icon
31
+ = t('stall.omniauth.sign_in_with', provider: provider.display_name)
20
32
 
21
33
  %p.help-block
22
34
  %label
@@ -6,15 +6,27 @@
6
6
  = t('stall.checkout.sign_in.click_to_sign_in')
7
7
 
8
8
  #sign-in-form.panel-body.collapse{ data: { :'sign-in-form' => true } }
9
- %p.help-block
10
- = t('stall.checkout.sign_in.sign_in_instructions', label: t('stall.checkout.sign_in.button_label'))
9
+ %fieldset
10
+ %legend.email-sign-in= t('stall.checkout.sign_in.email_sign_in')
11
11
 
12
- = simple_form_for resource, as: resource_name, url: session_path(resource_name), remote: true, html: { data: { :'stall-remote-sign-in-form' => true } } do |form|
13
- .row
14
- .col-md-6
15
- = form.input :email
16
- .col-md-6
17
- = form.input :password
12
+ %p.help-block
13
+ = t('stall.checkout.sign_in.sign_in_instructions', label: t('stall.checkout.sign_in.button_label'))
18
14
 
19
- %button.btn.btn-primary{ type: 'submit', autocomplete: 'off', data: { :'sign-in-submit-btn' => true, :'loading-text' => t('stall.shared.sending') } }
20
- = t('stall.checkout.sign_in.button_label')
15
+ = simple_form_for resource, as: resource_name, url: session_path(resource_name), remote: true, html: { data: { :'stall-remote-sign-in-form' => true } } do |form|
16
+ .row
17
+ .col-md-6
18
+ = form.input :email
19
+ .col-md-6
20
+ = form.input :password
21
+
22
+ %button.btn.btn-primary{ type: 'submit', autocomplete: 'off', data: { :'sign-in-submit-btn' => true, :'loading-text' => t('stall.shared.sending') } }
23
+ = t('stall.checkout.sign_in.button_label')
24
+
25
+ - if Stall.config.omniauth_providers.any?
26
+ %fieldset
27
+ %legend.omniauth-sign-in= t('stall.checkout.sign_in.omniauth_sign_in')
28
+
29
+ - Stall.config.omniauth_providers.each do |provider|
30
+ = link_to user_omniauth_redirect_path(provider.name, _redirect_to: request.path), class: 'btn btn-default' do
31
+ = fa_icon provider.icon
32
+ = t('stall.omniauth.sign_in_with', provider: provider.display_name)
@@ -1,6 +1,6 @@
1
1
  = simple_form_for line_item, as: :line_item, url: cart_line_items_path(cart), remote: true, data: { :'add-to-cart-form' => true, :'error-messages' => { choose: t('stall.line_items.errors.choose'), quantity: t('stall.line_items.errors.quantity') } } do |form|
2
- = form.hidden_field :sellable_type
3
- = form.hidden_field :sellable_id
2
+ = form.hidden_field :sellable_type, value: 'Variant'
3
+ = form.input_field :sellable, as: :variant_select, product: @product
4
4
 
5
5
  .input-group
6
6
  = form.input_field :quantity, spinner: false, value: 1, class: 'form-group', data: { :'quantity-field' => true }
@@ -9,4 +9,3 @@
9
9
  %button.btn.btn-primary{ type: 'submit', autocomplete: 'off', data: { :'loading-text' => t('stall.shared.sending') } }
10
10
  %i.fa.fa-shopping-cart
11
11
  = t('stall.line_items.form.add_to_cart')
12
-
@@ -0,0 +1,8 @@
1
+ %h1= @manufacturer.name
2
+
3
+ .row
4
+ .col-md-4
5
+ = render partial: 'stall/products/filters', locals: { search: @search, products: @filterable_products }
6
+
7
+ .col-md-8
8
+ = render partial: 'stall/products/list', locals: { products: @products }
@@ -0,0 +1,8 @@
1
+ %h1= @product_category.name
2
+
3
+ .row
4
+ .col-md-4
5
+ = render partial: 'stall/products/filters', locals: { search: @search, products: @filterable_products }
6
+
7
+ .col-md-8
8
+ = render partial: 'stall/products/list', locals: { products: @products }
@@ -0,0 +1,4 @@
1
+ .products-filters
2
+ = search_form_for search.form, url: request.path, as: :search, builder: SimpleForm::FormBuilder, html: { class: 'products-filters-form', data: { :'products-filters' => true } } do |form|
3
+ - product_filters_for(products).each do |filter|
4
+ = render filter.rendering_options(locals: { form: form })
@@ -0,0 +1,7 @@
1
+ .products-list
2
+ .row
3
+ - products.each do |product|
4
+ .col-md-3
5
+ = render partial: 'stall/products/product', locals: { product: product }
6
+
7
+ = paginate(products)
@@ -0,0 +1,4 @@
1
+ = link_to product_path(product), class: 'product' do
2
+ %span.product-name= product.name
3
+ = image_tag product.image.url(:thumb), class: 'img-responsive'
4
+ = number_to_currency(product.price)
@@ -0,0 +1,13 @@
1
+ .row.product-details
2
+ .col-md-12
3
+ %ul.nav.nav-tabs{ data: { tabs: 'tabs' } }
4
+ - product_details.each_with_index do |tab, index|
5
+ %li{ class: "#{'active' if index == 0}" }
6
+ = link_to tab.name, "##{tab.id}", data: { toggle: 'tab' }
7
+
8
+ .tab-content
9
+ - product_details.each_with_index do |tab, index|
10
+ .tab-pane{ id: "#{tab.id}", class: "#{'active' if index == 0}" }
11
+ = tab.content&.html_safe
12
+
13
+
@@ -0,0 +1,2 @@
1
+ .filter{ data: { :'filter' => filter.name, :'filter-submission' => 'change' } }
2
+ = form.input filter.param, as: :check_boxes, collection: filter.collection, label: filter.label, required: false
@@ -0,0 +1,2 @@
1
+ .filter{ data: { :'filter' => filter.name, :'filter-submission' => 'change' } }
2
+ = form.input filter.param, as: :check_boxes, collection: filter.collection, label: filter.label, required: false
@@ -0,0 +1,2 @@
1
+ .filter{ data: { :'filter' => 'price', :'filter-submission' => 'slide' } }
2
+ = form.input filter.param, as: :slider, label: filter.label, required: false, min: filter.min, max: filter.max, values: [filter.min, filter.max], range: true, input_html: { data: { :'slider-ticks' => filter.ticks, :'slider-ticks-labels' => filter.ticks } }
@@ -0,0 +1,2 @@
1
+ .filter{ data: { :'filter' => 'property', :'filter-name' => filter.name, :'filter-submission' => 'change' } }
2
+ = form.input filter.param, as: :check_boxes, collection: filter.collection, label: filter.label, required: false
@@ -0,0 +1,8 @@
1
+ %h1= t('stall.products.index.title')
2
+
3
+ .row
4
+ .col-md-4
5
+ = render partial: 'stall/products/filters', locals: { search: @search, products: @filterable_products }
6
+
7
+ .col-md-8
8
+ = render partial: 'stall/products/list', locals: { products: @products }
@@ -0,0 +1,26 @@
1
+ .product-page
2
+ .col-md-4
3
+ .product-images
4
+ = image_tag @product.image.url(:show), class: 'img-responsive'
5
+
6
+ .col-md-8
7
+ %h1.product-title= @product.name
8
+
9
+ = displayed_price_for_variants(@product.variants)
10
+
11
+ = add_to_cart_form_for(@product)
12
+
13
+ .description
14
+ = @product.description.try(:html_safe)
15
+
16
+ - if @product.product_details.length > 0
17
+ = render 'stall/products/product_details', product_details: @product.product_details
18
+
19
+ - if @product.suggested_products.length > 0
20
+ .related.products
21
+ %h2
22
+ = t('stall.products.suggested_products.title')
23
+
24
+ .products.row
25
+ - @product.suggested_products.each do |suggested_product|
26
+ = render partial: 'stall/products/product', locals: { product: suggested_product }
@@ -1,6 +1,10 @@
1
1
  fr:
2
2
  para:
3
3
  stall:
4
+ cart:
5
+ filters:
6
+ paid_after: Payé après le
7
+ paid_before: Payé avant le
4
8
  variants_matrix:
5
9
  enabled: "Publier ?"
6
10
  price: "Prix"
@@ -8,6 +12,7 @@ fr:
8
12
  choose_properties_to_build_variants: |
9
13
  Choisissez les propriétés ainsi que les valeurs dont vous disposez
10
14
  pour créer automatiquement les déclinaisons de votre produit.
15
+ apply_to_all: "Appliquer à toutes les déclinaisons"
11
16
 
12
17
  variant_select:
13
18
  property_placeholder: "Choisissez une option ..."
@@ -35,6 +40,21 @@ fr:
35
40
  payment: "Paiement"
36
41
  line_items: "Produits"
37
42
 
43
+ product:
44
+ informations: "Informations"
45
+ images: "Images"
46
+ descriptions: "Descriptions"
47
+ variants: "Déclinaisons"
48
+
49
+ components:
50
+ section:
51
+ products: "Catalogue"
52
+ component:
53
+ products: "Produits"
54
+ product_categories: "Catégories de produits"
55
+ properties: "Propriétés de produit"
56
+ manufacturers: "Fabricants"
57
+
38
58
  stall:
39
59
  shared:
40
60
  cancel: "Annuler"
@@ -42,6 +62,18 @@ fr:
42
62
  send: "Envoyer"
43
63
  sending: "Envoi en cours ..."
44
64
 
65
+ products:
66
+ index:
67
+ title: "Notre catalogue"
68
+ suggester_products:
69
+ title: "Vous pourriez aussi aimer ..."
70
+ prices:
71
+ from: "À partir de %{price}"
72
+ filters:
73
+ category_filter: "Catégorie"
74
+ manufacturer_filter: "Fabricant"
75
+ price_filter: "Prix"
76
+
45
77
  carts:
46
78
  actions:
47
79
  view_cart: "Voir mon panier"
@@ -93,11 +125,17 @@ fr:
93
125
  sign_in:
94
126
  already_have_an_account: "J'ai déjà un compte :"
95
127
  click_to_sign_in: "Cliquez-ici pour vous connecter"
128
+
96
129
  sign_in_instructions: |
97
130
  Renseigez dans les champs suivant vos identifiants de connexion puis
98
131
  cliquez sur le bouton "%{label}"
99
132
  button_label: "Me connecter"
100
133
 
134
+ email_sign_in: "Connexion par e-mail"
135
+ omniauth_sign_in: "ou"
136
+ password_sign_up: "Renseigner un mot de passe"
137
+ omniauth_sign_up: "ou"
138
+
101
139
  payment:
102
140
  title: "Paiement"
103
141
  error: |
@@ -173,6 +211,9 @@ fr:
173
211
  order_paid_email:
174
212
  subject: "Une nouvelle commande a été passée sur le site - %{ref}"
175
213
 
214
+ omniauth:
215
+ sign_in_with: "%{provider}"
216
+
176
217
  activerecord:
177
218
  enums:
178
219
  cart:
@@ -190,19 +231,51 @@ fr:
190
231
  paid: "Payé"
191
232
 
192
233
  models:
193
- line_item: "Produit"
194
- customer: "Client"
195
- address: "Adresse"
196
- cart: "Panier"
197
- shipment: "Livraison"
198
- payment: "Paiement"
199
- product: "Produit"
200
- product_category: "Catégorie"
201
- variant: "Déclinaison"
202
- product_detail: "Bloc de description"
203
- manufacturer: "Fabricant"
234
+ line_item:
235
+ one: "Produit"
236
+ other: "Produits"
237
+ customer:
238
+ one: "Client"
239
+ other: "Clients"
240
+ address:
241
+ one: "Adresse"
242
+ other: "Adresses"
243
+ cart:
244
+ one: "Panier"
245
+ other: "Paniers"
246
+ shipment:
247
+ one: "Livraison"
248
+ other: "Livraisons"
249
+ payment:
250
+ one: "Paiement"
251
+ other: "Paiements"
252
+ product:
253
+ one: "Produit"
254
+ other: "Produits"
255
+ product_category:
256
+ one: "Catégorie"
257
+ other: "Catégories"
258
+ variant:
259
+ one: "Déclinaison"
260
+ other: "Déclinaisons"
261
+ product_detail:
262
+ one: "Bloc de description"
263
+ other: "Blocs de description"
264
+ manufacturer:
265
+ one: "Fabricant"
266
+ other: "Fabricants"
267
+ curated_product_list:
268
+ one: "Curated list"
269
+ other: "Curated lists"
270
+ curated_list_product:
271
+ one: "Produit de curated list"
272
+ other: "Produits de curated list"
204
273
 
205
274
  attributes:
275
+ curated_product_list:
276
+ curated_list_products: Produits
277
+ curated_list_product:
278
+ product: Produit
206
279
  line_item:
207
280
  sellable: "Produit source"
208
281
  name: "Nom du produit"
@@ -268,10 +341,21 @@ fr:
268
341
  product_category: "Catégorie de produit"
269
342
  name: "Nom du produit"
270
343
  slug: "Fragment d'URL"
344
+ images: Images du produit
271
345
  description: "Description du produit"
272
346
  properties: "Propriétés"
273
347
  variants: "Déclinaisons"
274
348
  product_details: "Blocs de description produit"
349
+ manufacturer: "Fabricant"
350
+ suggested_products: "Produits suggérés"
351
+ price: "Prix"
352
+ product_category:
353
+ name: "Nom"
354
+ slug: "Fragment d'URL"
355
+ position: "Position"
356
+ parent: "Catégorie parente"
357
+ children: "Catégories enfant"
358
+ products: "Produits"
275
359
  product_detail:
276
360
  name: "Titre"
277
361
  content: "Contenu"
@@ -279,6 +363,8 @@ fr:
279
363
  name: "Nom du fabricant"
280
364
  logo: "Logo"
281
365
  products: "Produits"
366
+ image:
367
+ file: Image
282
368
 
283
369
  simple_form:
284
370
  placeholders:
@@ -0,0 +1,5 @@
1
+ class AddSlugToStallManufacturers < ActiveRecord::Migration
2
+ def change
3
+ add_column :stall_manufacturers, :slug, :text
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class CreateStallProductSuggestions < ActiveRecord::Migration
2
+ def change
3
+ create_table :stall_product_suggestions do |t|
4
+ t.references :product, index: true
5
+ t.references :suggestion, index: true
6
+
7
+ t.timestamps null: false
8
+ end
9
+
10
+ add_foreign_key :stall_product_suggestions, :stall_products, column: :product_id
11
+ add_foreign_key :stall_product_suggestions, :stall_products, column: :suggestion_id
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class AddPositionToStallManufacturers < ActiveRecord::Migration
2
+ def change
3
+ add_column :stall_manufacturers, :position, :integer, default: 0
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ class CreateStallCuratedProductLists < ActiveRecord::Migration
2
+ def change
3
+ create_table :stall_curated_product_lists do |t|
4
+ t.string :name
5
+ t.string :slug
6
+
7
+ t.timestamps null: false
8
+ end
9
+ end
10
+ end