spree_core 1.3.0.rc1 → 1.3.0.rc2
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 +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
|