anaconda 0.14.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -0
- data/LICENSE.txt +1 -1
- data/README.markdown +26 -81
- data/app/assets/javascripts/anaconda_uploader.js.coffee +80 -87
- data/lib/anaconda/form_builder_helpers.rb +5 -1
- data/lib/anaconda/railtie.rb +0 -2
- data/lib/anaconda/version.rb +1 -1
- metadata +2 -3
- data/lib/anaconda/upload_helper.rb +0 -100
- data/lib/generators/anaconda/USAGE +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 794e8b8942312082f80eaba9d5026be051931c6a
|
4
|
+
data.tar.gz: 787aad09d8fb4ca31d4e4af477e735f6e330d8bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6ca32198af10e738589304a3e5158c4c9560198ea04d2f6ba88090422a0c7a75bc55f90d468ac83bd916a2f81bf1fb5c8b5b67162ec980789593c38b8244d36
|
7
|
+
data.tar.gz: 7af5d7b85c26f3ec0baa6c5d7b5e4b8a6de4383d9af0b359fafd317edfb56e1ed4091820760893605ef3335475ee3765c206e4c3649e1ffb5a867a460c879018
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
* 0.14.0
|
2
|
+
* Add ability to specify protocol in the magic `asset_url` method
|
3
|
+
|
4
|
+
* 0.13.1
|
5
|
+
* Use UTC for timestamp in migration files.
|
6
|
+
|
7
|
+
* 0.13.0
|
8
|
+
* Set Content-Type for S3 file to match that of the uploaded source file.
|
9
|
+
|
10
|
+
* 0.12.2
|
11
|
+
* Fix bug introduced in 0.12.1
|
12
|
+
* Wrap hidden fields in the anaconda_dropzone div (to fix bug)
|
13
|
+
|
14
|
+
* 0.12.1
|
15
|
+
* Make progress bar go to 100% on upload complete
|
16
|
+
* Properly store ACL on file upload (`asset_stored_privately`)
|
17
|
+
* Properly store `original_filename` on upload
|
18
|
+
* Fix bug when dragging and dropping onto the file select button
|
19
|
+
|
20
|
+
* 0.12.0
|
21
|
+
* Delete files from S3 when a new one us uploaded, or the record is deleted.
|
22
|
+
* Add options to disable deleting files from S3 when a new one is uploaded (`remove_previous_s3_files_on_change` and `remove_previous_s3_files_on_destroy`). These default to `true`
|
23
|
+
* Add `Model.anaconda_fields_for_all_columns` and `Model.anaconda_fields_for(column_name)` methods to make strong parameters cleaner
|
24
|
+
|
25
|
+
* 0.11.0
|
26
|
+
* Change aws URLs to use path style URLs
|
27
|
+
|
28
|
+
* 0.10.0
|
29
|
+
* Add `download_url` magic method that uses content-disposition to force the browser to download the URL. This is a signed AWS url that is only valid for 1 hour
|
30
|
+
|
31
|
+
* 0.9.10
|
32
|
+
* Fix bug when attribute had more than one underscore
|
33
|
+
|
34
|
+
* 0.9.9
|
35
|
+
* Fix bug untroduced in previous version
|
36
|
+
* 0.9.8
|
37
|
+
* Add `base_key` option
|
38
|
+
* Change the way we identify hidden elements to work when we're using this in a nested form.
|
39
|
+
|
40
|
+
* 0.9.7
|
41
|
+
* Add percent sign to progress-percent div
|
42
|
+
|
43
|
+
* 0.9.6
|
44
|
+
* Fix `auto_upload` and `auto_submit` options.
|
45
|
+
|
46
|
+
* 0.9.5
|
47
|
+
* add `host` and `protocol` options to `anaconda_for`
|
48
|
+
|
49
|
+
* 0.9.4
|
50
|
+
* Fix uploads. Previous version broke them completely.
|
51
|
+
|
52
|
+
* 0.9.3
|
53
|
+
* If no files have been selected, let form submit as normal
|
54
|
+
|
55
|
+
* 0.9.2
|
56
|
+
* Always use UTC for policy expiration date, even if Time.zone is set to something else.
|
57
|
+
|
58
|
+
* 0.9.1
|
59
|
+
|
60
|
+
* Fix for anaconda:migration when the field name has an underscore in it
|
61
|
+
|
62
|
+
* 0.9.0
|
63
|
+
|
64
|
+
* Add support for multiple anaconda uploaders per form
|
65
|
+
|
66
|
+
* Completely refactor JavaScript file to support multiple uploaders
|
67
|
+
|
68
|
+
* Add auto_submit option
|
69
|
+
|
70
|
+
* Fix support for allowed_types
|
71
|
+
|
72
|
+
* Add file_types to anaconda config
|
73
|
+
|
74
|
+
* Add fix for sites using Turbolinks
|
75
|
+
|
76
|
+
* 0.2.0
|
77
|
+
|
78
|
+
* Add support for multiple `anaconda_for` calls per model. Currently limited to one per form, however.
|
79
|
+
|
80
|
+
* Improve migration generation file and class naming to include field name
|
81
|
+
|
82
|
+
* `post_media.asset_url` will now return nil if the file_path is nil
|
data/LICENSE.txt
CHANGED
data/README.markdown
CHANGED
@@ -1,12 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# Anaconda
|
2
2
|
|
3
3
|
Dead simple direct-to-s3 file uploading for your rails app.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
We intend to follow semantic versioning as of 1.0. Before that time breaking changes may occur, as development is very active.
|
8
|
-
|
9
|
-
If you require stability before that time, you are strongly encouraged to specify an exact version in your `Gemfile` to avoid updating to a version that breaks things for you.
|
5
|
+
Current Version: 1.0.0
|
10
6
|
|
11
7
|
## Installation
|
12
8
|
|
@@ -180,89 +176,38 @@ We highly recommend the `figaro` gem [https://github.com/laserlemon/figaro](http
|
|
180
176
|
|
181
177
|
`asset_download_url` will return a signed S3 URL with content-disposition set to attachment so the file will be downloaded instead of opened in the browser.
|
182
178
|
|
183
|
-
|
184
|
-
* 0.14.0
|
185
|
-
* Add ability to specify protocol in the magic `asset_url` method
|
179
|
+
### Advanced Usage
|
186
180
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
* 0.13.0
|
191
|
-
* Set Content-Type for S3 file to match that of the uploaded source file.
|
192
|
-
|
193
|
-
* 0.12.2
|
194
|
-
* Fix bug introduced in 0.12.1
|
195
|
-
* Wrap hidden fields in the anaconda_dropzone div (to fix bug)
|
196
|
-
|
197
|
-
* 0.12.1
|
198
|
-
* Make progress bar go to 100% on upload complete
|
199
|
-
* Properly store ACL on file upload (`asset_stored_privately`)
|
200
|
-
* Properly store `original_filename` on upload
|
201
|
-
* Fix bug when dragging and dropping onto the file select button
|
202
|
-
|
203
|
-
* 0.12.0
|
204
|
-
* Delete files from S3 when a new one us uploaded, or the record is deleted.
|
205
|
-
* Add options to disable deleting files from S3 when a new one is uploaded (`remove_previous_s3_files_on_change` and `remove_previous_s3_files_on_destroy`). These default to `true`
|
206
|
-
* Add `Model.anaconda_fields_for_all_columns` and `Model.anaconda_fields_for(column_name)` methods to make strong parameters cleaner
|
207
|
-
|
208
|
-
* 0.11.0
|
209
|
-
* Change aws URLs to use path style URLs
|
210
|
-
|
211
|
-
* 0.10.0
|
212
|
-
* Add `download_url` magic method that uses content-disposition to force the browser to download the URL. This is a signed AWS url that is only valid for 1 hour
|
181
|
+
#### Events
|
182
|
+
There are several events fired throughout the upload process that you can subscribe to. Many of them contain useful data along with the event. The documentation needs expanding here.
|
213
183
|
|
214
|
-
*
|
215
|
-
|
216
|
-
|
217
|
-
*
|
218
|
-
|
219
|
-
*
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
*
|
224
|
-
* Add percent sign to progress-percent div
|
225
|
-
|
226
|
-
* 0.9.6
|
227
|
-
* Fix `auto_upload` and `auto_submit` options.
|
228
|
-
|
229
|
-
* 0.9.5
|
230
|
-
* add `host` and `protocol` options to `anaconda_for`
|
184
|
+
* `anaconda:manager:upload-manager-constructor` fired when the first upload element constructs an upload manager for a form
|
185
|
+
* `anaconda:manager:upload-field-registered` fired when an upload field registers itself with an upload manager
|
186
|
+
* `anaconda:manager:uploads-starting` fired when the form is submitted and Anaconda starts uploading the selected files
|
187
|
+
* `anaconda:manager:upload-completed` fired each time an upload is completed
|
188
|
+
* `anaconda:manager:all-uploads-completed` fired once all uploads have completed
|
189
|
+
* `anaconda:file-selected` fired when a file is selected
|
190
|
+
* `anaconda:file-upload-failed` fired when an upload fails
|
191
|
+
* `anaconda:file-upload-started` fired for each upload when it is started
|
192
|
+
* `anaconda:invalid-file-type-selected` fired when a non-permitted file type is selected
|
193
|
+
* `anaconda:file-upload-completed` fired when an upload is completed
|
231
194
|
|
232
|
-
|
233
|
-
* Fix uploads. Previous version broke them completely.
|
234
|
-
|
235
|
-
* 0.9.3
|
236
|
-
* If no files have been selected, let form submit as normal
|
195
|
+
If you return false to the following events it will prevent the default behavior:
|
237
196
|
|
238
|
-
*
|
239
|
-
|
197
|
+
* `anaconda:invalid-file-type-selected` Default behavior is an alert with content `_filename_ is a _filetype_ file. Only _allowed file types_ files are allowed.`
|
198
|
+
* `anaconda:file-upload-failed` Default behavior is an alert with content `_filename_ failed to upload.`
|
240
199
|
|
241
|
-
* 0.9.1
|
242
|
-
|
243
|
-
* Fix for anaconda:migration when the field name has an underscore in it
|
244
200
|
|
245
|
-
|
201
|
+
## Versioning
|
202
|
+
From version 1.0.0 on we have used [Semantic Versioning](http://semver.org/).
|
246
203
|
|
247
|
-
|
248
|
-
|
249
|
-
*
|
250
|
-
|
251
|
-
* Add
|
252
|
-
|
253
|
-
* Fix support for allowed_types
|
254
|
-
|
255
|
-
* Add file_types to anaconda config
|
256
|
-
|
257
|
-
* Add fix for sites using Turbolinks
|
258
|
-
|
259
|
-
* 0.2.0
|
260
|
-
|
261
|
-
* Add support for multiple `anaconda_for` calls per model. Currently limited to one per form, however.
|
262
|
-
|
263
|
-
* Improve migration generation file and class naming to include field name
|
204
|
+
## Changelog
|
205
|
+
* 1.0.0
|
206
|
+
* Fix incorrect return value from `all_uploads_are_complete` method in AnacondaUploadManager
|
207
|
+
* Remove unused `upload_helper.rb` and other old code.
|
208
|
+
* Add a bunch of JavaScript events
|
264
209
|
|
265
|
-
|
210
|
+
See [changelog](CHANGELOG.md) for previous changes
|
266
211
|
|
267
212
|
## Contributing to anaconda
|
268
213
|
|
@@ -1,23 +1,29 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
4
|
-
|
1
|
+
triggerEvent = (name, data) ->
|
2
|
+
# Taken directly from Turbolinks with no shame.
|
3
|
+
# https://github.com/rails/turbolinks/blob/master/lib/assets/javascripts/turbolinks.js.coffee
|
4
|
+
event = document.createEvent 'Events'
|
5
|
+
event.data = data if data
|
6
|
+
event.initEvent name, true, true
|
7
|
+
document.dispatchEvent event
|
8
|
+
|
5
9
|
class @AnacondaUploadManager
|
6
10
|
constructor: (options = {}) ->
|
7
11
|
@anaconda_upload_fields = []
|
8
|
-
DLog options
|
12
|
+
# DLog options
|
9
13
|
@form = $("##{options.form_id}")
|
10
14
|
@upload_automatically = false
|
11
15
|
@submit_automatically = false
|
16
|
+
triggerEvent "anaconda:manager:upload-manager-constructor", { form: @form }
|
12
17
|
@setup_form_submit_handler()
|
13
18
|
@bind_dropzone_effects()
|
14
19
|
self = this
|
15
20
|
$(document).on "page:fetch", ->
|
16
|
-
DLog "page:fetch"
|
21
|
+
# DLog "page:fetch"
|
17
22
|
self.reset()
|
18
23
|
|
19
24
|
register_upload_field: (anaconda_upload_field)->
|
20
|
-
DLog "Registering Upload Field"
|
25
|
+
# DLog "Registering Upload Field"
|
26
|
+
triggerEvent "anaconda:manager:upload-field-registered", { uploadField: anaconda_upload_field, resource: "#{anaconda_upload_field.hyphenated_resource}-#{anaconda_upload_field.hyphenated_attribute}" }
|
21
27
|
@anaconda_upload_fields.push anaconda_upload_field
|
22
28
|
if anaconda_upload_field.upload_automatically
|
23
29
|
# If _any_ of them have an auto upload, we want to know
|
@@ -27,13 +33,14 @@ class @AnacondaUploadManager
|
|
27
33
|
@submit_automatically = true
|
28
34
|
|
29
35
|
setup_form_submit_handler: ->
|
30
|
-
DLog( "Setting up submit handler for form #{@form.attr('id')}")
|
36
|
+
# DLog( "Setting up submit handler for form #{@form.attr('id')}")
|
31
37
|
@form.on( 'submit', { self: this }, this.form_submit_handler )
|
32
38
|
|
33
39
|
form_submit_handler: (e) ->
|
34
40
|
self = e.data.self
|
35
41
|
return true if self.upload_automatically || self.all_uploads_are_complete()
|
36
42
|
e.preventDefault()
|
43
|
+
triggerEvent "anaconda:manager:uploads-starting", { form: @form }
|
37
44
|
$(this).off( 'submit', self.form_submit_handler )
|
38
45
|
|
39
46
|
for upload_field, i in self.anaconda_upload_fields
|
@@ -47,12 +54,13 @@ class @AnacondaUploadManager
|
|
47
54
|
all_uploads_are_complete: ->
|
48
55
|
all_completed = true
|
49
56
|
for upload_field, i in @anaconda_upload_fields
|
50
|
-
if upload_field.upload_in_progress || (!upload_field.upload_in_progress && upload_field.file != null)
|
57
|
+
if upload_field.upload_in_progress || (!upload_field.upload_in_progress && upload_field.file != null && !upload_field.upload_completed)
|
51
58
|
all_completed = false
|
52
59
|
break
|
53
60
|
return all_completed
|
54
61
|
|
55
62
|
upload_completed: ->
|
63
|
+
triggerEvent "anaconda:manager:upload-completed", { form: @form }
|
56
64
|
all_completed = true
|
57
65
|
for upload_field, i in @anaconda_upload_fields
|
58
66
|
if upload_field.upload_in_progress
|
@@ -62,6 +70,7 @@ class @AnacondaUploadManager
|
|
62
70
|
@all_uploads_completed()
|
63
71
|
|
64
72
|
all_uploads_completed: ->
|
73
|
+
triggerEvent "anaconda:manager:all-uploads-completed", { form: @form }
|
65
74
|
if !@upload_automatically || @submit_automatically
|
66
75
|
@form.submit()
|
67
76
|
else
|
@@ -107,13 +116,15 @@ class @AnacondaUploadField
|
|
107
116
|
constructor: (options = {}) ->
|
108
117
|
@upload_in_progress = false
|
109
118
|
@upload_completed = false
|
110
|
-
DLog "options:"
|
111
|
-
DLog options
|
119
|
+
# DLog "options:"
|
120
|
+
# DLog options
|
112
121
|
@element_id = options.element_id ? ""
|
113
122
|
@allowed_types = options.allowed_types ? []
|
114
|
-
DLog @allowed_types
|
123
|
+
# DLog @allowed_types
|
115
124
|
@resource = options.resource
|
116
125
|
@attribute = options.attribute
|
126
|
+
@hyphenated_resource = @resource.replace(/_/g, "-")
|
127
|
+
@hyphenated_attribute = @attribute.replace(/_/g, "-")
|
117
128
|
if options.upload_details_container != null && options.upload_details_container != ""
|
118
129
|
@upload_details_container = $("##{options.upload_details_container}")
|
119
130
|
else
|
@@ -132,6 +143,7 @@ class @AnacondaUploadField
|
|
132
143
|
@register_with_upload_manager()
|
133
144
|
|
134
145
|
@setup_fileupload()
|
146
|
+
@bind_remove_button()
|
135
147
|
|
136
148
|
register_with_upload_manager: ->
|
137
149
|
if (@closest_form().length == 0 || @closest_form().attr('id') == 'undefined')
|
@@ -139,7 +151,7 @@ class @AnacondaUploadField
|
|
139
151
|
if (typeof( window.anacondaUploadManagers ) == "undefined")
|
140
152
|
window.anacondaUploadManagers = []
|
141
153
|
if (typeof( window.anacondaUploadManagers[@closest_form().attr('id')] ) == "undefined")
|
142
|
-
DLog "registering new upload manager for form #{@closest_form().attr('id')}"
|
154
|
+
# DLog "registering new upload manager for form #{@closest_form().attr('id')}"
|
143
155
|
window.anacondaUploadManagers[@closest_form().attr('id')] = new AnacondaUploadManager({form_id: @closest_form().attr('id')})
|
144
156
|
@upload_manager().register_upload_field(this)
|
145
157
|
upload_manager: ->
|
@@ -154,9 +166,9 @@ class @AnacondaUploadField
|
|
154
166
|
add: (e, data) ->
|
155
167
|
self.file_selected data
|
156
168
|
progress: (e, data) ->
|
157
|
-
DLog data
|
169
|
+
# DLog data
|
158
170
|
progress = parseInt(data.loaded / data.total * 100, 10)
|
159
|
-
DLog( "Progress for #{self.file.name}: " + progress )
|
171
|
+
# DLog( "Progress for #{self.file.name}: " + progress )
|
160
172
|
self.update_progress_to(progress)
|
161
173
|
|
162
174
|
done: (e, data) ->
|
@@ -164,22 +176,28 @@ class @AnacondaUploadField
|
|
164
176
|
self.file_completed_upload data
|
165
177
|
|
166
178
|
fail: (e, data) ->
|
167
|
-
alert("#{data.files[0].name} failed to upload.")
|
168
|
-
DLog("Upload failed:")
|
169
|
-
DLog("Error:")
|
170
|
-
DLog(e)
|
171
|
-
DLog("data:")
|
172
|
-
DLog(data)
|
173
|
-
DLog("data.errorThrown:")
|
174
|
-
DLog(data.errorThrown )
|
175
|
-
DLog("data.textStatus:")
|
176
|
-
DLog(data.textStatus )
|
177
|
-
DLog("data.jqXHR:")
|
178
|
-
DLog(data.jqXHR )
|
179
|
-
|
179
|
+
alert("#{data.files[0].name} failed to upload.") if triggerEvent "anaconda:file-upload-failed", { data: data, resource: "#{@hyphenated_resource}-#{@hyphenated_attribute}" }
|
180
|
+
# DLog("Upload failed:")
|
181
|
+
# DLog("Error:")
|
182
|
+
# DLog(e)
|
183
|
+
# DLog("data:")
|
184
|
+
# DLog(data)
|
185
|
+
# DLog("data.errorThrown:")
|
186
|
+
# DLog(data.errorThrown )
|
187
|
+
# DLog("data.textStatus:")
|
188
|
+
# DLog(data.textStatus )
|
189
|
+
# DLog("data.jqXHR:")
|
190
|
+
# DLog(data.jqXHR )
|
191
|
+
|
192
|
+
bind_remove_button: ->
|
193
|
+
$("a[data-remove-#{@hyphenated_resource}-#{@hyphenated_attribute}]").click (e) =>
|
194
|
+
e.preventDefault()
|
195
|
+
@remove_file()
|
196
|
+
|
180
197
|
upload: ->
|
181
198
|
return if @upload_completed
|
182
199
|
if @file != null && @file_data != null
|
200
|
+
triggerEvent "anaconda:file-upload-started", { file: @file, resource: "#{@hyphenated_resource}-#{@hyphenated_attribute}" }
|
183
201
|
$("input#key").val @key
|
184
202
|
@file_data.submit()
|
185
203
|
@upload_in_progress = true
|
@@ -198,7 +216,7 @@ class @AnacondaUploadField
|
|
198
216
|
|
199
217
|
get_media_type: (file_obj) ->
|
200
218
|
media_type = "unknown"
|
201
|
-
DLog "get_media_type"
|
219
|
+
# DLog "get_media_type"
|
202
220
|
for k,v of @media_types
|
203
221
|
regexp = new RegExp(v, "i")
|
204
222
|
if regexp.test(file_obj.type) || regexp.test(file_obj.name)
|
@@ -215,23 +233,31 @@ class @AnacondaUploadField
|
|
215
233
|
false
|
216
234
|
|
217
235
|
file_selected: (data) ->
|
218
|
-
DLog "file_selected"
|
219
|
-
DLog data
|
236
|
+
# DLog "file_selected"
|
237
|
+
# DLog data
|
220
238
|
if @is_allowed_type(data.files[0])
|
221
239
|
@file = data.files[0]
|
222
240
|
@file_data = data
|
223
241
|
@set_content_type()
|
224
242
|
|
225
|
-
|
243
|
+
triggerEvent "anaconda:valid-file-selected", { file: data.files[0], resource: "#{@hyphenated_resource}-#{@hyphenated_attribute}" }
|
244
|
+
|
245
|
+
# This remove button is for removing an already uploaded file,
|
246
|
+
# not removing the just selected file. Let's not confuse people.
|
247
|
+
$("a[data-remove-#{@hyphenated_resource}-#{@hyphenated_attribute}]").hide()
|
248
|
+
|
249
|
+
|
250
|
+
# DLog @file
|
226
251
|
@upload_details_container.html "<div id='upload_file_#{@get_id()}' class='upload-file #{@get_media_type(@file)}'><span class='file-name'>#{@file.name}</span><span class='size'>#{@readable_size()}</span><span class='progress-percent'></span><div class='progress'><span class='progress-bar'></span></div></div>"
|
227
252
|
|
228
253
|
if @upload_automatically
|
229
|
-
DLog "auto upload"
|
254
|
+
# DLog "auto upload"
|
230
255
|
@upload()
|
231
256
|
else
|
232
|
-
DLog "Not auto upload"
|
257
|
+
# DLog "Not auto upload"
|
233
258
|
else
|
234
|
-
|
259
|
+
if triggerEvent "anaconda:invalid-file-selected", { file: data.files[0], resource: "#{@hyphenated_resource}-#{@hyphenated_attribute}" }
|
260
|
+
alert "#{data.files[0].name} is a #{@get_media_type(data.files[0])} file. Only #{@allowed_types.join(", ")} files are allowed."
|
235
261
|
|
236
262
|
set_content_type: ->
|
237
263
|
form_data = $(@element_id).data('form-data')
|
@@ -260,60 +286,27 @@ class @AnacondaUploadField
|
|
260
286
|
@upload_details_container.find('.progress-bar').css('width', progress + '%')
|
261
287
|
|
262
288
|
file_completed_upload: (data) ->
|
263
|
-
|
264
|
-
DLog @file
|
265
|
-
|
266
|
-
# if @upload_complete_post_url? && @upload_complete_post_url != ""
|
267
|
-
# DLog "will now post to #{@upload_complete_post_url}"
|
268
|
-
#
|
269
|
-
# file_data = {}
|
270
|
-
# file_data[@resource] = {}
|
271
|
-
# file_data[@resource]["#{@attribute}_file_path"] = "#{@base_key}/#{upload_file.file.name}"
|
272
|
-
# file_data[@resource]["#{@attribute}_filename"] = upload_file.file.name
|
273
|
-
# file_data[@resource]["#{@attribute}_size"] = upload_file.file.size
|
274
|
-
# file_data[@resource]["#{@attribute}_type"] = upload_file.file.media_type
|
275
|
-
# upload_file = this
|
276
|
-
# $.ajax({
|
277
|
-
# type: 'PATCH',
|
278
|
-
# url: @upload_complete_post_url,
|
279
|
-
# data: $.param(file_data)
|
280
|
-
# success: (data, textStatus, jqXHR) ->
|
281
|
-
# DLog "file completed handler complete"
|
282
|
-
# DLog data
|
283
|
-
# #TODO: handle a failure on this POST
|
284
|
-
# })
|
289
|
+
triggerEvent "anaconda:file-upload-completed", { file: @file, resource: "#{@hyphenated_resource}-#{@hyphenated_attribute}" }
|
290
|
+
# DLog "#{@file.name} completed uploading"
|
291
|
+
# DLog @file
|
285
292
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
$( @element_id ).siblings( "input[data-#{hyphenated_resource}-#{hyphenated_attribute}-
|
291
|
-
$( @element_id ).siblings( "input[data-#{hyphenated_resource}-#{hyphenated_attribute}-
|
292
|
-
$( @element_id ).siblings( "input[data-#{hyphenated_resource}-#{hyphenated_attribute}-size]" ).val( @file.size )
|
293
|
-
$( @element_id ).siblings( "input[data-#{hyphenated_resource}-#{hyphenated_attribute}-type]" ).val( @file.type )
|
294
|
-
$( @element_id ).siblings( "input[data-#{hyphenated_resource}-#{hyphenated_attribute}-original-filename]" ).val( @file.name )
|
295
|
-
$( @element_id ).siblings( "input[data-#{hyphenated_resource}-#{hyphenated_attribute}-stored-privately]" ).val( @stored_privately() )
|
293
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-file-path]" ).val( @key.replace("${filename}", @file.name) )
|
294
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-filename]" ).val( @file.name )
|
295
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-size]" ).val( @file.size )
|
296
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-type]" ).val( @file.type )
|
297
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-original-filename]" ).val( @file.name )
|
298
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-stored-privately]" ).val( @stored_privately() )
|
296
299
|
|
297
300
|
@upload_in_progress = false;
|
298
301
|
@upload_completed = true;
|
299
302
|
@upload_manager().upload_completed()
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
# get_media_type: ->
|
311
|
-
# media_type = "unknown"
|
312
|
-
# return media_type
|
313
|
-
# set_context: ->
|
314
|
-
# @data.context = this
|
315
|
-
# submit: ->
|
316
|
-
# @data.submit()
|
317
|
-
# update_progress_to: (progress) ->
|
318
|
-
# $("#upload_file_#{@id} .progress-percent").html progress
|
319
|
-
# $("#upload_file_#{@id}").find('.progress-bar').css('width', progress + '%')
|
303
|
+
|
304
|
+
remove_file: ->
|
305
|
+
triggerEvent "anaconda:remove-file", { resource: "#{@hyphenated_resource}-#{@hyphenated_attribute}" }
|
306
|
+
$("a[data-remove-#{@hyphenated_resource}-#{@hyphenated_attribute}]").hide()
|
307
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-file-path]" ).val("")
|
308
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-filename]" ).val("")
|
309
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-size]" ).val("")
|
310
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-type]" ).val("")
|
311
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-original-filename]" ).val("")
|
312
|
+
$( @element_id ).siblings( "input[data-#{@hyphenated_resource}-#{@hyphenated_attribute}-stored-privately]" ).val("")
|
@@ -35,12 +35,16 @@ module Anaconda
|
|
35
35
|
output += self.hidden_field "#{anaconda_field_name}_type".to_sym, data: {"#{instance.class.to_s.underscore}_#{anaconda_field_name}_type" => true}
|
36
36
|
# output += render(:template =>"anaconda/_uploader_form_for.html.haml", :locals => {resource: instance, options: options.merge(as: anaconda_field_name, form_options: form_options, element_id: element_id )}, layout: false).to_s
|
37
37
|
|
38
|
+
if form_options[:remove_button] && self.object.send("#{anaconda_field_name}_file_path").present?
|
39
|
+
remove_button_text = form_options[:remove_button].kind_of?(String) ? form_options[:remove_button] : "Remove"
|
40
|
+
output += "<a href='#' data-#{"remove_#{instance.class.to_s.underscore}_#{anaconda_field_name}".gsub('_', '-')}>#{remove_button_text}</a>"
|
41
|
+
end
|
42
|
+
|
38
43
|
output += "</div>" #anaconda_dropzone
|
39
44
|
|
40
45
|
options = options.merge(as: anaconda_field_name, form_options: form_options, element_id: element_id )
|
41
46
|
output += <<-END
|
42
47
|
<div id="#{instance.class.to_s.underscore}_#{anaconda_field_name}_details"></div>
|
43
|
-
|
44
48
|
<script>
|
45
49
|
(function() {
|
46
50
|
window.uploader = new AnacondaUploadField({
|
data/lib/anaconda/railtie.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
require 'rails/railtie'
|
2
|
-
require 'anaconda/upload_helper'
|
3
2
|
require 'anaconda/form_builder_helpers'
|
4
3
|
|
5
4
|
module Anaconda
|
6
5
|
class Railtie < ::Rails::Railtie
|
7
6
|
initializer "anaconda.upload_helper" do
|
8
|
-
ActionView::Base.send :include, UploadHelper
|
9
7
|
ActionView::Helpers::FormBuilder.send :include, FormBuilderHelpers
|
10
8
|
SimpleForm::FormBuilder.send :include, FormBuilderHelpers if SimpleForm::FormBuilder
|
11
9
|
end
|
data/lib/anaconda/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anaconda
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben McFadden
|
@@ -48,6 +48,7 @@ extra_rdoc_files:
|
|
48
48
|
files:
|
49
49
|
- ".document"
|
50
50
|
- ".gitignore"
|
51
|
+
- CHANGELOG.md
|
51
52
|
- Gemfile
|
52
53
|
- LICENSE.txt
|
53
54
|
- README.markdown
|
@@ -62,9 +63,7 @@ files:
|
|
62
63
|
- lib/anaconda/errors.rb
|
63
64
|
- lib/anaconda/form_builder_helpers.rb
|
64
65
|
- lib/anaconda/railtie.rb
|
65
|
-
- lib/anaconda/upload_helper.rb
|
66
66
|
- lib/anaconda/version.rb
|
67
|
-
- lib/generators/anaconda/USAGE
|
68
67
|
- lib/generators/anaconda/install_generator.rb
|
69
68
|
- lib/generators/anaconda/migration_generator.rb
|
70
69
|
- lib/generators/anaconda/templates/config/initializers/anaconda.rb
|
@@ -1,100 +0,0 @@
|
|
1
|
-
module Anaconda
|
2
|
-
# Greatly inspired by http://railscasts.com/episodes/383-uploading-to-amazon-s3
|
3
|
-
module UploadHelper
|
4
|
-
def anaconda_uploader_form_for(instance, attribute, form_options = {})
|
5
|
-
a_class = instance.class unless instance.kind_of? Class
|
6
|
-
if a_class.anaconda_options[attribute].present
|
7
|
-
options = a_class.anaconda_options[attribute].dup
|
8
|
-
else
|
9
|
-
raise AnacondaError, "attribute options not set for column #{attribute}. Did you add `anaconda_for :#{attribute}` to the model?"
|
10
|
-
end
|
11
|
-
options[:base_key] = instance.send(options[:base_key].to_s) if options[:base_key].kind_of? Symbol
|
12
|
-
render(:template =>"anaconda/_uploader_form_for.html.haml", :locals => {resource: instance, options: options.merge(as: attribute, form_options: form_options)}, layout: false).to_s
|
13
|
-
end
|
14
|
-
def anaconda_uploader_form(options = {}, &block)
|
15
|
-
uploader = S3Uploader.new(options)
|
16
|
-
form_tag(uploader.url, uploader.form_options) do
|
17
|
-
uploader.fields.map do |name, value|
|
18
|
-
hidden_field_tag(name, value)
|
19
|
-
end.join.html_safe + file_field_tag("file").html_safe# + capture(&block)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class S3Uploader
|
24
|
-
def initialize(options)
|
25
|
-
@options = options.reverse_merge(
|
26
|
-
id: "fileupload",
|
27
|
-
aws_access_key_id: Anaconda.aws[:aws_access_key],
|
28
|
-
aws_secret_access_key: Anaconda.aws[:aws_secret_key],
|
29
|
-
bucket: Anaconda.aws[:aws_bucket],
|
30
|
-
acl: "public-read",
|
31
|
-
expiration: 10.hours.from_now,
|
32
|
-
max_file_size: 500.megabytes,
|
33
|
-
as: "file"
|
34
|
-
)
|
35
|
-
end
|
36
|
-
|
37
|
-
def form_options
|
38
|
-
{
|
39
|
-
id: @options[:id],
|
40
|
-
method: "post",
|
41
|
-
authenticity_token: false,
|
42
|
-
multipart: true,
|
43
|
-
data: {
|
44
|
-
post: @options[:post],
|
45
|
-
as: @options[:as],
|
46
|
-
base_key: base_key
|
47
|
-
}
|
48
|
-
}
|
49
|
-
end
|
50
|
-
|
51
|
-
def fields
|
52
|
-
{
|
53
|
-
:key => key,
|
54
|
-
:acl => @options[:acl],
|
55
|
-
:policy => policy,
|
56
|
-
:signature => signature,
|
57
|
-
"AWSAccessKeyId" => @options[:aws_access_key_id],
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
|
-
def key
|
62
|
-
@key ||= "#{base_key}/${filename}"
|
63
|
-
end
|
64
|
-
|
65
|
-
def base_key
|
66
|
-
@options[:base_key]
|
67
|
-
end
|
68
|
-
|
69
|
-
def url
|
70
|
-
"https://s3.amazonaws.com/#{@options[:bucket]}/"
|
71
|
-
end
|
72
|
-
|
73
|
-
def policy
|
74
|
-
Base64.encode64(policy_data.to_json).gsub("\n", "")
|
75
|
-
end
|
76
|
-
|
77
|
-
def policy_data
|
78
|
-
{
|
79
|
-
expiration: @options[:expiration],
|
80
|
-
conditions: [
|
81
|
-
["starts-with", "$utf8", ""],
|
82
|
-
["starts-with", "$key", base_key],
|
83
|
-
["content-length-range", 1, @options[:max_file_size]],
|
84
|
-
{bucket: @options[:bucket]},
|
85
|
-
{acl: @options[:acl]}
|
86
|
-
]
|
87
|
-
}
|
88
|
-
end
|
89
|
-
|
90
|
-
def signature
|
91
|
-
Base64.encode64(
|
92
|
-
OpenSSL::HMAC.digest(
|
93
|
-
OpenSSL::Digest::Digest.new('sha1'),
|
94
|
-
@options[:aws_secret_access_key], policy
|
95
|
-
)
|
96
|
-
).gsub("\n", "")
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|