spree_core 1.2.2 → 1.2.3
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/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
|