solidus_product_assembly 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +18 -0
  6. data/LICENSE.md +13 -0
  7. data/README.md +80 -0
  8. data/Rakefile +21 -0
  9. data/app/assets/images/spinner.gif +0 -0
  10. data/app/assets/javascripts/spree/backend/solidus_product_assembly.js +1 -0
  11. data/app/assets/javascripts/spree/frontend/solidus_product_assembly.js +1 -0
  12. data/app/assets/stylesheets/spree/backend/solidus_product_assembly.css +3 -0
  13. data/app/assets/stylesheets/spree/frontend/solidus_product_assembly.css +3 -0
  14. data/app/controllers/spree/admin/parts_controller.rb +49 -0
  15. data/app/controllers/spree/checkout_controller_decorator.rb +9 -0
  16. data/app/helpers/spree/admin/orders_helper_decorator.rb +9 -0
  17. data/app/models/spree/assemblies_part.rb +12 -0
  18. data/app/models/spree/inventory_unit_decorator.rb +13 -0
  19. data/app/models/spree/line_item_decorator.rb +44 -0
  20. data/app/models/spree/order_inventory_assembly.rb +39 -0
  21. data/app/models/spree/product_decorator.rb +56 -0
  22. data/app/models/spree/shipment_decorator.rb +50 -0
  23. data/app/models/spree/stock/availability_validator.rb +28 -0
  24. data/app/models/spree/stock/inventory_unit_builder_decorator.rb +30 -0
  25. data/app/models/spree/stock/inventory_validator_decorator.rb +12 -0
  26. data/app/models/spree/variant_decorator.rb +13 -0
  27. data/app/overrides/add_admin_product_form_fields.rb +5 -0
  28. data/app/overrides/add_admin_tabs.rb +5 -0
  29. data/app/overrides/add_line_item_description.rb +5 -0
  30. data/app/overrides/spree/admin/orders/_form/inject_product_assemblies.html.erb.deface +3 -0
  31. data/app/overrides/spree/admin/orders/_shipment/stock_contents.html.erb.deface +2 -0
  32. data/app/overrides/spree/checkout/_delivery/remove_unshippable_markup.html.erb.deface +1 -0
  33. data/app/overrides/spree/checkout/_delivery/render_line_item_manifest.html.erb.deface +3 -0
  34. data/app/overrides/spree/products/show/add_links_to_parts.html.erb.deface +21 -0
  35. data/app/overrides/spree/products/show/remove_add_to_cart_button_for_non_individual_sale_products.html.erb.deface +4 -0
  36. data/app/overrides/spree/shared/_order_details/part_description.html.erb.deface +8 -0
  37. data/app/views/spree/admin/orders/_assemblies.html.erb +56 -0
  38. data/app/views/spree/admin/orders/_stock_contents.html.erb +69 -0
  39. data/app/views/spree/admin/orders/_stock_item.html.erb +46 -0
  40. data/app/views/spree/admin/parts/_parts_table.html.erb +33 -0
  41. data/app/views/spree/admin/parts/available.html.erb +55 -0
  42. data/app/views/spree/admin/parts/available.js.erb +54 -0
  43. data/app/views/spree/admin/parts/index.html.erb +70 -0
  44. data/app/views/spree/admin/parts/update_parts_table.js.erb +2 -0
  45. data/app/views/spree/admin/products/_product_assembly_fields.html.erb +23 -0
  46. data/app/views/spree/admin/shared/_product_assembly_product_tabs.html.erb +3 -0
  47. data/app/views/spree/checkout/_line_item_manifest.html.erb +17 -0
  48. data/app/views/spree/orders/_cart_description.html.erb +8 -0
  49. data/bin/rails +7 -0
  50. data/config/locales/en.yml +14 -0
  51. data/config/locales/fr.yml +12 -0
  52. data/config/locales/ru.yml +12 -0
  53. data/config/locales/sv.yml +12 -0
  54. data/config/routes.rb +19 -0
  55. data/db/migrate/20091028152124_add_many_to_many_relation_to_products.rb +13 -0
  56. data/db/migrate/20091029165620_add_parts_fields_to_products.rb +27 -0
  57. data/db/migrate/20120316141830_namespace_product_assembly_for_spree_one.rb +9 -0
  58. data/db/migrate/20140620223938_add_id_to_spree_assemblies_parts.rb +9 -0
  59. data/lib/generators/solidus_product_assembly/install/install_generator.rb +24 -0
  60. data/lib/solidus_product_assembly.rb +3 -0
  61. data/lib/solidus_product_assembly/engine.rb +15 -0
  62. data/lib/solidus_product_assembly/version.rb +3 -0
  63. data/lib/tasks/spree2_upgrade.rake +29 -0
  64. data/solidus_product_assembly.gemspec +35 -0
  65. data/spec/features/admin/orders_spec.rb +29 -0
  66. data/spec/features/admin/parts_spec.rb +28 -0
  67. data/spec/features/checkout_spec.rb +92 -0
  68. data/spec/models/spree/assemblies_part_spec.rb +18 -0
  69. data/spec/models/spree/inventory_unit_spec.rb +32 -0
  70. data/spec/models/spree/line_item_spec.rb +72 -0
  71. data/spec/models/spree/order_contents_spec.rb +40 -0
  72. data/spec/models/spree/order_inventory_assembly_spec.rb +55 -0
  73. data/spec/models/spree/order_inventory_spec.rb +35 -0
  74. data/spec/models/spree/product_spec.rb +35 -0
  75. data/spec/models/spree/shipment_spec.rb +112 -0
  76. data/spec/models/spree/stock/availability_validator_spec.rb +71 -0
  77. data/spec/models/spree/stock/coordinator_spec.rb +52 -0
  78. data/spec/models/spree/stock/inventory_unit_builder_spec.rb +36 -0
  79. data/spec/models/spree/variant_spec.rb +28 -0
  80. data/spec/spec_helper.rb +57 -0
  81. data/spec/support/shared_contexts/order_with_bundle.rb +13 -0
  82. metadata +272 -0
