Commit dd593502a79a30e138acf0a7ad62161bf3637510

Authored by Aurélio A. Heckert
1 parent 415d3eec

Fixing the ShoppingCartPlugin

This commit, with the participation of Lucas Melo, does:

* Make action list from ShoppingCartPluginController Fault-tolerant.
* Create a basic logging system and replace debug alerts.
* Limit the cart size to protect against cookie limit.
* Add more loading style possibilities.
* Add a little fault-tolerance to the process of loading the carts items.
* Force colorbox to "Shopping checkout" button.
* Add L10n to Cart JS interaction.
plugins/shopping_cart/controllers/shopping_cart_plugin_controller.rb
... ... @@ -57,14 +57,24 @@ class ShoppingCartPluginController < PublicController
57 57 def list
58 58 if validate_cart_presence
59 59 products = self.cart[:items].collect do |id, quantity|
60   - product = Product.find(id)
61   - { :id => product.id,
62   - :name => product.name,
63   - :price => get_price(product, product.enterprise.environment),
64   - :description => product.description,
65   - :picture => product.default_image(:minor),
66   - :quantity => quantity
67   - }
  60 + product = Product.find_by_id(id)
  61 + if product
  62 + { :id => product.id,
  63 + :name => product.name,
  64 + :price => get_price(product, product.enterprise.environment),
  65 + :description => product.description,
  66 + :picture => product.default_image(:minor),
  67 + :quantity => quantity
  68 + }
  69 + else
  70 + { :id => id,
  71 + :name => _('Undefined product'),
  72 + :price => 0,
  73 + :description => _('Wrong product id'),
  74 + :picture => '',
  75 + :quantity => quantity
  76 + }
  77 + end
