stall 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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