uploadbox 0.0.13 → 0.0.14
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.
- 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
|