spree_variant_options 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +54 -40
- data/Versionfile +1 -0
- data/app/assets/javascripts/store/product_variant_options.js +24 -0
- data/app/assets/javascripts/store/variant_options.js +2 -1
- data/app/assets/stylesheets/store/{variant_options.css → variant_options.css.erb} +1 -6
- data/app/controllers/spree/admin/option_values_controller.rb +18 -0
- data/app/models/option_value_decorator.rb +1 -1
- data/app/models/product_decorator.rb +1 -1
- data/app/overrides/spree_variant_options.rb +26 -5
- data/app/views/spree/admin/option_types/_option_value_fields.html.erb +7 -0
- data/app/views/spree/admin/option_values/_table_header.html.erb +7 -0
- data/app/views/{products → spree/products}/_variant_options.html.erb +2 -7
- data/config/routes.rb +4 -6
- data/db/migrate/20120213174249_add_image_to_option_values.rb +8 -0
- data/features/{admin_option_types.feature → spree/admin/option_types.feature} +0 -0
- data/features/{variant_options.feature → spree/variant_options.feature} +0 -0
- data/features/step_definitions/option_values.rb +8 -8
- data/features/step_definitions/variant_options.rb +6 -5
- data/features/step_definitions/web_steps.rb +36 -10
- data/features/support/env.rb +4 -6
- data/lib/generators/spree_variant_options/install_generator.rb +9 -26
- data/lib/spree_variant_options.rb +5 -21
- data/lib/spree_variant_options/engine.rb +19 -0
- data/lib/spree_variant_options/version.rb +1 -1
- data/spree_variant_options.gemspec +3 -3
- data/test/dummy_hooks/before_migrate.rb +16 -10
- data/test/dummy_hooks/templates/spree_user_error_fix.rb +3 -0
- data/test/dummy_hooks/templates/store/screen.css +749 -0
- data/test/support/factories.rb +8 -8
- data/test/support/user_fix.rb +5 -0
- data/test/test_helper.rb +1 -2
- data/test/unit/{option_value_test.rb → spree/option_value_test.rb} +4 -4
- data/test/unit/{product_test.rb → spree/product_test.rb} +1 -1
- metadata +45 -38
- data/app/assets/javascripts/store/product.js +0 -38
- data/app/controllers/admin/option_values_controller.rb +0 -14
- data/app/views/admin/option_types/_option_value_fields.html.erb +0 -8
- data/app/views/admin/option_types/edit.html.erb +0 -33
- data/lib/generators/templates/db/migrate/add_image_to_option_values.rb +0 -14
data/README.md
CHANGED
@@ -5,93 +5,107 @@ Spree Variant Options is a very simple spree extension that replaces the radio-b
|
|
5
5
|
|
6
6
|
|
7
7
|
#### When no selection has been made:
|
8
|
-
![Spree Variant Options - No selection](http://spree-docs.s3.amazonaws.com/spree_variant_options/1.jpg)
|
8
|
+
![Spree Variant Options - No selection](http://spree-docs.s3.amazonaws.com/spree_variant_options/v0.3.1/1.jpg)
|
9
9
|
|
10
|
-
#### After "
|
10
|
+
#### After "Large" is selected, "Large Blue" is out of stock:
|
11
11
|
|
12
|
-
![Spree Variant Options - Option Type/Value selected](http://spree-docs.s3.amazonaws.com/spree_variant_options/2.jpg)
|
12
|
+
![Spree Variant Options - Option Type/Value selected](http://spree-docs.s3.amazonaws.com/spree_variant_options/v0.3.1/2.jpg)
|
13
13
|
|
14
14
|
#### And after "Green" is selected:
|
15
|
-
![Spree Variant Options - Variant Selcted](http://spree-docs.s3.amazonaws.com/spree_variant_options/3.jpg)
|
15
|
+
![Spree Variant Options - Variant Selcted](http://spree-docs.s3.amazonaws.com/spree_variant_options/v0.3.1/3.jpg)
|
16
16
|
|
17
17
|
To see it in action, follow the steps for "Demo" below.
|
18
18
|
|
19
19
|
|
20
|
+
------------------------------------------------------------------------------
|
20
21
|
Installation
|
21
|
-
|
22
|
+
------------------------------------------------------------------------------
|
22
23
|
|
23
24
|
If you don't already have an existing Spree site, [click here](https://gist.github.com/946719) then come back later... You can also read the Spree docs [here](http://spreecommerce.com/documentation/getting_started.html)...
|
24
25
|
|
25
26
|
To install Spree Variant Options, just add the following to your Gemfile:
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
```ruby
|
29
|
+
gem 'spree_variant_options', '0.3.1'
|
30
|
+
```
|
29
31
|
|
30
32
|
Now, bundle up with:
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
+
```bash
|
35
|
+
bundle
|
36
|
+
```
|
34
37
|
|
35
38
|
Next, run the install generator to copy the necessary migration to your project and migrate your database:
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
```bash
|
41
|
+
rails g spree_variant_options:install
|
42
|
+
rake db:migrate
|
43
|
+
```
|
40
44
|
|
41
45
|
|
46
|
+
------------------------------------------------------------------------------
|
42
47
|
Versions
|
43
|
-
|
48
|
+
------------------------------------------------------------------------------
|
44
49
|
|
45
|
-
Spree Variant Options is compatible with Spree 0.30.x through 0.
|
50
|
+
Spree Variant Options is compatible with Spree 0.30.x through 1.0.x. Please reference `Versionfile` for more details.
|
46
51
|
|
47
52
|
|
53
|
+
------------------------------------------------------------------------------
|
48
54
|
Testing
|
49
|
-
|
55
|
+
------------------------------------------------------------------------------
|
50
56
|
|
51
57
|
Clone this repo to where you develop, bundle up, then run `dummier' to get the show started:
|
52
58
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
```bash
|
60
|
+
git clone git://github.com/citrus/spree_variant_options.git
|
61
|
+
cd spree_variant_options
|
62
|
+
bundle install
|
63
|
+
bundle exec dummier
|
64
|
+
|
65
|
+
# cucumber/capybara
|
66
|
+
bundle exec rake cucumber
|
67
|
+
|
68
|
+
# test/unit
|
69
|
+
bundle exec rake test
|
70
|
+
|
71
|
+
# both
|
72
|
+
bundle exec rake
|
73
|
+
```
|
57
74
|
|
58
|
-
# cucumber/capybara
|
59
|
-
rake cucumber
|
60
|
-
|
61
|
-
# test/unit
|
62
|
-
rake test
|
63
|
-
|
64
|
-
# both
|
65
|
-
rake
|
66
|
-
|
67
75
|
POW!
|
68
76
|
|
69
77
|
|
78
|
+
------------------------------------------------------------------------------
|
70
79
|
Demo
|
71
|
-
|
80
|
+
------------------------------------------------------------------------------
|
72
81
|
|
73
82
|
You can easily use the test/dummy app as a demo of spree_variant_options. Just `cd` to where you develop and run:
|
74
83
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
84
|
+
```bash
|
85
|
+
git clone git://github.com/citrus/spree_variant_options.git
|
86
|
+
cd spree_variant_options
|
87
|
+
cp test/dummy_hooks/after_migrate.rb.sample test/dummy_hooks/after_migrate.rb
|
88
|
+
bundle install
|
89
|
+
bundle exec dummier
|
90
|
+
cd test/dummy
|
91
|
+
rails s
|
92
|
+
```
|
83
93
|
|
94
|
+
|
95
|
+
------------------------------------------------------------------------------
|
84
96
|
Contributors
|
85
|
-
|
97
|
+
------------------------------------------------------------------------------
|
86
98
|
|
87
99
|
* Spencer Steffen ([@citrus](https://github.com/citrus))
|
100
|
+
* Dan Morin ([@danmorin](https://github.com/danmorin))
|
88
101
|
* Richard Brown ([@rbrown](https://github.com/rbrown))
|
89
102
|
* [@baracek](https://github.com/baracek)
|
90
103
|
|
91
104
|
If you'd like to help out feel free to fork and send me pull requests!
|
92
105
|
|
93
106
|
|
107
|
+
------------------------------------------------------------------------------
|
94
108
|
License
|
95
|
-
|
109
|
+
------------------------------------------------------------------------------
|
96
110
|
|
97
|
-
Copyright (c) 2011 Spencer Steffen and Citrus, released under the New BSD License All rights reserved.
|
111
|
+
Copyright (c) 2011 - 2012 Spencer Steffen and Citrus, released under the New BSD License All rights reserved.
|
data/Versionfile
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
var show_variant_images = function(variant_id) {
|
2
|
+
$('li.vtmb').hide();
|
3
|
+
$('li.vtmb-' + variant_id).show();
|
4
|
+
var currentThumb = $('#' + $("#main-image").data('selectedThumbId'));
|
5
|
+
// if currently selected thumb does not belong to current variant, nor to common images,
|
6
|
+
// hide it and select the first available thumb instead.
|
7
|
+
if(!currentThumb.hasClass('vtmb-' + variant_id)) {
|
8
|
+
//var thumb = $($('ul.thumbnails li:visible').eq(0));
|
9
|
+
var thumb = $($("ul.thumbnails li.vtmb-" + variant_id + ":first").eq(0));
|
10
|
+
if (thumb.length == 0) {
|
11
|
+
thumb = $($('ul.thumbnails li:visible').eq(0));
|
12
|
+
}
|
13
|
+
var newImg = thumb.find('a').attr('href');
|
14
|
+
$('ul.thumbnails li').removeClass('selected');
|
15
|
+
thumb.addClass('selected');
|
16
|
+
$('#main-image img').attr('src', newImg);
|
17
|
+
$("#main-image").data('selectedThumb', newImg);
|
18
|
+
$("#main-image").data('selectedThumbId', thumb.attr('id'));
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
var show_all_variant_images = function() {
|
23
|
+
$('li.vtmb').show();
|
24
|
+
}
|
@@ -164,7 +164,7 @@ function VariantOptions(options, allow_backorders) {
|
|
164
164
|
$('#product-price .price').removeClass('unselected').text(variant.price);
|
165
165
|
$('button[type=submit]').attr('disabled', false).fadeTo(100, 1);
|
166
166
|
try {
|
167
|
-
|
167
|
+
show_variant_images(variant.id);
|
168
168
|
} catch(error) {
|
169
169
|
// depends on modified version of product.js
|
170
170
|
}
|
@@ -184,6 +184,7 @@ function VariantOptions(options, allow_backorders) {
|
|
184
184
|
disable($(element).find('a.option-value').show().removeClass('in-stock out-of-stock').addClass('locked').unbind('click'));
|
185
185
|
$(element).find('a.clear-button').hide();
|
186
186
|
});
|
187
|
+
show_all_variant_images();
|
187
188
|
}
|
188
189
|
|
189
190
|
|
@@ -1,11 +1,6 @@
|
|
1
|
-
#product-variants {
|
2
|
-
|
3
|
-
}
|
4
|
-
|
5
1
|
#product-details .price.unselected {
|
6
2
|
color: #bbb;
|
7
3
|
}
|
8
|
-
|
9
4
|
.variant-option-type {
|
10
5
|
margin-bottom: 0;
|
11
6
|
}
|
@@ -55,7 +50,7 @@ li.clear-option a.clear-button:hover {
|
|
55
50
|
}
|
56
51
|
.option-value.out-of-stock {
|
57
52
|
display: block;
|
58
|
-
background: transparent url(/
|
53
|
+
background: transparent url(<%= asset_path "store/out-of-stock.png" %>) 0 0 repeat;
|
59
54
|
color: #aaa;
|
60
55
|
cursor: default;
|
61
56
|
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Spree
|
2
|
+
module Admin
|
3
|
+
class OptionValuesController < BaseController
|
4
|
+
|
5
|
+
def update_positions
|
6
|
+
params[:positions].each do |id, index|
|
7
|
+
OptionValue.update_all(['position=?', index], ['id=?', id])
|
8
|
+
end
|
9
|
+
|
10
|
+
respond_to do |format|
|
11
|
+
format.html { redirect_to edit_admin_option_type_url(params[:id]) }
|
12
|
+
format.js { render :text => 'Ok' }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,5 +1,26 @@
|
|
1
|
-
Deface::Override.new(:virtual_path
|
2
|
-
:name
|
3
|
-
:replace
|
4
|
-
:partial
|
5
|
-
:disabled
|
1
|
+
Deface::Override.new(:virtual_path => "spree/products/_cart_form",
|
2
|
+
:name => "spree_variant_options",
|
3
|
+
:replace => "#product-variants",
|
4
|
+
:partial => "spree/products/variant_options",
|
5
|
+
:disabled => false)
|
6
|
+
|
7
|
+
Deface::Override.new(:virtual_path => "spree/admin/option_types/edit",
|
8
|
+
:name => "admin_option_value_table_headers",
|
9
|
+
:replace => "thead[data-hook=option_header]",
|
10
|
+
:partial => "spree/admin/option_values/table_header",
|
11
|
+
:disabled => false)
|
12
|
+
|
13
|
+
Deface::Override.new(:virtual_path => "spree/admin/option_types/edit",
|
14
|
+
:name => "admin_option_value_table_empty_colspan",
|
15
|
+
:set_attributes => "tr[data-hook=option_none] td",
|
16
|
+
:attributes => { :colspan => 5 },
|
17
|
+
:disabled => false)
|
18
|
+
|
19
|
+
Deface::Override.new(:virtual_path => "spree/admin/option_types/edit",
|
20
|
+
:name => "admin_sortable_option_values",
|
21
|
+
:set_attributes => "table.index",
|
22
|
+
:attributes => {
|
23
|
+
"class" => "index sortable",
|
24
|
+
"data-sortable-link" => "/admin/option_values/update_positions"
|
25
|
+
},
|
26
|
+
:disabled => false)
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<tr class="option_value fields" id="<%= dom_id(f.object) %>" data-hook="option_value">
|
2
|
+
<td class="name"><span class="handle"></span> <%= f.text_field :name %></td>
|
3
|
+
<td class="presentation"><%= f.text_field :presentation %></td>
|
4
|
+
<td><%= image_tag f.object.image.url(:small) if f.object.has_image? %></td>
|
5
|
+
<td><%= f.file_field :image %></td>
|
6
|
+
<td class="actions"><%= link_to_remove_fields t(:remove), f %></td>
|
7
|
+
</tr>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
<% index = 0 %>
|
6
6
|
<% @product.grouped_option_values.each do |type, values| %>
|
7
7
|
<div id="<%= dom_id(type) %>" class="variant-options index-<%= index %>">
|
8
|
-
<
|
8
|
+
<h6 class="variant-option-type"><%= type.presentation %></h6>
|
9
9
|
<ul class="variant-option-values">
|
10
10
|
<% values.each do |value| %>
|
11
11
|
<% classes = ["option-value"] %>
|
@@ -30,15 +30,10 @@
|
|
30
30
|
<%= hidden_field_tag "products[#{@product.id}]", "", :id => "variant_id", :class => "hidden" %>
|
31
31
|
<script type="text/javascript">
|
32
32
|
//<![CDATA[
|
33
|
-
var variant_options = new VariantOptions(<%== @product.variant_options_hash.to_json %>, <%== Spree::Config[:allow_backorders] %>);
|
33
|
+
var variant_options = new VariantOptions(<%== @product.variant_options_hash.to_json %>, <%== !!Spree::Config[:allow_backorders] %>);
|
34
34
|
//]]>
|
35
35
|
</script>
|
36
36
|
|
37
37
|
</div>
|
38
|
-
|
39
|
-
<% content_for :head do %>
|
40
|
-
<%= stylesheet_link_tag 'store/variant_options' %>
|
41
|
-
<%= javascript_include_tag 'store/variant_options' %>
|
42
|
-
<% end %>
|
43
38
|
|
44
39
|
<% end%>
|
data/config/routes.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
|
1
|
+
Spree::Core::Engine.routes.append do
|
2
2
|
|
3
3
|
namespace :admin do
|
4
|
-
resources :
|
5
|
-
|
6
|
-
|
7
|
-
post :update_positions
|
8
|
-
end
|
4
|
+
resources :option_values do
|
5
|
+
collection do
|
6
|
+
post :update_positions
|
9
7
|
end
|
10
8
|
end
|
11
9
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class AddImageToOptionValues < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :spree_option_values, :image_file_name, :string
|
4
|
+
add_column :spree_option_values, :image_content_type, :string
|
5
|
+
add_column :spree_option_values, :image_file_size, :integer
|
6
|
+
add_column :spree_option_values, :image_updated_at, :datetime
|
7
|
+
end
|
8
|
+
end
|
File without changes
|
File without changes
|
@@ -9,11 +9,11 @@ end
|
|
9
9
|
|
10
10
|
Then /^I fill in the option value fields for (.*)$/ do |parent|
|
11
11
|
if parent == 'the new option value'
|
12
|
-
parent = "tr#
|
12
|
+
parent = "tr#new_spree_option_value"
|
13
13
|
else
|
14
14
|
matches = parent.match(/([^"]*)"$/)
|
15
|
-
ov = OptionValue.find_by_presentation(matches[matches.length - 1])
|
16
|
-
parent = "tr#
|
15
|
+
ov = Spree::OptionValue.find_by_presentation(matches[matches.length - 1])
|
16
|
+
parent = "tr#spree_option_value_#{ov.id}"
|
17
17
|
end
|
18
18
|
within parent do
|
19
19
|
%w(name presentation).each do |name|
|
@@ -31,8 +31,8 @@ Then /^I should see image "([^"]*)"$/ do |source|
|
|
31
31
|
end
|
32
32
|
|
33
33
|
When /^I follow "([^"]*)" for option type "([^"]*)"$/ do |link_text, value_string|
|
34
|
-
ov = OptionValue.find_by_presentation(value_string)
|
35
|
-
within "tr#
|
34
|
+
ov = Spree::OptionValue.find_by_presentation(value_string)
|
35
|
+
within "tr#spree_option_value_#{ov.id}" do
|
36
36
|
click_link link_text
|
37
37
|
end
|
38
38
|
end
|
@@ -42,12 +42,12 @@ end
|
|
42
42
|
|
43
43
|
#When /^I drag option value "([^"]*)" to the top$/ do |value_string|
|
44
44
|
# ov = OptionValue.find_by_presentation(value_string)
|
45
|
-
# page.driver.browser.drag_and_drop("#
|
45
|
+
# page.driver.browser.drag_and_drop("#spree_option_value_#{ov.id} span.handle", "0,-100")
|
46
46
|
#end
|
47
47
|
|
48
48
|
#When /^I drag option value "([^"]*)" to the top$/ do |value_string|
|
49
49
|
# ov = OptionValue.find_by_presentation(value_string)
|
50
|
-
# from = find("#
|
50
|
+
# from = find("#spree_option_value_#{ov.id} span.handle")
|
51
51
|
# to = find("table.index tr:first")
|
52
52
|
# from.drag_to(to)
|
53
53
|
#end
|
@@ -59,6 +59,6 @@ end
|
|
59
59
|
#Then /^I should see "([^"]*)" as the first option value$/ do |value_string|
|
60
60
|
# ov = OptionValue.find_by_presentation(value_string)
|
61
61
|
# #assert_equal 1, ov.position
|
62
|
-
# #assert_equal find("table.index tr:first"), find("#
|
62
|
+
# #assert_equal find("table.index tr:first"), find("#spree_option_value_#{ov.id}")
|
63
63
|
#end
|
64
64
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
def variant_by_descriptor(descriptor)
|
5
5
|
values = descriptor.split(" ")
|
6
|
-
values.map! { |word| OptionValue.find_by_presentation(word) rescue nil }.compact!
|
6
|
+
values.map! { |word| Spree::OptionValue.find_by_presentation(word) rescue nil }.compact!
|
7
7
|
return if values.blank?
|
8
8
|
@product.variants.includes(:option_values).select{|i| i.option_value_ids.sort == values.map(&:id) }.first
|
9
9
|
end
|
@@ -21,8 +21,9 @@ end
|
|
21
21
|
# Givens
|
22
22
|
|
23
23
|
Given /^I( don't)? allow backorders$/ do |dont|
|
24
|
+
Spree::Config.instance_variable_set("@configuration", nil)
|
24
25
|
Spree::Config.set(:allow_backorders => dont.nil?)
|
25
|
-
assert_equal dont.nil?, Spree::Config[:allow_backorders]
|
26
|
+
assert_equal dont.nil?, !!Spree::Config[:allow_backorders]
|
26
27
|
end
|
27
28
|
|
28
29
|
Given /^I have a product( with variants)?( and images)?$/ do |has_variants, has_images|
|
@@ -64,7 +65,7 @@ Given /^I have an? "([^"]*)" variant( for .*)?$/ do |descriptor, price|
|
|
64
65
|
return @variant if @variant
|
65
66
|
@product.option_type_ids.each_with_index do |otid, index|
|
66
67
|
word = values[index]
|
67
|
-
val = OptionValue.find_by_presentation(word) || Factory.create(:option_value, :option_type_id => otid, :presentation => word, :name => word.downcase)
|
68
|
+
val = Spree::OptionValue.find_by_presentation(word) || Factory.create(:option_value, :option_type_id => otid, :presentation => word, :name => word.downcase)
|
68
69
|
values[index] = val
|
69
70
|
end
|
70
71
|
@variant = Factory.create(:variant, :product => @product, :option_values => values, :price => price)
|
@@ -99,10 +100,10 @@ Then /^I should see (enabled|disabled)+ links for the ((?!option).*) option type
|
|
99
100
|
when "second"; @product.option_types[1];
|
100
101
|
when "last"; @product.option_types.last;
|
101
102
|
end
|
102
|
-
assert_seen option_type.presentation, :within => "#
|
103
|
+
assert_seen option_type.presentation, :within => "#spree_option_type_#{option_type.id} h6.variant-option-type"
|
103
104
|
option_type.option_values.each do |value|
|
104
105
|
rel = "#{option_type.id}-#{value.id}"
|
105
|
-
link = find("#
|
106
|
+
link = find("#spree_option_type_#{option_type.id} a[rel='#{option_type.id}-#{value.id}']")
|
106
107
|
assert_not_nil link
|
107
108
|
assert_equal value.presentation, link.text
|
108
109
|
assert_equal "#", link.native.attribute('href').last
|