spree_reviews_rating 0.70.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/README.md +30 -0
  2. data/app/assets/images/background.gif +0 -0
  3. data/app/assets/images/cancel-off-big.png +0 -0
  4. data/app/assets/images/cancel-off.png +0 -0
  5. data/app/assets/images/cancel-on-big.png +0 -0
  6. data/app/assets/images/cancel-on.png +0 -0
  7. data/app/assets/images/coffee.png +0 -0
  8. data/app/assets/images/face-a-off.png +0 -0
  9. data/app/assets/images/face-a.png +0 -0
  10. data/app/assets/images/face-b-off.png +0 -0
  11. data/app/assets/images/face-b.png +0 -0
  12. data/app/assets/images/face-c-off.png +0 -0
  13. data/app/assets/images/face-c.png +0 -0
  14. data/app/assets/images/face-d-off.png +0 -0
  15. data/app/assets/images/face-d.png +0 -0
  16. data/app/assets/images/face-off.png +0 -0
  17. data/app/assets/images/medal-off.png +0 -0
  18. data/app/assets/images/medal-on.png +0 -0
  19. data/app/assets/images/ratyloader.gif +0 -0
  20. data/app/assets/images/star-half-big.png +0 -0
  21. data/app/assets/images/star-half.png +0 -0
  22. data/app/assets/images/star-off-big.png +0 -0
  23. data/app/assets/images/star-off.png +0 -0
  24. data/app/assets/images/star-on-big.png +0 -0
  25. data/app/assets/images/star-on.png +0 -0
  26. data/app/assets/javascripts/admin/spree_reviews_rating.js +1 -0
  27. data/app/assets/javascripts/store/review/index.js +15 -0
  28. data/app/assets/javascripts/store/review/new.js +17 -0
  29. data/app/assets/javascripts/store/spree_reviews_rating.js +450 -0
  30. data/app/assets/stylesheets/admin/spree_reviews_rating.css +3 -0
  31. data/app/assets/stylesheets/store/spree_reviews_rating.css +95 -0
  32. data/app/controllers/admin/feedback_reviews_controller.rb +6 -0
  33. data/app/controllers/admin/review_settings_controller.rb +16 -0
  34. data/app/controllers/admin/reviews_controller.rb +20 -0
  35. data/app/controllers/feedback_reviews_controller.rb +20 -0
  36. data/app/controllers/products_controller_decorator.rb +3 -0
  37. data/app/controllers/reviews_controller.rb +52 -0
  38. data/app/helpers/admin/feedback_reviews_helper.rb +2 -0
  39. data/app/helpers/feedback_reviews_helper.rb +2 -0
  40. data/app/helpers/reviews_helper.rb +11 -0
  41. data/app/models/app_configuration_decorator.rb +16 -0
  42. data/app/models/feedback_review.rb +10 -0
  43. data/app/models/product_decorator.rb +16 -0
  44. data/app/models/review.rb +21 -0
  45. data/app/models/review_sweeper.rb +21 -0
  46. data/app/models/reviews_ability.rb +12 -0
  47. data/app/overrides/add_review_bottom_sidebar.rb +4 -0
  48. data/app/overrides/add_reviews_after_product_properties.rb +4 -0
  49. data/app/overrides/add_reviews_tab_to_admin.rb +4 -0
  50. data/app/overrides/add_reviews_to_admin_configuration_menu.rb +4 -0
  51. data/app/views/admin/feedback_reviews/index.html.erb +21 -0
  52. data/app/views/admin/review_settings/edit.html.erb +30 -0
  53. data/app/views/admin/review_settings/show.html.erb +30 -0
  54. data/app/views/admin/reviews/_form.html.erb +10 -0
  55. data/app/views/admin/reviews/edit.html.erb +17 -0
  56. data/app/views/admin/reviews/index.html.erb +51 -0
  57. data/app/views/feedback_reviews/_form.html.erb +15 -0
  58. data/app/views/feedback_reviews/_summary.html.erb +6 -0
  59. data/app/views/feedback_reviews/create.js.erb +7 -0
  60. data/app/views/reviews/_fine_print.html.erb +9 -0
  61. data/app/views/reviews/_form.html.erb +23 -0
  62. data/app/views/reviews/_stars.html.erb +16 -0
  63. data/app/views/reviews/all_list.html.erb +42 -0
  64. data/app/views/reviews/index.html.erb +1 -0
  65. data/app/views/reviews/new.html.erb +5 -0
  66. data/app/views/reviews/submissionguidelines.html.erb +6 -0
  67. data/app/views/reviews/terms.html.erb +6 -0
  68. data/app/views/shared/_rating.html.erb +25 -0
  69. data/app/views/shared/_review.html.erb +17 -0
  70. data/app/views/shared/_review_link.html.erb +4 -0
  71. data/app/views/shared/_review_summary.html.erb +10 -0
  72. data/app/views/shared/_reviews.html.erb +13 -0
  73. data/app/views/shared/_shortrating.html.erb +8 -0
  74. data/lib/generators/spree_reviews_rating/install/install_generator.rb +29 -0
  75. data/lib/spree_reviews_rating/engine.rb +24 -0
  76. data/lib/spree_reviews_rating.rb +2 -0
  77. metadata +213 -0
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ Reviews
2
+ =======
3
+
4
+ Straightforward review/rating facility
5
+
6
+
7
+ Installation
8
+ ------------
9
+ 1. Add the following to your Gemfile
10
+ <pre>
11
+ gem 'spree_reviews_rating', '~> 0.70.3'
12
+ </pre>
13
+ 2. Run `bundle install`
14
+ 3. To copy and apply migrations run:
15
+ <pre>
16
+ rails g spree_reviews_rating:install
17
+ </pre>
18
+
19
+
20
+ Usage
21
+ -----
22
+
23
+ 1. Action "submit" in "reviews" controller - goes to review entry form
24
+
25
+ 2. Users must be logged in to submit a review
26
+
27
+ 3. Administrator can edit and/or approve and/or delete reviews.
28
+
29
+
30
+ Copyright (c) 2012 [Damiano Giacomello], released under the New BSD License
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ //= require admin/spree_core
@@ -0,0 +1,15 @@
1
+ $(document).ready(function(){
2
+
3
+ $('.button-review').click(function (event) {
4
+ event.preventDefault();
5
+ $(this).hide();
6
+ $(".ratings").hide();
7
+ $.ajax({
8
+ type: 'GET',
9
+ url: this.href,
10
+ data: ({authenticity_token: jQuery('meta[name="csrf-token"]').attr('content')}),
11
+ beforeSend: function(r){ $('#new_review').html('<p style="padding: 20px">Loading <img src="/assets/ratyloader.gif"/></p>');},
12
+ success: function(r){ $('#new_review').html(r);} });
13
+ });
14
+
15
+ });
@@ -0,0 +1,17 @@
1
+ $('.cancel-review').click(function (event) {
2
+ event.preventDefault();
3
+ $('.button-review').show();
4
+ $(".ratings").show();
5
+ $('#new_review').html('');
6
+ });
7
+
8
+ $('.button-submit').click(function (event) {
9
+ event.preventDefault();
10
+ $.ajax({
11
+ type: 'POST',
12
+ url: $("#new_review").action,
13
+ data: ({authenticity_token: jQuery('meta[name="csrf-token"]').attr('content'), 'review[]': [$("#new_review").serializeArray()]}),
14
+ beforeSend: function(r){ $('#new_review').html('<p style="padding: 20px">Loading <img src="/assets/ratyloader.gif"/></p>');},
15
+ success: function(r){ $('#new_review').html(r);} });
16
+ });
17
+ });
@@ -0,0 +1,450 @@
1
+ /*
2
+ * jQuery Raty - A Star Rating Plugin - http://wbotelhos.com/raty
3
+ * ---------------------------------------------------------------------
4
+ *
5
+ * jQuery Raty is a plugin that generates a customizable star rating.
6
+ *
7
+ * Licensed under The MIT License
8
+ *
9
+ * @version 2.1.0
10
+ * @since 2010.06.11
11
+ * @author Washington Botelho
12
+ * @documentation wbotelhos.com/raty
13
+ * @twitter twitter.com/wbotelhos
14
+ *
15
+ * Usage with default values:
16
+ * ---------------------------------------------------------------------
17
+ *
18
+ */
19
+
20
+ ;(function($) {
21
+
22
+ var methods = {
23
+ init: function(options) {
24
+ return this.each(function() {
25
+
26
+ var opt = $.extend(true, {}, $.fn.raty.defaults, options),
27
+ $this = $(this).data('options', opt);
28
+
29
+ if (opt.number > 20) {
30
+ opt.number = 20;
31
+ } else if (opt.number < 0) {
32
+ opt.number = 0;
33
+ }
34
+
35
+ if (opt.path.substring(opt.path.length - 1, opt.path.length) != '/') {
36
+ opt.path += '/';
37
+ }
38
+
39
+ if (typeof opt.start == 'function') {
40
+ opt.start = opt.start.call(this);
41
+ }
42
+
43
+ var isValidStart = !isNaN(parseInt(opt.start, 10)),
44
+ start = '';
45
+
46
+ if (isValidStart) {
47
+ start = (opt.start > opt.number) ? opt.number : opt.start;
48
+ }
49
+
50
+ var starFile = opt.starOn,
51
+ space = (opt.space) ? 4 : 0,
52
+ hint = '';
53
+
54
+ for (var i = 1; i <= opt.number; i++) {
55
+ starFile = (start < i) ? opt.starOff : opt.starOn;
56
+
57
+ hint = (i <= opt.hintList.length && opt.hintList[i - 1] !== null) ? opt.hintList[i - 1] : i;
58
+
59
+ $this.append('<img src="' + opt.path + starFile + '" alt="' + i + '" title="' + hint + '" />');
60
+
61
+ if (opt.space) {
62
+ $this.append((i < opt.number) ? '&nbsp;' : '');
63
+ }
64
+ }
65
+
66
+ var $score = $('<input/>', { type: 'hidden', name: opt.scoreName}).appendTo($this);
67
+
68
+ if (isValidStart) {
69
+ if (opt.start > 0) {
70
+ $score.val(start);
71
+ }
72
+
73
+ methods.roundStar.call($this, start);
74
+ }
75
+
76
+ if (opt.iconRange) {
77
+ methods.fillStar.call($this, start);
78
+ }
79
+
80
+ methods.setTarget.call($this, start, opt.targetKeep);
81
+
82
+ var width = opt.width || (opt.number * opt.size + opt.number * space);
83
+
84
+ if (opt.cancel) {
85
+ var $cancel = $('<img src="' + opt.path + opt.cancelOff + '" alt="x" title="' + opt.cancelHint + '" class="raty-cancel"/>');
86
+
87
+ if (opt.cancelPlace == 'left') {
88
+ $this.prepend('&nbsp;').prepend($cancel);
89
+ } else {
90
+ $this.append('&nbsp;').append($cancel);
91
+ }
92
+
93
+ width += opt.size + space;
94
+ }
95
+
96
+ if (opt.readOnly) {
97
+ methods.fixHint.call($this);
98
+
99
+ $this.children('.raty-cancel').hide();
100
+ } else {
101
+ $this.css('cursor', 'pointer');
102
+
103
+ methods.bindAction.call($this);
104
+ }
105
+
106
+ $this.css('width', width);
107
+ });
108
+ }, bindAction: function() {
109
+ var self = this,
110
+ opt = this.data('options'),
111
+ $score = this.children('input');
112
+
113
+ self.mouseleave(function() {
114
+ methods.initialize.call(self, $score.val());
115
+
116
+ methods.setTarget.call(self, $score.val(), opt.targetKeep);
117
+ });
118
+
119
+ var $stars = this.children('img').not('.raty-cancel'),
120
+ action = (opt.half) ? 'mousemove' : 'mouseover';
121
+
122
+ if (opt.cancel) {
123
+ self.children('.raty-cancel').mouseenter(function() {
124
+ $(this).attr('src', opt.path + opt.cancelOn);
125
+
126
+ $stars.attr('src', opt.path + opt.starOff);
127
+
128
+ methods.setTarget.call(self, null, true);
129
+ }).mouseleave(function() {
130
+ $(this).attr('src', opt.path + opt.cancelOff);
131
+
132
+ self.mouseout();
133
+ }).click(function(evt) {
134
+ $score.removeAttr('value');
135
+
136
+ if (opt.click) {
137
+ opt.click.call(self[0], null, evt);
138
+ }
139
+ });
140
+ }
141
+
142
+ $stars.bind(action, function(evt) {
143
+ var value = parseInt(this.alt, 10);
144
+
145
+ if (opt.half) {
146
+ var position = parseFloat((evt.pageX - $(this).offset().left) / opt.size),
147
+ diff = (position > .5) ? 1 : .5;
148
+
149
+ value = parseFloat(this.alt) - 1 + diff;
150
+
151
+ methods.fillStar.call(self, value);
152
+
153
+ if (opt.precision) {
154
+ value = value - diff + position;
155
+ }
156
+
157
+ methods.showHalf.call(self, value);
158
+ } else {
159
+ methods.fillStar.call(self, value);
160
+ }
161
+
162
+ self.data('score', value);
163
+
164
+ methods.setTarget.call(self, value, true);
165
+ }).click(function(evt) {
166
+ $score.val((opt.half || opt.precision) ? self.data('score') : this.alt);
167
+
168
+ if (opt.click) {
169
+ opt.click.call(self[0], $score.val(), evt);
170
+ }
171
+ });
172
+ }, cancel: function(isClick) {
173
+ return this.each(function() {
174
+ var $this = $(this);
175
+
176
+ if ($this.data('readonly') == 'readonly') {
177
+ return false;
178
+ }
179
+
180
+ if (isClick) {
181
+ methods.click.call($this, null);
182
+ } else {
183
+ methods.start.call($this, null);
184
+ }
185
+
186
+ $this.mouseleave().children('input').removeAttr('value');
187
+ });
188
+ }, click: function(score) {
189
+ return this.each(function() {
190
+ var $this = $(this);
191
+
192
+ if ($this.data('readonly') == 'readonly') {
193
+ return false;
194
+ }
195
+
196
+ methods.initialize.call($this, score);
197
+
198
+ var opt = $this.data('options');
199
+
200
+ if (opt.click) {
201
+ opt.click.call($this[0], score);
202
+ } else {
203
+ $.error('you must add the "click: function(score, evt) { }" callback.');
204
+ }
205
+
206
+ methods.setTarget.call($this, score, true);
207
+ });
208
+ }, fillStar: function(score) {
209
+ var opt = this.data('options'),
210
+ $stars = this.children('img').not('.raty-cancel'),
211
+ qtyStar = $stars.length,
212
+ count = 0,
213
+ $star ,
214
+ star ,
215
+ icon ;
216
+
217
+ for (var i = 1; i <= qtyStar; i++) {
218
+ $star = $stars.eq(i - 1);
219
+
220
+ if (opt.iconRange && opt.iconRange.length > count) {
221
+ star = opt.iconRange[count];
222
+
223
+ if (opt.single) {
224
+ icon = (i == score) ? (star.on || opt.starOn) : (star.off || opt.starOff);
225
+ } else {
226
+ icon = (i <= score) ? (star.on || opt.starOn) : (star.off || opt.starOff);
227
+ }
228
+
229
+ if (i <= star.range) {
230
+ $star.attr('src', opt.path + icon);
231
+ }
232
+
233
+ if (i == star.range) {
234
+ count++;
235
+ }
236
+ } else {
237
+ if (opt.single) {
238
+ icon = (i == score) ? opt.starOn : opt.starOff;
239
+ } else {
240
+ icon = (i <= score) ? opt.starOn : opt.starOff;
241
+ }
242
+
243
+ $star.attr('src', opt.path + icon);
244
+ }
245
+ }
246
+ }, fixHint: function() {
247
+ var opt = this.data('options'),
248
+ $score = this.children('input'),
249
+ score = parseInt($score.val(), 10),
250
+ hint = opt.noRatedMsg;
251
+
252
+ if (!isNaN(score) && score > 0) {
253
+ hint = (score <= opt.hintList.length && opt.hintList[score - 1] !== null) ? opt.hintList[score - 1] : score;
254
+ }
255
+
256
+ $score.attr('readonly', 'readonly');
257
+ this.css('cursor', 'default').data('readonly', 'readonly').attr('title', hint).children('img').attr('title', hint);
258
+ }, readOnly: function(isReadOnly) {
259
+ return this.each(function() {
260
+ var $this = $(this),
261
+ $cancel = $this.children('.raty-cancel');
262
+
263
+ if ($cancel.length) {
264
+ if (isReadOnly) {
265
+ $cancel.hide();
266
+ } else {
267
+ $cancel.show();
268
+ }
269
+ }
270
+
271
+ if (isReadOnly) {
272
+ $this.unbind();
273
+
274
+ $this.children('img').unbind();
275
+
276
+ methods.fixHint.call($this);
277
+ } else {
278
+ methods.bindAction.call($this);
279
+
280
+ methods.unfixHint.call($this);
281
+ }
282
+ });
283
+ }, roundStar: function(score) {
284
+ var opt = this.data('options'),
285
+ diff = (score - Math.floor(score)).toFixed(2);
286
+
287
+ if (diff > opt.round.down) {
288
+ var icon = opt.starOn; // Full up: [x.76 .. x.99]
289
+
290
+ if (diff < opt.round.up && opt.halfShow) { // Half: [x.26 .. x.75]
291
+ icon = opt.starHalf;
292
+ } else if (diff < opt.round.full) { // Full down: [x.00 .. x.5]
293
+ icon = opt.starOff;
294
+ }
295
+
296
+ this.children('img').not('.raty-cancel').eq(Math.ceil(score) - 1).attr('src', opt.path + icon);
297
+ } // Full down: [x.00 .. x.25]
298
+ }, score: function() {
299
+ var score = [],
300
+ value ;
301
+
302
+ this.each(function() {
303
+ value = $(this).children('input').val();
304
+ value = (value == '') ? null : parseFloat(value);
305
+
306
+ score.push(value);
307
+ });
308
+
309
+ return (score.length > 1) ? score : score[0];
310
+ }, setTarget: function(value, isKeep) {
311
+ var opt = this.data('options');
312
+
313
+ if (opt.target) {
314
+ var $target = $(opt.target);
315
+
316
+ if ($target.length == 0) {
317
+ $.error('target selector invalid or missing!');
318
+ } else {
319
+ var score = value;
320
+
321
+ if (score == null && !opt.cancel) {
322
+ $.error('you must enable the "cancel" option to set hint on target.');
323
+ } else {
324
+ if (!isKeep || score == '') {
325
+ score = opt.targetText;
326
+ } else {
327
+ if (opt.targetType == 'hint') {
328
+ if (score === null && opt.cancel) {
329
+ score = opt.cancelHint;
330
+ } else {
331
+ score = opt.hintList[Math.ceil(score - 1)];
332
+ }
333
+ } else {
334
+ if (score != '' && !opt.precision) {
335
+ score = parseInt(score, 10);
336
+ } else {
337
+ score = parseFloat(score).toFixed(1);
338
+ }
339
+ }
340
+ }
341
+
342
+ if (opt.targetFormat.indexOf('{score}') < 0) {
343
+ $.error('template "{score}" missing!');
344
+ } else if (value !== null) {
345
+ score = opt.targetFormat.toString().replace('{score}', score);
346
+ }
347
+
348
+ if ($target.is(':input')) {
349
+ $target.val(score);
350
+ } else {
351
+ $target.html(score);
352
+ }
353
+ }
354
+ }
355
+ }
356
+ }, showHalf: function(score) {
357
+ var opt = this.data('options'),
358
+ diff = (score - Math.floor(score)).toFixed(1);
359
+
360
+ if (diff > 0 && diff < .6) {
361
+ this.children('img').not('.raty-cancel').eq(Math.ceil(score) - 1).attr('src', opt.path + opt.starHalf);
362
+ }
363
+ }, start: function(score) {
364
+ return this.each(function() {
365
+ var $this = $(this);
366
+
367
+ if ($this.data('readonly') == 'readonly') {
368
+ return false;
369
+ }
370
+
371
+ methods.initialize.call($this, score);
372
+
373
+ var opt = $this.data('options');
374
+
375
+ methods.setTarget.call($this, score, true);
376
+ });
377
+ }, initialize: function(score) {
378
+ var opt = this.data('options');
379
+
380
+ if (score < 0) {
381
+ score = 0;
382
+ } else if (score > opt.number) {
383
+ score = opt.number;
384
+ }
385
+
386
+ methods.fillStar.call(this, score);
387
+
388
+ if (score != '') {
389
+ if (opt.halfShow) {
390
+ methods.roundStar.call(this, score);
391
+ }
392
+
393
+ this.children('input').val(score);
394
+ }
395
+ }, unfixHint: function() {
396
+ var opt = this.data('options'),
397
+ $imgs = this.children('img').filter(':not(.raty-cancel)');
398
+
399
+ for (var i = 0; i < opt.number; i++) {
400
+ $imgs.eq(i).attr('title', (i < opt.hintList.length && opt.hintList[i] !== null) ? opt.hintList[i] : i);
401
+ }
402
+
403
+ this.css('cursor', 'pointer').removeData('readonly').removeAttr('title').children('input').attr('readonly', 'readonly');
404
+ }
405
+ };
406
+
407
+ $.fn.raty = function(method) {
408
+ if (methods[method]) {
409
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
410
+ } else if (typeof method === 'object' || !method) {
411
+ return methods.init.apply(this, arguments);
412
+ } else {
413
+ $.error('Method ' + method + ' does not exist!');
414
+ }
415
+ };
416
+
417
+ $.fn.raty.defaults = {
418
+ cancel: false,
419
+ cancelHint: 'cancel this rating!',
420
+ cancelOff: 'cancel-off.png',
421
+ cancelOn: 'cancel-on.png',
422
+ cancelPlace: 'left',
423
+ click: undefined,
424
+ half: false,
425
+ halfShow: true,
426
+ hintList: ['1', '2', '3', '4', '5'],
427
+ iconRange: undefined,
428
+ noRatedMsg: 'not rated yet',
429
+ number: 5,
430
+ path: '/assets/',
431
+ precision: false,
432
+ round: { down: .25, full: .6, up: .76 },
433
+ readOnly: false,
434
+ scoreName: 'score',
435
+ single: false,
436
+ size: 16,
437
+ space: true,
438
+ starHalf: 'star-half-big.png',
439
+ starOff: 'star-off-big.png',
440
+ starOn: 'star-on-big.png',
441
+ start: 0,
442
+ target: undefined,
443
+ targetFormat: '{score}',
444
+ targetKeep: false,
445
+ targetText: '',
446
+ targetType: 'hint',
447
+ width: undefined
448
+ };
449
+
450
+ })(jQuery);