spree_image_multi_upload 1.0.0

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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +26 -0
  6. data/README.md +29 -0
  7. data/Rakefile +15 -0
  8. data/Versionfile +1 -0
  9. data/app/assets/javascripts/admin/jquery-fileupload/basic.js +4 -0
  10. data/app/assets/javascripts/admin/jquery-fileupload/cors/jquery.postmessage-transport.js +117 -0
  11. data/app/assets/javascripts/admin/jquery-fileupload/cors/jquery.xdr-transport.js +87 -0
  12. data/app/assets/javascripts/admin/jquery-fileupload/index.js +9 -0
  13. data/app/assets/javascripts/admin/jquery-fileupload/jquery.fileupload-fp.js +223 -0
  14. data/app/assets/javascripts/admin/jquery-fileupload/jquery.fileupload-ui.js +799 -0
  15. data/app/assets/javascripts/admin/jquery-fileupload/jquery.fileupload.js +1164 -0
  16. data/app/assets/javascripts/admin/jquery-fileupload/jquery.iframe-transport.js +185 -0
  17. data/app/assets/javascripts/admin/jquery-fileupload/locale.js.erb +30 -0
  18. data/app/assets/javascripts/admin/jquery-fileupload/vendor/canvas-to-blob.js +91 -0
  19. data/app/assets/javascripts/admin/jquery-fileupload/vendor/jquery.ui.widget.js +530 -0
  20. data/app/assets/javascripts/admin/jquery-fileupload/vendor/load-image.js +121 -0
  21. data/app/assets/javascripts/admin/jquery-fileupload/vendor/tmpl.js +86 -0
  22. data/app/assets/javascripts/admin/spree_image_multi_upload.js +3 -0
  23. data/app/assets/stylesheets/admin/jquery.fileupload-ui.scss +84 -0
  24. data/app/assets/stylesheets/admin/spree_image_multi_upload.css +4 -0
  25. data/app/controllers/spree/admin/images_controller_decorator.rb +39 -0
  26. data/app/models/image_decorator.rb +17 -0
  27. data/app/overrides/admin_decorator.rb +6 -0
  28. data/app/views/spree/admin/images/_template_download.html.erb +33 -0
  29. data/app/views/spree/admin/images/_template_upload.html.erb +36 -0
  30. data/app/views/spree/admin/images/multi_upload.html.erb +48 -0
  31. data/app/views/spree/admin/images/multi_upload.js.erb +4 -0
  32. data/config/locales/en.yml +15 -0
  33. data/config/locales/ru.yml +15 -0
  34. data/config/routes.rb +11 -0
  35. data/lib/generators/spree_image_multi_upload/install/install_generator.rb +16 -0
  36. data/lib/spree_image_multi_upload.rb +2 -0
  37. data/lib/spree_image_multi_upload/engine.rb +22 -0
  38. data/script/rails +7 -0
  39. data/spec/spec_helper.rb +46 -0
  40. data/spree_image_multi_upload.gemspec +25 -0
  41. metadata +154 -0
