spree_core 1.2.2 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/javascripts/admin/admin.js.erb +27 -2
- data/app/assets/javascripts/admin/taxon_autocomplete.js.erb +25 -23
- data/app/assets/stylesheets/store/screen.css.scss +13 -0
- data/app/controllers/spree/admin/images_controller.rb +0 -11
- data/app/controllers/spree/admin/option_types_controller.rb +3 -14
- data/app/controllers/spree/admin/option_values_controller.rb +11 -0
- data/app/controllers/spree/admin/product_properties_controller.rb +12 -0
- data/app/controllers/spree/admin/resource_controller.rb +10 -0
- data/app/controllers/spree/admin/taxons_controller.rb +1 -1
- data/app/controllers/spree/admin/variants_controller.rb +0 -11
- data/app/controllers/spree/products_controller.rb +9 -3
- data/app/helpers/spree/admin/base_helper.rb +2 -1
- data/app/helpers/spree/admin/products_helper.rb +1 -1
- data/app/helpers/spree/checkout_helper.rb +15 -0
- data/app/models/spree/calculator/per_item.rb +3 -1
- data/app/models/spree/image.rb +1 -1
- data/app/models/spree/line_item.rb +1 -1
- data/app/models/spree/order.rb +25 -4
- data/app/models/spree/order/checkout.rb +4 -1
- data/app/models/spree/payment.rb +1 -1
- data/app/models/spree/payment/processing.rb +1 -4
- data/app/models/spree/preferences/preferable_class_methods.rb +6 -9
- data/app/models/spree/preferences/store.rb +22 -11
- data/app/models/spree/product.rb +1 -1
- data/app/models/spree/shipment.rb +19 -15
- data/app/models/spree/taxonomy.rb +2 -0
- data/app/views/spree/admin/image_settings/edit.html.erb +7 -0
- data/app/views/spree/admin/orders/edit.html.erb +1 -1
- data/app/views/spree/admin/products/_form.html.erb +6 -1
- data/app/views/spree/admin/shared/_order_tabs.html.erb +1 -1
- data/app/views/spree/admin/shared/_translations.html.erb +1 -1
- data/app/views/spree/admin/shipping_methods/_form.html.erb +1 -1
- data/app/views/spree/admin/taxonomies/_list.html.erb +2 -1
- data/app/views/spree/checkout/_address.html.erb +47 -47
- data/app/views/spree/checkout/payment/_gateway.html.erb +2 -2
- data/app/views/spree/layouts/spree_application.html.erb +1 -1
- data/app/views/spree/orders/_line_item.html.erb +1 -1
- data/app/views/spree/products/_thumbnails.html.erb +17 -15
- data/app/views/spree/products/show.html.erb +1 -1
- data/app/views/spree/shared/_footer.html.erb +1 -1
- data/app/views/spree/shared/_google_analytics.html.erb +8 -8
- data/app/views/spree/shared/_header.html.erb +1 -1
- data/app/views/spree/shared/_main_nav_bar.html.erb +1 -1
- data/app/views/spree/shared/_nav_bar.html.erb +1 -1
- data/app/views/spree/shared/_order_details.html.erb +3 -1
- data/app/views/spree/shared/_sidebar.html.erb +1 -1
- data/app/views/spree/taxons/show.html.erb +1 -1
- data/config/locales/en.yml +6 -15
- data/config/routes.rb +7 -0
- data/db/migrate/20121124203911_add_position_to_taxonomies.rb +5 -0
- data/lib/spree/core/controller_helpers.rb +1 -0
- data/lib/spree/core/testing_support/factories/payment_factory.rb +0 -18
- data/lib/spree/core/validators/email.rb +1 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/tasks/taxon.rake +1 -1
- metadata +147 -54
@@ -104,6 +104,13 @@ $(document).ready(function(){
|
|
104
104
|
el.attr("id", el.attr("id").replace(/\d+/, new_id))
|
105
105
|
el.attr("name", el.attr("name").replace(/\d+/, new_id))
|
106
106
|
})
|
107
|
+
// When cloning a new row, set the href of all icons to be an empty "#"
|
108
|
+
// This is so that clicking on them does not perform the actions for the
|
109
|
+
// duplicated row
|
110
|
+
new_table_row.find("a").each(function () {
|
111
|
+
var el = $(this);
|
112
|
+
el.attr('href', '#');
|
113
|
+
})
|
107
114
|
$(target).append(new_table_row);
|
108
115
|
})
|
109
116
|
|
@@ -130,8 +137,26 @@ $(document).ready(function(){
|
|
130
137
|
});
|
131
138
|
|
132
139
|
$('body').on('click', 'a.remove_fields', function() {
|
133
|
-
$(this)
|
134
|
-
|
140
|
+
el = $(this);
|
141
|
+
el.prev("input[type=hidden]").val("1");
|
142
|
+
el.closest(".fields").hide();
|
143
|
+
if (el.attr("href")) {
|
144
|
+
$.ajax({
|
145
|
+
type: 'POST',
|
146
|
+
url: el.attr("href"),
|
147
|
+
data: {
|
148
|
+
_method: 'delete',
|
149
|
+
authenticity_token: AUTH_TOKEN
|
150
|
+
},
|
151
|
+
success: function(response) {
|
152
|
+
el.parents("tr").fadeOut('hide');
|
153
|
+
},
|
154
|
+
error: function(response, textStatus, errorThrown) {
|
155
|
+
show_flash_error(response.responseText);
|
156
|
+
}
|
157
|
+
|
158
|
+
})
|
159
|
+
}
|
135
160
|
return false;
|
136
161
|
});
|
137
162
|
|
@@ -6,29 +6,31 @@ function cleanTaxons(data) {
|
|
6
6
|
}
|
7
7
|
|
8
8
|
$(document).ready(function() {
|
9
|
-
$("#product_taxon_ids").
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
return
|
15
|
-
|
16
|
-
|
17
|
-
ajax: {
|
18
|
-
url: Spree.routes.taxon_search,
|
19
|
-
datatype: 'json',
|
20
|
-
data: function(term, page) {
|
21
|
-
return { q: term }
|
9
|
+
if ($("#product_taxon_ids").length > 0) {
|
10
|
+
$("#product_taxon_ids").select2({
|
11
|
+
placeholder: "Add a taxon",
|
12
|
+
multiple: true,
|
13
|
+
initSelection: function(element, callback) {
|
14
|
+
return $.getJSON(Spree.routes.taxon_search + "?ids=" + (element.val()), null, function(data) {
|
15
|
+
return callback(self.cleanTaxons(data));
|
16
|
+
})
|
22
17
|
},
|
23
|
-
|
24
|
-
|
18
|
+
ajax: {
|
19
|
+
url: Spree.routes.taxon_search,
|
20
|
+
datatype: 'json',
|
21
|
+
data: function(term, page) {
|
22
|
+
return { q: term }
|
23
|
+
},
|
24
|
+
results: function (data, page) {
|
25
|
+
return { results: self.cleanTaxons(data) }
|
26
|
+
}
|
27
|
+
},
|
28
|
+
formatResult: function(taxon) {
|
29
|
+
return taxon.pretty_name
|
30
|
+
},
|
31
|
+
formatSelection: function(taxon) {
|
32
|
+
return taxon.pretty_name
|
25
33
|
}
|
26
|
-
}
|
27
|
-
|
28
|
-
return taxon.pretty_name
|
29
|
-
},
|
30
|
-
formatSelection: function(taxon) {
|
31
|
-
return taxon.pretty_name
|
32
|
-
}
|
33
|
-
})
|
34
|
+
})
|
35
|
+
}
|
34
36
|
})
|
@@ -479,6 +479,10 @@ mark {background-color: $link_text_color; color: $layout_background_color; font-
|
|
479
479
|
border-color: $link_text_color;
|
480
480
|
}
|
481
481
|
|
482
|
+
img {
|
483
|
+
max-width: 100%; /* Fluid images for product */
|
484
|
+
}
|
485
|
+
|
482
486
|
}
|
483
487
|
|
484
488
|
.price {
|
@@ -533,6 +537,7 @@ mark {background-color: $link_text_color; color: $layout_background_color; font-
|
|
533
537
|
|
534
538
|
img {
|
535
539
|
min-height: 240px;
|
540
|
+
max-width: 100%; /* Fluid images for product */
|
536
541
|
}
|
537
542
|
}
|
538
543
|
#product-thumbnails {
|
@@ -600,6 +605,14 @@ mark {background-color: $link_text_color; color: $layout_background_color; font-
|
|
600
605
|
/*--------------------------------------*/
|
601
606
|
/* Checkout
|
602
607
|
/*--------------------------------------*/
|
608
|
+
.out-of-stock {
|
609
|
+
background: #df0000;
|
610
|
+
color: white;
|
611
|
+
padding: 5px;
|
612
|
+
padding-right: 10px;
|
613
|
+
font-weight: bold;
|
614
|
+
}
|
615
|
+
|
603
616
|
.progress-steps {
|
604
617
|
list-style: decimal inside;
|
605
618
|
overflow: auto;
|
@@ -7,17 +7,6 @@ module Spree
|
|
7
7
|
update.before :set_viewable
|
8
8
|
destroy.before :destroy_before
|
9
9
|
|
10
|
-
def update_positions
|
11
|
-
params[:positions].each do |id, index|
|
12
|
-
Image.where(:id => id).update_all(:position => index)
|
13
|
-
end
|
14
|
-
|
15
|
-
respond_to do |format|
|
16
|
-
format.js { render :text => 'Ok' }
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
10
|
private
|
22
11
|
|
23
12
|
def location_after_save
|
@@ -3,17 +3,6 @@ module Spree
|
|
3
3
|
class OptionTypesController < ResourceController
|
4
4
|
before_filter :setup_new_option_value, :only => [:edit]
|
5
5
|
|
6
|
-
def update_positions
|
7
|
-
params[:positions].each do |id, index|
|
8
|
-
OptionType.where(:id => id).update_all(:position => index)
|
9
|
-
end
|
10
|
-
|
11
|
-
respond_to do |format|
|
12
|
-
format.html { redirect_to admin_product_variants_url(params[:product_id]) }
|
13
|
-
format.js { render :text => 'Ok' }
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
6
|
def update_values_positions
|
18
7
|
params[:positions].each do |id, index|
|
19
8
|
OptionValue.where(:id => id).update_all(:position => index)
|
@@ -26,7 +15,7 @@ module Spree
|
|
26
15
|
end
|
27
16
|
|
28
17
|
protected
|
29
|
-
|
18
|
+
|
30
19
|
def location_after_save
|
31
20
|
if @option_type.created_at == @option_type.updated_at
|
32
21
|
edit_admin_option_type_url(@option_type)
|
@@ -44,8 +33,8 @@ module Spree
|
|
44
33
|
def setup_new_option_value
|
45
34
|
@option_type.option_values.build if @option_type.option_values.empty?
|
46
35
|
end
|
47
|
-
|
48
|
-
def set_available_option_types
|
36
|
+
|
37
|
+
def set_available_option_types
|
49
38
|
@available_option_types = if @product.option_type_ids.any?
|
50
39
|
OptionType.where('id NOT IN (?)', @product.option_type_ids)
|
51
40
|
else
|
@@ -5,6 +5,18 @@ module Spree
|
|
5
5
|
before_filter :find_properties
|
6
6
|
before_filter :setup_property, :only => [:index]
|
7
7
|
|
8
|
+
# We use a "custom" finder in destroy
|
9
|
+
# Because the request is scoped without a product
|
10
|
+
# on account of the request coming from the "link_to_remove_fields"
|
11
|
+
# helper on the admin/product_properties view
|
12
|
+
skip_before_filter :load_resource, :only => [:destroy]
|
13
|
+
|
14
|
+
def destroy
|
15
|
+
product_property = Spree::ProductProperty.find(params[:id])
|
16
|
+
product_property.destroy
|
17
|
+
render :text => nil
|
18
|
+
end
|
19
|
+
|
8
20
|
private
|
9
21
|
def find_properties
|
10
22
|
@properties = Spree::Property.pluck(:name)
|
@@ -53,6 +53,16 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
def update_positions
|
57
|
+
params[:positions].each do |id, index|
|
58
|
+
model_class.where(:id => id).update_all(:position => index)
|
59
|
+
end
|
60
|
+
|
61
|
+
respond_to do |format|
|
62
|
+
format.js { render :text => 'Ok' }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
56
66
|
def destroy
|
57
67
|
invoke_callbacks(:destroy, :before)
|
58
68
|
if @object.destroy
|
@@ -63,7 +63,7 @@ module Spree
|
|
63
63
|
elsif new_position < new_siblings.index(@taxon)
|
64
64
|
@taxon.move_to_left_of(new_siblings[new_position]) # we move up
|
65
65
|
else
|
66
|
-
@taxon.move_to_right_of(new_siblings[new_position]) # we move down
|
66
|
+
@taxon.move_to_right_of(new_siblings[new_position-1]) # we move down
|
67
67
|
end
|
68
68
|
# Reset legacy position, if any extensions still rely on it
|
69
69
|
new_parent.children.reload.each{|t| t.update_column(:position, t.position)}
|
@@ -30,17 +30,6 @@ module Spree
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def update_positions
|
34
|
-
params[:positions].each do |id, index|
|
35
|
-
Variant.where(:id => id).update_all(:position => index)
|
36
|
-
end
|
37
|
-
|
38
|
-
respond_with(@variant) do |format|
|
39
|
-
format.html { redirect_to admin_product_variants_url(params[:product_id]) }
|
40
|
-
format.js { render :text => 'Ok' }
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
33
|
protected
|
45
34
|
|
46
35
|
def create_before
|
@@ -21,9 +21,15 @@ module Spree
|
|
21
21
|
|
22
22
|
referer = request.env['HTTP_REFERER']
|
23
23
|
if referer
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
begin
|
25
|
+
referer_path = URI.parse(request.env['HTTP_REFERER']).path
|
26
|
+
# Fix for #2249
|
27
|
+
rescue URI::InvalidURIError
|
28
|
+
# Do nothing
|
29
|
+
else
|
30
|
+
if referer_path && referer_path.match(/\/t\/(.*)/)
|
31
|
+
@taxon = Taxon.find_by_permalink($1)
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
29
35
|
|
@@ -148,7 +148,8 @@ module Spree
|
|
148
148
|
|
149
149
|
# renders hidden field and link to remove record using nested_attributes
|
150
150
|
def link_to_remove_fields(name, f)
|
151
|
-
f.
|
151
|
+
url = f.object.persisted? ? [:admin, f.object] : '#'
|
152
|
+
f.hidden_field(:_destroy) + link_to_with_icon(:delete, name, url, :class => 'remove_fields')
|
152
153
|
end
|
153
154
|
|
154
155
|
def spree_dom_id(record)
|
@@ -4,6 +4,16 @@ module Spree
|
|
4
4
|
@order.checkout_steps
|
5
5
|
end
|
6
6
|
|
7
|
+
def state_required_class
|
8
|
+
'required' if state_required?
|
9
|
+
end
|
10
|
+
|
11
|
+
def state_required_label
|
12
|
+
if state_required?
|
13
|
+
content_tag :span, '*', :class => state_required_class
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
7
17
|
def checkout_progress
|
8
18
|
states = checkout_states
|
9
19
|
items = states.map do |state|
|
@@ -27,5 +37,10 @@ module Spree
|
|
27
37
|
end
|
28
38
|
content_tag('ol', raw(items.join("\n")), :class => 'progress-steps', :id => "checkout-step-#{@order.state}")
|
29
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def state_required?
|
43
|
+
Spree::Config[:address_requires_state]
|
44
|
+
end
|
30
45
|
end
|
31
46
|
end
|
@@ -33,7 +33,9 @@ module Spree
|
|
33
33
|
# Shipping methods do not have promotions attached, but promotions do
|
34
34
|
# Therefore we must check for promotions
|
35
35
|
if self.calculable.respond_to?(:promotion)
|
36
|
-
self.calculable.promotion.rules.map
|
36
|
+
self.calculable.promotion.rules.map do |rule|
|
37
|
+
rule.respond_to?(:products) ? rule.products : []
|
38
|
+
end.flatten
|
37
39
|
end
|
38
40
|
end
|
39
41
|
end
|
data/app/models/spree/image.rb
CHANGED
@@ -10,7 +10,7 @@ module Spree
|
|
10
10
|
:default_style => :product,
|
11
11
|
:url => '/spree/products/:id/:style/:basename.:extension',
|
12
12
|
:path => ':rails_root/public/spree/products/:id/:style/:basename.:extension',
|
13
|
-
:convert_options => { :all => '-strip' }
|
13
|
+
:convert_options => { :all => '-strip -auto-orient' }
|
14
14
|
# save the w,h of the original image (from which others can be calculated)
|
15
15
|
# we need to look at the write-queue for images which have not been saved yet
|
16
16
|
after_post_process :find_dimensions
|
@@ -94,7 +94,7 @@ module Spree
|
|
94
94
|
# Validation
|
95
95
|
def stock_availability
|
96
96
|
return if sufficient_stock?
|
97
|
-
errors.add(:quantity, I18n.t('validation.
|
97
|
+
errors.add(:quantity, I18n.t('validation.exceeds_available_stock'))
|
98
98
|
end
|
99
99
|
|
100
100
|
def quantity_no_less_than_shipped
|
data/app/models/spree/order.rb
CHANGED
@@ -15,9 +15,16 @@ module Spree
|
|
15
15
|
checkout_flow do
|
16
16
|
go_to_state :address
|
17
17
|
go_to_state :delivery
|
18
|
-
go_to_state :payment, :if => lambda { |order|
|
18
|
+
go_to_state :payment, :if => lambda { |order|
|
19
|
+
# Fix for #2191
|
20
|
+
if order.shipping_method
|
21
|
+
order.create_shipment!
|
22
|
+
order.send(:update_totals)
|
23
|
+
end
|
24
|
+
order.payment_required?
|
25
|
+
}
|
19
26
|
go_to_state :confirm, :if => lambda { |order| order.confirmation_required? }
|
20
|
-
go_to_state :complete
|
27
|
+
go_to_state :complete, :if => lambda { |order| (order.payment_required? && order.payments.exists?) || !order.payment_required? }
|
21
28
|
remove_transition :from => :delivery, :to => :confirm
|
22
29
|
end
|
23
30
|
|
@@ -63,7 +70,8 @@ module Spree
|
|
63
70
|
before_create :link_by_email
|
64
71
|
after_create :create_tax_charge!
|
65
72
|
|
66
|
-
validates :email, :presence => true, :
|
73
|
+
validates :email, :presence => true, :if => :require_email
|
74
|
+
validates :email, :email => true, :if => :require_email, :allow_blank => true
|
67
75
|
validate :has_available_shipment
|
68
76
|
validate :has_available_payment
|
69
77
|
|
@@ -344,6 +352,10 @@ module Spree
|
|
344
352
|
end
|
345
353
|
end
|
346
354
|
|
355
|
+
def can_ship?
|
356
|
+
self.complete? || self.resumed?
|
357
|
+
end
|
358
|
+
|
347
359
|
def credit_cards
|
348
360
|
credit_card_ids = payments.from_credit_card.map(&:source_id).uniq
|
349
361
|
CreditCard.scoped(:conditions => { :id => credit_card_ids })
|
@@ -477,8 +489,17 @@ module Spree
|
|
477
489
|
|
478
490
|
def merge!(order)
|
479
491
|
order.line_items.each do |line_item|
|
480
|
-
self.
|
492
|
+
current_line_item = self.line_items.find_by_variant_id(line_item.variant_id)
|
493
|
+
if current_line_item
|
494
|
+
current_line_item.quantity += line_item.quantity
|
495
|
+
current_line_item.save
|
496
|
+
else
|
497
|
+
line_item.order_id = self.id
|
498
|
+
line_item.save
|
499
|
+
end
|
481
500
|
end
|
501
|
+
# So that the destroy doesn't take out line items which may have been re-assigned
|
502
|
+
order.line_items.reload
|
482
503
|
order.destroy
|
483
504
|
end
|
484
505
|
|
@@ -126,7 +126,10 @@ module Spree
|
|
126
126
|
end
|
127
127
|
checkout_steps << step
|
128
128
|
end
|
129
|
-
checkout_steps.map(&:to_s)
|
129
|
+
steps = checkout_steps.map(&:to_s)
|
130
|
+
# Ensure there is always a complete step
|
131
|
+
steps << "complete" unless steps.include?("complete")
|
132
|
+
steps
|
130
133
|
end
|
131
134
|
end
|
132
135
|
end
|
data/app/models/spree/payment.rb
CHANGED
@@ -32,7 +32,7 @@ module Spree
|
|
32
32
|
end
|
33
33
|
# When processing during checkout fails
|
34
34
|
event :failure do
|
35
|
-
transition :from => 'processing', :to => 'failed'
|
35
|
+
transition :from => ['pending', 'processing'], :to => 'failed'
|
36
36
|
end
|
37
37
|
# With card payments this represents authorizing the payment
|
38
38
|
event :pend do
|