asset_host_core 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +138 -0
  3. data/Rakefile +11 -0
  4. data/app/assets/images/asset_host_core/alert-overlay.png +0 -0
  5. data/app/assets/images/asset_host_core/arrow-left.gif +0 -0
  6. data/app/assets/images/asset_host_core/arrow-right.gif +0 -0
  7. data/app/assets/images/asset_host_core/fallback-img-rect.png +0 -0
  8. data/app/assets/images/asset_host_core/videoplayer-play.png +0 -0
  9. data/app/assets/images/asset_host_core/x.png +0 -0
  10. data/app/assets/javascripts/asset_host_core/admin/assets.js.coffee +221 -0
  11. data/app/assets/javascripts/asset_host_core/application.js +20 -0
  12. data/app/assets/javascripts/asset_host_core/assetadmin.js.coffee +56 -0
  13. data/app/assets/javascripts/asset_host_core/assethost.js.coffee.erb +17 -0
  14. data/app/assets/javascripts/asset_host_core/browserui.js.coffee +139 -0
  15. data/app/assets/javascripts/asset_host_core/chooserui.js.coffee +381 -0
  16. data/app/assets/javascripts/asset_host_core/client.js.coffee +29 -0
  17. data/app/assets/javascripts/asset_host_core/clients/BrightcoveVideo.js.coffee +64 -0
  18. data/app/assets/javascripts/asset_host_core/clients/templates/brightcove_embed.jst.eco +18 -0
  19. data/app/assets/javascripts/asset_host_core/clients/templates/vimeo_embed.jst.eco +1 -0
  20. data/app/assets/javascripts/asset_host_core/clients/templates/youtube_embed.jst.eco +1 -0
  21. data/app/assets/javascripts/asset_host_core/clients/vimeo_video.js.coffee +21 -0
  22. data/app/assets/javascripts/asset_host_core/clients/youtube_video.js.coffee +21 -0
  23. data/app/assets/javascripts/asset_host_core/cmsplugin.js.coffee +235 -0
  24. data/app/assets/javascripts/asset_host_core/models.js.coffee +586 -0
  25. data/app/assets/javascripts/asset_host_core/railsCMS.js.coffee +141 -0
  26. data/app/assets/javascripts/asset_host_core/slideshow.js.coffee +428 -0
  27. data/app/assets/javascripts/asset_host_core/templates/after_upload_button.jst.eco +3 -0
  28. data/app/assets/javascripts/asset_host_core/templates/asset_drop_asset.jst.eco +4 -0
  29. data/app/assets/javascripts/asset_host_core/templates/asset_modal.jst.eco +13 -0
  30. data/app/assets/javascripts/asset_host_core/templates/asset_preview.jst.eco +35 -0
  31. data/app/assets/javascripts/asset_host_core/templates/asset_search.jst.eco +2 -0
  32. data/app/assets/javascripts/asset_host_core/templates/browser_asset.jst.eco +1 -0
  33. data/app/assets/javascripts/asset_host_core/templates/browser_asset_tip.jst.eco +3 -0
  34. data/app/assets/javascripts/asset_host_core/templates/edit_modal.jst.eco +40 -0
  35. data/app/assets/javascripts/asset_host_core/templates/import_help.jst.eco +59 -0
  36. data/app/assets/javascripts/asset_host_core/templates/pagination_link.jst.eco +1 -0
  37. data/app/assets/javascripts/asset_host_core/templates/pagination_links.jst.eco +13 -0
  38. data/app/assets/javascripts/asset_host_core/templates/queued_file.jst.eco +11 -0
  39. data/app/assets/javascripts/asset_host_core/templates/save_and_close_view.jst.eco +4 -0
  40. data/app/assets/javascripts/asset_host_core/templates/upload_all_button.jst.eco +4 -0
  41. data/app/assets/javascripts/asset_host_core/templates/url_input.jst.eco +8 -0
  42. data/app/assets/stylesheets/asset_host_core/application.css.scss +384 -0
  43. data/app/assets/stylesheets/asset_host_core/jquery-ui.css +105 -0
  44. data/app/assets/stylesheets/asset_host_core/public.css.scss +204 -0
  45. data/app/assets/stylesheets/asset_host_core/slidetest.css.scss +93 -0
  46. data/app/controllers/asset_host_core/admin/api_users_controller.rb +72 -0
  47. data/app/controllers/asset_host_core/admin/assets_controller.rb +140 -0
  48. data/app/controllers/asset_host_core/admin/base_controller.rb +36 -0
  49. data/app/controllers/asset_host_core/admin/home_controller.rb +13 -0
  50. data/app/controllers/asset_host_core/admin/outputs_controller.rb +55 -0
  51. data/app/controllers/asset_host_core/api/assets_controller.rb +110 -0
  52. data/app/controllers/asset_host_core/api/base_controller.rb +43 -0
  53. data/app/controllers/asset_host_core/api/outputs_controller.rb +33 -0
  54. data/app/controllers/asset_host_core/application_controller.rb +43 -0
  55. data/app/controllers/asset_host_core/public_controller.rb +104 -0
  56. data/app/models/asset_host_core/api_user.rb +44 -0
  57. data/app/models/asset_host_core/api_user_permission.rb +6 -0
  58. data/app/models/asset_host_core/asset.rb +265 -0
  59. data/app/models/asset_host_core/asset_output.rb +69 -0
  60. data/app/models/asset_host_core/brightcove_video.rb +20 -0
  61. data/app/models/asset_host_core/output.rb +52 -0
  62. data/app/models/asset_host_core/permission.rb +19 -0
  63. data/app/models/asset_host_core/video.rb +8 -0
  64. data/app/models/asset_host_core/vimeo_video.rb +17 -0
  65. data/app/models/asset_host_core/youtube_video.rb +17 -0
  66. data/app/views/asset_host_core/admin/api_users/_form_fields.html.erb +5 -0
  67. data/app/views/asset_host_core/admin/api_users/edit.html.erb +26 -0
  68. data/app/views/asset_host_core/admin/api_users/index.html.erb +31 -0
  69. data/app/views/asset_host_core/admin/api_users/new.html.erb +17 -0
  70. data/app/views/asset_host_core/admin/api_users/show.html.erb +23 -0
  71. data/app/views/asset_host_core/admin/assets/index.html.erb +19 -0
  72. data/app/views/asset_host_core/admin/assets/metadata.html.erb +24 -0
  73. data/app/views/asset_host_core/admin/assets/show.html.erb +86 -0
  74. data/app/views/asset_host_core/admin/home/chooser.html.erb +49 -0
  75. data/app/views/asset_host_core/admin/outputs/_form_fields.html.erb +5 -0
  76. data/app/views/asset_host_core/admin/outputs/edit.html.erb +26 -0
  77. data/app/views/asset_host_core/admin/outputs/index.html.erb +27 -0
  78. data/app/views/asset_host_core/admin/outputs/new.html.erb +13 -0
  79. data/app/views/asset_host_core/admin/outputs/show.html.erb +17 -0
  80. data/app/views/asset_host_core/shared/_footerjs.html.erb +3 -0
  81. data/app/views/asset_host_core/shared/_navbar.html.erb +28 -0
  82. data/app/views/kaminari/_first_page.html.erb +3 -0
  83. data/app/views/kaminari/_gap.html.erb +3 -0
  84. data/app/views/kaminari/_last_page.html.erb +3 -0
  85. data/app/views/kaminari/_next_page.html.erb +3 -0
  86. data/app/views/kaminari/_page.html.erb +3 -0
  87. data/app/views/kaminari/_paginator.html.erb +17 -0
  88. data/app/views/kaminari/_prev_page.html.erb +3 -0
  89. data/app/views/layouts/asset_host_core/application.html.erb +54 -0
  90. data/app/views/layouts/asset_host_core/full_width.html.erb +32 -0
  91. data/app/views/layouts/asset_host_core/minimal.html.erb +45 -0
  92. data/config/initializers/simple_form.rb +142 -0
  93. data/config/initializers/simple_form_bootstrap.rb +45 -0
  94. data/config/locales/simple_form.en.yml +26 -0
  95. data/config/routes.rb +49 -0
  96. data/lib/asset_host_core.rb +38 -0
  97. data/lib/asset_host_core/config.rb +39 -0
  98. data/lib/asset_host_core/engine.rb +94 -0
  99. data/lib/asset_host_core/loaders.rb +34 -0
  100. data/lib/asset_host_core/loaders/asset_host.rb +30 -0
  101. data/lib/asset_host_core/loaders/base.rb +22 -0
  102. data/lib/asset_host_core/loaders/brightcove.rb +67 -0
  103. data/lib/asset_host_core/loaders/flickr.rb +114 -0
  104. data/lib/asset_host_core/loaders/url.rb +59 -0
  105. data/lib/asset_host_core/loaders/vimeo.rb +76 -0
  106. data/lib/asset_host_core/loaders/youtube.rb +90 -0
  107. data/lib/asset_host_core/model_methods.rb +61 -0
  108. data/lib/asset_host_core/paperclip.rb +4 -0
  109. data/lib/asset_host_core/paperclip/asset_thumbnail.rb +92 -0
  110. data/lib/asset_host_core/paperclip/attachment.rb +206 -0
  111. data/lib/asset_host_core/paperclip/trimmer.rb +33 -0
  112. data/lib/asset_host_core/resque_job.rb +13 -0
  113. data/lib/asset_host_core/version.rb +3 -0
  114. data/lib/tasks/asset_host_core_tasks.rake +4 -0
  115. data/spec/controllers/admin/api_users_controller_spec.rb +21 -0
  116. data/spec/controllers/admin/assets_controller_spec.rb +59 -0
  117. data/spec/controllers/admin/home_controller_spec.rb +4 -0
  118. data/spec/controllers/admin/outputs_controller_spec.rb +4 -0
  119. data/spec/controllers/api/assets_controller_spec.rb +133 -0
  120. data/spec/controllers/api/outputs_controller_spec.rb +51 -0
  121. data/spec/controllers/public_controller_spec.rb +4 -0
  122. data/spec/factories.rb +39 -0
  123. data/spec/features/api_users_spec.rb +78 -0
  124. data/spec/fixtures/api/brightcove/video.json +137 -0
  125. data/spec/fixtures/api/flickr/photos_getInfo.json +78 -0
  126. data/spec/fixtures/api/flickr/photos_getSizes.json +82 -0
  127. data/spec/fixtures/api/flickr/photos_licenses_getInfo.json +52 -0
  128. data/spec/fixtures/api/vimeo/video.json +28 -0
  129. data/spec/fixtures/api/youtube/discovery.json +5190 -0
  130. data/spec/fixtures/api/youtube/video.json +44 -0
  131. data/spec/fixtures/images/chipmunk.jpg +0 -0
  132. data/spec/fixtures/images/dude.jpg +0 -0
  133. data/spec/fixtures/images/ernie.jpg +0 -0
  134. data/spec/fixtures/images/fry.png +0 -0
  135. data/spec/fixtures/images/hat.jpg +0 -0
  136. data/spec/fixtures/images/spongebob.png +0 -0
  137. data/spec/fixtures/images/stars.jpg +0 -0
  138. data/spec/internal/app/controllers/application_controller.rb +16 -0
  139. data/spec/internal/app/controllers/sessions_controller.rb +24 -0
  140. data/spec/internal/app/models/user.rb +10 -0
  141. data/spec/internal/app/views/sessions/new.html.erb +14 -0
  142. data/spec/internal/config/database.yml +3 -0
  143. data/spec/internal/config/initializers/assethost_config.rb +57 -0
  144. data/spec/internal/config/routes.rb +7 -0
  145. data/spec/internal/db/combustion_test.sqlite +0 -0
  146. data/spec/internal/db/schema.rb +106 -0
  147. data/spec/internal/log/test.log +14769 -0
  148. data/spec/internal/public/favicon.ico +0 -0
  149. data/spec/internal/public/images/1_27f7745237849975ca90591c1fba5934_original. +0 -0
  150. data/spec/internal/public/images/1_7d33319deca787d5bb3f62ff06563ad2_original. +0 -0
  151. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original. +0 -0
  152. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.jpg +0 -0
  153. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.txt +0 -0
  154. data/spec/internal/public/images/1_e179cbd27e07cb55042d0db36cdac095_original. +0 -0
  155. data/spec/internal/public/images/1_e669edd3dfd74be66fc38416e82e3a37_original. +0 -0
  156. data/spec/lib/asset_host_core/loaders/asset_host_spec.rb +33 -0
  157. data/spec/lib/asset_host_core/loaders/brightcove_spec.rb +51 -0
  158. data/spec/lib/asset_host_core/loaders/flickr_spec.rb +72 -0
  159. data/spec/lib/asset_host_core/loaders/url_spec.rb +42 -0
  160. data/spec/lib/asset_host_core/loaders/vimeo_spec.rb +51 -0
  161. data/spec/lib/asset_host_core/loaders/youtube_spec.rb +73 -0
  162. data/spec/lib/asset_host_core/loaders_spec.rb +4 -0
  163. data/spec/lib/asset_host_core/model_methods_spec.rb +4 -0
  164. data/spec/lib/asset_host_core/paperclip/asset_thumbnail_spec.rb +4 -0
  165. data/spec/lib/asset_host_core/paperclip/attachment_spec.rb +4 -0
  166. data/spec/lib/asset_host_core/resque_job_spec.rb +4 -0
  167. data/spec/lib/asset_host_core_spec.rb +4 -0
  168. data/spec/models/api_user_spec.rb +58 -0
  169. data/spec/models/asset_output_spec.rb +4 -0
  170. data/spec/models/asset_spec.rb +4 -0
  171. data/spec/models/output_spec.rb +4 -0
  172. data/spec/models/permission_spec.rb +4 -0
  173. data/spec/spec_helper.rb +30 -0
  174. data/spec/support/fixture_loader.rb +9 -0
  175. data/spec/support/param_helper.rb +14 -0
  176. data/spec/support/permission_matcher.rb +17 -0
  177. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  178. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  179. data/vendor/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  180. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  181. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  182. data/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  183. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  184. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  185. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  186. data/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  187. data/vendor/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  188. data/vendor/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  189. data/vendor/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  190. data/vendor/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  191. data/vendor/assets/javascripts/backbone.js +1158 -0
  192. data/vendor/assets/javascripts/backbone.modelbinding.js +475 -0
  193. data/vendor/assets/javascripts/exif.js +695 -0
  194. data/vendor/assets/javascripts/jquery-ui.js +5614 -0
  195. data/vendor/assets/javascripts/simplemodal.js +698 -0
  196. data/vendor/assets/javascripts/spin.jquery.js +81 -0
  197. data/vendor/assets/javascripts/spin.min.js +1 -0
  198. data/vendor/assets/javascripts/underscore.min.js +1 -0
  199. metadata +658 -0
