anaconda 0.14.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|