spree_core 1.3.0.rc1 → 1.3.0.rc2
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 +28 -2
- data/app/assets/javascripts/admin/checkouts/edit.js +52 -96
- data/app/assets/javascripts/admin/handlebar_extensions.js +9 -0
- data/app/assets/javascripts/admin/spree-select2.js.erb +17 -19
- data/app/assets/javascripts/admin/spree_core.js +0 -1
- data/app/assets/javascripts/admin/states.js +9 -0
- data/app/assets/javascripts/admin/taxon_autocomplete.js.erb +1 -1
- data/app/assets/javascripts/admin/variant_autocomplete.js.erb +2 -6
- data/app/assets/javascripts/store/checkout.js.coffee +4 -4
- data/app/assets/stylesheets/store/screen.css.scss +8 -0
- 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/products_controller.rb +9 -0
- data/app/helpers/spree/admin/base_helper.rb +2 -8
- data/app/models/spree/app_configuration.rb +1 -0
- data/app/models/spree/calculator/per_item.rb +3 -1
- data/app/models/spree/line_item.rb +2 -2
- data/app/models/spree/order/checkout.rb +4 -1
- data/app/models/spree/order.rb +5 -1
- data/app/models/spree/payment/processing.rb +1 -1
- 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/scopes.rb +5 -1
- data/app/models/spree/shipment.rb +7 -4
- data/app/models/spree/shipping_method.rb +4 -0
- data/app/views/spree/admin/orders/customer_details/_autocomplete.js.erb +19 -0
- data/app/views/spree/admin/orders/customer_details/edit.html.erb +4 -3
- data/app/views/spree/admin/orders/edit.html.erb +1 -1
- data/app/views/spree/admin/products/search.rabl +6 -0
- data/app/views/spree/admin/search/users.rabl +23 -25
- data/app/views/spree/admin/shared/_head.html.erb +1 -1
- data/app/views/spree/admin/shared/_routes.html.erb +3 -2
- data/app/views/spree/admin/shared/_translations.html.erb +3 -0
- data/app/views/spree/admin/shipping_methods/_form.html.erb +1 -1
- data/app/views/spree/admin/variants/_autocomplete.js.erb +2 -2
- data/app/views/spree/admin/variants/search.rabl +8 -10
- data/app/views/spree/checkout/payment/_gateway.html.erb +2 -2
- data/app/views/spree/order_mailer/cancel_email.text.erb +2 -2
- data/app/views/spree/order_mailer/confirm_email.text.erb +2 -2
- data/app/views/spree/orders/_line_item.html.erb +1 -1
- data/app/views/spree/products/_cart_form.html.erb +6 -2
- data/app/views/spree/shared/_google_analytics.html.erb +8 -8
- data/app/views/spree/shared/_order_details.html.erb +3 -1
- data/config/locales/en.yml +9 -7
- data/config/routes.rb +9 -0
- data/db/migrate/20121126040517_add_last_ip_to_spree_orders.rb +5 -0
- data/lib/spree/core/calculated_adjustments.rb +2 -1
- data/lib/spree/core/controller_helpers/common.rb +5 -0
- data/lib/spree/core/controller_helpers/order.rb +1 -0
- data/lib/spree/core/search/base.rb +5 -1
- data/lib/spree/core/testing_support/capybara_ext.rb +79 -0
- data/lib/spree/core/version.rb +1 -1
- metadata +13 -6
- data/vendor/assets/javascripts/jquery.tokeninput.js +0 -860
@@ -1,4 +1,5 @@
|
|
1
1
|
//= require_self
|
2
|
+
//= require admin/handlebar_extensions
|
2
3
|
//= require admin/variant_autocomplete
|
3
4
|
//= require admin/taxon_autocomplete
|
4
5
|
//= require admin/spree-select2
|
@@ -157,6 +158,13 @@ $(document).ready(function(){
|
|
157
158
|
el.attr("id", el.attr("id").replace(/\d+/, new_id))
|
158
159
|
el.attr("name", el.attr("name").replace(/\d+/, new_id))
|
159
160
|
})
|
161
|
+
// When cloning a new row, set the href of all icons to be an empty "#"
|
162
|
+
// This is so that clicking on them does not perform the actions for the
|
163
|
+
// duplicated row
|
164
|
+
new_table_row.find("a").each(function () {
|
165
|
+
var el = $(this);
|
166
|
+
el.attr('href', '#');
|
167
|
+
})
|
160
168
|
$(target).prepend(new_table_row);
|
161
169
|
})
|
162
170
|
|
@@ -183,8 +191,26 @@ $(document).ready(function(){
|
|
183
191
|
});
|
184
192
|
|
185
193
|
$('body').on('click', 'a.remove_fields', function() {
|
186
|
-
$(this)
|
187
|
-
|
194
|
+
el = $(this);
|
195
|
+
el.prev("input[type=hidden]").val("1");
|
196
|
+
el.closest(".fields").hide();
|
197
|
+
if (el.attr("href")) {
|
198
|
+
$.ajax({
|
199
|
+
type: 'POST',
|
200
|
+
url: el.attr("href"),
|
201
|
+
data: {
|
202
|
+
_method: 'delete',
|
203
|
+
authenticity_token: AUTH_TOKEN
|
204
|
+
},
|
205
|
+
success: function(response) {
|
206
|
+
el.parents("tr").fadeOut('hide');
|
207
|
+
},
|
208
|
+
error: function(response, textStatus, errorThrown) {
|
209
|
+
show_flash_error(response.responseText);
|
210
|
+
}
|
211
|
+
|
212
|
+
})
|
213
|
+
}
|
188
214
|
return false;
|
189
215
|
});
|
190
216
|
|
@@ -1,108 +1,68 @@
|
|
1
|
-
$(document).ready(function(){
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
if(addr['state_id']!=null){
|
11
|
-
html += addr['state']['name'] + ", ";
|
12
|
-
}else{
|
13
|
-
html += addr['state_name'] + ", ";
|
14
|
-
}
|
15
|
-
|
16
|
-
html += addr['country']['name'];
|
17
|
-
}
|
18
|
-
return html;
|
19
|
-
}
|
20
|
-
|
21
|
-
format_user_autocomplete = function(item){
|
22
|
-
var data = item.data
|
23
|
-
var html = "<h4>" + data['email'] +"</h4>";
|
24
|
-
html += "<span><strong>Billing:</strong> ";
|
25
|
-
html += add_address(data['bill_address']);
|
26
|
-
html += "</span>";
|
27
|
-
|
28
|
-
html += "<span><strong>Shipping:</strong> ";
|
29
|
-
html += add_address(data['ship_address']);
|
30
|
-
html += "</span>";
|
31
|
-
|
32
|
-
return html
|
33
|
-
}
|
34
|
-
|
35
|
-
prep_user_autocomplete_data = function(data){
|
36
|
-
return $.map(eval(data['users']), function(row) {
|
37
|
-
return {
|
38
|
-
data: row,
|
39
|
-
value: row['email'],
|
40
|
-
result: row['email']
|
41
|
-
}
|
42
|
-
});
|
1
|
+
$(document).ready(function() {
|
2
|
+
window.customerTemplate = Handlebars.compile($('#customer_autocomplete_template').text());
|
3
|
+
|
4
|
+
formatCustomerResult = function(customer) {
|
5
|
+
return customerTemplate({
|
6
|
+
customer: customer,
|
7
|
+
bill_address: customer.bill_address,
|
8
|
+
ship_address: customer.ship_address
|
9
|
+
})
|
43
10
|
}
|
44
11
|
|
45
12
|
if ($("#customer_search").length > 0) {
|
46
|
-
$("#customer_search").
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
focus: function(event, ui) {
|
58
|
-
$('#customer_search').val(ui.item.label);
|
59
|
-
$(ui).addClass('ac_over');
|
60
|
-
return false;
|
13
|
+
$("#customer_search").select2({
|
14
|
+
placeholder: Spree.translations.choose_a_customer,
|
15
|
+
ajax: {
|
16
|
+
url: Spree.routes.user_search,
|
17
|
+
datatype: 'json',
|
18
|
+
data: function(term, page) {
|
19
|
+
return { q: term }
|
20
|
+
},
|
21
|
+
results: function(data, page) {
|
22
|
+
return { results: data }
|
23
|
+
}
|
61
24
|
},
|
62
|
-
|
63
|
-
|
64
|
-
_.each(['
|
65
|
-
var
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
$(
|
25
|
+
formatResult: formatCustomerResult,
|
26
|
+
formatSelection: function (customer) {
|
27
|
+
_.each(['bill_address', 'ship_address'], function(address) {
|
28
|
+
var data = customer[address];
|
29
|
+
address_parts = ['firstname', 'lastname',
|
30
|
+
'company', 'address1',
|
31
|
+
'address2', 'city',
|
32
|
+
'zipcode', 'phone']
|
33
|
+
var attribute_wrapper = '#order_' + address + '_attributes_'
|
34
|
+
if(data != undefined) {
|
35
|
+
_.each(address_parts, function(part) {
|
36
|
+
$(attribute_wrapper + part).val(data[part]);
|
37
|
+
})
|
38
|
+
|
39
|
+
$(attribute_wrapper + 'state_id').select2("val", data['state_id']);
|
40
|
+
$(attribute_wrapper + 'country_id').select2("val", data['country_id']);
|
41
|
+
}
|
42
|
+
else {
|
43
|
+
_.each(address_parts, function(part) {
|
44
|
+
$(attribute_wrapper + part).val("");
|
45
|
+
})
|
46
|
+
|
47
|
+
$(attribute_wrapper + 'state_id').select2("val", '');
|
48
|
+
$(attribute_wrapper + 'country_id').select2("val", '');
|
77
49
|
}
|
78
50
|
});
|
79
51
|
|
80
|
-
$('#order_email').val(
|
81
|
-
$('#user_id').val(
|
52
|
+
$('#order_email').val(customer.email);
|
53
|
+
$('#user_id').val(customer.id);
|
82
54
|
$('#guest_checkout_true').prop("checked", false);
|
83
55
|
$('#guest_checkout_false').prop("checked", true);
|
84
56
|
$('#guest_checkout_false').prop("disabled", false);
|
85
|
-
return true;
|
86
|
-
}
|
87
|
-
}).data("autocomplete")._renderItem = function(ul, item) {
|
88
|
-
$(ul).addClass('ac_results');
|
89
|
-
html = format_user_autocomplete(item);
|
90
|
-
return $("<li></li>")
|
91
|
-
.data("item.autocomplete", item)
|
92
|
-
.append("<a class='ui-menu-item'>" + html + "</a>")
|
93
|
-
.appendTo(ul);
|
94
|
-
}
|
95
|
-
|
96
|
-
$("#customer_search").data("autocomplete")._resizeMenu = function() {
|
97
|
-
var ul = this.menu.element;
|
98
|
-
ul.outerWidth(this.element.outerWidth());
|
99
|
-
}
|
100
|
-
|
101
57
|
|
58
|
+
return customer.email;
|
59
|
+
}
|
60
|
+
})
|
102
61
|
}
|
103
62
|
|
104
|
-
|
105
|
-
|
63
|
+
|
64
|
+
$('input#order_use_billing').click(function() {
|
65
|
+
if(!$(this).is(':checked')) {
|
106
66
|
$('#shipping').show();
|
107
67
|
$('#shipping input').prop("disabled", false);
|
108
68
|
$('#shipping select').prop("disabled", false);
|
@@ -111,10 +71,6 @@ $(document).ready(function(){
|
|
111
71
|
$('#shipping input').prop("disabled", true);
|
112
72
|
$('#shipping select').prop("disabled", true);
|
113
73
|
}
|
114
|
-
}
|
115
|
-
|
116
|
-
$('input#order_use_billing').click(function() {
|
117
|
-
show_billing(!$(this).is(':checked'));
|
118
74
|
});
|
119
75
|
|
120
76
|
$('#guest_checkout_true').change(function() {
|
@@ -0,0 +1,9 @@
|
|
1
|
+
//= require handlebars
|
2
|
+
Handlebars.registerHelper("t", function(key) {
|
3
|
+
if (Spree.translations[key]) {
|
4
|
+
return Spree.translations[key]
|
5
|
+
} else {
|
6
|
+
console.error("No translation found for " + key + ". Does it exist within spree/admin/shared/_translations.html.erb?")
|
7
|
+
}
|
8
|
+
});
|
9
|
+
|
@@ -1,24 +1,22 @@
|
|
1
1
|
//= require select2
|
2
2
|
jQuery(function($) {
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
});
|
3
|
+
// Make select beautiful
|
4
|
+
$('select.select2').select2({
|
5
|
+
allowClear: true
|
6
|
+
});
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
function format_taxons(taxon) {
|
9
|
+
new_taxon = taxon.text.replace('->', '<i class="icon-arrow-right">')
|
10
|
+
return new_taxon;
|
11
|
+
}
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
<% end %>
|
13
|
+
$("#product_taxon_ids").on({
|
14
|
+
change: function(e){
|
15
|
+
$('.select2-search-choice .with-tip').powerTip({
|
16
|
+
smartPlacement: true,
|
17
|
+
fadeInTime: 50,
|
18
|
+
fadeOutTime: 50
|
19
|
+
})
|
20
|
+
}
|
21
|
+
})
|
24
22
|
})
|
@@ -0,0 +1,9 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
$("#country").change(function() {
|
3
|
+
var new_state_link_href = $('#new_state_link a').attr('href');
|
4
|
+
var selected_country_id = $('#country option:selected').attr('value');
|
5
|
+
var new_link = new_state_link_href.replace(/countries\/(\d+)/,
|
6
|
+
'countries/'+selected_country_id);
|
7
|
+
$('#new_state_link a').attr('href', new_link);
|
8
|
+
});
|
9
|
+
});
|
@@ -8,7 +8,7 @@ function cleanTaxons(data) {
|
|
8
8
|
$(document).ready(function() {
|
9
9
|
if ($("#product_taxon_ids").length > 0) {
|
10
10
|
$("#product_taxon_ids").select2({
|
11
|
-
placeholder:
|
11
|
+
placeholder: Spree.translations.taxon_placeholder,
|
12
12
|
multiple: true,
|
13
13
|
initSelection: function(element, callback) {
|
14
14
|
return $.getJSON(Spree.routes.taxon_search + "?ids=" + (element.val()), null, function(data) {
|
@@ -1,4 +1,3 @@
|
|
1
|
-
//= require handlebars
|
2
1
|
<%#encoding: UTF-8%>
|
3
2
|
// variant autocompletion
|
4
3
|
|
@@ -10,7 +9,7 @@ formatVariantResult = function(variant) {
|
|
10
9
|
if (variant["images"][0] != undefined) {
|
11
10
|
variant.image = variant.images[0].image.mini_url
|
12
11
|
}
|
13
|
-
return variantTemplate({ variant: variant
|
12
|
+
return variantTemplate({ variant: variant })
|
14
13
|
}
|
15
14
|
|
16
15
|
$.fn.variantAutocomplete = function() {
|
@@ -25,10 +24,7 @@ $.fn.variantAutocomplete = function() {
|
|
25
24
|
return { q: term }
|
26
25
|
},
|
27
26
|
results: function (data, page) {
|
28
|
-
|
29
|
-
return result['variant']
|
30
|
-
})
|
31
|
-
return { results: variants }
|
27
|
+
return { results: data }
|
32
28
|
}
|
33
29
|
},
|
34
30
|
formatResult: formatVariantResult,
|
@@ -69,11 +69,11 @@ $ ->
|
|
69
69
|
).triggerHandler 'click'
|
70
70
|
|
71
71
|
if ($ '#checkout_form_payment').is('*')
|
72
|
-
# Activate already checked payment method if form is re-rendered
|
73
|
-
# i.e. if user enters invalid data
|
74
|
-
($ 'input[type="radio"]:checked').click()
|
75
|
-
|
76
72
|
($ 'input[type="radio"][name="order[payments_attributes][][payment_method_id]"]').click(->
|
77
73
|
($ '#payment-methods li').hide()
|
78
74
|
($ '#payment_method_' + @value).show() if @checked
|
79
75
|
)
|
76
|
+
|
77
|
+
# Activate already checked payment method if form is re-rendered
|
78
|
+
# i.e. if user enters invalid data
|
79
|
+
($ 'input[type="radio"]:checked').click()
|
@@ -610,6 +610,14 @@ mark {background-color: $link_text_color; color: $layout_background_color; font-
|
|
610
610
|
/*--------------------------------------*/
|
611
611
|
/* Checkout
|
612
612
|
/*--------------------------------------*/
|
613
|
+
.out-of-stock {
|
614
|
+
background: #df0000;
|
615
|
+
color: white;
|
616
|
+
padding: 5px;
|
617
|
+
padding-right: 10px;
|
618
|
+
font-weight: bold;
|
619
|
+
}
|
620
|
+
|
613
621
|
.progress-steps {
|
614
622
|
list-style: decimal inside;
|
615
623
|
overflow: auto;
|
@@ -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)
|
@@ -16,6 +16,15 @@ module Spree
|
|
16
16
|
respond_with(@collection)
|
17
17
|
end
|
18
18
|
|
19
|
+
def search
|
20
|
+
if params[:ids]
|
21
|
+
@products = Spree::Product.where(:id => params[:ids].split(","))
|
22
|
+
else
|
23
|
+
search_params = { :name_cont => params[:q], :sku_cont => params[:q] }
|
24
|
+
@products = Spree::Product.ransack(search_params.merge(:m => 'or')).result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
19
28
|
def update
|
20
29
|
if params[:product][:taxon_ids].present?
|
21
30
|
params[:product][:taxon_ids] = params[:product][:taxon_ids].split(',')
|
@@ -132,13 +132,6 @@ module Spree
|
|
132
132
|
}.join("<br />").html_safe
|
133
133
|
end
|
134
134
|
|
135
|
-
def product_picker_field(name, value)
|
136
|
-
products = Product.with_ids(value.split(','))
|
137
|
-
product_names = products.inject({}){|memo,item| memo[item.id] = item.name; memo}
|
138
|
-
product_rules = products.collect{ |p| { :id => p.id, :name => p.name } }
|
139
|
-
%(<input type="text" name="#{name}" value="#{value}" class="tokeninput products" data-names='#{product_names.to_json}' data-pre='#{product_rules.to_json}'/>).html_safe
|
140
|
-
end
|
141
|
-
|
142
135
|
def link_to_add_fields(name, target, options = {})
|
143
136
|
name = '' if options[:no_text]
|
144
137
|
css_classes = options[:class] ? options[:class] + " add_fields" : "add_fields"
|
@@ -150,7 +143,8 @@ module Spree
|
|
150
143
|
name = '' if options[:no_text]
|
151
144
|
options[:class] = '' unless options[:class]
|
152
145
|
options[:class] += 'no-text with-tip' if options[:no_text]
|
153
|
-
|
146
|
+
url = f.object.persisted? ? [:admin, f.object] : '#'
|
147
|
+
link_to_with_icon('icon-trash', name, url, :class => "remove_fields #{options[:class]}", :data => {:action => 'remove'}, :title => t(:remove)) + f.hidden_field(:_destroy)
|
154
148
|
end
|
155
149
|
|
156
150
|
def spree_dom_id(record)
|
@@ -61,6 +61,7 @@ module Spree
|
|
61
61
|
preference :show_only_complete_orders_by_default, :boolean, :default => true
|
62
62
|
preference :show_zero_stock_products, :boolean, :default => true
|
63
63
|
preference :show_variant_full_price, :boolean, :default => false #Displays variant full price or difference with product price. Default false to be compatible with older behavior
|
64
|
+
preference :show_products_without_price, :boolean, :default => false
|
64
65
|
preference :site_name, :string, :default => 'Spree Demo Site'
|
65
66
|
preference :site_url, :string, :default => 'demo.spreecommerce.com'
|
66
67
|
preference :tax_using_ship_address, :boolean, :default => true
|