spree_image_multi_upload 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+