@@ -0,0 +1,17 @@
1
+ ###
2
+ Welcome to AssetHost
3
+ ###
4
+
5
+ # stub console.log() for IE
6
+ if !window.console
7
+ class window.console
8
+ @log: ->
9
+
10
+ window.AssetHost ?= {}
11
+ AssetHost.SERVER = "<%= Rails.application.config.assethost.server %>"
12
+
13
+ AssetHost.PATH_PREFIX = "<%= AssetHostCore::Engine.mounted_path %>"
14
+ AssetHost.SIZES =
15
+ thumb: "<%= AssetHostCore.config.thumb_size || "thumb" %>"
16
+ modal: "<%= AssetHostCore.config.modal_size || "modal" %>"
17
+ detail: "<%= AssetHostCore.config.detail_size || "wide" %>"
@@ -0,0 +1,139 @@
1
+ class AssetHost.BrowserUI
2
+ DefaultOptions:
3
+ assetBrowserEl: "#asset_browser"
4
+ modalSelect: true
5
+ modalAdmin: true
6
+ assets: []
7
+
8
+ constructor: (options={}) ->
9
+ @options = _.defaults options, @DefaultOptions
10
+
11
+ @assets = new AssetHost.Models.PaginatedAssets @options.assets
12
+
13
+ if @options.page
14
+ @assets.page @options.page
15
+
16
+ if @options.query
17
+ @assets.query @options.query
18
+
19
+ if @options.total
20
+ @assets.total_entries = @options.total
21
+
22
+ @browserEl = $(@options.assetBrowserEl)
23
+ @browser = new AssetHost.Models.AssetBrowserView collection: @assets
24
+
25
+ @browserEl.html @browser.el
26
+ @browserEl.after @browser.pages().el
27
+
28
+ # add search box
29
+ @search = new AssetHost.Models.AssetSearchView collection:@assets
30
+ $('#search_box').html @search.render().el
31
+
32
+ # -- Handle Routing -- #
33
+
34
+ @router = new BrowserUI.Router
35
+ @router.bind "route:asset", (id) => @previewAsset id
36
+ @router.bind "route:index", => @clearDisplay()
37
+ @router.bind "route:search", (page,query) =>
38
+ @clearDisplay()
39
+ @loadAssets query:query, page:page
40
+
41
+ # -- Handle Events from UI Elements -- #
42
+
43
+ @browser.pages().bind "page", (page) =>
44
+ @clearDisplay()
45
+ @loadAssets page: page
46
+ @navToAssets()
47
+
48
+ @search.bind "search", (query) =>
49
+ @clearDisplay()
50
+ @loadAssets query:query, page:1
51
+ @navToAssets()
52
+
53
+ @browser.bind "click", (asset) =>
54
+ @clearDisplay()
55
+ @_previewAsset(asset)
56
+
57
+ Backbone.history.start pushState:true, root:@options.root_path
58
+
59
+ $(@browserEl).delegate "button", "dragstart", (evt) ->
60
+ if url = $(evt.currentTarget).attr 'data-asset-url'
61
+ evt.originalEvent.dataTransfer.setData 'text/uri-list', url
62
+
63
+ @assets.trigger 'reset'
64
+
65
+ #----------
66
+
67
+ navToAssets: ->
68
+ page = @assets.page()
69
+ query = @assets.query()
70
+
71
+ if page && query
72
+ @router.navigate("/p/#{page}/#{query}")
73
+ else if page && page != 1
74
+ @router.navigate("/p/#{page}")
75
+ else
76
+ @router.navigate("/")
77
+
78
+ #----------
79
+
80
+ # given a query string and/or page number, grab assets via the API and
81
+ # fill in the asset browser
82
+ loadAssets: (options = {}) ->
83
+ qDirty = (options['query'] || @assets.query()) && options['query'] != @assets.query()
84
+ pDirty = options['page'] && Number(options['page']) != Number(@assets.page())
85
+
86
+ if qDirty || pDirty || options['force']
87
+ # display loading status. browserView will clear on its own
88
+ @browser.loading()
89
+
90
+ # fire off AJAX API request
91
+ @assets.query(options['query'])
92
+ @assets.page(options['page'])
93
+ @assets.fetch(reset: true)
94
+
95
+ false
96
+
97
+ #----------
98
+
99
+ clearDisplay: ->
100
+ # clear any asset modal
101
+ $(".ui-dialog-titlebar-close").trigger('click')
102
+
103
+ #----------
104
+
105
+ previewAsset: (id) ->
106
+ # check if we have the asset
107
+ asset = @assets.get(id)
108
+
109
+ if !asset
110
+ a = new AssetHost.Models.Asset(id: id)
111
+ a.fetch
112
+ success:(a)=> @_previewAsset(a)
113
+
114
+ else
115
+ @_previewAsset(asset)
116
+
117
+ _previewAsset: (asset) ->
118
+ asset.modal().open
119
+ options:
120
+ close: => @navToAssets(),
121
+ select: @options.modalSelect,
122
+ admin: @options.modalAdmin
123
+
124
+ #----------
125
+
126
+ class @Router extends Backbone.Router
127
+ routes:
128
+ '/a/:id': "asset"
129
+ '/p/:p/:query': "search"
130
+ '/p/:p': "search"
131
+ '/': "index"
132
+ '': "index"
133
+
134
+ asset: ->
135
+
136
+ search: ->
137
+
138
+ index: ->
139
+
@@ -0,0 +1,381 @@
1
+ class AssetHost.ChooserUI
2
+ DefaultOptions:
3
+ dropEl: "#my_assets"
4
+ browser: ''
5
+ saveButton: 1
6
+ assets: true
7
+ uploads: true
8
+ limit: 0
9
+ uploadPath: "#{AssetHost.PATH_PREFIX}/a/assets/upload"
10
+
11
+ #----------
12
+
13
+ constructor: (options = {}) ->
14
+ @options = _.defaults options, @DefaultOptions
15
+
16
+ # add in events
17
+ _.extend @, Backbone.Events
18
+
19
+ # do we have an asset browser to attach to?
20
+ @browser = @options.browser || false
21
+
22
+ @drop = $(@options['dropEl'])
23
+
24
+ # hang onto whatever starts out in drop... we'll use it when it's empty
25
+ @emptyMsg = $ '<div/>', html: @drop.html()
26
+ @drop.html @emptyMsg
27
+
28
+ # set up collection and view to manage assets
29
+ @myassets = new AssetHost.Models.Assets
30
+ @assetsView = new AssetHost.Models.AssetDropView collection: @myassets
31
+ @urlInput = new ChooserUI.URLInput(chooserUI: @)
32
+
33
+ @assetsView.bind 'click', (asset) =>
34
+ new ChooserUI.EditModal model:asset
35
+
36
+ @assetsView.bind 'remove', (asset) =>
37
+ @myassets.remove(asset)
38
+
39
+ # connect to our AssetBrowser instance, if one is given
40
+ if @browser
41
+ @browser.assets.bind "selected", (asset) =>
42
+ @myassets.add(asset)
43
+ new ChooserUI.EditModal model:asset
44
+
45
+ @browser.assets.bind "admin", (asset) =>
46
+ window.open("#{AssetHost.PATH_PREFIX}/a/assets/#{asset.get('id')}")
47
+
48
+ # set up collection to manage uploads and convert to assets
49
+ @uploads = new AssetHost.Models.QueuedFiles null, urlRoot:@options.uploadPath
50
+ @uploads.bind "uploaded", (f) =>
51
+ # add this to our selected assets
52
+ @myassets.add(f.get('ASSET'))
53
+
54
+ # also add it to our browser, just for fun
55
+ @browser?.assets?.add f.get('ASSET')
56
+
57
+ # finally, remove the asset from our collection of uploads
58
+ @uploads.remove(f)
59
+
60
+ @uploadsView = new AssetHost.Models.QueuedFilesView collection:@uploads
61
+
62
+ # manage the msg that shows when we have no assets or uploads
63
+ @myassets.bind "all", => @_manageEmptyMsg()
64
+ @uploads.bind "all", => @_manageEmptyMsg()
65
+
66
+ # manage the upload all button
67
+ @uploadAll = new ChooserUI.UploadAllButton collection:@uploads
68
+
69
+ @drop.append(@assetsView.el, @uploadsView.el)
70
+ @drop.after(@urlInput.render()) # Below all the buttons
71
+
72
+ # manage button that pops up after uploads
73
+ if @options.afterUploadURL and @options.afterUploadText
74
+ @afterUpload = new ChooserUI.AfterUploadButton
75
+ collection: @uploads
76
+ text: @options.afterUploadText
77
+ url: @options.afterUploadURL
78
+
79
+ @drop.after @afterUpload.el
80
+
81
+ @drop.after(@uploadAll.el)
82
+
83
+
84
+ # should we add a Save and Close button to the display?
85
+ if @options.saveButton
86
+ @saveAndClose = new AssetHost.Models.SaveAndCloseView collection: @myassets
87
+ @saveAndClose.bind 'saveAndClose', (json) => @trigger 'saveAndClose', json
88
+ @drop.before @saveAndClose.el
89
+
90
+ # attach drag-n-drop listeners to my_assets
91
+ @drop.bind "dragenter", (evt) => @_dropDragEnter evt
92
+ @drop.bind "dragover", (evt) => @_dropDragOver evt
93
+ @drop.bind "drop", (evt) => @_dropDrop evt
94
+
95
+ #----------
96
+
97
+ _manageEmptyMsg: ->
98
+ if @myassets.length + @uploads.length > 0
99
+ # turn empty msg off
100
+ $(@emptyMsg).slideUp()
101
+ else
102
+ # turn empty msg on
103
+ $(@emptyMsg).slideDown()
104
+
105
+ #----------
106
+
107
+ selectAssets: (assets) ->
108
+ _(assets).each (obj) =>
109
+ asset = @myassets.get(obj.id)
110
+
111
+ if !asset
112
+ asset = new AssetHost.Models.Asset(obj)
113
+ asset.fetch success:(a)=>
114
+ a.set caption:obj.caption
115
+
116
+ if obj.ORDER
117
+ a.set ORDER:obj.ORDER
118
+
119
+ @myassets.add(a)
120
+
121
+ @myassets.sort()
122
+
123
+ #----------
124
+
125
+ _dropDragEnter: (evt) ->
126
+ evt = evt.originalEvent
127
+ evt.stopPropagation()
128
+ evt.preventDefault()
129
+ false
130
+
131
+ _dropDragOver: (evt) ->
132
+ evt = evt.originalEvent
133
+ evt.stopPropagation()
134
+ evt.preventDefault()
135
+ false
136
+
137
+ #----------
138
+
139
+ # When we receive a drop, we need to test whether it is an asset (or can
140
+ # be made into an asset), and if so add it to our display.
141
+ _dropDrop: (evt) ->
142
+ evt = evt.originalEvent
143
+
144
+ evt.stopPropagation()
145
+ evt.preventDefault()
146
+
147
+ # first thing we need to test is whether we have a limit on uploads
148
+ if @options.limit && @uploads.length >= @options.limit
149
+ # we're at our limit... shake our UI element and then do nothing
150
+ $(@drop).effect "shake", {times: 3}, 100
151
+ return false
152
+
153
+ # if we get here, we're allowed to take an upload
154
+ if evt.dataTransfer.files.length > 0
155
+ # drop is file(s)... stage for uploader
156
+ for f in evt.dataTransfer.files
157
+ @uploads.add name: f.name, size: f.size, file: f
158
+
159
+ else
160
+ # drop is a URL. Pass it to AssetHost API and see what happens
161
+ uri = evt.dataTransfer.getData 'text/uri-list'
162
+ @importUri uri,
163
+ beforeSend: _.bind @importSetup, this
164
+ success: _.bind @importSuccess, this
165
+ error: _.bind @importError, this
166
+ complete: _.bind @importComplete, this
167
+
168
+ false
169
+
170
+ importSetup: (jqXHR, settings) ->
171
+ $('.importNotification').hide()
172
+ $(@assetsView.el).spin()
173
+
174
+ importSuccess: (data, textStatus, jqXHR) ->
175
+ # We might get a success response even if the asset wasn't imported
176
+ if data.id
177
+ $('#importSuccess').html('Successfully imported.')
178
+ $('#importSuccess').show()
179
+ @myassets.add data
180
+ else
181
+ $('#importError').html("This URL couldn't be imported.")
182
+ $('#importError').show()
183
+
184
+ importError: (jqXHR, textStatus, errorThrown) ->
185
+ $('#importError').html("This URL couldn't be imported. (#{errorThrown})")
186
+ $('#importError').show()
187
+
188
+ importComplete: (jqXHR, status) ->
189
+ $(@assetsView.el).spin(false)
190
+
191
+ #----------
192
+
193
+ importUri: (uri, callbacks={}) ->
194
+ $.ajax "#{AssetHost.PATH_PREFIX}/api/assets",
195
+ _.extend
196
+ dataType : "json"
197
+ type : 'POST'
198
+ data:
199
+ url: uri
200
+ callbacks
201
+
202
+ #----------
203
+
204
+
205
+
206
+ class @URLInput extends Backbone.View
207
+ template: JST["asset_host_core/templates/url_input"]
208
+ className: "ah_chooser_url_input"
209
+ events:
210
+ 'click a.add': "addToChooser"
211
+
212
+ initialize: (attributes={}) ->
213
+ @chooserUI = attributes['chooserUI']
214
+
215
+ addToChooser: (event) ->
216
+ event.preventDefault()
217
+ event.stopPropagation()
218
+
219
+ input = $(event.target).siblings('input')
220
+ uri = input.val()
221
+
222
+ @chooserUI.importUri uri,
223
+ beforeSend: _.bind @importSetup, this
224
+ success: _.bind @importSuccess, this
225
+ error: _.bind @importError, this
226
+ complete: _.bind @importComplete, this
227
+
228
+ importSetup: (jqXHR, settings) ->
229
+ $('.importNotification').hide()
230
+ $(@el).spin('small')
231
+
232
+ importSuccess: (data, textStatus, jqXHR) ->
233
+ # We might get a success response even if the asset wasn't imported
234
+ if data.id
235
+ $('#importSuccess').html('Successfully imported.')
236
+ $('#importSuccess').show()
237
+ $('input', $(@el)).val('')
238
+ @chooserUI.myassets.add data
239
+ else
240
+ $('#importError').html("This URL couldn't be imported.")
241
+ $('#importError').show()
242
+
243
+ importError: (jqXHR, textStatus, errorThrown) ->
244
+ $('#importError').html("This URL couldn't be imported. (#{errorThrown})")
245
+ $('#importError').show()
246
+
247
+ importComplete: (jqXHR, status) ->
248
+ $(@el).spin(false)
249
+
250
+ # Must return $el
251
+ render: ->
252
+ $(@el).html @template()
253
+
254
+ #----------
255
+
256
+
257
+
258
+
259
+ class @EditModal extends Backbone.View
260
+ template: JST["asset_host_core/templates/edit_modal"]
261
+ className: "ah_asset_edit modal"
262
+ events:
263
+ 'click button.save': '_save'
264
+ 'click button.admin': '_admin'
265
+
266
+ #----------
267
+
268
+ initialize: (options) ->
269
+ # stash model attributes for later comparison
270
+ @original =
271
+ title: @model.get("title")
272
+ owner: @model.get("owner")
273
+ notes: @model.get("notes")
274
+
275
+ $(@render().el).modal()
276
+
277
+ # bind model to form
278
+ Backbone.ModelBinding.bind(this)
279
+
280
+ # attach listener for metadata changes
281
+ @model.bind "change", =>
282
+ if _(@original).any((v,k) => v != @model.get(k))
283
+ @meta_dirty = true
284
+ @$(".meta_dirty").show()
285
+ else
286
+ @meta_dirty = false
287
+ @$(".meta_dirty").hide()
288
+
289
+ #----------
290
+
291
+ close: ->
292
+ Backbone.ModelBinding.unbind(this)
293
+ $(@el).modal('hide')
294
+
295
+ #----------
296
+
297
+ _save: ->
298
+ # see whether we should save anything back to the server
299
+ if @meta_dirty || @$("#save_caption_check")[0].checked
300
+ @model.clone().fetch success:(m)=>
301
+ # set title,owner,notes
302
+ attr = title:@model.get("title"),owner:@model.get("owner"),notes:@model.get("notes")
303
+
304
+ if @$("#save_caption_check")[0].checked
305
+ attr.caption = @model.get("caption")
306
+
307
+ m.save(attr)
308
+ @close()
309
+
310
+ else
311
+ @close()
312
+
313
+ #----------
314
+
315
+ _admin: ->
316
+ window.open("#{AssetHost.PATH_PREFIX}/a/assets/#{@model.get('id')}")
317
+
318
+ #----------
319
+
320
+ render: ->
321
+ $(@el).html @template(@model.toJSON())
322
+
323
+ # set metadata state
324
+ @$(".meta_dirty").hide()
325
+
326
+ # set default state for caption save checkbox
327
+ if _.isEmpty(@model.get("caption"))
328
+ @$("#save_caption_check")[0].checked = true
329
+
330
+ @
331
+
332
+ #----------
333
+
334
+ class @AfterUploadButton extends Backbone.View
335
+ template: JST['asset_host_core/templates/after_upload_button']
336
+ events:
337
+ 'click a': '_clicked'
338
+
339
+ initialize: (options) ->
340
+ @text = options.text
341
+ @url = options.url
342
+ @ids = []
343
+
344
+ @collection.bind "uploaded", (f) =>
345
+ @ids.push f.get('ASSET').id
346
+ @render()
347
+
348
+ _clicked: (event) ->
349
+ event.preventDefault()
350
+ event.stopPropagation()
351
+ window.location = _.template @url.replace(/{{([^}]+)}}/,"<%= $1 %>"), ids:@ids.join(",")
352
+
353
+ render: ->
354
+ if @ids
355
+ $(@el).html @template(text: @text)
356
+
357
+
358
+ #----------
359
+
360
+
361
+ class @UploadAllButton extends Backbone.View
362
+ template: JST['asset_host_core/templates/upload_all_button']
363
+ events:
364
+ 'click button': 'uploadAll'
365
+
366
+ initialize: ->
367
+ @collection.bind "all", => @render()
368
+
369
+ uploadAll: ->
370
+ @collection.each (f) ->
371
+ f.upload() if !f.xhr
372
+
373
+
374
+ render: ->
375
+ staged = @collection.reduce(
376
+ (i,f) -> if f.xhr then i else i+1
377
+ , 0)
378
+
379
+ $(@el).html if staged > 1 then @template(count: staged) else ''
380
+
381
+ @