spree_variant_options 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-

|
8
|
+

|
9
9
|
|
10
|
-
#### After "
|
10
|
+
#### After "Large" is selected, "Large Blue" is out of stock:
|
11
11
|
|
12
|
-

|
12
|
+

|
13
13
|
|
14
14
|
#### And after "Green" is selected:
|
15
|
-

|
15
|
+

|
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
|