caboose-cms 0.4.151 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/app/assets/javascripts/caboose/admin_products.js +79 -0
- data/app/assets/javascripts/caboose/application.js +2 -1
- data/app/assets/javascripts/caboose/cart.js +168 -0
- data/app/assets/javascripts/caboose/checkout.js +151 -0
- data/app/assets/javascripts/caboose/checkout_module.js +312 -0
- data/app/assets/javascripts/caboose/checkout_step1.js +179 -0
- data/app/assets/javascripts/caboose/checkout_step2.js +39 -0
- data/app/assets/javascripts/caboose/checkout_step3.js +34 -0
- data/app/assets/javascripts/caboose/checkout_step4.js +97 -0
- data/app/assets/javascripts/caboose/main.js +99 -8
- data/app/assets/javascripts/caboose/product.js +284 -0
- data/app/assets/stylesheets/caboose/admin_products.css +86 -0
- data/app/assets/templates/caboose/cart/add_to_cart.jst.ejs +7 -0
- data/app/assets/templates/caboose/cart/line_items.jst.ejs +41 -0
- data/app/assets/templates/caboose/checkout/address.jst.ejs +53 -0
- data/app/assets/templates/caboose/checkout/forms/guest.jst.ejs +8 -0
- data/app/assets/templates/caboose/checkout/forms/register.jst.ejs +11 -0
- data/app/assets/templates/caboose/checkout/forms/signin.jst.ejs +7 -0
- data/app/assets/templates/caboose/checkout/line_items.jst.ejs +31 -0
- data/app/assets/templates/caboose/checkout/login.jst.ejs +21 -0
- data/app/assets/templates/caboose/checkout/payment.jst.ejs +5 -0
- data/app/assets/templates/caboose/checkout/shipping.jst.ejs +18 -0
- data/app/assets/templates/caboose/product/images.jst.ejs +8 -0
- data/app/assets/templates/caboose/product/options.jst.ejs +19 -0
- data/app/controllers/caboose/application_controller.rb +29 -1
- data/app/controllers/caboose/cart_controller.rb +52 -0
- data/app/controllers/caboose/categories_controller.rb +108 -0
- data/app/controllers/caboose/checkout_controller.rb +325 -0
- data/app/controllers/caboose/orders_controller.rb +439 -0
- data/app/controllers/caboose/product_images_controller.rb +38 -0
- data/app/controllers/caboose/products_controller.rb +737 -0
- data/app/controllers/caboose/reviews_controller.rb +15 -0
- data/app/controllers/caboose/variants_controller.rb +218 -0
- data/app/controllers/caboose/vendors_controller.rb +73 -0
- data/app/helpers/caboose/application_helper.rb +4 -0
- data/app/helpers/caboose/categories_helper.rb +82 -0
- data/app/helpers/caboose/checkout_helper.rb +20 -0
- data/app/helpers/caboose/products_helper.rb +8 -0
- data/app/mailers/caboose/orders_mailer.rb +30 -0
- data/app/models/caboose/address.rb +26 -0
- data/app/models/caboose/category.rb +89 -0
- data/app/models/caboose/category_membership.rb +10 -0
- data/app/models/caboose/core_plugin.rb +15 -37
- data/app/models/caboose/customization_membership.rb +10 -0
- data/app/models/caboose/discount.rb +16 -0
- data/app/models/caboose/line_item.rb +81 -0
- data/app/models/caboose/message.rb +20 -0
- data/app/models/caboose/order.rb +191 -0
- data/app/models/caboose/order_discount.rb +10 -0
- data/app/models/caboose/order_pdf.rb +78 -0
- data/app/models/caboose/payment_processors/authorizenet.rb +53 -0
- data/app/models/caboose/payment_processors/base.rb +39 -0
- data/app/models/caboose/payment_processors/payscape.rb +94 -0
- data/app/models/caboose/product.rb +145 -0
- data/app/models/caboose/product_image.rb +62 -0
- data/app/models/caboose/product_image_variant.rb +10 -0
- data/app/models/caboose/review.rb +13 -0
- data/app/models/caboose/schema.rb +205 -1
- data/app/models/caboose/search_filter.rb +191 -0
- data/app/models/caboose/shipping_calculator.rb +81 -0
- data/app/models/caboose/states.rb +61 -52
- data/app/models/caboose/tax_calculator.rb +23 -0
- data/app/models/caboose/tax_line.rb +9 -0
- data/app/models/caboose/variant.rb +99 -0
- data/app/models/caboose/vendor.rb +22 -0
- data/app/views/caboose/cart/index.html.erb +8 -0
- data/app/views/caboose/categories/admin_edit.html.erb +79 -0
- data/app/views/caboose/categories/admin_index.html.erb +11 -0
- data/app/views/caboose/categories/admin_new.html.erb +62 -0
- data/app/views/caboose/checkout/_address_form.html.erb +111 -0
- data/app/views/caboose/checkout/_billing_form.html.erb +47 -0
- data/app/views/caboose/checkout/_cart.html.erb +52 -0
- data/app/views/caboose/checkout/_confirm.html.erb +61 -0
- data/app/views/caboose/checkout/_order_discount.html.erb +40 -0
- data/app/views/caboose/checkout/_shipping_address.html.erb +10 -0
- data/app/views/caboose/checkout/_shipping_method.html.erb +2 -0
- data/app/views/caboose/checkout/_shipping_method_form.html.erb +21 -0
- data/app/views/caboose/checkout/billing.html.erb +11 -0
- data/app/views/caboose/checkout/discount.html.erb +11 -0
- data/app/views/caboose/checkout/empty.html.erb +2 -0
- data/app/views/caboose/checkout/error.html.erb +2 -0
- data/app/views/caboose/checkout/index.html.erb +43 -0
- data/app/views/caboose/checkout/login.html.erb +2 -0
- data/app/views/caboose/checkout/payment.html.erb +79 -0
- data/app/views/caboose/checkout/relay.html.erb +23 -0
- data/app/views/caboose/checkout/relay_old.html.erb +12 -0
- data/app/views/caboose/checkout/relay_postMessage.html.erb +19 -0
- data/app/views/caboose/checkout/shipping.html.erb +15 -0
- data/app/views/caboose/checkout/step_four.html.erb +93 -0
- data/app/views/caboose/checkout/step_one.html.erb +56 -0
- data/app/views/caboose/checkout/step_one_old.html.erb +13 -0
- data/app/views/caboose/checkout/step_three.html.erb +23 -0
- data/app/views/caboose/checkout/step_two.html.erb +52 -0
- data/app/views/caboose/checkout/step_two_old.html.erb +14 -0
- data/app/views/caboose/checkout/thanks.html.erb +5 -0
- data/app/views/caboose/orders/_admin_footer.html.erb +2 -0
- data/app/views/caboose/orders/_admin_header.html.erb +31 -0
- data/app/views/caboose/orders/_quickbooks_order.html.erb +0 -0
- data/app/views/caboose/orders/admin_delete_form.html.erb +21 -0
- data/app/views/caboose/orders/admin_edit.html.erb +271 -0
- data/app/views/caboose/orders/admin_index.html.erb +89 -0
- data/app/views/caboose/orders/admin_new.html.erb +42 -0
- data/app/views/caboose/orders/admin_print.html.erb +72 -0
- data/app/views/caboose/orders_mailer/customer_new_order.html.erb +1 -0
- data/app/views/caboose/orders_mailer/customer_status_updated.html.erb +1 -0
- data/app/views/caboose/orders_mailer/fulfillment_new_order.html.erb +1 -0
- data/app/views/caboose/orders_mailer/shipping_order_ready.html.erb +1 -0
- data/app/views/caboose/products/_admin_footer.html.erb +2 -0
- data/app/views/caboose/products/_admin_header.html.erb +32 -0
- data/app/views/caboose/products/_sort_options.html.erb +19 -0
- data/app/views/caboose/products/admin_add_upcs.html.erb +58 -0
- data/app/views/caboose/products/admin_delete_form.html.erb +21 -0
- data/app/views/caboose/products/admin_edit_categories.html.erb +73 -0
- data/app/views/caboose/products/admin_edit_category_images.html.erb +233 -0
- data/app/views/caboose/products/admin_edit_description.html.erb +38 -0
- data/app/views/caboose/products/admin_edit_general.html.erb +104 -0
- data/app/views/caboose/products/admin_edit_images.html.erb +236 -0
- data/app/views/caboose/products/admin_edit_options.html.erb +51 -0
- data/app/views/caboose/products/admin_edit_seo.html.erb +37 -0
- data/app/views/caboose/products/admin_edit_variant_columns.html.erb +75 -0
- data/app/views/caboose/products/admin_edit_variant_sort_order.html.erb +63 -0
- data/app/views/caboose/products/admin_edit_variants.html.erb +171 -0
- data/app/views/caboose/products/admin_edit_variants_single.html.erb +68 -0
- data/app/views/caboose/products/admin_group_variants.html.erb +433 -0
- data/app/views/caboose/products/admin_index.html.erb +95 -0
- data/app/views/caboose/products/admin_new.html.erb +41 -0
- data/app/views/caboose/products/admin_sort.html copy.erb +155 -0
- data/app/views/caboose/products/admin_sort.html.erb +254 -0
- data/app/views/caboose/products/details.html.erb +438 -0
- data/app/views/caboose/products/index.html.erb +46 -0
- data/app/views/caboose/products/not_available.html.erb +35 -0
- data/app/views/caboose/variants/admin_edit.html.erb +82 -0
- data/app/views/caboose/variants/admin_group.html.erb +184 -0
- data/app/views/caboose/variants/admin_new.html.erb +59 -0
- data/app/views/caboose/vendors/admin_edit.html.erb +24 -0
- data/app/views/caboose/vendors/admin_index.html.erb +30 -0
- data/app/views/caboose/vendors/admin_new.html.erb +34 -0
- data/app/views/layouts/caboose/store/_banner.html.erb +10 -0
- data/app/views/layouts/caboose/store/_banner2.html.erb +10 -0
- data/app/views/layouts/caboose/store/_footer.html.erb +55 -0
- data/app/views/layouts/caboose/store/_header.html.erb +69 -0
- data/app/views/layouts/caboose/store/_sidebar.html.erb +27 -0
- data/app/views/layouts/caboose/store/application.html.erb +33 -0
- data/app/views/layouts/caboose/store/authorize_net.erb +18 -0
- data/app/views/layouts/caboose/store/layout_about.html.erb +42 -0
- data/app/views/layouts/caboose/store/layout_blog.html.erb +159 -0
- data/app/views/layouts/caboose/store/layout_confirm.html.erb +85 -0
- data/app/views/layouts/caboose/store/layout_contact.html.erb +38 -0
- data/app/views/layouts/caboose/store/layout_default.html.erb +10 -0
- data/app/views/layouts/caboose/store/layout_detail.html.erb +114 -0
- data/app/views/layouts/caboose/store/layout_order.html.erb +77 -0
- data/app/views/layouts/caboose/store/layout_pricing.html.erb +182 -0
- data/app/views/layouts/caboose/store/layout_product.html.erb +110 -0
- data/app/views/layouts/caboose/store/layout_profile.html.erb +55 -0
- data/app/views/layouts/caboose/store/layout_single.html.erb +3 -0
- data/app/views/layouts/caboose/store/layout_testimonial.html.erb +110 -0
- data/app/views/layouts/caboose/store/layout_testing.html.erb +4 -0
- data/config/routes.rb +126 -0
- data/lib/caboose.rb +46 -1
- data/lib/caboose/engine.rb +39 -1
- data/lib/caboose/version.rb +1 -1
- data/lib/tasks/caboose.rake +12 -0
- metadata +151 -4
- data/app/assets/javascripts/caboose/admin_page_edit_content_bak.js +0 -164
- data/app/assets/javascripts/caboose/model/#Untitled-1# +0 -2
@@ -0,0 +1,75 @@
|
|
1
|
+
<%
|
2
|
+
p = @product
|
3
|
+
%>
|
4
|
+
<%= render :partial => 'caboose/products/admin_header' %>
|
5
|
+
|
6
|
+
<p class='note'>Check which columns you want to show in the list of variants.</p>
|
7
|
+
<table>
|
8
|
+
<tr>
|
9
|
+
<td valign='top'>
|
10
|
+
<div id='variantcol_1_option1' ></div>
|
11
|
+
<div id='variantcol_1_option2' ></div>
|
12
|
+
<div id='variantcol_1_option3' ></div>
|
13
|
+
</td><td valign='top'>
|
14
|
+
<div id='variantcol_1_status' ></div>
|
15
|
+
<div id='variantcol_1_sku' ></div>
|
16
|
+
<div id='variantcol_1_barcode' ></div>
|
17
|
+
<div id='variantcol_1_price' ></div>
|
18
|
+
<div id='variantcol_1_quantity_in_stock' ></div>
|
19
|
+
</td><td valign='top'>
|
20
|
+
<div id='variantcol_1_weight' ></div>
|
21
|
+
<div id='variantcol_1_length' ></div>
|
22
|
+
<div id='variantcol_1_width' ></div>
|
23
|
+
<div id='variantcol_1_height' ></div>
|
24
|
+
<div id='variantcol_1_cylinder' ></div>
|
25
|
+
</td><td valign='top'>
|
26
|
+
<div id='variantcol_1_requires_shipping' ></div>
|
27
|
+
<div id='variantcol_1_allow_backorder' ></div>
|
28
|
+
<div id='variantcol_1_taxable' ></div>
|
29
|
+
</td>
|
30
|
+
</tr>
|
31
|
+
</table>
|
32
|
+
<div id='message'></div>
|
33
|
+
<p><input type='button' value='< Back' onclick="window.location='/admin/products/<%= p.id %>/variants';" /></p>
|
34
|
+
|
35
|
+
<%= render :partial => 'caboose/products/admin_footer' %>
|
36
|
+
<% content_for :caboose_js do %>
|
37
|
+
<script type='text/javascript'>
|
38
|
+
|
39
|
+
$(document).ready(function() {
|
40
|
+
<% p.variants.each do |v| %>
|
41
|
+
new ModelBinder({
|
42
|
+
name: 'VariantCol',
|
43
|
+
id: 1,
|
44
|
+
update_url: '/admin/products/<%= p.id %>/variant-cols',
|
45
|
+
authenticity_token: '<%= form_authenticity_token %>',
|
46
|
+
attributes: [
|
47
|
+
<% if p.option1 %>{ name: 'option1' , nice_name: <%= raw Caboose.json(p.option1) %> , type: 'checkbox', align: 'right', value: <%= @cols['option1' ] == true ? true : false %>, width: 150 },<% end %>
|
48
|
+
<% if p.option2 %>{ name: 'option2' , nice_name: <%= raw Caboose.json(p.option2) %> , type: 'checkbox', align: 'right', value: <%= @cols['option1' ] == true ? true : false %>, width: 150 },<% end %>
|
49
|
+
<% if p.option3 %>{ name: 'option3' , nice_name: <%= raw Caboose.json(p.option3) %> , type: 'checkbox', align: 'right', value: <%= @cols['option1' ] == true ? true : false %>, width: 150 },<% end %>
|
50
|
+
{ name: 'status' , nice_name: 'Status' , type: 'checkbox', align: 'right', value: <%= @cols['status' ] == true ? true : false %>, width: 150 },
|
51
|
+
{ name: 'sku' , nice_name: 'SKU' , type: 'checkbox', align: 'right', value: <%= @cols['sku' ] == true ? true : false %>, width: 150 },
|
52
|
+
{ name: 'barcode' , nice_name: 'Barcode' , type: 'checkbox', align: 'right', value: <%= @cols['barcode' ] == true ? true : false %>, width: 150 },
|
53
|
+
{ name: 'price' , nice_name: 'Price' , type: 'checkbox', align: 'right', value: <%= @cols['price' ] == true ? true : false %>, width: 150 },
|
54
|
+
{ name: 'quantity_in_stock' , nice_name: 'Quantity' , type: 'checkbox', align: 'right', value: <%= @cols['quantity_in_stock'] == true ? true : false %>, width: 150 },
|
55
|
+
{ name: 'weight' , nice_name: 'Weight (grams)' , type: 'checkbox', align: 'right', value: <%= @cols['weight' ] == true ? true : false %>, width: 175 },
|
56
|
+
{ name: 'length' , nice_name: 'Length (in)' , type: 'checkbox', align: 'right', value: <%= @cols['length' ] == true ? true : false %>, width: 175 },
|
57
|
+
{ name: 'width' , nice_name: 'Width (in)' , type: 'checkbox', align: 'right', value: <%= @cols['width' ] == true ? true : false %>, width: 175 },
|
58
|
+
{ name: 'height' , nice_name: 'Height (in)' , type: 'checkbox', align: 'right', value: <%= @cols['height' ] == true ? true : false %>, width: 175 },
|
59
|
+
{ name: 'cylinder' , nice_name: 'Cylinder' , type: 'checkbox', align: 'right', value: <%= @cols['cylinder' ] == true ? true : false %>, width: 175 },
|
60
|
+
{ name: 'requires_shipping' , nice_name: 'Requires shipping' , type: 'checkbox', align: 'right', value: <%= @cols['requires_shipping'] == true ? true : false %>, width: 200 },
|
61
|
+
{ name: 'taxable' , nice_name: 'Taxable' , type: 'checkbox', align: 'right', value: <%= @cols['taxable' ] == true ? true : false %>, width: 200 },
|
62
|
+
{ name: 'allow_backorder' , nice_name: 'Allow backorder' , type: 'checkbox', align: 'right', value: <%= @cols['allow_backorder' ] == true ? true : false %>, width: 200 },
|
63
|
+
|
64
|
+
]
|
65
|
+
});
|
66
|
+
<% end %>
|
67
|
+
});
|
68
|
+
|
69
|
+
var modal = false;
|
70
|
+
$(window).load(function() {
|
71
|
+
modal = new CabooseModal(800);
|
72
|
+
});
|
73
|
+
|
74
|
+
</script>
|
75
|
+
<% end %>
|
@@ -0,0 +1,63 @@
|
|
1
|
+
<%
|
2
|
+
p = @product
|
3
|
+
%>
|
4
|
+
|
5
|
+
<%= render :partial => 'caboose/products/admin_header' %>
|
6
|
+
|
7
|
+
<div id='options'>
|
8
|
+
<% if p.option1 %><div id='option1_container'><h2><%= p.option1 %></h2><ul id='option1'><% p.option1_values.each do |option| %><li id='values_<%= option %>'><%= option %></li><% end %></ul></div><% end %>
|
9
|
+
<% if p.option2 %><div id='option2_container'><h2><%= p.option2 %></h2><ul id='option2'><% p.option2_values.each do |option| %><li id='values_<%= option %>'><%= option %></li><% end %></ul></div><% end %>
|
10
|
+
<% if p.option3 %><div id='option3_container'><h2><%= p.option3 %></h2><ul id='option3'><% p.option3_values.each do |option| %><li id='values_<%= option %>'><%= option %></li><% end %></ul></div><% end %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div id='message'></div>
|
14
|
+
|
15
|
+
<%= render :partial => 'caboose/products/admin_footer' %>
|
16
|
+
|
17
|
+
<% content_for :caboose_css do %>
|
18
|
+
<style type='text/css'>
|
19
|
+
#options div { width: 33%; float: left; }
|
20
|
+
#options ul { margin: 0 10px 0 0; padding: 0; list-style: none; }
|
21
|
+
#options li { margin: 0; padding: 4px 8px; list-style: none; border: #ccc 1px solid; }
|
22
|
+
#message { clear: left; }
|
23
|
+
</style>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<% content_for :caboose_js do %>
|
27
|
+
<script type='text/javascript'>
|
28
|
+
|
29
|
+
$(document).ready(function() {
|
30
|
+
$('#option1').sortable({
|
31
|
+
update: function(event, ui) {
|
32
|
+
$.ajax({
|
33
|
+
url: '/admin/products/<%= p.id %>/variants/option1-sort-order',
|
34
|
+
type: 'put',
|
35
|
+
data: $('#option1').sortable('serialize'),
|
36
|
+
success: function(resp) {}
|
37
|
+
});
|
38
|
+
}
|
39
|
+
});
|
40
|
+
$('#option2').sortable({
|
41
|
+
update: function(event, ui) {
|
42
|
+
$.ajax({
|
43
|
+
url: '/admin/products/<%= p.id %>/variants/option2-sort-order',
|
44
|
+
type: 'put',
|
45
|
+
data: $('#option2').sortable('serialize'),
|
46
|
+
success: function(resp) {}
|
47
|
+
});
|
48
|
+
}
|
49
|
+
});
|
50
|
+
$('#option3').sortable({
|
51
|
+
update: function(event, ui) {
|
52
|
+
$.ajax({
|
53
|
+
url: '/admin/products/<%= p.id %>/variants/option3-sort-order',
|
54
|
+
type: 'put',
|
55
|
+
data: $('#option3').sortable('serialize'),
|
56
|
+
success: function(resp) {}
|
57
|
+
});
|
58
|
+
}
|
59
|
+
});
|
60
|
+
});
|
61
|
+
|
62
|
+
</script>
|
63
|
+
<% end %>
|
@@ -0,0 +1,171 @@
|
|
1
|
+
<% content_for :caboose_css do %>
|
2
|
+
<style>
|
3
|
+
ul {
|
4
|
+
list-style-type: square;
|
5
|
+
padding: 0 0 0 24px;
|
6
|
+
margin: 12px 0 24px;
|
7
|
+
}
|
8
|
+
</style>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%
|
12
|
+
p = @product
|
13
|
+
v = @variant
|
14
|
+
%>
|
15
|
+
|
16
|
+
<%= render :partial => 'caboose/products/admin_header' %>
|
17
|
+
|
18
|
+
<p style='font-size: 75%;'><a href='/admin/products/<%= p.id %>/variant-cols'>Edit visible columns</a></p>
|
19
|
+
|
20
|
+
<div id='message'><%
|
21
|
+
# Make sure we're not trying to highlight a deleted variant
|
22
|
+
if @highlight_variant_id
|
23
|
+
v = Variant.where(:id => @highlight_variant_id).first
|
24
|
+
if v.nil?
|
25
|
+
%><p class='note error'>The variant you want to highlight is not in the database.</p><%
|
26
|
+
elsif v.status == 'Deleted'
|
27
|
+
%><p class='note error'>The variant you want to highlight has been deleted.</p><%
|
28
|
+
end
|
29
|
+
end
|
30
|
+
%></div>
|
31
|
+
|
32
|
+
<div id='variants_wrapper'>
|
33
|
+
<table id='variants'>
|
34
|
+
<tr>
|
35
|
+
<th> </th>
|
36
|
+
<% if @cols['option1' ] && p.option1 %><th valign='bottom'><%= p.option1 %></th><% end %>
|
37
|
+
<% if @cols['option2' ] && p.option2 %><th valign='bottom'><%= p.option2 %></th><% end %>
|
38
|
+
<% if @cols['option3' ] && p.option3 %><th valign='bottom'><%= p.option3 %></th><% end %>
|
39
|
+
<% if @cols['status' ] == true %><th valign='bottom'>Status </th><% end %>
|
40
|
+
<% if @cols['alternate_id' ] == true %><th valign='bottom'>Alternate ID </th><% end %>
|
41
|
+
<% if @cols['barcode' ] == true %><th valign='bottom'>Barcode </th><% end %>
|
42
|
+
<% if @cols['price' ] == true %><th valign='bottom'>Price </th><% end %>
|
43
|
+
<% if @cols['quantity_in_stock' ] == true %><th valign='bottom'>Quantity </th><% end %>
|
44
|
+
<% if @cols['weight' ] == true %><th valign='bottom'>Weight </th><% end %>
|
45
|
+
<% if @cols['length' ] == true %><th valign='bottom'>Length </th><% end %>
|
46
|
+
<% if @cols['width' ] == true %><th valign='bottom'>Width </th><% end %>
|
47
|
+
<% if @cols['height' ] == true %><th valign='bottom'>Height </th><% end %>
|
48
|
+
<% if @cols['cylinder' ] == true %><th valign='bottom'>Cylinder </th><% end %>
|
49
|
+
<% if @cols['requires_shipping' ] == true %><th valign='bottom'>Requires Shipping </th><% end %>
|
50
|
+
<% if @cols['allow_backorder' ] == true %><th valign='bottom'>Allow Backorder </th><% end %>
|
51
|
+
<% if @cols['taxable' ] == true %><th valign='bottom'>Taxable </th><% end %>
|
52
|
+
<th> </th>
|
53
|
+
<th> </th>
|
54
|
+
</tr>
|
55
|
+
<tbody id='variants_tbody'>
|
56
|
+
<% p.variants.where(:status => ['Active', 'Inactive']).each do |v| %>
|
57
|
+
<tr id='variant_<%= v.id %>' <% if @highlight_variant_id && v.id == @highlight_variant_id %>class='highlight'<% end %>>
|
58
|
+
<td class='sort_handle'> </td>
|
59
|
+
<% if @cols['option1' ] && p.option1 %><td><div id='variant_<%= v.id %>_option1' ></div></td><% end %>
|
60
|
+
<% if @cols['option2' ] && p.option2 %><td><div id='variant_<%= v.id %>_option2' ></div></td><% end %>
|
61
|
+
<% if @cols['option3' ] && p.option3 %><td><div id='variant_<%= v.id %>_option3' ></div></td><% end %>
|
62
|
+
<% if @cols['status' ] == true %><td><div id='variant_<%= v.id %>_status' ></div></td><% end %>
|
63
|
+
<% if @cols['alternate_id' ] == true %><td><div id='variant_<%= v.id %>_alternate_id' ></div></td><% end %>
|
64
|
+
<% if @cols['barcode' ] == true %><td><div id='variant_<%= v.id %>_barcode' ></div></td><% end %>
|
65
|
+
<% if @cols['price' ] == true %><td><div id='variant_<%= v.id %>_price' ></div></td><% end %>
|
66
|
+
<% if @cols['quantity_in_stock' ] == true %><td><div id='variant_<%= v.id %>_quantity_in_stock' ></div></td><% end %>
|
67
|
+
<% if @cols['weight' ] == true %><td><div id='variant_<%= v.id %>_weight' ></div></td><% end %>
|
68
|
+
<% if @cols['length' ] == true %><td><div id='variant_<%= v.id %>_length' ></div></td><% end %>
|
69
|
+
<% if @cols['width' ] == true %><td><div id='variant_<%= v.id %>_width' ></div></td><% end %>
|
70
|
+
<% if @cols['height' ] == true %><td><div id='variant_<%= v.id %>_height' ></div></td><% end %>
|
71
|
+
<% if @cols['cylinder' ] == true %><td><div id='variant_<%= v.id %>_cylinder' ></div></td><% end %>
|
72
|
+
<% if @cols['requires_shipping' ] == true %><td><div id='variant_<%= v.id %>_requires_shipping' ></div></td><% end %>
|
73
|
+
<% if @cols['allow_backorder' ] == true %><td><div id='variant_<%= v.id %>_allow_backorder' ></div></td><% end %>
|
74
|
+
<% if @cols['taxable' ] == true %><td><div id='variant_<%= v.id %>_taxable' ></div></td><% end %>
|
75
|
+
<td class='edit'><a href='/admin/products/<%= p.id %>/variants/<%= v.id %>/edit'>Edit</a></td>
|
76
|
+
<td class='delete'><a href='#' onclick='delete_variant(<%= v.id %>);'>Delete</a></td>
|
77
|
+
</tr>
|
78
|
+
<% end %>
|
79
|
+
</tbody>
|
80
|
+
</table>
|
81
|
+
</div>
|
82
|
+
|
83
|
+
<p><input type='button' value='New Variant' onclick="add_variant(<%= p.id %>);" /></p>
|
84
|
+
|
85
|
+
<form id="add-multiple" action="/admin/products/<%= @product.id %>/variants/add-multiple" method="post">
|
86
|
+
<p style="margin: 0 0 12px"><small>CSV format: Alternate ID, Quantity, Price<%= ', ' if @product.option1 || @product.option2 || @product.option3 %><%= [@product.option1, @product.option2, @product.option3].compact.join(', ') %></small></p>
|
87
|
+
<textarea id="variants_csv" name="variants_csv" rows="8" cols="12" style="min-width: 500px; min-height: 250px; margin: 0 0 16px; padding: 12px"></textarea><br />
|
88
|
+
<input type="submit" value="Submit" />
|
89
|
+
<p class="message" style="margin: 12px 0 0; color: red"></p>
|
90
|
+
</form>
|
91
|
+
|
92
|
+
<%= render :partial => 'caboose/products/admin_footer' %>
|
93
|
+
|
94
|
+
<% content_for :caboose_css do %>
|
95
|
+
<style type='text/css'>
|
96
|
+
tr.highlight td { background: #ffff99 }
|
97
|
+
td.sort_handle { background: #ccc; width: 20px; }
|
98
|
+
</style>
|
99
|
+
<% end %>
|
100
|
+
|
101
|
+
<% content_for :caboose_js do %>
|
102
|
+
<script type='text/javascript'>
|
103
|
+
|
104
|
+
$(document).ready(function() {
|
105
|
+
$('form#add-multiple').on('submit', function(event) {
|
106
|
+
event.preventDefault();
|
107
|
+
var $form = $(event.target);
|
108
|
+
|
109
|
+
$.ajax({
|
110
|
+
type: $form.attr('method'),
|
111
|
+
url: $form.attr('action'),
|
112
|
+
data: $form.serialize(),
|
113
|
+
success: function(response) {
|
114
|
+
console.log(response);
|
115
|
+
if (response.success) {
|
116
|
+
location.reload();
|
117
|
+
} else {
|
118
|
+
$form.find('.message').empty().text(response.error);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
});
|
122
|
+
});
|
123
|
+
|
124
|
+
<% p.variants.each do |v| %>
|
125
|
+
new ModelBinder({
|
126
|
+
name: 'Variant',
|
127
|
+
id: <%= v.id %>,
|
128
|
+
update_url: '/admin/variants/<%= v.id %>',
|
129
|
+
authenticity_token: '<%= form_authenticity_token %>',
|
130
|
+
attributes: [
|
131
|
+
<% if @cols['option1' ] && p.option1 %>{ name: 'option1' , nice_name: <%= raw Caboose.json(p.option1) %> , type: 'text' , align: 'left' , value: <%= raw Caboose.json(v.option1 ) %>, width: 75, fixed_placeholder: false },<% end %>
|
132
|
+
<% if @cols['option2' ] && p.option2 %>{ name: 'option2' , nice_name: <%= raw Caboose.json(p.option2) %> , type: 'text' , align: 'left' , value: <%= raw Caboose.json(v.option2 ) %>, width: 75, fixed_placeholder: false },<% end %>
|
133
|
+
<% if @cols['option3' ] && p.option3 %>{ name: 'option3' , nice_name: <%= raw Caboose.json(p.option3) %> , type: 'text' , align: 'left' , value: <%= raw Caboose.json(v.option3 ) %>, width: 75, fixed_placeholder: false },<% end %>
|
134
|
+
<% if @cols['status' ] == true %>{ name: 'status' , nice_name: 'Status' , type: 'text' , align: 'left' , value: <%= raw Caboose.json(v.status ) %>, width: 75, fixed_placeholder: false },<% end %>
|
135
|
+
<% if @cols['alternate_id' ] == true %>{ name: 'alternate_id' , nice_name: 'Alternate ID' , type: 'text' , align: 'left' , value: <%= raw Caboose.json(v.alternate_id ) %>, width: 75, fixed_placeholder: false },<% end %>
|
136
|
+
<% if @cols['sku' ] == true %>{ name: 'sku' , nice_name: 'SKU' , type: 'text' , align: 'left' , value: <%= raw Caboose.json(v.sku ) %>, width: 75, fixed_placeholder: false },<% end %>
|
137
|
+
<% if @cols['barcode' ] == true %>{ name: 'barcode' , nice_name: 'Barcode' , type: 'text' , align: 'left' , value: <%= raw Caboose.json(v.barcode ) %>, width: 75, fixed_placeholder: false },<% end %>
|
138
|
+
<% if @cols['price' ] == true %>{ name: 'price' , nice_name: 'Price' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.price ) %>, width: 75, fixed_placeholder: false },<% end %>
|
139
|
+
<% if @cols['quantity_in_stock' ] == true %>{ name: 'quantity_in_stock' , nice_name: 'Quantity' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.quantity_in_stock ) %>, width: 50, fixed_placeholder: false },<% end %>
|
140
|
+
<% if @cols['weight' ] == true %>{ name: 'weight' , nice_name: 'Weight (grams)' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.weight ) %>, width: 50, fixed_placeholder: false },<% end %>
|
141
|
+
<% if @cols['length' ] == true %>{ name: 'length' , nice_name: 'Length (in)' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.length ) %>, width: 50, fixed_placeholder: false },<% end %>
|
142
|
+
<% if @cols['width' ] == true %>{ name: 'width' , nice_name: 'Width (in)' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.width ) %>, width: 50, fixed_placeholder: false },<% end %>
|
143
|
+
<% if @cols['height' ] == true %>{ name: 'height' , nice_name: 'Height (in)' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.height ) %>, width: 50, fixed_placeholder: false },<% end %>
|
144
|
+
<% if @cols['cylinder' ] == true %>{ name: 'cylinder' , nice_name: 'Cylinder' , type: 'checkbox' , align: 'center', value: <%= raw Caboose.json(v.cylinder ) %>, width: 50, fixed_placeholder: false },<% end %>
|
145
|
+
<% if @cols['requires_shipping' ] == true %>{ name: 'requires_shipping' , nice_name: 'Requires shipping' , type: 'checkbox' , align: 'center', value: <%= raw Caboose.json(v.requires_shipping ) %>, width: 50, fixed_placeholder: false },<% end %>
|
146
|
+
<% if @cols['taxable' ] == true %>{ name: 'taxable' , nice_name: 'Taxable' , type: 'checkbox' , align: 'center', value: <%= raw Caboose.json(v.taxable ) %>, width: 50, fixed_placeholder: false },<% end %>
|
147
|
+
<% if @cols['allow_backorder' ] == true %>{ name: 'allow_backorder' , nice_name: 'Allow backorder' , type: 'checkbox' , align: 'center', value: <%= raw Caboose.json(v.allow_backorder ) %>, width: 50, fixed_placeholder: false } <% end %>
|
148
|
+
]
|
149
|
+
});
|
150
|
+
<% end %>
|
151
|
+
|
152
|
+
$('#variants_tbody').sortable({
|
153
|
+
handle: '.sort_handle',
|
154
|
+
update: function(event, ui) {
|
155
|
+
$.ajax({
|
156
|
+
url: '/admin/products/<%= p.id %>/variants/sort-order',
|
157
|
+
type: 'put',
|
158
|
+
data: $('#variants_tbody').sortable('serialize', { key: 'variant_ids[]' }),
|
159
|
+
success: function(resp) {}
|
160
|
+
});
|
161
|
+
}
|
162
|
+
});
|
163
|
+
});
|
164
|
+
|
165
|
+
var modal = false;
|
166
|
+
$(window).load(function() {
|
167
|
+
modal = new CabooseModal('100%');
|
168
|
+
});
|
169
|
+
|
170
|
+
</script>
|
171
|
+
<% end %>
|
@@ -0,0 +1,68 @@
|
|
1
|
+
<%
|
2
|
+
p = @product
|
3
|
+
v = @variant
|
4
|
+
%>
|
5
|
+
<%= render :partial => 'caboose/products/admin_header' %>
|
6
|
+
|
7
|
+
<p style='font-size: 75%;'><a href='/admin/products/<%= p.id %>/options'>Need options like color or size?</a></p>
|
8
|
+
|
9
|
+
<table>
|
10
|
+
<tr>
|
11
|
+
<td valign='top'>
|
12
|
+
<div id='variant_<%= v.id %>_alternate_id' ></div>
|
13
|
+
<div id='variant_<%= v.id %>_sku' ></div>
|
14
|
+
<div id='variant_<%= v.id %>_barcode' ></div>
|
15
|
+
<div id='variant_<%= v.id %>_price' ></div>
|
16
|
+
<div id='variant_<%= v.id %>_quantity_in_stock' ></div>
|
17
|
+
<div id='variant_<%= v.id %>_allow_backorder' ></div>
|
18
|
+
<div id='variant_<%= v.id %>_taxable' ></div>
|
19
|
+
</td><td valign='top'>
|
20
|
+
<div id='variant_<%= v.id %>_status' ></div>
|
21
|
+
<div id='variant_<%= v.id %>_requires_shipping' ></div>
|
22
|
+
<div id='variant_<%= v.id %>_weight' ></div>
|
23
|
+
<div id='variant_<%= v.id %>_cylinder' ></div>
|
24
|
+
<div id='variant_<%= v.id %>_length' ></div>
|
25
|
+
<div id='variant_<%= v.id %>_width' ></div>
|
26
|
+
<div id='variant_<%= v.id %>_height' ></div>
|
27
|
+
</td>
|
28
|
+
</tr>
|
29
|
+
</table>
|
30
|
+
<div id='message'></div>
|
31
|
+
|
32
|
+
<%= render :partial => 'caboose/products/admin_footer' %>
|
33
|
+
|
34
|
+
<% content_for :caboose_js do %>
|
35
|
+
<script type='text/javascript'>
|
36
|
+
|
37
|
+
$(document).ready(function() {
|
38
|
+
m = new ModelBinder({
|
39
|
+
name: 'Variant',
|
40
|
+
id: <%= v.id %>,
|
41
|
+
update_url: '/admin/variants/<%= v.id %>',
|
42
|
+
authenticity_token: '<%= form_authenticity_token %>',
|
43
|
+
attributes: [
|
44
|
+
{ name: 'status' , nice_name: 'Status' , type: 'select' , align: 'right' , value: <%= raw Caboose.json(v.status ) %>, text: <%= raw Caboose.json(v.status) %>, width: 250, options_url: '/admin/variants/status-options' },
|
45
|
+
{ name: 'alternate_id' , nice_name: 'Alternate ID' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.alternate_id ) %>, width: 250 },
|
46
|
+
{ name: 'sku' , nice_name: 'SKU' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.sku ) %>, width: 250 },
|
47
|
+
{ name: 'barcode' , nice_name: 'Barcode' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.barcode ) %>, width: 250 },
|
48
|
+
{ name: 'price' , nice_name: 'Price' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(sprintf("%.2f", v.price || 0 ) ) %>, width: 250 },
|
49
|
+
{ name: 'quantity_in_stock' , nice_name: 'Quantity' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.quantity_in_stock ) %>, width: 250 },
|
50
|
+
{ name: 'weight' , nice_name: 'Weight (grams)' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.weight ) %>, width: 250 },
|
51
|
+
{ name: 'length' , nice_name: 'Length (in)' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.length ) %>, width: 250 },
|
52
|
+
{ name: 'width' , nice_name: 'Width (in)' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.width ) %>, width: 250 },
|
53
|
+
{ name: 'height' , nice_name: 'Height (in)' , type: 'text' , align: 'right' , value: <%= raw Caboose.json(v.height ) %>, width: 250 },
|
54
|
+
{ name: 'cylinder' , nice_name: 'Cylinder' , type: 'checkbox' , align: 'right' , value: <%= raw Caboose.json(v.cylinder ) %>, width: 250 },
|
55
|
+
{ name: 'requires_shipping' , nice_name: 'Requires shipping' , type: 'checkbox' , align: 'right' , value: <%= raw Caboose.json(v.requires_shipping ) %>, width: 250 },
|
56
|
+
{ name: 'taxable' , nice_name: 'Taxable' , type: 'checkbox' , align: 'right' , value: <%= raw Caboose.json(v.taxable ) %>, width: 250 },
|
57
|
+
{ name: 'allow_backorder' , nice_name: 'Allow backorder' , type: 'checkbox' , align: 'right' , value: <%= raw Caboose.json(v.allow_backorder ) %>, width: 250 }
|
58
|
+
]
|
59
|
+
});
|
60
|
+
});
|
61
|
+
|
62
|
+
var modal = false;
|
63
|
+
$(window).load(function() {
|
64
|
+
modal = new CabooseModal(800);
|
65
|
+
});
|
66
|
+
|
67
|
+
</script>
|
68
|
+
<% end %>
|
@@ -0,0 +1,433 @@
|
|
1
|
+
<% content_for :caboose_css do %>
|
2
|
+
<style>
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Sidebar
|
6
|
+
*/
|
7
|
+
|
8
|
+
.sidebar { padding: 0 12px; }
|
9
|
+
.sidebar, .sidebar > section { overflow: hidden; }
|
10
|
+
|
11
|
+
.sidebar > aside {
|
12
|
+
float: left;
|
13
|
+
margin-right: 12px;
|
14
|
+
width: 300px;
|
15
|
+
}
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Media
|
19
|
+
*/
|
20
|
+
|
21
|
+
.media, .media > section { overflow: hidden; }
|
22
|
+
|
23
|
+
.media > aside {
|
24
|
+
float: left;
|
25
|
+
margin-right: 6px;
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Forms
|
30
|
+
*/
|
31
|
+
|
32
|
+
form { overflow: hidden; }
|
33
|
+
form *, button { outline: none !important; }
|
34
|
+
button { cursor: pointer; }
|
35
|
+
|
36
|
+
/* filters */
|
37
|
+
|
38
|
+
form#filters { display: none; }
|
39
|
+
|
40
|
+
form#filters fieldset {
|
41
|
+
border: none;
|
42
|
+
margin: 12px 0;
|
43
|
+
padding: 0;
|
44
|
+
}
|
45
|
+
|
46
|
+
form#filters select {
|
47
|
+
height: 350px;
|
48
|
+
padding: 6px;
|
49
|
+
}
|
50
|
+
|
51
|
+
form#filters label,
|
52
|
+
form#filters input[type=text],
|
53
|
+
form#filters select {
|
54
|
+
box-sizing: border-box;
|
55
|
+
display: block;
|
56
|
+
width: 100%;
|
57
|
+
}
|
58
|
+
|
59
|
+
form#filters label + input,
|
60
|
+
form#filters input + label,
|
61
|
+
form#filters label + select,
|
62
|
+
form#filters select + label { margin: 12px 0 0; }
|
63
|
+
|
64
|
+
input#category-filter,
|
65
|
+
input#vendor-filter { border-bottom: none; }
|
66
|
+
|
67
|
+
/*select#categories.filtered option { display: none; }
|
68
|
+
select#categories.filtered option.show { display: block; }*/
|
69
|
+
|
70
|
+
/* variants */
|
71
|
+
|
72
|
+
form#variants fieldset {
|
73
|
+
border: none;
|
74
|
+
margin: 0;
|
75
|
+
padding: 0;
|
76
|
+
}
|
77
|
+
form#variants fieldset + fieldset { margin: 24px 0 0; }
|
78
|
+
|
79
|
+
form#variants label {
|
80
|
+
background: #eee;
|
81
|
+
display: block;
|
82
|
+
margin: 0 0 12px;
|
83
|
+
padding: 12px;
|
84
|
+
}
|
85
|
+
form#variants label,
|
86
|
+
form#variants label * { cursor: pointer; }
|
87
|
+
|
88
|
+
form#variants input[type=checkbox] {
|
89
|
+
height: 16px;
|
90
|
+
left: auto;
|
91
|
+
position: relative;
|
92
|
+
top: auto;
|
93
|
+
}
|
94
|
+
|
95
|
+
form#variants ul.info {
|
96
|
+
font-size: 12px;
|
97
|
+
list-style-type: none;
|
98
|
+
padding: 0 0 0 12px;
|
99
|
+
}
|
100
|
+
|
101
|
+
form#variants ul.info li { margin: 0 0 6px; }
|
102
|
+
|
103
|
+
</style>
|
104
|
+
<% end %>
|
105
|
+
|
106
|
+
<%= render partial: 'caboose/products/admin_header' %>
|
107
|
+
|
108
|
+
<button id="toggle-filters">Toggle Filters</button>
|
109
|
+
<button id="toggle-info">Toggle Variant Info</button>
|
110
|
+
|
111
|
+
<div class="sidebar">
|
112
|
+
<aside>
|
113
|
+
<form id="filters" action="/admin/products/<%= @product.id %>/variants/group" method="get">
|
114
|
+
<h4><label for="title">Title</label></h4>
|
115
|
+
<input id="title" name="title" type="text" />
|
116
|
+
|
117
|
+
<h4><label for="categories">Categories</label></h4>
|
118
|
+
<input id="category-filter" type="text" autocomplete="off" />
|
119
|
+
<select id="categories" name="category_ids[]" multiple>
|
120
|
+
|
121
|
+
<% @categories.each do |category| %>
|
122
|
+
<option value="<%= category.id %>"
|
123
|
+
<%= 'selected="selected"' if params[:category_ids] and params[:category_ids].include?(category.id.to_s) %>
|
124
|
+
><%= category.url.gsub('/products/', '') %></option>
|
125
|
+
<% end %>
|
126
|
+
</select>
|
127
|
+
|
128
|
+
<h4><label for="vendors">Vendors</label><h4>
|
129
|
+
<input id="vendor-filter" type="text" autocomplete="off" />
|
130
|
+
<select id="vendors" name="vendor_ids[]" multiple>
|
131
|
+
<% @vendors.each do |vendor| %>
|
132
|
+
<option value="<%= vendor.id %>"
|
133
|
+
<%= 'selected="selected"' if params[:vendor_ids] and params[:vendor_ids].include?(vendor.id.to_s) %>
|
134
|
+
><%= vendor.name %></option>
|
135
|
+
<% end %>
|
136
|
+
</select>
|
137
|
+
|
138
|
+
<fieldset>
|
139
|
+
<input id="clear" type="button" value="Clear" />
|
140
|
+
<input type="submit" value="Filter" />
|
141
|
+
</fieldset>
|
142
|
+
</form>
|
143
|
+
</aside>
|
144
|
+
|
145
|
+
<section>
|
146
|
+
<h4>Variants</h4>
|
147
|
+
|
148
|
+
<% if @variants.any? %>
|
149
|
+
<form id="variants" action="/admin/products/<%= @product.id %>/variants/add" method="post" data-product-id="<%= @product.id %>">
|
150
|
+
<fieldset>
|
151
|
+
<input class="remove" type="button" value="Remove these variants" />
|
152
|
+
<input class="check" type="button" value="Toggle Variants" />
|
153
|
+
<input type="submit" value="Add To Product" />
|
154
|
+
</fieldset>
|
155
|
+
|
156
|
+
<fieldset>
|
157
|
+
<% @variants.each do |variant| %>
|
158
|
+
<label>
|
159
|
+
<div class="media">
|
160
|
+
<aside><input name="variant_ids[]" type="checkbox" value="<%= variant.id %>" /></aside>
|
161
|
+
|
162
|
+
<section>
|
163
|
+
<%= variant.product.title %>
|
164
|
+
|
165
|
+
<ul class="info">
|
166
|
+
<li><strong>SKU:</strong> <%= variant.sku %></li>
|
167
|
+
<li><strong>Vendor:</strong> <%= variant.product.vendor.name %></li>
|
168
|
+
|
169
|
+
<% if variant.option1 %>
|
170
|
+
<li><strong><%= variant.product.option1 %>:</strong> <%= variant.option1 %></li>
|
171
|
+
<% end %>
|
172
|
+
|
173
|
+
<% if variant.option2 %>
|
174
|
+
<li><strong><%= variant.product.option2 %>:</strong> <%= variant.option2 %></li>
|
175
|
+
<% end %>
|
176
|
+
|
177
|
+
<% if variant.option3 %>
|
178
|
+
<li><strong><%= variant.product.option3 %>:</strong> <%= variant.option3 %></li>
|
179
|
+
<% end %>
|
180
|
+
</ul>
|
181
|
+
</section>
|
182
|
+
</div>
|
183
|
+
</label>
|
184
|
+
<% end %>
|
185
|
+
</fieldset>
|
186
|
+
|
187
|
+
<fieldset>
|
188
|
+
<input class="remove" type="button" value="Remove these variants" />
|
189
|
+
<input class="check" type="button" value="Toggle Variants" />
|
190
|
+
<input type="submit" value="Add To Product" />
|
191
|
+
</fieldset>
|
192
|
+
</form>
|
193
|
+
<% else %>
|
194
|
+
<p>No variants to show.</p>
|
195
|
+
<% end %>
|
196
|
+
</section>
|
197
|
+
</div>
|
198
|
+
|
199
|
+
<%= render partial: 'caboose/products/admin_footer' %>
|
200
|
+
|
201
|
+
<% content_for :caboose_js do %>
|
202
|
+
<%= javascript_include_tag 'underscore' %>
|
203
|
+
|
204
|
+
<script>
|
205
|
+
window.count = <%= @variants.count %>;
|
206
|
+
|
207
|
+
// Define categories
|
208
|
+
window.categories = <%= @categories.collect { |category|
|
209
|
+
{ id: category.id.to_s, url: category.url.gsub('/products/', ''), selected: false }
|
210
|
+
}.compact.to_json.html_safe %>;
|
211
|
+
|
212
|
+
// Define vendors
|
213
|
+
window.vendors = <%= @vendors.collect { |vendor|
|
214
|
+
{ id: vendor.id.to_s, name: vendor.name, selected: false }
|
215
|
+
}.compact.to_json.html_safe %>;
|
216
|
+
|
217
|
+
$(document).ready(function() {
|
218
|
+
|
219
|
+
// Events
|
220
|
+
$('form#variants').on('submit', check_for_variants);
|
221
|
+
$('button#toggle-filters').on('click', toggle_filters);
|
222
|
+
$(document).on('click', '#categories option', persist_categories);
|
223
|
+
$(document).on('click', '#vendors option', persist_vendors);
|
224
|
+
$('input#category-filter').on('keyup', filter_categories);
|
225
|
+
$('input#vendor-filter').on('keyup', filter_vendors);
|
226
|
+
$('form#filters input#clear').on('click', clear_filters);
|
227
|
+
$('button#toggle-info').on('click', toggle_variant_info);
|
228
|
+
$('form#variants input.remove').on('click', remove_variants);
|
229
|
+
$('form#variants input.check').on('click', toggle_variants);
|
230
|
+
|
231
|
+
// Show filters if there are no variants
|
232
|
+
if (window.count == 0) toggle_filters();
|
233
|
+
|
234
|
+
// Check for filters to persist initially
|
235
|
+
|
236
|
+
$('#categories option:selected').each(function(value, option) {
|
237
|
+
window.categories[ _.indexOf(_.pluck(window.categories, 'id'), $(this).val()) ].selected = true;
|
238
|
+
});
|
239
|
+
|
240
|
+
$('#vendors option:selected').each(function(value, option) {
|
241
|
+
window.vendors[ _.indexOf(_.pluck(window.vendors, 'id'), $(this).val()) ].selected = true;
|
242
|
+
});
|
243
|
+
});
|
244
|
+
|
245
|
+
// submit form#variants
|
246
|
+
function check_for_variants(event) {
|
247
|
+
event.preventDefault();
|
248
|
+
|
249
|
+
var $form = $('form#variants');
|
250
|
+
|
251
|
+
if ($('input:checked', $form).length) {
|
252
|
+
$form.off('submit').submit();
|
253
|
+
} else {
|
254
|
+
alert('No variants selected');
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
// click button#toggle
|
259
|
+
function toggle_filters() {
|
260
|
+
$('form#filters').toggle();
|
261
|
+
}
|
262
|
+
|
263
|
+
// click #categories option
|
264
|
+
function persist_categories() {
|
265
|
+
var selected_ids = _.map($('#categories option:selected'), function(option) { return option.value })
|
266
|
+
, persisted_categories = _.where(window.categories, {selected: true})
|
267
|
+
, clicked_id = $(this).val()
|
268
|
+
, clicked_selected = $(this).prop('selected');
|
269
|
+
|
270
|
+
// Make sure the clicked_id is in the selected_ids selected or no
|
271
|
+
// It will be disabled if the selected status is false
|
272
|
+
if (!_.contains(selected_ids, clicked_id)) selected_ids.push(clicked_id);
|
273
|
+
|
274
|
+
// Set the selected status
|
275
|
+
_.each(persisted_categories, function(category) {
|
276
|
+
|
277
|
+
// Only change the selected status if it's listed on the page; for usability
|
278
|
+
if ($('#categories option[value=' + category.id + ']').length) {
|
279
|
+
category.selected = _.contains(selected_ids, category.id);
|
280
|
+
}
|
281
|
+
});
|
282
|
+
|
283
|
+
// For each selected ID set the selected status
|
284
|
+
_.each(selected_ids, function(id) {
|
285
|
+
var selected = id == clicked_id ? clicked_selected : true;
|
286
|
+
window.categories[ _.indexOf(_.pluck(window.categories, 'id'), id) ].selected = selected;
|
287
|
+
});
|
288
|
+
}
|
289
|
+
|
290
|
+
// click #vendors option
|
291
|
+
function persist_vendors() {
|
292
|
+
var selected_ids = _.map($('#vendors option:selected'), function(option) { return option.value })
|
293
|
+
, persisted_vendors = _.where(window.vendors, {selected: true})
|
294
|
+
, clicked_id = $(this).val()
|
295
|
+
, clicked_selected = $(this).prop('selected');
|
296
|
+
|
297
|
+
// Make sure the clicked_id is in the selected_ids selected or no
|
298
|
+
// It will be disabled if the selected status is false
|
299
|
+
if (!_.contains(selected_ids, clicked_id)) selected_ids.push(clicked_id);
|
300
|
+
|
301
|
+
// Set the selected status
|
302
|
+
_.each(persisted_vendors, function(vendor) {
|
303
|
+
|
304
|
+
// Only change the selected status if it's listed on the page; for usability
|
305
|
+
if ($('#vendors option[value=' + vendor.id + ']').length) {
|
306
|
+
vendor.selected = _.contains(selected_ids, vendor.id);
|
307
|
+
}
|
308
|
+
});
|
309
|
+
|
310
|
+
// For each selected ID set the selected status
|
311
|
+
_.each(selected_ids, function(id) {
|
312
|
+
var selected = id == clicked_id ? clicked_selected : true;
|
313
|
+
window.vendors[ _.indexOf(_.pluck(window.vendors, 'id'), id) ].selected = selected;
|
314
|
+
});
|
315
|
+
}
|
316
|
+
|
317
|
+
// keyup #category-filter
|
318
|
+
function filter_categories() {
|
319
|
+
var $categories = $('#categories');
|
320
|
+
|
321
|
+
// Get value to test against from input
|
322
|
+
var string = $('#category-filter').val().toLowerCase();
|
323
|
+
|
324
|
+
// Filter category names
|
325
|
+
var filtered_categories = _.filter(window.categories, function(category) {
|
326
|
+
return category.url.toLowerCase().indexOf(string) != -1;
|
327
|
+
});
|
328
|
+
|
329
|
+
// Empty category select box
|
330
|
+
$categories.empty();
|
331
|
+
|
332
|
+
// Append filtered category names
|
333
|
+
_.each(filtered_categories, function(category) {
|
334
|
+
var $option = $('<option/>');
|
335
|
+
|
336
|
+
// Add value and text
|
337
|
+
$option.val(category.id);
|
338
|
+
$option.text(category.url);
|
339
|
+
|
340
|
+
// Mark as selected if it was persisted
|
341
|
+
if (category.selected) $option.attr('selected', 'selected');
|
342
|
+
|
343
|
+
// Append to container
|
344
|
+
$categories.append($option);
|
345
|
+
});
|
346
|
+
}
|
347
|
+
|
348
|
+
// keyup #vendor-filter
|
349
|
+
function filter_vendors() {
|
350
|
+
var $vendors = $('#vendors');
|
351
|
+
|
352
|
+
// Get value to test against from input
|
353
|
+
var string = $('#vendor-filter').val().toLowerCase();
|
354
|
+
|
355
|
+
// Filter category names
|
356
|
+
var filtered_vendors = _.filter(window.vendors, function(vendor) {
|
357
|
+
return vendor.name.toLowerCase().indexOf(string) != -1;
|
358
|
+
});
|
359
|
+
|
360
|
+
// Empty category select box
|
361
|
+
$vendors.empty();
|
362
|
+
|
363
|
+
// Append filtered category names
|
364
|
+
_.each(filtered_vendors, function(vendor) {
|
365
|
+
var $option = $('<option/>');
|
366
|
+
|
367
|
+
// Add value and text
|
368
|
+
$option.val(vendor.id);
|
369
|
+
$option.text(vendor.name);
|
370
|
+
|
371
|
+
// Mark as selected if it was persisted
|
372
|
+
if (vendor.selected) $option.attr('selected', 'selected');
|
373
|
+
|
374
|
+
// Append to container
|
375
|
+
$vendors.append($option);
|
376
|
+
});
|
377
|
+
}
|
378
|
+
|
379
|
+
// form#filters input#clear
|
380
|
+
function clear_filters() {
|
381
|
+
var $filters = $('form#fitlers');
|
382
|
+
|
383
|
+
// Clear all textboxes
|
384
|
+
$('form#filters input[type=text]').val('');
|
385
|
+
|
386
|
+
// Clear all selects
|
387
|
+
$('form#filters option:selected').removeAttr('selected');
|
388
|
+
|
389
|
+
// Clear persisted options
|
390
|
+
_.each(window.categories, function(category) { category.selected = false });
|
391
|
+
_.each(window.vendors, function(vendor) { vendor.selected = false });
|
392
|
+
}
|
393
|
+
|
394
|
+
// click button#toggle-info
|
395
|
+
function toggle_variant_info() {
|
396
|
+
$('ul.info').toggle();
|
397
|
+
}
|
398
|
+
|
399
|
+
// click form#variants input.check
|
400
|
+
function toggle_variants() {
|
401
|
+
var $variants = $('form#variants input[type=checkbox]:checked');
|
402
|
+
|
403
|
+
// If there are checked checkboxes, uncheck them; Otherwise, check everything
|
404
|
+
if ($variants.length > 0) {
|
405
|
+
$variants.prop('checked', false)
|
406
|
+
} else {
|
407
|
+
$('form#variants input[type=checkbox]').prop('checked', true);
|
408
|
+
}
|
409
|
+
}
|
410
|
+
|
411
|
+
// click form#variants input.remove
|
412
|
+
function remove_variants() {
|
413
|
+
var confirmed = confirm('Are you sure you want remove these items?');
|
414
|
+
|
415
|
+
if (confirmed) {
|
416
|
+
var $variants = $('form#variants input[type=checkbox]:checked');
|
417
|
+
|
418
|
+
if ($variants.length > 0) {
|
419
|
+
$.ajax({
|
420
|
+
type: 'post',
|
421
|
+
url: '/admin/products/' + $('form#variants').data('product-id') + '/variants/remove',
|
422
|
+
data: $('form#variants').serialize(),
|
423
|
+
success: function(response) {
|
424
|
+
console.log('foobar');
|
425
|
+
}
|
426
|
+
})
|
427
|
+
} else {
|
428
|
+
alert('No variants selected');
|
429
|
+
}
|
430
|
+
}
|
431
|
+
}
|
432
|
+
</script>
|
433
|
+
<% end %>
|