uploadbox 0.0.13 → 0.0.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/font/fontello.eot +0 -0
- data/app/assets/font/fontello.svg +1 -0
- data/app/assets/font/fontello.ttf +0 -0
- data/app/assets/font/fontello.woff +0 -0
- data/app/assets/javascripts/_gallery_uploader.coffee +64 -0
- data/app/assets/javascripts/_manager.coffee +18 -0
- data/app/assets/javascripts/_uploader_preview.coffee +134 -0
- data/app/assets/javascripts/_uuid.js +245 -0
- data/app/assets/javascripts/uploadbox.coffee +4 -0
- data/app/assets/stylesheets/{fontello.scss → fontello.css} +8 -7
- data/app/assets/stylesheets/uploadbox.sass +3 -5
- data/app/views/uploadbox/images/_uploads_many.slim +61 -0
- data/app/views/uploadbox/images/{_uploader.html.slim → _uploads_one.slim} +8 -5
- data/config/spring.rb +1 -0
- data/lib/uploadbox/engine.rb +28 -3
- data/lib/uploadbox/image_uploader.rb +94 -12
- data/lib/uploadbox/version.rb +1 -1
- metadata +38 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93240b0280249b35b89cd367932e1b2de5e6cce9
|
4
|
+
data.tar.gz: e94a982a1aeb55497b4825a2ff89be06037d2914
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c1221c95ae558e91ac8699db2ea603bdfb46b5b85a77aea927b58733ebaa52c66a7a621872ade40572d6f988d08998c8e92f370499d9f50c214b29443447649
|
7
|
+
data.tar.gz: 2386b4127cedfc97a72c7ec8133748fddb14ebcbb88f921a73f36bd3218d13f88dfdc6774482631f5aecc9d36e09fb303b899df23bc5ad152d699d68a95383bf
|
Binary file
|
@@ -7,6 +7,7 @@
|
|
7
7
|
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
|
8
8
|
<missing-glyph horiz-adv-x="1000" />
|
9
9
|
<glyph glyph-name="picture-1" unicode="" d="m357 529q0-45-31-76t-76-32t-76 32t-31 76t31 75t76 32t76-32t31-75z m572-215v-250h-786v107l178 179l90-89l285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-8 6-13t12-5h893q7 0 13 5t5 13v678q0 7-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
|
10
|
+
<glyph glyph-name="plus-1" unicode="" d="m786 439v-107q0-22-16-38t-38-15h-232v-233q0-22-16-37t-38-16h-107q-22 0-38 16t-15 37v233h-232q-23 0-38 15t-16 38v107q0 23 16 38t38 16h232v232q0 22 15 38t38 16h107q23 0 38-16t16-38v-232h232q22 0 38-16t16-38z" horiz-adv-x="785.7" />
|
10
11
|
</font>
|
11
12
|
</defs>
|
12
13
|
</svg>
|
Binary file
|
Binary file
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class @GalleryUploader
|
2
|
+
constructor: (@container) ->
|
3
|
+
@previews = {}
|
4
|
+
|
5
|
+
@container.find('input[type="file"]:first').show().fileupload
|
6
|
+
type: 'POST'
|
7
|
+
dataType: 'xml'
|
8
|
+
replaceFileInput: false
|
9
|
+
autoUpload: true
|
10
|
+
formData: @getFormData
|
11
|
+
dropZone: @container
|
12
|
+
pasteZone: @container
|
13
|
+
add: @add
|
14
|
+
progress: @progress
|
15
|
+
done: @done
|
16
|
+
fail: @fail
|
17
|
+
|
18
|
+
add: (e, data) =>
|
19
|
+
if @loader
|
20
|
+
@loader.detach()
|
21
|
+
|
22
|
+
if @verifyProcessingInterval
|
23
|
+
clearInterval(@verifyProcessingInterval)
|
24
|
+
|
25
|
+
if data.files[0].type.match /gif|jpe?g|png/
|
26
|
+
@clone = @container.find('[data-container="uploader"]:first').clone()
|
27
|
+
@container.append(@clone)
|
28
|
+
previewInstanceName = Manager.getInstanceName('UploaderPreview')
|
29
|
+
preview = new UploaderPreview(@clone, data.files[0])
|
30
|
+
@clone.data(previewInstanceName, preview)
|
31
|
+
@previews[preview.id()] = preview
|
32
|
+
data.context = preview.id()
|
33
|
+
|
34
|
+
@container.closest('form').find('[type=submit]').attr("disabled", true)
|
35
|
+
data.submit()
|
36
|
+
|
37
|
+
getFormData: =>
|
38
|
+
preview = @nextPreview()
|
39
|
+
filePath = "uploads/#{preview.id()}/" + preview.file.name
|
40
|
+
preview.filePath = filePath
|
41
|
+
[
|
42
|
+
{ name: 'key', value: filePath },
|
43
|
+
{ name: 'acl', value: @container.find('input[name="acl"]').val() },
|
44
|
+
{ name: 'Content-Type', value: preview.file.type },
|
45
|
+
{ name: 'AWSAccessKeyId', value: @container.find('input[name="AWSAccessKeyId"]').val() },
|
46
|
+
{ name: 'policy', value: @container.find('input[name="policy"]').val() },
|
47
|
+
{ name: 'signature', value: @container.find('input[name="signature"]').val() },
|
48
|
+
{ name: 'file', value: preview.file }
|
49
|
+
]
|
50
|
+
|
51
|
+
progress: (e, data) =>
|
52
|
+
@previews[data.context].progress(data)
|
53
|
+
|
54
|
+
done: (e, data) =>
|
55
|
+
@previews[data.context].done(data)
|
56
|
+
|
57
|
+
fail: (e, data) =>
|
58
|
+
@previews[data.context].fail(data)
|
59
|
+
|
60
|
+
nextPreview: =>
|
61
|
+
@currentIndex ||= 0
|
62
|
+
key = Object.keys(@previews)[@currentIndex]
|
63
|
+
@currentIndex++
|
64
|
+
@previews[key]
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class @Manager
|
2
|
+
@getInstanceName: (className) ->
|
3
|
+
className.charAt(0).toLowerCase() + className.slice(1)
|
4
|
+
|
5
|
+
@init = (container) ->
|
6
|
+
classNames = container.data('component').split(' ')
|
7
|
+
|
8
|
+
for className in classNames
|
9
|
+
try
|
10
|
+
instance = new (eval(className))(container)
|
11
|
+
instanceName = Manager.getInstanceName(className)
|
12
|
+
container.data(instanceName, instance)
|
13
|
+
catch error
|
14
|
+
try
|
15
|
+
console.warn "#{className} component not found"
|
16
|
+
|
17
|
+
$(document).ready ->
|
18
|
+
$('[data-component]').each (i, el) -> Manager.init($(el))
|
@@ -0,0 +1,134 @@
|
|
1
|
+
class @UploaderPreview
|
2
|
+
constructor: (@container, @file) ->
|
3
|
+
@loader = $('<div class="progress progress-striped active"><div class="bar" style="width: 0%;"></div></div>').hide()
|
4
|
+
|
5
|
+
@startLoader() if @isUploadStarting()
|
6
|
+
|
7
|
+
@container.find('a.btn.fileupload-exists').bind('ajax:success', @delete)
|
8
|
+
|
9
|
+
@container.find('input[type="file"]:first').show().fileupload
|
10
|
+
type: 'POST'
|
11
|
+
dataType: 'xml'
|
12
|
+
replaceFileInput: false
|
13
|
+
autoUpload: true
|
14
|
+
formData: @getFormData
|
15
|
+
dropZone: @container
|
16
|
+
pasteZone: @container
|
17
|
+
add: @add
|
18
|
+
progress: @progress
|
19
|
+
done: @done
|
20
|
+
fail: @fail
|
21
|
+
|
22
|
+
@fileInput = @container.find('input[type="file"]')
|
23
|
+
@typeInput = @container.find('input[name="image[imageable_type]"]')
|
24
|
+
@uploadNameInput = @container.find('input[name="image[upload_name]"]')
|
25
|
+
@idInput = @container.find('[data-item="id"]')
|
26
|
+
@thumbContainer = @container.find('.fileupload-preview.thumbnail')
|
27
|
+
|
28
|
+
startLoader: =>
|
29
|
+
@container.prepend(@loader.fadeIn())
|
30
|
+
@container.find('.fileupload').removeClass('processing').addClass('uploading')
|
31
|
+
|
32
|
+
|
33
|
+
add: (e, data) =>
|
34
|
+
@file = data.files[0]
|
35
|
+
|
36
|
+
if @loader
|
37
|
+
@loader.detach()
|
38
|
+
|
39
|
+
if @verifyProcessingInterval
|
40
|
+
clearInterval(@verifyProcessingInterval)
|
41
|
+
|
42
|
+
if @file.type.match /gif|jpe?g|png/
|
43
|
+
data.context = @id()
|
44
|
+
@startLoader()
|
45
|
+
@container.closest('form').find('[type=submit]').attr("disabled", true)
|
46
|
+
data.submit()
|
47
|
+
|
48
|
+
getFormData: =>
|
49
|
+
@filePath = "uploads/#{@id()}/" + @file.name
|
50
|
+
|
51
|
+
[
|
52
|
+
{ name: 'key', value: @filePath },
|
53
|
+
{ name: 'acl', value: @container.find('input[name="acl"]').val() },
|
54
|
+
{ name: 'Content-Type', value: @file.type },
|
55
|
+
{ name: 'AWSAccessKeyId', value: @container.find('input[name="AWSAccessKeyId"]').val() },
|
56
|
+
{ name: 'policy', value: @container.find('input[name="policy"]').val() },
|
57
|
+
{ name: 'signature', value: @container.find('input[name="signature"]').val() },
|
58
|
+
{ name: 'file', value: @file }
|
59
|
+
]
|
60
|
+
|
61
|
+
|
62
|
+
isUploadStarting: =>
|
63
|
+
@container.find('.fileupload').hasClass('fileupload-new')
|
64
|
+
|
65
|
+
id: =>
|
66
|
+
@_id ||= uuid.v4()
|
67
|
+
|
68
|
+
progress: (data) =>
|
69
|
+
progress = parseInt(data.loaded / data.total * 100, 10)
|
70
|
+
@loader.find('.bar').css({width: progress + '%'})
|
71
|
+
|
72
|
+
done: (data) =>
|
73
|
+
@container.find('.fileupload').removeClass('uploading').addClass('processing')
|
74
|
+
$.ajax
|
75
|
+
type: 'POST'
|
76
|
+
url: @fileInput.data('callback-url')
|
77
|
+
data:
|
78
|
+
'image[remote_file_url]': @fileInput.data('url') + @filePath
|
79
|
+
'image[imageable_type]': @typeInput.val()
|
80
|
+
'image[upload_name]': @uploadNameInput.val()
|
81
|
+
'image[secure_random]': @id()
|
82
|
+
|
83
|
+
complete: =>
|
84
|
+
@verifyProcessingInterval = setInterval(@verifyProcessing, 5000)
|
85
|
+
|
86
|
+
error: =>
|
87
|
+
@loader.detach()
|
88
|
+
@container.find('.fileupload').removeClass('uploading').removeClass('processing')
|
89
|
+
@container.closest('form').find('[type=submit]').attr("disabled", false)
|
90
|
+
|
91
|
+
verifyProcessing: =>
|
92
|
+
arr = @filePath.split('/')
|
93
|
+
filename = arr[arr.length - 1]
|
94
|
+
$.ajax
|
95
|
+
type: 'GET'
|
96
|
+
dataType: 'json'
|
97
|
+
url: @fileInput.data('find-url')
|
98
|
+
data:
|
99
|
+
'name': filename
|
100
|
+
'imageable_type': @typeInput.val()
|
101
|
+
'upload_name': @uploadNameInput.val()
|
102
|
+
'secure_random': @id()
|
103
|
+
|
104
|
+
complete: (data) =>
|
105
|
+
if data.responseJSON.hasOwnProperty('id')
|
106
|
+
clearInterval(@verifyProcessingInterval)
|
107
|
+
@showThumb(data.responseJSON)
|
108
|
+
|
109
|
+
error: =>
|
110
|
+
@loader.detach()
|
111
|
+
@container.detach()
|
112
|
+
|
113
|
+
showThumb: (image) =>
|
114
|
+
@loader.detach()
|
115
|
+
@idInput.val(image.id)
|
116
|
+
@container.find('a.btn.fileupload-exists').attr('href', image.url)
|
117
|
+
@thumbContainer.find('img').detach()
|
118
|
+
img = $('<img/>')
|
119
|
+
img.attr('src', image.versions[@thumbContainer.data('version')])
|
120
|
+
img.attr('width', @thumbContainer.data('width'))
|
121
|
+
img.attr('height', @thumbContainer.data('height')).hide()
|
122
|
+
@container.find('.fileupload-preview.thumbnail').append(img.fadeIn())
|
123
|
+
@container.find('.fileupload').removeClass('fileupload-new').addClass('fileupload-exists')
|
124
|
+
@container.find('.fileupload').removeClass('uploading').removeClass('processing')
|
125
|
+
@container.closest('form').find('[type=submit]').attr("disabled", false)
|
126
|
+
|
127
|
+
fail: =>
|
128
|
+
@loader.detach()
|
129
|
+
@container.detach()
|
130
|
+
|
131
|
+
delete: =>
|
132
|
+
@idInput.val('')
|
133
|
+
@container.detach()
|
134
|
+
|
@@ -0,0 +1,245 @@
|
|
1
|
+
// uuid.js
|
2
|
+
//
|
3
|
+
// Copyright (c) 2010-2012 Robert Kieffer
|
4
|
+
// MIT License - http://opensource.org/licenses/mit-license.php
|
5
|
+
|
6
|
+
(function() {
|
7
|
+
var _global = this;
|
8
|
+
|
9
|
+
// Unique ID creation requires a high quality random # generator. We feature
|
10
|
+
// detect to determine the best RNG source, normalizing to a function that
|
11
|
+
// returns 128-bits of randomness, since that's what's usually required
|
12
|
+
var _rng;
|
13
|
+
|
14
|
+
// Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
|
15
|
+
//
|
16
|
+
// Moderately fast, high quality
|
17
|
+
if (typeof(_global.require) == 'function') {
|
18
|
+
try {
|
19
|
+
var _rb = _global.require('crypto').randomBytes;
|
20
|
+
_rng = _rb && function() {return _rb(16);};
|
21
|
+
} catch(e) {}
|
22
|
+
}
|
23
|
+
|
24
|
+
if (!_rng && _global.crypto && crypto.getRandomValues) {
|
25
|
+
// WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
|
26
|
+
//
|
27
|
+
// Moderately fast, high quality
|
28
|
+
var _rnds8 = new Uint8Array(16);
|
29
|
+
_rng = function whatwgRNG() {
|
30
|
+
crypto.getRandomValues(_rnds8);
|
31
|
+
return _rnds8;
|
32
|
+
};
|
33
|
+
}
|
34
|
+
|
35
|
+
if (!_rng) {
|
36
|
+
// Math.random()-based (RNG)
|
37
|
+
//
|
38
|
+
// If all else fails, use Math.random(). It's fast, but is of unspecified
|
39
|
+
// quality.
|
40
|
+
var _rnds = new Array(16);
|
41
|
+
_rng = function() {
|
42
|
+
for (var i = 0, r; i < 16; i++) {
|
43
|
+
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
|
44
|
+
_rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
|
45
|
+
}
|
46
|
+
|
47
|
+
return _rnds;
|
48
|
+
};
|
49
|
+
}
|
50
|
+
|
51
|
+
// Buffer class to use
|
52
|
+
var BufferClass = typeof(_global.Buffer) == 'function' ? _global.Buffer : Array;
|
53
|
+
|
54
|
+
// Maps for number <-> hex string conversion
|
55
|
+
var _byteToHex = [];
|
56
|
+
var _hexToByte = {};
|
57
|
+
for (var i = 0; i < 256; i++) {
|
58
|
+
_byteToHex[i] = (i + 0x100).toString(16).substr(1);
|
59
|
+
_hexToByte[_byteToHex[i]] = i;
|
60
|
+
}
|
61
|
+
|
62
|
+
// **`parse()` - Parse a UUID into it's component bytes**
|
63
|
+
function parse(s, buf, offset) {
|
64
|
+
var i = (buf && offset) || 0, ii = 0;
|
65
|
+
|
66
|
+
buf = buf || [];
|
67
|
+
s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
|
68
|
+
if (ii < 16) { // Don't overflow!
|
69
|
+
buf[i + ii++] = _hexToByte[oct];
|
70
|
+
}
|
71
|
+
});
|
72
|
+
|
73
|
+
// Zero out remaining bytes if string was short
|
74
|
+
while (ii < 16) {
|
75
|
+
buf[i + ii++] = 0;
|
76
|
+
}
|
77
|
+
|
78
|
+
return buf;
|
79
|
+
}
|
80
|
+
|
81
|
+
// **`unparse()` - Convert UUID byte array (ala parse()) into a string**
|
82
|
+
function unparse(buf, offset) {
|
83
|
+
var i = offset || 0, bth = _byteToHex;
|
84
|
+
return bth[buf[i++]] + bth[buf[i++]] +
|
85
|
+
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
86
|
+
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
87
|
+
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
88
|
+
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
89
|
+
bth[buf[i++]] + bth[buf[i++]] +
|
90
|
+
bth[buf[i++]] + bth[buf[i++]] +
|
91
|
+
bth[buf[i++]] + bth[buf[i++]];
|
92
|
+
}
|
93
|
+
|
94
|
+
// **`v1()` - Generate time-based UUID**
|
95
|
+
//
|
96
|
+
// Inspired by https://github.com/LiosK/UUID.js
|
97
|
+
// and http://docs.python.org/library/uuid.html
|
98
|
+
|
99
|
+
// random #'s we need to init node and clockseq
|
100
|
+
var _seedBytes = _rng();
|
101
|
+
|
102
|
+
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
|
103
|
+
var _nodeId = [
|
104
|
+
_seedBytes[0] | 0x01,
|
105
|
+
_seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
|
106
|
+
];
|
107
|
+
|
108
|
+
// Per 4.2.2, randomize (14 bit) clockseq
|
109
|
+
var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
|
110
|
+
|
111
|
+
// Previous uuid creation time
|
112
|
+
var _lastMSecs = 0, _lastNSecs = 0;
|
113
|
+
|
114
|
+
// See https://github.com/broofa/node-uuid for API details
|
115
|
+
function v1(options, buf, offset) {
|
116
|
+
var i = buf && offset || 0;
|
117
|
+
var b = buf || [];
|
118
|
+
|
119
|
+
options = options || {};
|
120
|
+
|
121
|
+
var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
|
122
|
+
|
123
|
+
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
|
124
|
+
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
|
125
|
+
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
|
126
|
+
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
|
127
|
+
var msecs = options.msecs != null ? options.msecs : new Date().getTime();
|
128
|
+
|
129
|
+
// Per 4.2.1.2, use count of uuid's generated during the current clock
|
130
|
+
// cycle to simulate higher resolution clock
|
131
|
+
var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
|
132
|
+
|
133
|
+
// Time since last uuid creation (in msecs)
|
134
|
+
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
|
135
|
+
|
136
|
+
// Per 4.2.1.2, Bump clockseq on clock regression
|
137
|
+
if (dt < 0 && options.clockseq == null) {
|
138
|
+
clockseq = clockseq + 1 & 0x3fff;
|
139
|
+
}
|
140
|
+
|
141
|
+
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
|
142
|
+
// time interval
|
143
|
+
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
|
144
|
+
nsecs = 0;
|
145
|
+
}
|
146
|
+
|
147
|
+
// Per 4.2.1.2 Throw error if too many uuids are requested
|
148
|
+
if (nsecs >= 10000) {
|
149
|
+
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
|
150
|
+
}
|
151
|
+
|
152
|
+
_lastMSecs = msecs;
|
153
|
+
_lastNSecs = nsecs;
|
154
|
+
_clockseq = clockseq;
|
155
|
+
|
156
|
+
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
|
157
|
+
msecs += 12219292800000;
|
158
|
+
|
159
|
+
// `time_low`
|
160
|
+
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
|
161
|
+
b[i++] = tl >>> 24 & 0xff;
|
162
|
+
b[i++] = tl >>> 16 & 0xff;
|
163
|
+
b[i++] = tl >>> 8 & 0xff;
|
164
|
+
b[i++] = tl & 0xff;
|
165
|
+
|
166
|
+
// `time_mid`
|
167
|
+
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
|
168
|
+
b[i++] = tmh >>> 8 & 0xff;
|
169
|
+
b[i++] = tmh & 0xff;
|
170
|
+
|
171
|
+
// `time_high_and_version`
|
172
|
+
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
|
173
|
+
b[i++] = tmh >>> 16 & 0xff;
|
174
|
+
|
175
|
+
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
|
176
|
+
b[i++] = clockseq >>> 8 | 0x80;
|
177
|
+
|
178
|
+
// `clock_seq_low`
|
179
|
+
b[i++] = clockseq & 0xff;
|
180
|
+
|
181
|
+
// `node`
|
182
|
+
var node = options.node || _nodeId;
|
183
|
+
for (var n = 0; n < 6; n++) {
|
184
|
+
b[i + n] = node[n];
|
185
|
+
}
|
186
|
+
|
187
|
+
return buf ? buf : unparse(b);
|
188
|
+
}
|
189
|
+
|
190
|
+
// **`v4()` - Generate random UUID**
|
191
|
+
|
192
|
+
// See https://github.com/broofa/node-uuid for API details
|
193
|
+
function v4(options, buf, offset) {
|
194
|
+
// Deprecated - 'format' argument, as supported in v1.2
|
195
|
+
var i = buf && offset || 0;
|
196
|
+
|
197
|
+
if (typeof(options) == 'string') {
|
198
|
+
buf = options == 'binary' ? new BufferClass(16) : null;
|
199
|
+
options = null;
|
200
|
+
}
|
201
|
+
options = options || {};
|
202
|
+
|
203
|
+
var rnds = options.random || (options.rng || _rng)();
|
204
|
+
|
205
|
+
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
206
|
+
rnds[6] = (rnds[6] & 0x0f) | 0x40;
|
207
|
+
rnds[8] = (rnds[8] & 0x3f) | 0x80;
|
208
|
+
|
209
|
+
// Copy bytes to buffer, if provided
|
210
|
+
if (buf) {
|
211
|
+
for (var ii = 0; ii < 16; ii++) {
|
212
|
+
buf[i + ii] = rnds[ii];
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
return buf || unparse(rnds);
|
217
|
+
}
|
218
|
+
|
219
|
+
// Export public API
|
220
|
+
var uuid = v4;
|
221
|
+
uuid.v1 = v1;
|
222
|
+
uuid.v4 = v4;
|
223
|
+
uuid.parse = parse;
|
224
|
+
uuid.unparse = unparse;
|
225
|
+
uuid.BufferClass = BufferClass;
|
226
|
+
|
227
|
+
if (typeof define === 'function' && define.amd) {
|
228
|
+
// Publish as AMD module
|
229
|
+
define(function() {return uuid;});
|
230
|
+
} else if (typeof(module) != 'undefined' && module.exports) {
|
231
|
+
// Publish as node.js module
|
232
|
+
module.exports = uuid;
|
233
|
+
} else {
|
234
|
+
// Publish as global (in browsers)
|
235
|
+
var _previousRoot = _global.uuid;
|
236
|
+
|
237
|
+
// **`noConflict()` - (browser only) to reset global 'uuid' var**
|
238
|
+
uuid.noConflict = function() {
|
239
|
+
_global.uuid = _previousRoot;
|
240
|
+
return uuid;
|
241
|
+
};
|
242
|
+
|
243
|
+
_global.uuid = uuid;
|
244
|
+
}
|
245
|
+
}).call(this);
|
@@ -2,5 +2,9 @@
|
|
2
2
|
#= require jquery.iframe-transport
|
3
3
|
#= require cors/jquery.postmessage-transport
|
4
4
|
#= require cors/jquery.xdr-transport
|
5
|
+
#= require _uuid
|
5
6
|
#= require jquery.fileupload
|
6
7
|
#= require _image_uploader
|
8
|
+
#= require _uploader_preview
|
9
|
+
#= require _gallery_uploader
|
10
|
+
#= require _manager
|
@@ -1,10 +1,10 @@
|
|
1
1
|
@font-face {
|
2
2
|
font-family: 'fontello';
|
3
|
-
src: url('fontello.eot?
|
4
|
-
src: url('fontello.eot?
|
5
|
-
url('fontello.woff?
|
6
|
-
url('fontello.ttf?
|
7
|
-
url('fontello.svg?
|
3
|
+
src: url('fontello.eot?18809145');
|
4
|
+
src: url('fontello.eot?18809145#iefix') format('embedded-opentype'),
|
5
|
+
url('fontello.woff?18809145') format('woff'),
|
6
|
+
url('fontello.ttf?18809145') format('truetype'),
|
7
|
+
url('fontello.svg?18809145#fontello') format('svg');
|
8
8
|
font-weight: normal;
|
9
9
|
font-style: normal;
|
10
10
|
}
|
@@ -14,7 +14,7 @@
|
|
14
14
|
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
15
15
|
@font-face {
|
16
16
|
font-family: 'fontello';
|
17
|
-
src: url('../font/fontello.svg?
|
17
|
+
src: url('../font/fontello.svg?18809145#fontello') format('svg');
|
18
18
|
}
|
19
19
|
}
|
20
20
|
*/
|
@@ -50,4 +50,5 @@
|
|
50
50
|
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
|
51
51
|
}
|
52
52
|
|
53
|
-
.icon-picture-1:before { content: '\e800'; } /* '' */
|
53
|
+
.icon-picture-1:before { content: '\e800'; } /* '' */
|
54
|
+
.icon-plus-1:before { content: '\e802'; } /* '' */
|
@@ -3,7 +3,6 @@
|
|
3
3
|
|
4
4
|
.uploadbox-image-uploader
|
5
5
|
position: relative
|
6
|
-
padding-bottom: 30px
|
7
6
|
|
8
7
|
.btn
|
9
8
|
background-color: #f7f7f7
|
@@ -15,18 +14,17 @@
|
|
15
14
|
.btn
|
16
15
|
border: 1px solid darken(#f7f7f7, 20%)
|
17
16
|
|
18
|
-
.icon
|
17
|
+
.icon
|
19
18
|
opacity: .5
|
20
19
|
|
21
20
|
.fileupload-exists
|
22
|
-
.icon
|
21
|
+
.icon
|
23
22
|
display: none
|
24
23
|
|
25
|
-
.icon
|
24
|
+
.icon
|
26
25
|
position: absolute
|
27
26
|
top: 0
|
28
27
|
left: 0
|
29
|
-
font-size: 40px
|
30
28
|
width: 100%
|
31
29
|
height: 100%
|
32
30
|
opacity: .3
|
@@ -0,0 +1,61 @@
|
|
1
|
+
= form.fields_for :image do
|
2
|
+
div data-component="GalleryUploader"
|
3
|
+
.uploadbox-image-uploader.uploads-many data-container="uploader" style="width: #{width}px; height: #{height}px;"
|
4
|
+
- if namespace
|
5
|
+
input name="[#{resource.class.name.underscore}][#{namespace}]#{upload_name}[]" data-item="id" type="hidden"
|
6
|
+
- else
|
7
|
+
input name="[#{resource.class.name.underscore}]#{upload_name}[]" data-item="id" type="hidden"
|
8
|
+
|
9
|
+
.fileupload data-provides="fileupload" class="fileupload-new"
|
10
|
+
.fileupload-preview.thumbnail data-version="#{version}" data-width="#{width}" data-height="#{height}" style="width: #{width}px; height: #{height}px;"
|
11
|
+
|
12
|
+
.fileupload-actions
|
13
|
+
span.btn.btn-file style="width: #{width}px; height: #{height}px;"
|
14
|
+
span.fileupload-new = choose_label
|
15
|
+
span.fileupload-exists = update_label
|
16
|
+
i.icon.icon-plus-1 style="line-height: #{height}px; font-size: #{(width * 0.4).to_i}px"
|
17
|
+
|
18
|
+
input type="file" name="image[file]" data-callback-url="#{uploadbox.images_path}" data-find-url="#{uploadbox.find_images_path(format: :json)}" data-url="https://#{ENV['S3_BUCKET']}.s3.amazonaws.com/" accept="image/png image/x-png, image/gif, image/jpeg" style="display: none; width: #{width}px; height: #{height}px;" multiple="true"
|
19
|
+
input type="hidden" name="policy" value="#{s3_policy}"
|
20
|
+
input type="hidden" name="signature" value="#{s3_signature}"
|
21
|
+
input type="hidden" name="AWSAccessKeyId" value="#{ENV['S3_KEY']}"
|
22
|
+
input type="hidden" name="acl" value="public-read"
|
23
|
+
input type="hidden" name="key"
|
24
|
+
|
25
|
+
input type="hidden" name="image[imageable_type]" value="#{resource.class}"
|
26
|
+
input type="hidden" name="image[upload_name]" value="#{upload_name}"
|
27
|
+
- if removable
|
28
|
+
- if resource.send(upload_name).present?
|
29
|
+
= link_to destroy_label, uploadbox.image_path(resource.send(upload_name)), class: 'btn fileupload-exists', remote: true, method: :delete
|
30
|
+
- else
|
31
|
+
= link_to destroy_label, '#', class: 'btn fileupload-exists', remote: true, method: :delete
|
32
|
+
|
33
|
+
- for image in resource.send(upload_name)
|
34
|
+
.uploadbox-image-uploader.uploads-many data-component="UploaderPreview" data-container="uploader" style="width: #{width}px; height: #{height}px;"
|
35
|
+
- if namespace
|
36
|
+
input name="[#{resource.class.name.underscore}][#{namespace}]#{upload_name}[]" data-item="id" type="hidden" value="#{image.id}"
|
37
|
+
- else
|
38
|
+
input name="[#{resource.class.name.underscore}]#{upload_name}[]" data-item="id" type="hidden" value="#{image.id}"
|
39
|
+
|
40
|
+
.fileupload data-provides="fileupload" class="fileupload-exists"
|
41
|
+
.fileupload-preview.thumbnail data-version="#{version}" data-width="#{width}" data-height="#{height}" style="width: #{width}px; height: #{height}px;"
|
42
|
+
= img image.send(version)
|
43
|
+
|
44
|
+
.fileupload-actions
|
45
|
+
span.btn.btn-file style="width: #{width}px; height: #{height}px;"
|
46
|
+
span.fileupload-new = choose_label
|
47
|
+
span.fileupload-exists = update_label
|
48
|
+
i.icon.icon-plus-1 style="line-height: #{height}px; font-size: #{(width * 0.4).to_i}px"
|
49
|
+
|
50
|
+
input type="file" name="image[file]" data-callback-url="#{uploadbox.images_path}" data-find-url="#{uploadbox.find_images_path(format: :json)}" data-url="https://#{ENV['S3_BUCKET']}.s3.amazonaws.com/" accept="image/png image/x-png, image/gif, image/jpeg" style="display: none; width: #{width}px; height: #{height}px;" multiple="true"
|
51
|
+
input type="hidden" name="policy" value="#{s3_policy}"
|
52
|
+
input type="hidden" name="signature" value="#{s3_signature}"
|
53
|
+
input type="hidden" name="AWSAccessKeyId" value="#{ENV['S3_KEY']}"
|
54
|
+
input type="hidden" name="acl" value="public-read"
|
55
|
+
input type="hidden" name="key"
|
56
|
+
|
57
|
+
input type="hidden" name="image[imageable_type]" value="#{resource.class}"
|
58
|
+
input type="hidden" name="image[upload_name]" value="#{upload_name}"
|
59
|
+
- if removable
|
60
|
+
= link_to destroy_label, uploadbox.image_path(image), class: 'btn fileupload-exists', remote: true, method: :delete
|
61
|
+
|
@@ -1,10 +1,11 @@
|
|
1
1
|
= form.fields_for :image do
|
2
2
|
- secure_random = SecureRandom.uuid
|
3
|
-
.uploadbox-image-uploader data-component="ImageUploader" style="width: #{width}px; height: #{height}px;"
|
3
|
+
.uploadbox-image-uploader.uploads-one data-component="ImageUploader" style="width: #{width}px; height: #{height}px;"
|
4
4
|
- if namespace
|
5
|
-
input name="[#{namespace}]#{upload_name}
|
5
|
+
input name="[#{resource.class.name.underscore}][#{namespace}]#{upload_name}" data-item="id" type="hidden" value="#{resource.send(upload_name).try :id}"
|
6
6
|
- else
|
7
|
-
input name="#{upload_name}
|
7
|
+
input name="[#{resource.class.name.underscore}]#{upload_name}" data-item="id" type="hidden" value="#{resource.send(upload_name).try :id}"
|
8
|
+
|
8
9
|
.fileupload data-provides="fileupload" class="fileupload-#{(resource.send("#{upload_name}?") or default) ? 'exists' : 'new'}"
|
9
10
|
.fileupload-preview.thumbnail data-version="#{version}" data-width="#{width}" data-height="#{height}" style="width: #{width}px; height: #{height}px;"
|
10
11
|
- if resource.send("#{upload_name}?")
|
@@ -16,8 +17,10 @@
|
|
16
17
|
span.btn.btn-file style="width: #{width}px; height: #{height}px;"
|
17
18
|
span.fileupload-new = choose_label
|
18
19
|
span.fileupload-exists = update_label
|
19
|
-
i.icon-picture-1 style="line-height: #{height}px"
|
20
|
-
|
20
|
+
i.icon.icon-picture-1 style="line-height: #{height}px; font-size: #{(width * 0.4).to_i}px"
|
21
|
+
|
22
|
+
|
23
|
+
input type="file" name="image[file]" data-callback-url="#{uploadbox.images_path}" data-find-url="#{uploadbox.find_images_path(format: :json)}" data-url="https://#{ENV['S3_BUCKET']}.s3.amazonaws.com/" data-secure-random="#{secure_random}" accept="image/png image/x-png, image/gif, image/jpeg" style="display: none; width: #{width}px; height: #{height}px;"
|
21
24
|
input type="hidden" name="policy" value="#{s3_policy}"
|
22
25
|
input type="hidden" name="signature" value="#{s3_signature}"
|
23
26
|
input type="hidden" name="AWSAccessKeyId" value="#{ENV['S3_KEY']}"
|
data/config/spring.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Spring.application_root = './spec/dummy'
|
data/lib/uploadbox/engine.rb
CHANGED
@@ -28,7 +28,7 @@ module Uploadbox
|
|
28
28
|
end
|
29
29
|
|
30
30
|
class ActionView::Helpers::FormBuilder
|
31
|
-
def
|
31
|
+
def uploads_one(upload_name, options={})
|
32
32
|
upload_model_class = "Uploadbox::#{@object.class.to_s + upload_name.to_s.camelize}".constantize
|
33
33
|
options.reverse_merge!(preview: upload_model_class.versions.keys.first,
|
34
34
|
namespace: false,
|
@@ -37,7 +37,32 @@ class ActionView::Helpers::FormBuilder
|
|
37
37
|
choose_label: 'Escolher',
|
38
38
|
destroy_label: '×'.html_safe)
|
39
39
|
dimensions = upload_model_class.versions[options[:preview]]
|
40
|
-
@template.render partial: 'uploadbox/images/
|
40
|
+
@template.render partial: 'uploadbox/images/uploads_one', locals: {
|
41
|
+
upload_name: upload_name,
|
42
|
+
resource: @object,
|
43
|
+
form: self,
|
44
|
+
version: options[:preview],
|
45
|
+
width: dimensions[0],
|
46
|
+
height: dimensions[1],
|
47
|
+
namespace: options[:namespace],
|
48
|
+
default: options[:default],
|
49
|
+
removable: upload_model_class.removable?,
|
50
|
+
update_label: options[:update_label],
|
51
|
+
choose_label: options[:choose_label],
|
52
|
+
destroy_label: options[:destroy_label]
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def uploads_many(upload_name, options={})
|
57
|
+
upload_model_class = "Uploadbox::#{@object.class.to_s + upload_name.to_s.camelize}".constantize
|
58
|
+
options.reverse_merge!(preview: upload_model_class.versions.keys.first,
|
59
|
+
namespace: false,
|
60
|
+
default: false,
|
61
|
+
update_label: 'Alterar',
|
62
|
+
choose_label: 'Escolher',
|
63
|
+
destroy_label: '×'.html_safe)
|
64
|
+
dimensions = upload_model_class.versions[options[:preview]]
|
65
|
+
@template.render partial: 'uploadbox/images/uploads_many', locals: {
|
41
66
|
upload_name: upload_name,
|
42
67
|
resource: @object,
|
43
68
|
form: self,
|
@@ -54,4 +79,4 @@ class ActionView::Helpers::FormBuilder
|
|
54
79
|
end
|
55
80
|
end
|
56
81
|
|
57
|
-
require 'uploadbox/image_uploader'
|
82
|
+
require 'uploadbox/image_uploader'
|
@@ -23,6 +23,7 @@ module Uploadbox
|
|
23
23
|
upload and upload.file?
|
24
24
|
end
|
25
25
|
|
26
|
+
# @post.picture
|
26
27
|
define_method(upload_name) do
|
27
28
|
upload = send("#{upload_name}_upload")
|
28
29
|
|
@@ -48,22 +49,15 @@ module Uploadbox
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
|
-
# @post.
|
52
|
-
define_method("
|
53
|
-
|
54
|
-
self.send("attach_#{upload_name}!", upload_id)
|
55
|
-
end
|
52
|
+
# @post.picture=(id)
|
53
|
+
define_method("#{upload_name}=") do |upload_id|
|
54
|
+
self.send("#{upload_name}_upload=", upload_class.find(upload_id))
|
56
55
|
end
|
57
56
|
|
58
57
|
# @post.remote_picture_url=('http://exemple.com/image.jpg')
|
59
58
|
define_method("remote_#{upload_name}_url=") do |url|
|
60
59
|
upload = Uploadbox.const_get(upload_class_name).create!(remote_file_url: url)
|
61
|
-
self.send("#{upload_name}=", upload)
|
62
|
-
end
|
63
|
-
|
64
|
-
# @post.attach_picture!
|
65
|
-
define_method("attach_#{upload_name}!") do |upload_id|
|
66
|
-
self.send("#{upload_name}=", upload_class.find(upload_id))
|
60
|
+
self.send("#{upload_name}_upload=", upload)
|
67
61
|
end
|
68
62
|
|
69
63
|
# Post.update_picture_versions!
|
@@ -80,6 +74,94 @@ module Uploadbox
|
|
80
74
|
options[:removable]
|
81
75
|
end
|
82
76
|
|
77
|
+
upload_class.instance_eval do
|
78
|
+
delegate *upload_versions.keys, to: :file
|
79
|
+
|
80
|
+
default_scope -> { where(imageable_type: imageable_type).where(upload_name: upload_name.to_s) }
|
81
|
+
|
82
|
+
# Uploabox::PostPictureUploader < UploadBox::ImgProcessing < CarrierWave
|
83
|
+
dynamic_uploader = Class.new(Uploadbox::ImageProcessingUploader)
|
84
|
+
Uploadbox.const_set(self.name.demodulize + 'Uploader', dynamic_uploader)
|
85
|
+
dynamic_uploader.class_eval do
|
86
|
+
upload_versions.each do |version_name, dimensions|
|
87
|
+
if options[:retina]
|
88
|
+
dimensions = dimensions.map{ |d| d * 2 }
|
89
|
+
end
|
90
|
+
|
91
|
+
version version_name do
|
92
|
+
process resize_to_fill: dimensions
|
93
|
+
process quality: quality = options[:quality]
|
94
|
+
end
|
95
|
+
|
96
|
+
def dimensions
|
97
|
+
model.class.versions[version_name]
|
98
|
+
end
|
99
|
+
|
100
|
+
def width
|
101
|
+
dimensions[0]
|
102
|
+
end
|
103
|
+
|
104
|
+
def height
|
105
|
+
dimensions[1]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
mount_uploader :file, dynamic_uploader
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
has_one "#{upload_name}_upload".to_sym, as: :imageable,
|
114
|
+
class_name: "Uploadbox::#{self.to_s + upload_name.to_s.camelize}",
|
115
|
+
autosave: true
|
116
|
+
accepts_nested_attributes_for "#{upload_name}_upload".to_sym
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
def uploads_many(upload_name, options={})
|
121
|
+
default_options = {
|
122
|
+
default: false,
|
123
|
+
placeholder: false,
|
124
|
+
removable: true,
|
125
|
+
retina: Uploadbox.retina,
|
126
|
+
quality: Uploadbox.retina ? (Uploadbox.retina_quality || 40) : (Uploadbox.image_quality || 80)
|
127
|
+
}
|
128
|
+
options = options.reverse_merge(default_options)
|
129
|
+
upload_versions = options.select{ |key| default_options.keys.exclude? key }
|
130
|
+
options = options.select{ |key| default_options.keys.include? key }
|
131
|
+
|
132
|
+
imageable_type = self.to_s
|
133
|
+
upload_class_name = imageable_type + upload_name.to_s.camelize
|
134
|
+
upload_class = Class.new(Image)
|
135
|
+
Uploadbox.const_set(upload_class_name, upload_class)
|
136
|
+
|
137
|
+
# @post.images?
|
138
|
+
define_method("#{upload_name}?") do
|
139
|
+
upload = send(upload_name)
|
140
|
+
upload and upload.any?
|
141
|
+
end
|
142
|
+
|
143
|
+
# @post.images=([id, id])
|
144
|
+
define_method("#{upload_name}=") do |ids|
|
145
|
+
self.send(upload_name).send('replace', [])
|
146
|
+
for id in ids.select(&:present?)
|
147
|
+
self.send(upload_name).send('<<', upload_class.find(id))
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Post.update_images_versions!
|
152
|
+
self.define_singleton_method "update_#{upload_name}_versions!" do
|
153
|
+
Uploadbox.const_get(upload_class_name).find_each{|upload| upload.file.recreate_versions!}
|
154
|
+
end
|
155
|
+
|
156
|
+
# Uploadbox::PostImages < Image
|
157
|
+
upload_class.define_singleton_method :versions do
|
158
|
+
upload_versions
|
159
|
+
end
|
160
|
+
|
161
|
+
upload_class.define_singleton_method :removable? do
|
162
|
+
options[:removable]
|
163
|
+
end
|
164
|
+
|
83
165
|
upload_class.instance_eval do
|
84
166
|
delegate *upload_versions.keys, to: :file
|
85
167
|
|
@@ -115,7 +197,7 @@ module Uploadbox
|
|
115
197
|
mount_uploader :file, dynamic_uploader
|
116
198
|
end
|
117
199
|
|
118
|
-
|
200
|
+
has_many upload_name, as: :imageable, class_name: "Uploadbox::#{self.to_s + upload_name.to_s.camelize}"
|
119
201
|
end
|
120
202
|
|
121
203
|
end
|
data/lib/uploadbox/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uploadbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julio Protzek
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-10-
|
12
|
+
date: 2013-10-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -347,6 +347,34 @@ dependencies:
|
|
347
347
|
- - ~>
|
348
348
|
- !ruby/object:Gem::Version
|
349
349
|
version: 0.3.2
|
350
|
+
- !ruby/object:Gem::Dependency
|
351
|
+
name: dotenv-rails
|
352
|
+
requirement: !ruby/object:Gem::Requirement
|
353
|
+
requirements:
|
354
|
+
- - '>='
|
355
|
+
- !ruby/object:Gem::Version
|
356
|
+
version: '0'
|
357
|
+
type: :development
|
358
|
+
prerelease: false
|
359
|
+
version_requirements: !ruby/object:Gem::Requirement
|
360
|
+
requirements:
|
361
|
+
- - '>='
|
362
|
+
- !ruby/object:Gem::Version
|
363
|
+
version: '0'
|
364
|
+
- !ruby/object:Gem::Dependency
|
365
|
+
name: launchy
|
366
|
+
requirement: !ruby/object:Gem::Requirement
|
367
|
+
requirements:
|
368
|
+
- - '>='
|
369
|
+
- !ruby/object:Gem::Version
|
370
|
+
version: '0'
|
371
|
+
type: :development
|
372
|
+
prerelease: false
|
373
|
+
version_requirements: !ruby/object:Gem::Requirement
|
374
|
+
requirements:
|
375
|
+
- - '>='
|
376
|
+
- !ruby/object:Gem::Version
|
377
|
+
version: '0'
|
350
378
|
description: Uploadbox makes easy to manage files in your Rails application.
|
351
379
|
email:
|
352
380
|
- julio@startae.com.br
|
@@ -359,7 +387,11 @@ files:
|
|
359
387
|
- app/assets/font/fontello.svg
|
360
388
|
- app/assets/font/fontello.ttf
|
361
389
|
- app/assets/font/fontello.woff
|
390
|
+
- app/assets/javascripts/_gallery_uploader.coffee
|
362
391
|
- app/assets/javascripts/_image_uploader.coffee
|
392
|
+
- app/assets/javascripts/_manager.coffee
|
393
|
+
- app/assets/javascripts/_uploader_preview.coffee
|
394
|
+
- app/assets/javascripts/_uuid.js
|
363
395
|
- app/assets/javascripts/cors/jquery.postmessage-transport.js
|
364
396
|
- app/assets/javascripts/cors/jquery.xdr-transport.js
|
365
397
|
- app/assets/javascripts/jquery.fileupload.js
|
@@ -367,7 +399,7 @@ files:
|
|
367
399
|
- app/assets/javascripts/jquery.ui.widget.js
|
368
400
|
- app/assets/javascripts/uploadbox.coffee
|
369
401
|
- app/assets/stylesheets/bootstrap/_progress.css
|
370
|
-
- app/assets/stylesheets/fontello.
|
402
|
+
- app/assets/stylesheets/fontello.css
|
371
403
|
- app/assets/stylesheets/uploadbox.sass
|
372
404
|
- app/controllers/uploadbox/application_controller.rb
|
373
405
|
- app/controllers/uploadbox/images_controller.rb
|
@@ -377,9 +409,11 @@ files:
|
|
377
409
|
- app/models/image.rb
|
378
410
|
- app/uploaders/uploadbox/image_processing_uploader.rb
|
379
411
|
- app/views/layouts/uploadbox/application.html.erb
|
380
|
-
- app/views/uploadbox/images/
|
412
|
+
- app/views/uploadbox/images/_uploads_many.slim
|
413
|
+
- app/views/uploadbox/images/_uploads_one.slim
|
381
414
|
- app/views/uploadbox/images/find.json.jbuilder
|
382
415
|
- config/routes.rb
|
416
|
+
- config/spring.rb
|
383
417
|
- lib/form_builder.rb
|
384
418
|
- lib/generators/uploadbox/image/image_generator.rb
|
385
419
|
- lib/generators/uploadbox/image/templates/initializers/uploadbox.rb
|