@@ -0,0 +1,28 @@
1
+ module Spree
2
+ module Stock
3
+ # Overridden from spree core to make it also check for assembly parts stock
4
+ class AvailabilityValidator < ActiveModel::Validator
5
+ def validate(line_item)
6
+ line_item.quantity_by_variant.each do |variant, variant_quantity|
7
+ inventory_units = line_item.inventory_units.where(variant: variant).count
8
+ quantity = variant_quantity - inventory_units
9
+
10
+ next if quantity <= 0
11
+ next unless variant
12
+
13
+ quantifier = Stock::Quantifier.new(variant)
14
+
15
+ unless quantifier.can_supply? quantity
16
+ display_name = %Q{#{variant.name}}
17
+ display_name += %Q{ (#{variant.options_text})} unless variant.options_text.blank?
18
+
19
+ line_item.errors[:quantity] << Spree.t(
20
+ :selected_quantity_not_available,
21
+ item: display_name.inspect
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ module Spree
2
+ module Stock
3
+ InventoryUnitBuilder.class_eval do
4
+ def units
5
+ @order.line_items.flat_map do |line_item|
6
+ line_item.quantity_by_variant.flat_map do |variant, quantity|
7
+ quantity.times.map { build_inventory_unit(variant, line_item) }
8
+ end
9
+ end
10
+ end
11
+
12
+ def build_inventory_unit(variant, line_item)
13
+ @order.inventory_units.includes(
14
+ variant: {
15
+ product: {
16
+ shipping_category: {
17
+ shipping_methods: [:calculator, { zones: :zone_members }]
18
+ }
19
+ }
20
+ }
21
+ ).build(
22
+ pending: true,
23
+ variant: variant,
24
+ line_item: line_item,
25
+ order: @order
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,12 @@
1
+ Spree::Stock::InventoryValidator.class_eval do
2
+ def validate(line_item)
3
+ total_quantity = line_item.quantity_by_variant.values.sum
4
+
5
+ if line_item.inventory_units.count != total_quantity
6
+ line_item.errors[:inventory] << Spree.t(
7
+ :inventory_not_available,
8
+ item: line_item.variant.name
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ Spree::Variant.class_eval do
2
+ has_and_belongs_to_many :assemblies, :class_name => "Spree::Product",
3
+ :join_table => "spree_assemblies_parts",
4
+ :foreign_key => "part_id", :association_foreign_key => "assembly_id"
5
+
6
+ def assemblies_for(products)
7
+ assemblies.where(id: products)
8
+ end
9
+
10
+ def part?
11
+ assemblies.exists?
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ Deface::Override.new(:virtual_path => "spree/admin/products/_form",
2
+ :name => "product_assembly_admin_product_form_right",
3
+ :insert_after => "[data-hook='admin_product_form_right'], #admin_product_form_right[data-hook]",
4
+ :partial => "spree/admin/products/product_assembly_fields",
5
+ :disabled => false)
@@ -0,0 +1,5 @@
1
+ Deface::Override.new(:virtual_path => "spree/admin/shared/_product_tabs",
2
+ :name => "product_assembly_admin_product_tabs",
3
+ :insert_bottom => "[data-hook='admin_product_tabs']",
4
+ :partial => "spree/admin/shared/product_assembly_product_tabs",
5
+ :disabled => false)
@@ -0,0 +1,5 @@
1
+ Deface::Override.new(:virtual_path => "spree/orders/_line_item",
2
+ :name => "product_assembly_cart_item_description",
3
+ :insert_bottom => "[data-hook='cart_item_description']",
4
+ :partial => "spree/orders/cart_description",
5
+ :disabled => false)
@@ -0,0 +1,3 @@
1
+ <!-- insert_top 'div[data-hook=admin_order_form_fields]' -->
2
+
3
+ <%= render partial: 'spree/admin/orders/assemblies', locals: { order: order } %>
@@ -0,0 +1,2 @@
1
+ <!-- replace_contents '.stock-contents tbody' -->
2
+ <%= render 'stock_contents', shipment: shipment %>
@@ -0,0 +1,3 @@
1
+ <!-- replace_contents 'table[data-hook=stock-contents] tbody' -->
2
+
3
+ <%= render 'line_item_manifest', ship_form: ship_form %>
@@ -0,0 +1,21 @@
1
+ <!-- insert_after '#cart-form' -->
2
+ <% if @product.parts.any?(&:in_stock?) %>
3
+
4
+ <h6><%= Spree.t(:parts_included) %></h6>
5
+
6
+ <ul id="products" class="inline product-listing" data-hook>
7
+ <% @product.parts.each do |variant| %>
8
+ <% if variant.in_stock? %>
9
+ <li id="product_<%= variant.product.id %>" class="columns three <%= cycle("alpha", "secondary", "", "omega secondary") %>" data-hook="products_list_item" itemscope itemtype="http://schema.org/Product">
10
+ <div class="product-image">
11
+ <%= link_to small_image(variant.product, :itemprop => "name"), variant.product %>
12
+ </div>
13
+ <%= link_to truncate(variant.product.name, :length => 50), variant.product, :class => 'info', :itemprop => "name", :title => variant.product.name %>
14
+ <% if variant.product.individual_sale? %>
15
+ <span class="price selling" itemprop="price"><%= number_to_currency variant.price %></span>
16
+ <% end %>
17
+ </li>
18
+ <% end %>
19
+ <% end %>
20
+ </ul>
21
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <!-- surround '[data-hook="cart_form"]' -->
2
+ <% if @product.individual_sale? %>
3
+ <%= render_original %>
4
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <!-- insert_bottom 'td[data-hook=order_item_description]' -->
2
+ <% if item.product.assembly? %>
3
+ <ul class='assembly_parts'>
4
+ <% item.parts.each do |v| %>
5
+ <li>(<%= item.count_of(v) %>) <%= link_to v.name, product_path(v.product) %> (<%= v.sku %>)</li>
6
+ <% end %>
7
+ </ul>
8
+ <% end %>
@@ -0,0 +1,56 @@
1
+ <% if order.line_items.assemblies.any? %>
2
+ <fieldset class="no-border-bottom">
3
+ <legend align="center" class="" data-hook="">
4
+ <%= Spree.t(:product_bundles) %>
5
+ </legend>
6
+ </fieldset>
7
+
8
+ <table class="product-bundles index" data-hook="line-items">
9
+ <colgroup>
10
+ <col style="width: 10%;" />
11
+ <col style="width: 20%;" />
12
+ <col style="width: 20%;" />
13
+ <col style="width: 15%;" />
14
+ </colgroup>
15
+
16
+ <thead>
17
+ <tr>
18
+ <th colspan="2"><%= Spree::Product.human_attribute_name(:name) %></th>
19
+ <th><%= Spree::LineItem.human_attribute_name(:price) %></th>
20
+ <th><%= Spree::LineItem.human_attribute_name(:quantity) %></th>
21
+ <th><%= Spree::LineItem.human_attribute_name(:total) %></th>
22
+ <th class="orders-actions actions" data-hook="admin_order_form_line_items_header_actions">&nbsp;</th>
23
+ </tr>
24
+ </thead>
25
+
26
+ <tbody>
27
+ <% order.line_items.assemblies.each do |item| %>
28
+ <%= content_tag :tr, class: 'line-item', id: "line-item-#{item.id}", data: { line_item_id: item.id } do %>
29
+ <td class="line-item-image"><%= image_tag item.variant.display_image.attachment(:mini) %></td>
30
+ <td class="line-item-name">
31
+ <%= item.variant.product.name %><br><%= "(" + variant_options(item.variant) + ")" unless item.variant.option_values.empty? %>
32
+ <% if item.variant.sku.present? %>
33
+ <strong><%= Spree::Variant.human_attribute_name(:sku) %>:</strong> <%= item.variant.sku %>
34
+ <% end %>
35
+ </td>
36
+ <td class="line-item-price align-center"><%= item.single_money.to_html %></td>
37
+ <td class="line-item-qty-show align-center">
38
+ <%= item.quantity %>
39
+ </td>
40
+ <td class="line-item-qty-edit">
41
+ <%= number_field_tag :quantity, item.quantity, :min => 0, :class => "line_item_quantity", :size => 5 %>
42
+ </td>
43
+ <td class="line-item-total align-center"><%= line_item_shipment_price(item, item.quantity) %></td>
44
+ <td class="cart-line-item-delete actions" data-hook="cart_line_item_delete">
45
+ <% if can? :update, item %>
46
+ <%= link_to '', '#', :class => 'save-line-item fa fa-ok no-text with-tip', :title => Spree.t('actions.save') %>
47
+ <%= link_to '', '#', :class => 'cancel-line-item fa fa-cancel no-text with-tip', :title => Spree.t('actions.cancel') %>
48
+ <%= link_to '', '#', :class => 'edit-line-item fa fa-edit no-text with-tip', :title => Spree.t('actions.edit') %>
49
+ <%= link_to '', '#', :class => 'delete-line-item fa fa-trash no-text with-tip', :title => Spree.t('actions.delete') %>
50
+ <% end %>
51
+ </td>
52
+ <% end %>
53
+ <% end %>
54
+ </tbody>
55
+ </table>
56
+ <% end %>
@@ -0,0 +1,69 @@
1
+ <%= render 'stock_item', shipment: shipment %>
2
+
3
+ <% unless shipment.shipped? %>
4
+ <tr class="edit-method hidden total">
5
+ <td colspan="5">
6
+ <div class="field alpha five columns">
7
+ <%= label_tag 'selected_shipping_rate_id', Spree.t(:shipping_method) %>
8
+ <%= select_tag :selected_shipping_rate_id,
9
+ options_for_select(shipment.shipping_rates.map {|sr| ["#{sr.name} #{sr.display_price}", sr.id] }, shipment.selected_shipping_rate_id),
10
+ {:class => 'select2 fullwidth', :data => {'shipment-number' => shipment.number } } %>
11
+ </div>
12
+ </td>
13
+ <td class="actions">
14
+ <% if can? :update, shipment %>
15
+ <%= link_to '', '#', :class => 'save-method fa fa-ok no-text with-tip',
16
+ :data => {'shipment-number' => shipment.number, :action => 'save'}, title: Spree.t('actions.save') %>
17
+ <%= link_to '', '#', :class => 'cancel-method fa fa-cancel no-text with-tip',
18
+ :data => {:action => 'cancel'}, :title => Spree.t('actions.cancel') %>
19
+ <% end %>
20
+ </td>
21
+ </tr>
22
+ <% end %>
23
+
24
+ <tr class="show-method total">
25
+ <% if shipment.shipping_method %>
26
+ <td colspan="4">
27
+ <strong><%= shipment.shipping_method.name %></strong>
28
+ </td>
29
+ <td class="total" align="center">
30
+ <span><%= shipment.display_cost %></span>
31
+ </td>
32
+ <% else %>
33
+ <td colspan='5'><%= Spree.t(:no_shipping_method_selected) %></td>
34
+ <% end %>
35
+
36
+ <td class="actions">
37
+ <% if can? :update, shipment %>
38
+ <%= link_to '', '#', :class => 'edit-method fa fa-edit no-text with-tip', :data => {:action => 'edit'}, :title => Spree.t('edit') %>
39
+ <% end %>
40
+ </td>
41
+ </tr>
42
+
43
+ <tr class="edit-tracking hidden total">
44
+ <td colspan="5">
45
+ <label><%= Spree.t(:tracking_number) %>:</label>
46
+ <%= text_field_tag :tracking, shipment.tracking %>
47
+ </td>
48
+ <td class="actions">
49
+ <% if can? :update, shipment %>
50
+ <%= link_to '', '#', :class => 'save-tracking fa fa-ok no-text with-tip', :data => {'shipment-number' => shipment.number, :action => 'save'}, :title => Spree.t('actions.save') %>
51
+ <%= link_to '', '#', :class => 'cancel-tracking fa fa-cancel no-text with-tip', :data => {:action => 'cancel'}, :title => Spree.t('actions.cancel') %>
52
+ <% end %>
53
+ </td>
54
+ </tr>
55
+
56
+ <tr class="show-tracking total">
57
+ <td colspan="5">
58
+ <% if shipment.tracking.present? %>
59
+ <strong><%= Spree.t(:tracking) %>:</strong> <%= shipment.tracking %>
60
+ <% else %>
61
+ <%= Spree.t(:no_tracking_present) %>
62
+ <% end %>
63
+ </td>
64
+ <td class="actions">
65
+ <% if can? :update, shipment %>
66
+ <%= link_to '', '#', :class => 'edit-tracking fa fa-edit no-text with-tip', :data => {:action => 'edit'}, :title => Spree.t('edit') %>
67
+ <% end %>
68
+ </td>
69
+ </tr>
@@ -0,0 +1,46 @@
1
+ <% shipment.manifest.each do |item| %>
2
+ <tr class="stock-item" data-item-quantity="<%= item.quantity %>">
3
+ <td class="item-image"><%= mini_image(item.variant) %></td>
4
+ <td class="item-name">
5
+ <%= item.variant.product.name %><br><%= "(" + variant_options(item.variant) + ")" unless item.variant.option_values.empty? %>
6
+ <% if item.part && item.line_item %>
7
+ <i><%= Spree.t(:part_of_bundle, sku: item.product.sku) %></i>
8
+ <% end %>
9
+ </td>
10
+ <td class="item-price align-center">
11
+ <% if item.part %>
12
+ ---
13
+ <% else %>
14
+ <%= item.line_item.single_money.to_html if item.line_item %>
15
+ <% end %>
16
+ </td>
17
+ <td class="item-qty-show align-center">
18
+ <% item.states.each do |state,count| %>
19
+ <%= count %> x <%= state.humanize.downcase %>
20
+ <% end %>
21
+ </td>
22
+ <% unless shipment.shipped? %>
23
+ <td class="item-qty-edit hidden">
24
+ <%= number_field_tag :quantity, item.quantity, :min => 0, :class => "line_item_quantity", :size => 5 %>
25
+ </td>
26
+ <% end %>
27
+ <td class="item-total align-center">
28
+ <% if item.part %>
29
+ ---
30
+ <% else %>
31
+ <%= line_item_shipment_price(item.line_item, item.quantity) if item.line_item %>
32
+ <% end %>
33
+ </td>
34
+ <td class="cart-item-delete actions" data-hook="cart_item_delete">
35
+ <% if !shipment.shipped? && !item.part %>
36
+ <% if can? :update, item %>
37
+ <%= link_to '', '#', :class => 'save-item fa fa-ok no-text with-tip', :data => {'shipment-number' => shipment.number, 'variant-id' => item.variant.id, :action => 'save'}, :title => Spree.t('actions.save'), :style => 'display: none' %>
38
+ <%= link_to '', '#', :class => 'cancel-item fa fa-cancel no-text with-tip', :data => {:action => 'cancel'}, :title => Spree.t('actions.cancel'), :style => 'display: none' %>
39
+ <%= link_to '', '#', :class => 'edit-item fa fa-edit no-text with-tip', :data => {:action => 'edit'}, :title => Spree.t('edit') %>
40
+ <%= link_to '', '#', :class => 'split-item fa fa-arrows-h no-text with-tip', :data => {:action => 'split', 'variant-id' => item.variant.id}, :title => Spree.t('split') %>
41
+ <%= link_to '', '#', :class => 'delete-item fa fa-trash no-text with-tip', :data => {'shipment-number' => shipment.number, 'variant-id' => item.variant.id, :action => 'remove'}, :title => Spree.t('actions.delete') %>
42
+ <% end %>
43
+ <% end %>
44
+ </td>
45
+ </tr>
46
+ <% end %>
@@ -0,0 +1,33 @@
1
+ <table class="index">
2
+ <thead>
3
+ <tr>
4
+ <th><%= Spree.t(:sku) %></th>
5
+ <th><%= Spree.t(:name) %></th>
6
+ <th><%= Spree.t(:options) %></th>
7
+ <th><%= Spree.t(:qty) %></th>
8
+ </tr>
9
+ </thead>
10
+ <tbody>
11
+ <% parts.each do |part| %>
12
+ <tr id="<%= dom_id(part, :sel)%>">
13
+ <td><%= part.sku %></td>
14
+ <td><%= part.product.name %></td>
15
+ <td><%= variant_options part %></td>
16
+ <td><%= text_field_tag :count, @product.count_of(part) %></td>
17
+ <td class="actions">
18
+ <%= link_to(icon('edit'),
19
+ set_count_admin_product_part_url(@product, part),
20
+ :class => "set_count_admin_product_part_link save-line-item fa fa-ok no-text") %>
21
+
22
+ <%= link_to(icon('delete'),
23
+ remove_admin_product_part_url(@product, part),
24
+ :class => "remove_admin_product_part_link delete-line-item fa fa-trash no-text") %>
25
+ </td>
26
+ </tr>
27
+ <% end %>
28
+ <% if parts.empty? %>
29
+ <tr><td colspan="5"><%= Spree.t(:none) %>.</td></tr>
30
+ <% end %>
31
+ </tbody>
32
+ </table>
33
+ <%= javascript_tag("subscribe_product_part_links();") if request.xhr? %>
@@ -0,0 +1,55 @@
1
+ <script type="text/javascript">
2
+ function displayRow(){
3
+ var row = document.getElementById("captionRow");
4
+ if (row.style.display == '') row.style.display = 'none';
5
+ else row.style.display = '';
6
+ }
7
+ </script>
8
+
9
+ <h4><%= Spree.t(:available_parts) %></h4>
10
+ <table class="index">
11
+ <thead>
12
+ <tr>
13
+ <th><%= Spree.t(:name) %></th>
14
+ <th><%= Spree.t(:options) %></th>
15
+ <th><%= Spree.t(:qty) %></th>
16
+ <th></th>
17
+ </tr>
18
+ </thead>
19
+ <tbody>
20
+ <% @available_products.each do |product| %>
21
+ <tr id="<%= dom_id(product) %>">
22
+
23
+ <td><%= product.name %></td>
24
+ <td>
25
+ <% if product.has_variants? %>
26
+ <%= select_tag "part[id]",
27
+ options_for_select(product.variants.map { |v| [variant_options(v), v.id] }) %>
28
+ <% else %>
29
+ <%= hidden_field_tag "part[id]", product.master.id %>
30
+ <%= Spree.t(:no_variants) %>
31
+ <% end %>
32
+ </td>
33
+ <td><%= text_field_tag "part[count]", 1 %></td>
34
+ <td class="actions">
35
+ <%= link_to(icon('add') + ' ' + Spree.t(:select),
36
+ admin_product_parts_path(@product),
37
+ :class => "add_product_part_link") %>
38
+ </td>
39
+ </tr>
40
+ <% end %>
41
+ <% if @available_products.empty? %>
42
+ <tr><td colspan="3"><%= Spree.t(:no_match_found) %>.</td></tr>
43
+ <% end %>
44
+ </tbody>
45
+ </table>
46
+
47
+ <%= javascript_tag do %>
48
+ $("a.add_product_part_link").click(function(){
49
+ part_id_val = $('select option:selected', $(this).parent().parent()).val() ||
50
+ $('input:first', $(this).parent().parent()).val();
51
+ params = { part_count : $('input:last', $(this).parent().parent()).val(),
52
+ part_id : part_id_val};
53
+ return make_post_request($(this), params);
54
+ });
55
+ <% end %>
@@ -0,0 +1,54 @@
1
+ <script type="text/javascript">
2
+ function displayRow(){
3
+ var row = document.getElementById("captionRow");
4
+ if (row.style.display == '') row.style.display = 'none';
5
+ else row.style.display = '';
6
+ }
7
+ </script>
8
+ <h4><%= Spree.t(:available_parts) %></h4>
9
+ <table class="index">
10
+ <thead>
11
+ <tr>
12
+ <th><%= Spree.t(:name) %></th>
13
+ <th><%= Spree.t(:options) %></th>
14
+ <th><%= Spree.t(:qty) %></th>
15
+ <th></th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <% @available_products.each do |product| %>
20
+ <tr id="<%= dom_id(product) %>">
21
+
22
+ <td><%= product.name %></td>
23
+ <td>
24
+ <% if product.has_variants? %>
25
+ <%= select_tag "part[id]",
26
+ options_for_select(product.variants.map { |v| [variant_options(v), v.id] }) %>
27
+ <% else %>
28
+ <%= hidden_field_tag "part[id]", product.master.id %>
29
+ <%= Spree.t(:no_variants) %>
30
+ <% end %>
31
+ </td>
32
+ <td><%= text_field_tag "part[count]", 1 %></td>
33
+ <td class="actions">
34
+ <%= link_to(icon('add') + ' ' + Spree.t(:select),
35
+ admin_product_parts_path(@product),
36
+ :class => "add_product_part_link") %>
37
+ </td>
38
+ </tr>
39
+ <% end %>
40
+ <% if @available_products.empty? %>
41
+ <tr><td colspan="3"><%= Spree.t(:no_match_found) %>.</td></tr>
42
+ <% end %>
43
+ </tbody>
44
+ </table>
45
+
46
+ <%= javascript_tag do %>
47
+ $("a.add_product_part_link").click(function(){
48
+ part_id_val = $('select option:selected', $(this).parent().parent()).val() ||
49
+ $('input:first', $(this).parent().parent()).val();
50
+ params = { part_count : $('input:last', $(this).parent().parent()).val(),
51
+ part_id : part_id_val};
52
+ return make_post_request($(this), params);
53
+ });
54
+ <% end %>