@@ -0,0 +1,121 @@
1
+ /*
2
+ * JavaScript Load Image 1.2.1
3
+ * https://github.com/blueimp/JavaScript-Load-Image
4
+ *
5
+ * Copyright 2011, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ */
11
+
12
+ /*jslint nomen: true */
13
+ /*global window, document, URL, webkitURL, Blob, File, FileReader, define */
14
+
15
+ (function ($) {
16
+ 'use strict';
17
+
18
+ // Loads an image for a given File object.
19
+ // Invokes the callback with an img or optional canvas
20
+ // element (if supported by the browser) as parameter:
21
+ var loadImage = function (file, callback, options) {
22
+ var img = document.createElement('img'),
23
+ url,
24
+ oUrl;
25
+ img.onerror = callback;
26
+ img.onload = function () {
27
+ if (oUrl && !(options && options.noRevoke)) {
28
+ loadImage.revokeObjectURL(oUrl);
29
+ }
30
+ callback(loadImage.scale(img, options));
31
+ };
32
+ if ((window.Blob && file instanceof Blob) ||
33
+ // Files are also Blob instances, but some browsers
34
+ // (Firefox 3.6) support the File API but not Blobs:
35
+ (window.File && file instanceof File)) {
36
+ url = oUrl = loadImage.createObjectURL(file);
37
+ } else {
38
+ url = file;
39
+ }
40
+ if (url) {
41
+ img.src = url;
42
+ return img;
43
+ }
44
+ return loadImage.readFile(file, function (url) {
45
+ img.src = url;
46
+ });
47
+ },
48
+ // The check for URL.revokeObjectURL fixes an issue with Opera 12,
49
+ // which provides URL.createObjectURL but doesn't properly implement it:
50
+ urlAPI = (window.createObjectURL && window) ||
51
+ (window.URL && URL.revokeObjectURL && URL) ||
52
+ (window.webkitURL && webkitURL);
53
+
54
+ // Scales the given image (img or canvas HTML element)
55
+ // using the given options.
56
+ // Returns a canvas object if the browser supports canvas
57
+ // and the canvas option is true or a canvas object is passed
58
+ // as image, else the scaled image:
59
+ loadImage.scale = function (img, options) {
60
+ options = options || {};
61
+ var canvas = document.createElement('canvas'),
62
+ width = img.width,
63
+ height = img.height,
64
+ scale = Math.max(
65
+ (options.minWidth || width) / width,
66
+ (options.minHeight || height) / height
67
+ );
68
+ if (scale > 1) {
69
+ width = parseInt(width * scale, 10);
70
+ height = parseInt(height * scale, 10);
71
+ }
72
+ scale = Math.min(
73
+ (options.maxWidth || width) / width,
74
+ (options.maxHeight || height) / height
75
+ );
76
+ if (scale < 1) {
77
+ width = parseInt(width * scale, 10);
78
+ height = parseInt(height * scale, 10);
79
+ }
80
+ if (img.getContext || (options.canvas && canvas.getContext)) {
81
+ canvas.width = width;
82
+ canvas.height = height;
83
+ canvas.getContext('2d')
84
+ .drawImage(img, 0, 0, width, height);
85
+ return canvas;
86
+ }
87
+ img.width = width;
88
+ img.height = height;
89
+ return img;
90
+ };
91
+
92
+ loadImage.createObjectURL = function (file) {
93
+ return urlAPI ? urlAPI.createObjectURL(file) : false;
94
+ };
95
+
96
+ loadImage.revokeObjectURL = function (url) {
97
+ return urlAPI ? urlAPI.revokeObjectURL(url) : false;
98
+ };
99
+
100
+ // Loads a given File object via FileReader interface,
101
+ // invokes the callback with a data url:
102
+ loadImage.readFile = function (file, callback) {
103
+ if (window.FileReader && FileReader.prototype.readAsDataURL) {
104
+ var fileReader = new FileReader();
105
+ fileReader.onload = function (e) {
106
+ callback(e.target.result);
107
+ };
108
+ fileReader.readAsDataURL(file);
109
+ return fileReader;
110
+ }
111
+ return false;
112
+ };
113
+
114
+ if (typeof define === 'function' && define.amd) {
115
+ define(function () {
116
+ return loadImage;
117
+ });
118
+ } else {
119
+ $.loadImage = loadImage;
120
+ }
121
+ }(this));
@@ -0,0 +1,86 @@
1
+ /*
2
+ * JavaScript Templates 2.1.0
3
+ * https://github.com/blueimp/JavaScript-Templates
4
+ *
5
+ * Copyright 2011, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ *
11
+ * Inspired by John Resig's JavaScript Micro-Templating:
12
+ * http://ejohn.org/blog/javascript-micro-templating/
13
+ */
14
+
15
+ /*jslint evil: true, regexp: true */
16
+ /*global document, define */
17
+
18
+ (function ($) {
19
+ "use strict";
20
+ var tmpl = function (str, data) {
21
+ var f = !/[^\w\-\.:]/.test(str) ? tmpl.cache[str] = tmpl.cache[str] ||
22
+ tmpl(tmpl.load(str)) :
23
+ new Function(
24
+ tmpl.arg + ',tmpl',
25
+ "var _e=tmpl.encode" + tmpl.helper + ",_s='" +
26
+ str.replace(tmpl.regexp, tmpl.func) +
27
+ "';return _s;"
28
+ );
29
+ return data ? f(data, tmpl) : function (data) {
30
+ return f(data, tmpl);
31
+ };
32
+ };
33
+ tmpl.cache = {};
34
+ tmpl.load = function (id) {
35
+ return document.getElementById(id).innerHTML;
36
+ };
37
+ tmpl.regexp = /([\s'\\])(?![^%]*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g;
38
+ tmpl.func = function (s, p1, p2, p3, p4, p5) {
39
+ if (p1) { // whitespace, quote and backspace in interpolation context
40
+ return {
41
+ "\n": "\\n",
42
+ "\r": "\\r",
43
+ "\t": "\\t",
44
+ " " : " "
45
+ }[s] || "\\" + s;
46
+ }
47
+ if (p2) { // interpolation: {%=prop%}, or unescaped: {%#prop%}
48
+ if (p2 === "=") {
49
+ return "'+_e(" + p3 + ")+'";
50
+ }
51
+ return "'+(" + p3 + "||'')+'";
52
+ }
53
+ if (p4) { // evaluation start tag: {%
54
+ return "';";
55
+ }
56
+ if (p5) { // evaluation end tag: %}
57
+ return "_s+='";
58
+ }
59
+ };
60
+ tmpl.encReg = /[<>&"'\x00]/g;
61
+ tmpl.encMap = {
62
+ "<" : "&lt;",
63
+ ">" : "&gt;",
64
+ "&" : "&amp;",
65
+ "\"" : "&quot;",
66
+ "'" : "&#39;"
67
+ };
68
+ tmpl.encode = function (s) {
69
+ return String(s || "").replace(
70
+ tmpl.encReg,
71
+ function (c) {
72
+ return tmpl.encMap[c] || "";
73
+ }
74
+ );
75
+ };
76
+ tmpl.arg = "o";
77
+ tmpl.helper = ",print=function(s,e){_s+=e&&(s||'')||_e(s);}" +
78
+ ",include=function(s,d){_s+=tmpl(s,d);}";
79
+ if (typeof define === "function" && define.amd) {
80
+ define(function () {
81
+ return tmpl;
82
+ });
83
+ } else {
84
+ $.tmpl = tmpl;
85
+ }
86
+ }(this));
@@ -0,0 +1,3 @@
1
+ //= require admin/spree_core
2
+ //= require admin/jquery-fileupload/index
3
+
@@ -0,0 +1,84 @@
1
+ @charset 'UTF-8';
2
+ /*
3
+ * jQuery File Upload UI Plugin CSS 6.3
4
+ * https://github.com/blueimp/jQuery-File-Upload
5
+ *
6
+ * Copyright 2010, Sebastian Tschan
7
+ * https://blueimp.net
8
+ *
9
+ * Licensed under the MIT license:
10
+ * http://www.opensource.org/licenses/MIT
11
+ */
12
+
13
+ .fileinput-button {
14
+ position: relative;
15
+ overflow: hidden;
16
+ float: left;
17
+ margin-right: 4px;
18
+ }
19
+ .fileinput-button input {
20
+ position: absolute;
21
+ top: 0;
22
+ right: 0;
23
+ margin: 0;
24
+ border: solid transparent;
25
+ border-width: 0 0 100px 200px;
26
+ opacity: 0;
27
+ filter: alpha(opacity=0);
28
+ -moz-transform: translate(-300px, 0) scale(4);
29
+ direction: ltr;
30
+ cursor: pointer;
31
+ }
32
+ .fileupload-buttonbar .btn,
33
+ .fileupload-buttonbar .toggle {
34
+ margin-bottom: 5px;
35
+ }
36
+ .files .progress {
37
+ width: 200px;
38
+ }
39
+ .progress-animated .bar {
40
+ background: image-url('progressbar.gif') !important;
41
+ filter: none;
42
+ }
43
+ .fileupload-loading {
44
+ position: absolute;
45
+ left: 50%;
46
+ width: 128px;
47
+ height: 128px;
48
+ background: image-url('loading.gif') center no-repeat;
49
+ display: none;
50
+ }
51
+ .fileupload-processing .fileupload-loading {
52
+ display: block;
53
+ }
54
+
55
+ /* Fix for IE 6: */
56
+ * html .fileinput-button {
57
+ line-height: 22px;
58
+ margin: 1px -3px 0 0;
59
+ }
60
+
61
+ /* Fix for IE 7: */
62
+ * + html .fileinput-button {
63
+ margin: 1px 0 0 0;
64
+ }
65
+
66
+ @media (max-width: 480px) {
67
+ .files .btn span {
68
+ display: none;
69
+ }
70
+ .files .preview * {
71
+ width: 40px;
72
+ }
73
+ .files .name * {
74
+ width: 80px;
75
+ display: inline-block;
76
+ word-wrap: break-word;
77
+ }
78
+ .files .progress {
79
+ width: 20px;
80
+ }
81
+ .files .delete {
82
+ width: 60px;
83
+ }
84
+ }
@@ -0,0 +1,4 @@
1
+ /*
2
+ *= require admin/spree_core
3
+ *= require admin/jquery.fileupload-ui
4
+ */
@@ -0,0 +1,39 @@
1
+ Spree::Admin::ImagesController.class_eval do
2
+
3
+ def create
4
+
5
+ product = Spree::Product.where('slug' => params['product_id'])
6
+ params[object_name][:attachment].each do |attachment_object|
7
+ #@object.attributes = params[object_name]
8
+ product = Spree::Product.where('slug' => params['product_id'])
9
+ #@object = Spree::Image.create
10
+ #@object.viewable.product = product
11
+ #@object.viewable_id = product[0].id
12
+
13
+
14
+ image = Spree::Image.new
15
+ image.attachment = attachment_object
16
+ image.viewable_id = params[:image][:viewable_id] #product[0].id
17
+ image.type = 'Spree::Image'
18
+ image.viewable_type = 'Spree::Variant'
19
+ #binding.pry
20
+ image.save
21
+
22
+ #invoke_callbacks(:create, :before)
23
+ #@object.attachment = attachment_object
24
+ #@object.save
25
+ #invoke_callbacks(:create, :after)
26
+
27
+ end
28
+ redirect_to '/admin/products/' + product[0].slug + '/images' #admin_product_url(product)
29
+
30
+ end
31
+
32
+ def multi_upload
33
+
34
+ end
35
+
36
+ def new_actions
37
+ [:new, :create, :multi_upload]
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ Spree::Image.class_eval do
2
+
3
+ def to_jq_upload
4
+ {
5
+ 'name' => read_attribute(:attachment_file_name),
6
+ 'size' => read_attribute(:attachment_file_size),
7
+ 'thumbnail_url' => attachment.url(:mini, false),
8
+ 'url' => attachment.url(:product, false),
9
+
10
+ # TODO: find the way to generate edit and delete urls here
11
+ #include Rails.application.routes.url_helpers doesn't work
12
+ 'edit_url' => '',
13
+ 'delete_url' => ''
14
+ }
15
+ end
16
+
17
+ end
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ :virtual_path => 'spree/admin/images/index',
3
+ :replace => %q{code[erb-loud]:contains('t(:new_image)')},
4
+ :text => %q{<%= link_to_with_icon('icon-upload', t('multi_upload.title'), multi_upload_admin_product_images_path(@product), :id => 'multi_upload_images_link', :class => 'button', :remote => true) %>},
5
+ :name => 'add_images_multi_upload_button'
6
+ )
@@ -0,0 +1,33 @@
1
+ <script id="template-download" type="text/x-tmpl">
2
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
3
+ <tr class="template-download fade">
4
+
5
+ {% if (file.error) { %}
6
+
7
+ <td class="name"><span>{%=file.name%}</span></td>
8
+ <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
9
+ <td class="error"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] ||
10
+ file.error%}
11
+ </td>
12
+
13
+ {% } else { %}
14
+
15
+ <td class="preview">{% if (file.thumbnail_url) { %}
16
+ <a href="{%=file.url%}" title="{%=file.name%}" rel="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}"></a>
17
+ {% } %}
18
+ </td>
19
+ <td class="name">
20
+ <a href="{%=file.url%}" title="{%=file.name%}" rel="{%=file.thumbnail_url&&'gallery'%}" download="{%=file.name%}">{%=file.name%}</a>
21
+ </td>
22
+ <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
23
+
24
+ {% } %}
25
+
26
+ <td class="actions">
27
+ <a data-action="edit" class="icon_link with-tip icon-edit no-text" href="{%=file.edit_url%}" target="_blank"></a>
28
+ <a url="{%=file.delete_url%}" data-confirm="<%= t(:are_you_sure) %>" data-action="remove" class="delete-resource icon_link with-tip icon-trash no-text" href="{%=file.delete_url%}"></a>
29
+ </td>
30
+
31
+ </tr>
32
+ {% } %}
33
+ </script>
@@ -0,0 +1,36 @@
1
+ <script id="template-upload" type="text/x-tmpl">
2
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
3
+ <tr class="template-upload fade">
4
+ <td class="preview"><span class="fade"></span></td>
5
+ <td class="name"><span>{%=file.name%}</span></td>
6
+
7
+ {% if (file.error) { %}
8
+ <td class="error">
9
+ <span class="label label-important"><%= t(:error) %></span>
10
+ {%=locale.fileupload.errors[file.error] || file.error%}
11
+ </td>
12
+ {% } else if (o.files.valid) { %}
13
+ <td class="size">
14
+ <span>{%=o.formatFileSize(file.size)%}</span>
15
+ </td>
16
+ {% } %}
17
+
18
+ <td class="actions">
19
+
20
+ {% if (!o.options.autoUpload) { %}
21
+ <span class="start">
22
+ <button class="button icon-upload">{%=locale.fileupload.start%}</button>
23
+ </span>
24
+ {% } %}
25
+
26
+ {% if (!i) { %}
27
+ <span class="cancel">
28
+ <button class="button icon-ban-circle">{%=locale.fileupload.cancel%}</button>
29
+ </span>
30
+ {% } %}
31
+
32
+ </td>
33
+
34
+ </tr>
35
+ {% } %}
36
+ </script>
@@ -0,0 +1,48 @@
1
+ <%= render :partial => 'spree/admin/shared/product_sub_menu' %>
2
+ <%= render :partial => 'spree/admin/shared/product_tabs', :locals => { :current => 'Images' } %>
3
+
4
+ <%= render :partial => 'spree/shared/error_messages', :locals => {:target => @product} %>
5
+
6
+ <%= form_for [:admin, @product, @image], :html => {:multipart => true, :id => "fileupload", :method => :post} do |f| %>
7
+ <fieldset data-hook="new_product">
8
+ <legend align="center"><%= t('multi_upload.title') %></legend>
9
+
10
+ <div class="row fileupload-buttonbar">
11
+ <div data-hook="variant" class="field">
12
+ <%= f.label Spree::Variant.model_name.human %>
13
+ <br>
14
+ <%= f.select :viewable_id, @variants, {}, {:class => 'select2'} %>
15
+ </div>
16
+
17
+ <span class="icon-plus button fileinput-button">
18
+ <%= t('multi_upload.add_files') %>
19
+ <%= f.file_field :attachment, {:multiple => true} %>
20
+ </span>
21
+
22
+ <button type="submit" class="icon-upload button start"><%= t('multi_upload.start') %></button>
23
+ <button type="reset" class="icon-ban-circle button cancel"><%= t('multi_upload.cancel') %></button>
24
+
25
+ </div>
26
+
27
+ <div class="fileupload-progress fade">
28
+ <div class="progress-extended">&nbsp;</div>
29
+ </div>
30
+
31
+ <br />
32
+
33
+ <table role="presentation" class="table table-striped">
34
+ <tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody>
35
+ </table>
36
+
37
+ </fieldset>
38
+ <% end %>
39
+
40
+ <script type="text/javascript" charset="utf-8">
41
+ $(function () {
42
+ $('#fileupload').fileupload();
43
+ });
44
+ </script>
45
+
46
+ <%= render :partial => 'template_upload' %>
47
+ <%= render :partial => 'template_download' %>
48
+