rails_admin_uploader 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 (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +78 -0
  6. data/Rakefile +1 -0
  7. data/app/assets/images/rails_admin_uploader/loading.gif +0 -0
  8. data/app/assets/images/rails_admin_uploader/progressbar.gif +0 -0
  9. data/app/assets/javascripts/rails_admin_uploader.coffee +261 -0
  10. data/app/assets/javascripts/rails_admin_uploader/canvas-to-blob.js +95 -0
  11. data/app/assets/javascripts/rails_admin_uploader/jquery.fileupload-audio.js +112 -0
  12. data/app/assets/javascripts/rails_admin_uploader/jquery.fileupload-image.js +321 -0
  13. data/app/assets/javascripts/rails_admin_uploader/jquery.fileupload-process.js +175 -0
  14. data/app/assets/javascripts/rails_admin_uploader/jquery.fileupload-ui.js +710 -0
  15. data/app/assets/javascripts/rails_admin_uploader/jquery.fileupload-validate.js +122 -0
  16. data/app/assets/javascripts/rails_admin_uploader/jquery.fileupload-video.js +112 -0
  17. data/app/assets/javascripts/rails_admin_uploader/jquery.fileupload.js +1477 -0
  18. data/app/assets/javascripts/rails_admin_uploader/jquery.iframe-transport.js +217 -0
  19. data/app/assets/javascripts/rails_admin_uploader/load-image.all.min.js +1 -0
  20. data/app/assets/javascripts/rails_admin_uploader/tmpl.js +87 -0
  21. data/app/assets/stylesheets/rails_admin_uploader.sass +2 -0
  22. data/app/assets/stylesheets/rails_admin_uploader/jquery.fileupload-ui.scss +57 -0
  23. data/app/assets/stylesheets/rails_admin_uploader/jquery.fileupload.scss +37 -0
  24. data/app/controllers/rails_admin_uploader/attachments_controller.rb +94 -0
  25. data/app/views/rails_admin/main/_rails_admin_uploader.html.haml +16 -0
  26. data/bin/console +14 -0
  27. data/bin/setup +7 -0
  28. data/config/locales/ru.yml +6 -0
  29. data/config/routes.rb +8 -0
  30. data/lib/rails_admin_uploader.rb +15 -0
  31. data/lib/rails_admin_uploader/asset.rb +19 -0
  32. data/lib/rails_admin_uploader/base.rb +50 -0
  33. data/lib/rails_admin_uploader/engine.rb +6 -0
  34. data/lib/rails_admin_uploader/field.rb +12 -0
  35. data/lib/rails_admin_uploader/version.rb +3 -0
  36. data/rails_admin_uploader.gemspec +24 -0
  37. metadata +107 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fdc91b58e311a7ff0e82b52fade2fb14ebf6d885
4
+ data.tar.gz: 5f14d3f71459413afb96a773ed01b99911d1a3fa
5
+ SHA512:
6
+ metadata.gz: 3a23bb89acbb9557bf99aacd9563798bddc30ce62adade4d027575c3ff165652c8a7042249c954ed9ffda54591c23e11d4f4844db6bbf06d680c6358652d0d24
7
+ data.tar.gz: 818c8e433a60b716a25e4fe344dc460f46de4b63e316c6c7b44a45f01d0c336351217d94189c8b5385cfbc65a66b2b98d33f93450611cf40c8aa03b3b68f5db4
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rails_admin_uploader.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 glebtv
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,78 @@
1
+ # RailsAdminUploader
2
+
3
+ Mass file uploads via [jQuery-File-Upload](https://github.com/blueimp/jQuery-File-Upload) for Rails Admin
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'rails_admin_uploader'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install rails_admin_uploader
20
+
21
+ Mount the gem's engine. Add to ```config/routes.rb```:
22
+
23
+ mount RailsAdminUploader::Engine => '/ra_uploader', as: 'rails_admin_uploader'
24
+
25
+ Add this line to ```app/assets/javascripts/rails_admin/custom/ui.coffee```
26
+
27
+ #= require rails_admin_uploader
28
+
29
+ Create this file if it doesn't exist in your project.
30
+
31
+
32
+ Add this line to ```app/assets/stylesheets/rails_admin/custom/theming.sass```
33
+
34
+ @import rails_admin_uploader
35
+
36
+ Create this file if it doesn't exist in your project.
37
+
38
+ ## Usage
39
+
40
+ Configure your models:
41
+
42
+ class Obj
43
+ has_many :images
44
+ has_many :plans
45
+ include RailsAdminUploader::Base
46
+ rails_admin_uploader :images, :plans
47
+ # add a string field :ra_token to DB (required)
48
+ rails_admin do
49
+ edit do
50
+ field :image, :rails_admin_uploader
51
+ field :plans, :rails_admin_uploader
52
+ end
53
+ end
54
+ end
55
+ class Image
56
+ belongs_to :obj
57
+ include RailsAdminUploader::Asset
58
+
59
+ # add a string field :ra_token to DB (required)
60
+ # add an image field :image to DB (required)
61
+ # add an integer field :sort to DB (optional)
62
+ # add a boolean field :enabled to DB (optional)
63
+ end
64
+
65
+ Set up CanCan (required)
66
+
67
+ ## Contributing
68
+
69
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/rs-pro/rails_admin_uploader).
70
+
71
+ ## License
72
+
73
+ Somewhat based on [rails-uploader](https://github.com/superp/rails-uploader)
74
+ Copyright (c) 2013 Fodojo, released under the MIT license
75
+
76
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
77
+ Copyright (c) 2015 glebtv, released under the MIT license
78
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,261 @@
1
+ #= require rails_admin_uploader/tmpl
2
+ #= require rails_admin_uploader/canvas-to-blob
3
+ #= require rails_admin_uploader/load-image.all.min.js
4
+ #= require rails_admin_uploader/jquery.fileupload
5
+ #= require rails_admin_uploader/jquery.fileupload-process
6
+ #= require rails_admin_uploader/jquery.fileupload-image
7
+ #= require rails_admin_uploader/jquery.fileupload-audio
8
+ #= require rails_admin_uploader/jquery.fileupload-video
9
+ #= require rails_admin_uploader/jquery.fileupload-validate
10
+ #= require rails_admin_uploader/jquery.iframe-transport
11
+ #= require rails_admin_uploader/jquery.fileupload-ui
12
+
13
+ upload_template = """
14
+ <script id="ra_uploader_upload" type="text/x-tmpl">
15
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
16
+ <tr class="template-upload">
17
+ {% if (o.options.flags.sortable) { %}
18
+ <td></td>
19
+ {% } %}
20
+ {% if (o.options.flags.enableable) { %}
21
+ <td></td>
22
+ {% } %}
23
+ <td width="200">
24
+ <span class="preview"></span>
25
+ </td>
26
+ <td width="200">
27
+ <div class="fileName">{%=file.name%}</div>
28
+ <div class="fileError"><strong class="error text-danger"></strong></div>
29
+ <div class="fileWeight">{%=o.formatFileSize(file.size)%}</div>
30
+ </td>
31
+ <td>
32
+ <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
33
+ </td>
34
+ <td>
35
+ <button class="btn btn-warning btn-sm cancel">
36
+ <i class="fa fa-ban"></i>
37
+ </button>
38
+ </td>
39
+ </tr>
40
+ {% } %}
41
+ </script>
42
+
43
+ """
44
+
45
+ e_spin = '<a class="label label-primary">
46
+ <i class="fa fa-spinner fa-spin"></i>
47
+ </a>'
48
+ e_on = '<a class="label label-success">
49
+ <i class="fa fa-check"></i>
50
+ </a>'
51
+ e_off = '<a class="label label-danger">
52
+ <i class="fa fa-times"></i>
53
+ </a>'
54
+
55
+ download_template = """
56
+ <script id="ra_uploader_download" type="text/x-tmpl">
57
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
58
+ <tr data-id="{%=file.id%}" class="template-download">
59
+ {% if (o.options.flags.sortable) { %}
60
+ <td class="sort-handle">
61
+ <i class="fa fa-sort"></i>
62
+ </td>
63
+ {% } %}
64
+ {%= JSON.stringify(o) %}
65
+ {% if (o.options.flags.enableable) { %}
66
+ <td class="enable-button">
67
+ {% if (file.enabled) { %}
68
+ #{e_on}
69
+ {% } else { %}
70
+ #{e_off}
71
+ {% } %}
72
+ </td>
73
+ {% } %}
74
+ <td width="200">
75
+ <a target="_blank" href="{%=file.url%}">
76
+ <img src="{%=file.thumb_url%}" title="{%=file.filename%}" />
77
+ </a>
78
+ </td>
79
+ <td width="200">
80
+ <div class="fileName">
81
+ <a target="_blank" href="{%=file.url%}">{%=file.filename%}</a>
82
+ </div>
83
+ <div class="fileWeight">{%=o.formatFileSize(file.size)%}</div>
84
+ {% if (file.error) { %}
85
+ <div><span class="label label-danger">Ошибка</span> {%=file.error%}</div>
86
+ {% } %}
87
+ </td>
88
+ <td>
89
+ {% if (o.options.flags.nameable) { %}
90
+ <input class="nameable" value="{%=file.name%}" placeholder="Название"/>
91
+ <i class="spinner fa fa-spinner fa-spin" style="display: none;"></i>
92
+ {% } %}
93
+ <td>
94
+ <a class="btn btn-danger btn-sm delete">
95
+ <i class="fa fa-trash-o"></i>
96
+ </a>
97
+ </td>
98
+ </div>
99
+ {% } %}
100
+ </script>
101
+
102
+ """
103
+
104
+ class RaUploader
105
+ constructor: ($t)->
106
+ @$t = $t
107
+
108
+ @url = @$t.data('url')
109
+ @klass = @$t.data('klass')
110
+ @id = @$t.data('id')
111
+ @field = @$t.data('field')
112
+ @$f = @$t.find('.files')
113
+ @flags = @$t.data('flags')
114
+
115
+ @guid = @$t.find('input[type=hidden]').val()
116
+
117
+ @$t.disableSelection()
118
+
119
+ @initUploader()
120
+ @loadFiles()
121
+
122
+ data: =>
123
+ r = {
124
+ field: @field
125
+ klass: @klass
126
+ guid: @guid
127
+ }
128
+ if @id
129
+ r.obj_id = @id
130
+ r
131
+
132
+ initSortable: ->
133
+ return false unless @flags.sortable
134
+ @$t.find('.files tbody').sortable
135
+ placeholder: 'attach_item'
136
+ cursor: 'move'
137
+ handle: ".sort-handle",
138
+ update: (event, ui) =>
139
+ order = []
140
+ @$t.find('.template-download').each ->
141
+ $i = $(this)
142
+ order.push($i.data('id'))
143
+ d = @data()
144
+ d.order = order
145
+ $.ajax
146
+ url: @url
147
+ type: 'POST'
148
+ dataType: 'json'
149
+ data: d
150
+ error: (r)->
151
+ alert(r)
152
+
153
+ initEnableable: =>
154
+ return false unless @flags.enableable
155
+ t = @
156
+ @$t.on('click', '.enable-button a', (e)->
157
+ $t = $(this)
158
+ $i = $t.parents('.template-download')
159
+ e.preventDefault()
160
+ d = t.data()
161
+ d.img = {enabled: !$t.hasClass('label-success')}
162
+ $p = $t.parent()
163
+ $p.html(e_spin)
164
+ id = $i.data('id')
165
+ $.ajax
166
+ url: "#{t.url}/#{id}"
167
+ type: 'PUT'
168
+ dataType: 'json'
169
+ data: d
170
+ success: (r)->
171
+ $p.html(if r.enabled then e_on else e_off)
172
+ error: (r)->
173
+ alert(r)
174
+ )
175
+
176
+ initNameable: =>
177
+ return false unless @flags.nameable
178
+ t = @
179
+ @$t.on('blur', 'input.nameable', (e)->
180
+ $t = $(this)
181
+ $i = $t.parents('.template-download')
182
+ e.preventDefault()
183
+ d = t.data()
184
+ d.img = {name: $t.val()}
185
+ id = $i.data('id')
186
+ $t.next('.spinner').show()
187
+ $.ajax
188
+ url: "#{t.url}/#{id}"
189
+ type: 'PUT'
190
+ dataType: 'json'
191
+ data: d
192
+ success: (r)->
193
+ $t.next('.spinner').hide()
194
+ error: (r)->
195
+ alert(r)
196
+ )
197
+
198
+ initUploader: =>
199
+ t = @
200
+ @$fo = @$t.find('input.fileupload').fileupload(
201
+ url: @url
202
+ dataType: 'json'
203
+ autoUpload: true
204
+ previewMaxWidth: 100
205
+ previewMaxHeight: 100
206
+ formData: (form)=>
207
+ formData = []
208
+ $.each @data(), (name, value) ->
209
+ formData.push
210
+ name: name
211
+ value: value
212
+ formData
213
+ uploadTemplateId: "ra_uploader_upload",
214
+ downloadTemplateId: "ra_uploader_download"
215
+ dropZone: @$t
216
+ filesContainer: @$f
217
+ previewCrop: true
218
+ flags: @flags
219
+ destroy: (e, data) ->
220
+ $i = data.context
221
+ d = t.data()
222
+ id = $i.data('id')
223
+ if confirm("Точно удалить?")
224
+ $.ajax
225
+ url: "#{t.url}/#{id}"
226
+ type: 'DELETE'
227
+ dataType: 'json'
228
+ data: d
229
+ success: (r)->
230
+ $i.remove()
231
+ error: (r)->
232
+ alert(r)
233
+ )
234
+ @uploader = @$fo.data('blueimpFileupload')
235
+
236
+ loadFiles: ->
237
+ $.ajax
238
+ type: 'GET'
239
+ dataType: 'json'
240
+ url: @url
241
+ data: @data()
242
+ success: (r)=>
243
+ @$f.html("")
244
+ @uploader._renderDownload(r.files).appendTo(@$f)
245
+ @initSortable()
246
+ @initEnableable()
247
+ @initNameable()
248
+ error: ->
249
+ @$f.html("Ошибка загрузки списка файлов...").css(color: 'red')
250
+
251
+ init = ->
252
+ $('.fileupload-block').each ->
253
+ new RaUploader($(this))
254
+
255
+
256
+ $(document).on 'pjax:complete', init
257
+ $ ->
258
+ $('body').append(upload_template)
259
+ $('body').append(download_template)
260
+ init()
261
+
@@ -0,0 +1,95 @@
1
+ /*
2
+ * JavaScript Canvas to Blob 2.0.5
3
+ * https://github.com/blueimp/JavaScript-Canvas-to-Blob
4
+ *
5
+ * Copyright 2012, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ *
11
+ * Based on stackoverflow user Stoive's code snippet:
12
+ * http://stackoverflow.com/q/4998908
13
+ */
14
+
15
+ /*jslint nomen: true, regexp: true */
16
+ /*global window, atob, Blob, ArrayBuffer, Uint8Array, define */
17
+
18
+ (function (window) {
19
+ 'use strict';
20
+ var CanvasPrototype = window.HTMLCanvasElement &&
21
+ window.HTMLCanvasElement.prototype,
22
+ hasBlobConstructor = window.Blob && (function () {
23
+ try {
24
+ return Boolean(new Blob());
25
+ } catch (e) {
26
+ return false;
27
+ }
28
+ }()),
29
+ hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&
30
+ (function () {
31
+ try {
32
+ return new Blob([new Uint8Array(100)]).size === 100;
33
+ } catch (e) {
34
+ return false;
35
+ }
36
+ }()),
37
+ BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||
38
+ window.MozBlobBuilder || window.MSBlobBuilder,
39
+ dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&
40
+ window.ArrayBuffer && window.Uint8Array && function (dataURI) {
41
+ var byteString,
42
+ arrayBuffer,
43
+ intArray,
44
+ i,
45
+ mimeString,
46
+ bb;
47
+ if (dataURI.split(',')[0].indexOf('base64') >= 0) {
48
+ // Convert base64 to raw binary data held in a string:
49
+ byteString = atob(dataURI.split(',')[1]);
50
+ } else {
51
+ // Convert base64/URLEncoded data component to raw binary data:
52
+ byteString = decodeURIComponent(dataURI.split(',')[1]);
53
+ }
54
+ // Write the bytes of the string to an ArrayBuffer:
55
+ arrayBuffer = new ArrayBuffer(byteString.length);
56
+ intArray = new Uint8Array(arrayBuffer);
57
+ for (i = 0; i < byteString.length; i += 1) {
58
+ intArray[i] = byteString.charCodeAt(i);
59
+ }
60
+ // Separate out the mime component:
61
+ mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
62
+ // Write the ArrayBuffer (or ArrayBufferView) to a blob:
63
+ if (hasBlobConstructor) {
64
+ return new Blob(
65
+ [hasArrayBufferViewSupport ? intArray : arrayBuffer],
66
+ {type: mimeString}
67
+ );
68
+ }
69
+ bb = new BlobBuilder();
70
+ bb.append(arrayBuffer);
71
+ return bb.getBlob(mimeString);
72
+ };
73
+ if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {
74
+ if (CanvasPrototype.mozGetAsFile) {
75
+ CanvasPrototype.toBlob = function (callback, type, quality) {
76
+ if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {
77
+ callback(dataURLtoBlob(this.toDataURL(type, quality)));
78
+ } else {
79
+ callback(this.mozGetAsFile('blob', type));
80
+ }
81
+ };
82
+ } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {
83
+ CanvasPrototype.toBlob = function (callback, type, quality) {
84
+ callback(dataURLtoBlob(this.toDataURL(type, quality)));
85
+ };
86
+ }
87
+ }
88
+ if (typeof define === 'function' && define.amd) {
89
+ define(function () {
90
+ return dataURLtoBlob;
91
+ });
92
+ } else {
93
+ window.dataURLtoBlob = dataURLtoBlob;
94
+ }
95
+ }(window));