68 78 end
69 79 render :text => {
70 80 :ok => true,
... ...
plugins/shopping_cart/public/cart.js
... ... @@ -21,7 +21,7 @@ function Cart(config) {
21 21 },
22 22 cache: false,
23 23 error: function(ajax, status, errorThrown) {
24   - alert('Visibility - HTTP '+status+': '+errorThrown);
  24 + log.error('Visibility - HTTP '+status, errorThrown);
25 25 }
26 26 });
27 27 $(".cart-buy", this.cartElem).colorbox({ href: '/plugin/shopping_cart/buy' });
... ... @@ -36,12 +36,12 @@ function Cart(config) {
36 36 url: '/plugin/shopping_cart/list',
37 37 dataType: 'json',
38 38 success: function(data, ststus, ajax){
39   - if ( !data.ok ) alert(data.error.message);
  39 + if ( !data.ok ) log.error(data.error);
40 40 else me.addToList(data, true);
41 41 },
42 42 cache: false,
43 43 error: function(ajax, status, errorThrown) {
44   - alert('List cart items - HTTP '+status+': '+errorThrown);
  44 + log.error('List cart items - HTTP '+status, errorThrown);
45 45 }
46 46 });
47 47 }
... ... @@ -49,6 +49,7 @@ function Cart(config) {
49 49 Cart.prototype.addToList = function(data, clear) {
50 50 if( clear ) this.itemsBox.empty();
51 51 var me = this;
  52 + this.productsLength = data.products.length;
52 53 for( var item,i=0; item=data.products[i]; i++ ) {
53 54 this.items[item.id] = { price:item.price, quantity:item.quantity };
54 55 this.updateTotal();
... ... @@ -75,9 +76,7 @@ function Cart(config) {
75 76 input.onchange = function() {
76 77 me.updateQuantity(this, this.productId, this.value);
77 78 };
78   -// document.location.href = "#"+liId;
79   -// document.location.href = "#"+this.cartElem.id;
80   -// history.go(-2);
  79 + // TODO: Scroll to newest item
81 80 var liBg = li.css("background-color");
82 81 li[0].style.backgroundColor = "#FF0";
83 82 li.animate({ backgroundColor: liBg }, 1000);
... ... @@ -103,7 +102,7 @@ function Cart(config) {
103 102 dataType: 'json',
104 103 success: function(data, status, ajax){
105 104 if ( !data.ok ) {
106   - alert(data.error.message);
  105 + log.error(data.error);
107 106 input.value = input.lastValue;
108 107 }
109 108 else {
... ... @@ -114,7 +113,7 @@ function Cart(config) {
114 113 },
115 114 cache: false,
116 115 error: function(ajax, status, errorThrown) {
117   - alert('Add item - HTTP '+status+': '+errorThrown);
  116 + log.error('Add item - HTTP '+status, errorThrown);
118 117 input.value = input.lastValue;
119 118 },
120 119 complete: function(){
... ... @@ -132,7 +131,14 @@ function Cart(config) {
132 131 }
133 132  
134 133 Cart.addItem = function(itemId, link) {
  134 + if ( this.productsLength > 100 ) {
  135 + // This limit protect the user from losing data on cookie limit.
  136 + // This is NOT limiting to 100 products, is limiting to 100 kinds of products.
  137 + alert(shoppingCartPluginL10n.maxNumberOfItens);
  138 + return false;
  139 + }
135 140 link.intervalId = setInterval(function() {
  141 + $(link).addClass('loading');
136 142 steps = ['w', 'n', 'e', 's'];
137 143 if( !link.step || link.step==3 ) link.step = 0;
138 144 link.step++;
... ... @@ -140,6 +146,7 @@ function Cart(config) {
140 146 }, 100);
141 147 var stopBtLoading = function() {
142 148 clearInterval(link.intervalId);
  149 + $(link).removeClass('loading');
143 150 $(link).button({ icons: { primary: 'ui-icon-cart'}, disable: false });
144 151 };
145 152 this.instance.addItem(itemId, stopBtLoading);
... ... @@ -151,12 +158,12 @@ function Cart(config) {
151 158 url: '/plugin/shopping_cart/add/'+ itemId,
152 159 dataType: 'json',
153 160 success: function(data, status, ajax){
154   - if ( !data.ok ) alert(data.error.message);
  161 + if ( !data.ok ) log.error('Shopping cart data failure', data.error);
155 162 else me.addToList(data);
156 163 },
157 164 cache: false,
158 165 error: function(ajax, status, errorThrown) {
159   - alert('Add item - HTTP '+status+': '+errorThrown);
  166 + log.error('Add item - HTTP '+status, errorThrown);
160 167 },
161 168 complete: callback
162 169 });
... ... @@ -174,12 +181,12 @@ function Cart(config) {
174 181 url: '/plugin/shopping_cart/remove/'+ itemId,
175 182 dataType: 'json',
176 183 success: function(data, status, ajax){
177   - if ( !data.ok ) alert(data.error.message);
  184 + if ( !data.ok ) log.error(data.error);
178 185 else me.removeFromList(data.product_id);
179 186 },
180 187 cache: false,
181 188 error: function(ajax, status, errorThrown) {
182   - alert('Remove item - HTTP '+status+': '+errorThrown);
  189 + log.error('Remove item - HTTP '+status, errorThrown);
183 190 }
184 191 });
185 192 }
... ... @@ -197,7 +204,7 @@ function Cart(config) {
197 204 dataType: 'json',
198 205 cache: false,
199 206 error: function(ajax, status, errorThrown) {
200   - alert('Show - HTTP '+status+': '+errorThrown);
  207 + log.error('Show - HTTP '+status, errorThrown);
201 208 }
202 209 });
203 210 this.visible = true;
... ... @@ -212,7 +219,7 @@ function Cart(config) {
212 219 dataType: 'json',
213 220 cache: false,
214 221 error: function(ajax, status, errorThrown) {
215   - alert('Hide - HTTP '+status+': '+errorThrown);
  222 + log.error('Hide - HTTP '+status, errorThrown);
216 223 }
217 224 });
218 225 this.visible = false;
... ... @@ -248,7 +255,7 @@ function Cart(config) {
248 255 url: '/plugin/shopping_cart/clean',
249 256 dataType: 'json',
250 257 success: function(data, status, ajax){
251   - if ( !data.ok ) alert(data.error.message);
  258 + if ( !data.ok ) log.error(data.error);
252 259 else{
253 260 me.items = {};
254 261 $(me.cartElem).slideUp(500, function() {
... ... @@ -261,7 +268,7 @@ function Cart(config) {
261 268 },
262 269 cache: false,
263 270 error: function(ajax, status, errorThrown) {
264   - alert('Remove item - HTTP '+status+': '+errorThrown);
  271 + log.error('Remove item - HTTP '+status, errorThrown);
265 272 }
266 273 });
267 274 }
... ... @@ -288,7 +295,7 @@ function Cart(config) {
288 295 },
289 296 cache: false,
290 297 error: function(ajax, status, errorThrown) {
291   - alert('Send request - HTTP '+status+': '+errorThrown);
  298 + log.error('Send request - HTTP '+status, errorThrown);
292 299 },
293 300 complete: function() {
294 301 $.colorbox.close();
... ... @@ -311,7 +318,10 @@ function Cart(config) {
311 318 },
312 319 cache: false,
313 320 error: function(ajax, status, errorThrown) {
314   - alert('Error getting shopping cart - HTTP '+status+': '+errorThrown);
  321 + log.error('Error getting shopping cart - HTTP '+status, errorThrown);
  322 + if ( confirm(shoppingCartPluginL10n.getProblemConfirmReload) ) {
  323 + document.location.reload();
  324 + }
315 325 }
316 326 });
317 327 });
... ...
plugins/shopping_cart/views/cart.html.erb
... ... @@ -7,7 +7,7 @@
7 7 <a href="cart:clean" onclick="Cart.clean(this); return false" class="cart-clean"><%=_('Clean basket')%></a>
8 8 <ul class="cart-items"></ul>
9 9 <div class="cart-total"><%=_('Total:')%> <b></b></div>
10   - <a href="/plugin/shopping_cart/buy" class="cart-buy"><%=_('Shopping checkout')%></a>
  10 + <a href="/plugin/shopping_cart/buy" class="cart-buy colorbox"><%=_('Shopping checkout')%></a>
11 11 </div>
12 12 <a href="#" onclick="Cart.toggle(this); return false" class="cart-toggle">
13 13 <span class="str-show"><%=_('Show basket')%></span>
... ... @@ -15,3 +15,15 @@
15 15 </a>
16 16 </div>
17 17 </div>
  18 +<script>
  19 + shoppingCartPluginL10n = {
  20 + getProblemConfirmReload: <%= (
  21 + _('Ups... I had a problem to load the basket list.') +
  22 + "\n" +
  23 + _('Did you want to reload this page?')
  24 + ).to_json %>,
  25 + maxNumberOfItens: <%= (
  26 + _('Sorry, you can\'t have more then 100 kinds of items on this basket.')
  27 + ).to_json %>
  28 + }
  29 +</script>
... ...
public/javascripts/application.js
... ... @@ -918,6 +918,41 @@ function facet_options_toggle(id, url) {
918 918 });
919 919 }
920 920  
  921 +if ( !console ) console = {};
  922 +if ( !console.log ) console.log = function(){};
  923 +
  924 +// Two ways to call it:
  925 +// log(mixin1[, mixin2[, ...]]);
  926 +// log('<type>', mixin1[, mixin2[, ...]]);
  927 +// Where <type> may be: log, info warn, or error
  928 +window.log = function log() {
  929 + var type = arguments[0];
  930 + var argsClone = jQuery.merge([], arguments); // cloning the read-only arguments array.
  931 + if ( ['info', 'warn', 'error'].indexOf(type) == -1 ) {
  932 + type = 'log';
  933 + } else {
  934 + argsClone.shift();
  935 + }
  936 + var method = type;
  937 + if ( !console[method] ) method = 'log';
  938 + console[method].apply( console, jQuery.merge([(new Date).toISOString()], argsClone) );
  939 +}
  940 +
  941 +// Call log.info(mixin1[, mixin2[, ...]]);
  942 +log.info = function() {
  943 + window.log.apply(window, jQuery.merge(['info'], arguments));
  944 +}
  945 +
  946 +// Call log.warn(mixin1[, mixin2[, ...]]);
  947 +log.warn = function() {
  948 + window.log.apply(window, jQuery.merge(['warn'], arguments));
  949 +}
  950 +
  951 +// Call log.error(mixin1[, mixin2[, ...]]);
  952 +log.error = function() {
  953 + window.log.apply(window, jQuery.merge(['error'], arguments));
  954 +}
  955 +
921 956 jQuery(function($) {
922 957 $('.colorbox').live('click', function() {
923 958 $.fn.colorbox({
... ...