asset_host_core 2.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.markdown +138 -0
- data/Rakefile +11 -0
- data/app/assets/images/asset_host_core/alert-overlay.png +0 -0
- data/app/assets/images/asset_host_core/arrow-left.gif +0 -0
- data/app/assets/images/asset_host_core/arrow-right.gif +0 -0
- data/app/assets/images/asset_host_core/fallback-img-rect.png +0 -0
- data/app/assets/images/asset_host_core/videoplayer-play.png +0 -0
- data/app/assets/images/asset_host_core/x.png +0 -0
- data/app/assets/javascripts/asset_host_core/admin/assets.js.coffee +221 -0
- data/app/assets/javascripts/asset_host_core/application.js +20 -0
- data/app/assets/javascripts/asset_host_core/assetadmin.js.coffee +56 -0
- data/app/assets/javascripts/asset_host_core/assethost.js.coffee.erb +17 -0
- data/app/assets/javascripts/asset_host_core/browserui.js.coffee +139 -0
- data/app/assets/javascripts/asset_host_core/chooserui.js.coffee +381 -0
- data/app/assets/javascripts/asset_host_core/client.js.coffee +29 -0
- data/app/assets/javascripts/asset_host_core/clients/BrightcoveVideo.js.coffee +64 -0
- data/app/assets/javascripts/asset_host_core/clients/templates/brightcove_embed.jst.eco +18 -0
- data/app/assets/javascripts/asset_host_core/clients/templates/vimeo_embed.jst.eco +1 -0
- data/app/assets/javascripts/asset_host_core/clients/templates/youtube_embed.jst.eco +1 -0
- data/app/assets/javascripts/asset_host_core/clients/vimeo_video.js.coffee +21 -0
- data/app/assets/javascripts/asset_host_core/clients/youtube_video.js.coffee +21 -0
- data/app/assets/javascripts/asset_host_core/cmsplugin.js.coffee +235 -0
- data/app/assets/javascripts/asset_host_core/models.js.coffee +586 -0
- data/app/assets/javascripts/asset_host_core/railsCMS.js.coffee +141 -0
- data/app/assets/javascripts/asset_host_core/slideshow.js.coffee +428 -0
- data/app/assets/javascripts/asset_host_core/templates/after_upload_button.jst.eco +3 -0
- data/app/assets/javascripts/asset_host_core/templates/asset_drop_asset.jst.eco +4 -0
- data/app/assets/javascripts/asset_host_core/templates/asset_modal.jst.eco +13 -0
- data/app/assets/javascripts/asset_host_core/templates/asset_preview.jst.eco +35 -0
- data/app/assets/javascripts/asset_host_core/templates/asset_search.jst.eco +2 -0
- data/app/assets/javascripts/asset_host_core/templates/browser_asset.jst.eco +1 -0
- data/app/assets/javascripts/asset_host_core/templates/browser_asset_tip.jst.eco +3 -0
- data/app/assets/javascripts/asset_host_core/templates/edit_modal.jst.eco +40 -0
- data/app/assets/javascripts/asset_host_core/templates/import_help.jst.eco +59 -0
- data/app/assets/javascripts/asset_host_core/templates/pagination_link.jst.eco +1 -0
- data/app/assets/javascripts/asset_host_core/templates/pagination_links.jst.eco +13 -0
- data/app/assets/javascripts/asset_host_core/templates/queued_file.jst.eco +11 -0
- data/app/assets/javascripts/asset_host_core/templates/save_and_close_view.jst.eco +4 -0
- data/app/assets/javascripts/asset_host_core/templates/upload_all_button.jst.eco +4 -0
- data/app/assets/javascripts/asset_host_core/templates/url_input.jst.eco +8 -0
- data/app/assets/stylesheets/asset_host_core/application.css.scss +384 -0
- data/app/assets/stylesheets/asset_host_core/jquery-ui.css +105 -0
- data/app/assets/stylesheets/asset_host_core/public.css.scss +204 -0
- data/app/assets/stylesheets/asset_host_core/slidetest.css.scss +93 -0
- data/app/controllers/asset_host_core/admin/api_users_controller.rb +72 -0
- data/app/controllers/asset_host_core/admin/assets_controller.rb +140 -0
- data/app/controllers/asset_host_core/admin/base_controller.rb +36 -0
- data/app/controllers/asset_host_core/admin/home_controller.rb +13 -0
- data/app/controllers/asset_host_core/admin/outputs_controller.rb +55 -0
- data/app/controllers/asset_host_core/api/assets_controller.rb +110 -0
- data/app/controllers/asset_host_core/api/base_controller.rb +43 -0
- data/app/controllers/asset_host_core/api/outputs_controller.rb +33 -0
- data/app/controllers/asset_host_core/application_controller.rb +43 -0
- data/app/controllers/asset_host_core/public_controller.rb +104 -0
- data/app/models/asset_host_core/api_user.rb +44 -0
- data/app/models/asset_host_core/api_user_permission.rb +6 -0
- data/app/models/asset_host_core/asset.rb +265 -0
- data/app/models/asset_host_core/asset_output.rb +69 -0
- data/app/models/asset_host_core/brightcove_video.rb +20 -0
- data/app/models/asset_host_core/output.rb +52 -0
- data/app/models/asset_host_core/permission.rb +19 -0
- data/app/models/asset_host_core/video.rb +8 -0
- data/app/models/asset_host_core/vimeo_video.rb +17 -0
- data/app/models/asset_host_core/youtube_video.rb +17 -0
- data/app/views/asset_host_core/admin/api_users/_form_fields.html.erb +5 -0
- data/app/views/asset_host_core/admin/api_users/edit.html.erb +26 -0
- data/app/views/asset_host_core/admin/api_users/index.html.erb +31 -0
- data/app/views/asset_host_core/admin/api_users/new.html.erb +17 -0
- data/app/views/asset_host_core/admin/api_users/show.html.erb +23 -0
- data/app/views/asset_host_core/admin/assets/index.html.erb +19 -0
- data/app/views/asset_host_core/admin/assets/metadata.html.erb +24 -0
- data/app/views/asset_host_core/admin/assets/show.html.erb +86 -0
- data/app/views/asset_host_core/admin/home/chooser.html.erb +49 -0
- data/app/views/asset_host_core/admin/outputs/_form_fields.html.erb +5 -0
- data/app/views/asset_host_core/admin/outputs/edit.html.erb +26 -0
- data/app/views/asset_host_core/admin/outputs/index.html.erb +27 -0
- data/app/views/asset_host_core/admin/outputs/new.html.erb +13 -0
- data/app/views/asset_host_core/admin/outputs/show.html.erb +17 -0
- data/app/views/asset_host_core/shared/_footerjs.html.erb +3 -0
- data/app/views/asset_host_core/shared/_navbar.html.erb +28 -0
- data/app/views/kaminari/_first_page.html.erb +3 -0
- data/app/views/kaminari/_gap.html.erb +3 -0
- data/app/views/kaminari/_last_page.html.erb +3 -0
- data/app/views/kaminari/_next_page.html.erb +3 -0
- data/app/views/kaminari/_page.html.erb +3 -0
- data/app/views/kaminari/_paginator.html.erb +17 -0
- data/app/views/kaminari/_prev_page.html.erb +3 -0
- data/app/views/layouts/asset_host_core/application.html.erb +54 -0
- data/app/views/layouts/asset_host_core/full_width.html.erb +32 -0
- data/app/views/layouts/asset_host_core/minimal.html.erb +45 -0
- data/config/initializers/simple_form.rb +142 -0
- data/config/initializers/simple_form_bootstrap.rb +45 -0
- data/config/locales/simple_form.en.yml +26 -0
- data/config/routes.rb +49 -0
- data/lib/asset_host_core.rb +38 -0
- data/lib/asset_host_core/config.rb +39 -0
- data/lib/asset_host_core/engine.rb +94 -0
- data/lib/asset_host_core/loaders.rb +34 -0
- data/lib/asset_host_core/loaders/asset_host.rb +30 -0
- data/lib/asset_host_core/loaders/base.rb +22 -0
- data/lib/asset_host_core/loaders/brightcove.rb +67 -0
- data/lib/asset_host_core/loaders/flickr.rb +114 -0
- data/lib/asset_host_core/loaders/url.rb +59 -0
- data/lib/asset_host_core/loaders/vimeo.rb +76 -0
- data/lib/asset_host_core/loaders/youtube.rb +90 -0
- data/lib/asset_host_core/model_methods.rb +61 -0
- data/lib/asset_host_core/paperclip.rb +4 -0
- data/lib/asset_host_core/paperclip/asset_thumbnail.rb +92 -0
- data/lib/asset_host_core/paperclip/attachment.rb +206 -0
- data/lib/asset_host_core/paperclip/trimmer.rb +33 -0
- data/lib/asset_host_core/resque_job.rb +13 -0
- data/lib/asset_host_core/version.rb +3 -0
- data/lib/tasks/asset_host_core_tasks.rake +4 -0
- data/spec/controllers/admin/api_users_controller_spec.rb +21 -0
- data/spec/controllers/admin/assets_controller_spec.rb +59 -0
- data/spec/controllers/admin/home_controller_spec.rb +4 -0
- data/spec/controllers/admin/outputs_controller_spec.rb +4 -0
- data/spec/controllers/api/assets_controller_spec.rb +133 -0
- data/spec/controllers/api/outputs_controller_spec.rb +51 -0
- data/spec/controllers/public_controller_spec.rb +4 -0
- data/spec/factories.rb +39 -0
- data/spec/features/api_users_spec.rb +78 -0
- data/spec/fixtures/api/brightcove/video.json +137 -0
- data/spec/fixtures/api/flickr/photos_getInfo.json +78 -0
- data/spec/fixtures/api/flickr/photos_getSizes.json +82 -0
- data/spec/fixtures/api/flickr/photos_licenses_getInfo.json +52 -0
- data/spec/fixtures/api/vimeo/video.json +28 -0
- data/spec/fixtures/api/youtube/discovery.json +5190 -0
- data/spec/fixtures/api/youtube/video.json +44 -0
- data/spec/fixtures/images/chipmunk.jpg +0 -0
- data/spec/fixtures/images/dude.jpg +0 -0
- data/spec/fixtures/images/ernie.jpg +0 -0
- data/spec/fixtures/images/fry.png +0 -0
- data/spec/fixtures/images/hat.jpg +0 -0
- data/spec/fixtures/images/spongebob.png +0 -0
- data/spec/fixtures/images/stars.jpg +0 -0
- data/spec/internal/app/controllers/application_controller.rb +16 -0
- data/spec/internal/app/controllers/sessions_controller.rb +24 -0
- data/spec/internal/app/models/user.rb +10 -0
- data/spec/internal/app/views/sessions/new.html.erb +14 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/config/initializers/assethost_config.rb +57 -0
- data/spec/internal/config/routes.rb +7 -0
- data/spec/internal/db/combustion_test.sqlite +0 -0
- data/spec/internal/db/schema.rb +106 -0
- data/spec/internal/log/test.log +14769 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/internal/public/images/1_27f7745237849975ca90591c1fba5934_original. +0 -0
- data/spec/internal/public/images/1_7d33319deca787d5bb3f62ff06563ad2_original. +0 -0
- data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original. +0 -0
- data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.jpg +0 -0
- data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.txt +0 -0
- data/spec/internal/public/images/1_e179cbd27e07cb55042d0db36cdac095_original. +0 -0
- data/spec/internal/public/images/1_e669edd3dfd74be66fc38416e82e3a37_original. +0 -0
- data/spec/lib/asset_host_core/loaders/asset_host_spec.rb +33 -0
- data/spec/lib/asset_host_core/loaders/brightcove_spec.rb +51 -0
- data/spec/lib/asset_host_core/loaders/flickr_spec.rb +72 -0
- data/spec/lib/asset_host_core/loaders/url_spec.rb +42 -0
- data/spec/lib/asset_host_core/loaders/vimeo_spec.rb +51 -0
- data/spec/lib/asset_host_core/loaders/youtube_spec.rb +73 -0
- data/spec/lib/asset_host_core/loaders_spec.rb +4 -0
- data/spec/lib/asset_host_core/model_methods_spec.rb +4 -0
- data/spec/lib/asset_host_core/paperclip/asset_thumbnail_spec.rb +4 -0
- data/spec/lib/asset_host_core/paperclip/attachment_spec.rb +4 -0
- data/spec/lib/asset_host_core/resque_job_spec.rb +4 -0
- data/spec/lib/asset_host_core_spec.rb +4 -0
- data/spec/models/api_user_spec.rb +58 -0
- data/spec/models/asset_output_spec.rb +4 -0
- data/spec/models/asset_spec.rb +4 -0
- data/spec/models/output_spec.rb +4 -0
- data/spec/models/permission_spec.rb +4 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/fixture_loader.rb +9 -0
- data/spec/support/param_helper.rb +14 -0
- data/spec/support/permission_matcher.rb +17 -0
- data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/javascripts/backbone.js +1158 -0
- data/vendor/assets/javascripts/backbone.modelbinding.js +475 -0
- data/vendor/assets/javascripts/exif.js +695 -0
- data/vendor/assets/javascripts/jquery-ui.js +5614 -0
- data/vendor/assets/javascripts/simplemodal.js +698 -0
- data/vendor/assets/javascripts/spin.jquery.js +81 -0
- data/vendor/assets/javascripts/spin.min.js +1 -0
- data/vendor/assets/javascripts/underscore.min.js +1 -0
- metadata +658 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# AssetHost
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/SCPR/AssetHost.png)](https://travis-ci.org/SCPR/AssetHost)
|
4
|
+
|
5
|
+
AssetHost is an attempt to create a one-stop-shop for hosting and linking
|
6
|
+
to media assets that are intended for inclusion in news stories. The goal is
|
7
|
+
to create a hub that multiple frontend CMS systems can hook into, querying
|
8
|
+
images, videos and documents from one source and enabling the easier
|
9
|
+
interchange of data.
|
10
|
+
|
11
|
+
# Philosophy
|
12
|
+
|
13
|
+
AssetHost is built around the idea that all web media assets need to
|
14
|
+
have a static visual fallback, either to support limited-functionality
|
15
|
+
devices or to support rendering of rich media assets in contexts where
|
16
|
+
a rich implementation isn't desired.
|
17
|
+
|
18
|
+
AssetHost is intended to run as two pieces: a backend asset server and
|
19
|
+
lightweight frontend plugins that attach to the CMS system. The pieces
|
20
|
+
should speak to each other using a secure API.
|
21
|
+
|
22
|
+
|
23
|
+
### Backend Engine
|
24
|
+
|
25
|
+
This repository provides the AssetHostCore engine, which can be run either
|
26
|
+
on the root of a standalone application (perhaps powering multiple frontend
|
27
|
+
applications) or at a namespace in an existing application.
|
28
|
+
|
29
|
+
The backend server provides the primary UI for uploading, managing, and
|
30
|
+
serving assets. It also provides an API endpoint that can be accessed either
|
31
|
+
by the local application (this is how much of the admin works) or by other
|
32
|
+
applications or plugins.
|
33
|
+
|
34
|
+
A sample host application can be found at <http://github.com/SCPR/AssetHostApp>
|
35
|
+
|
36
|
+
|
37
|
+
### Plugins for Other Applications
|
38
|
+
|
39
|
+
AssetHost provides an API and a Chooser UI that can be integrated into
|
40
|
+
your application, allowing you to integrate the system in a minimal amount
|
41
|
+
of code.
|
42
|
+
|
43
|
+
_TODO: More documentation on CMS interaction. External Rails example. Django example._
|
44
|
+
|
45
|
+
### Integrating with the AssetHost engine
|
46
|
+
|
47
|
+
To integrate with a locally-installed AssetHostCore engine, simply make your
|
48
|
+
mapping data model belong to AssetHostCore::Asset.
|
49
|
+
|
50
|
+
_TODO: More documentation on creating content/asset models._
|
51
|
+
|
52
|
+
|
53
|
+
### Workflow
|
54
|
+
|
55
|
+
1. Photographer / Author / Editor goes to AssetHost and uploads or imports
|
56
|
+
a media asset.
|
57
|
+
|
58
|
+
2. Author / Editor goes to their frontend CMS and uses the plugin UI to
|
59
|
+
select the asset they want to attach to their content (which might be a
|
60
|
+
story, a blog post, etc).
|
61
|
+
|
62
|
+
3. CMS plugin uses API to query AssetHost and retrieve presentation code
|
63
|
+
for the asset.
|
64
|
+
|
65
|
+
4. The CMS should call new AssetHost.Client() to put in place the handler
|
66
|
+
for rich assets.
|
67
|
+
|
68
|
+
4. The CMS should display the image asset. If it contains tags for a
|
69
|
+
rich asset, the Client library will catch it and put in place the
|
70
|
+
appropriate handling.
|
71
|
+
|
72
|
+
5. AssetHost will return a 302 Found to the rendered image asset if it
|
73
|
+
exists, or render it on-the-fly if it does not yet exist.
|
74
|
+
|
75
|
+
# Rich Media Support
|
76
|
+
|
77
|
+
Rich media assets are delivered as specially-tagged img tags, and are
|
78
|
+
replaced on the client-side via an AssetHost.Client plugin.
|
79
|
+
|
80
|
+
|
81
|
+
### Brightcove Video
|
82
|
+
|
83
|
+
Brightcove videos can be imported as assets and used to place videos into
|
84
|
+
image display contexts. The video is delivered as an img tag, and the
|
85
|
+
AssetHost.Client library will see the tag and call the
|
86
|
+
AssetHost.Client.Brightcove plugin. The plugin will replace the asset with
|
87
|
+
the video.
|
88
|
+
|
89
|
+
Brightcove assets can be imported via a key in the URL Input field. See
|
90
|
+
Importing Help for more.
|
91
|
+
|
92
|
+
|
93
|
+
# Setup
|
94
|
+
|
95
|
+
TODO: Setup generators for migrations
|
96
|
+
|
97
|
+
See `spec/internal/db/schema.rb` for the tables you'll need to setup:
|
98
|
+
|
99
|
+
* asset_host_core_outputs
|
100
|
+
|
101
|
+
|
102
|
+
# Image Storage
|
103
|
+
|
104
|
+
AssetHost intends to support any image storage supported by
|
105
|
+
[Paperclip](https://github.com/thoughtbot/paperclip), the underlying gem
|
106
|
+
responsible for adding image file functionality to our Asset model.
|
107
|
+
|
108
|
+
Currently, Paperclip supports local filesystem storage and storage on
|
109
|
+
Amazon's S3.
|
110
|
+
|
111
|
+
|
112
|
+
# External Requirements
|
113
|
+
|
114
|
+
### Async Workers via Redis
|
115
|
+
|
116
|
+
The AssetHost server uses Redis (via the Resque gem) to coordinate async
|
117
|
+
processing of images. Configure for your Redis setup in config/resque.yml.
|
118
|
+
|
119
|
+
### Image Processing via ImageMagick
|
120
|
+
|
121
|
+
AssetHost, via Paperclip, does image processing using ImageMagick. If
|
122
|
+
needed, make sure to specify Paperclip.options[:command_path] in your config.
|
123
|
+
|
124
|
+
### Text Search via Sphinx
|
125
|
+
|
126
|
+
Searches are done via Sphinx, using the Thinking Sphinx gem. Set up your
|
127
|
+
configuration in config/sphinx.yml, and make sure you have an external trigger
|
128
|
+
for indexing (cron, etc).
|
129
|
+
|
130
|
+
|
131
|
+
# Credits
|
132
|
+
|
133
|
+
AssetHost is being developed to serve the media asset needs of [KPCC](http://kpcc.org)
|
134
|
+
and Southern California Public Radio, a member-supported public radio network that
|
135
|
+
serves Los Angeles and Orange County on 89.3, the Inland Empire on 89.1, and the
|
136
|
+
Coachella Valley on 90.3.
|
137
|
+
|
138
|
+
AssetHost development is led by Eric Richardson (erichardson@kpcc.org).
|
data/Rakefile
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,221 @@
|
|
1
|
+
class window.AssetHostUpload
|
2
|
+
DefaultOptions:
|
3
|
+
{
|
4
|
+
dropEl: "#filedrop",
|
5
|
+
url: "",
|
6
|
+
posturl: "",
|
7
|
+
readyClass: "ready",
|
8
|
+
uploadClass: "uploading",
|
9
|
+
errorClass: "error",
|
10
|
+
pendingClass: "pending",
|
11
|
+
completeClass: "complete",
|
12
|
+
token: '',
|
13
|
+
emptyText: "Drop File(s) Here",
|
14
|
+
afterText: "Go to Metadata Entry",
|
15
|
+
allowMultiple: true
|
16
|
+
}
|
17
|
+
|
18
|
+
#----------
|
19
|
+
|
20
|
+
constructor: (options={}) ->
|
21
|
+
@options = _.defaults options, @DefaultOptions
|
22
|
+
|
23
|
+
@drop = $(@options.dropEl)
|
24
|
+
|
25
|
+
@files = []
|
26
|
+
@_ids = []
|
27
|
+
@_uploading = []
|
28
|
+
|
29
|
+
@fileUL = $ "<ul/>"
|
30
|
+
$(@drop).append @fileUL
|
31
|
+
|
32
|
+
@_emptyEl = $ "<li/>", { class: "help", text: this.options.emptyText }
|
33
|
+
$(@fileUL).append @_emptyEl
|
34
|
+
|
35
|
+
@uploadButton = $ "<p/>", { class: "ahUp_upbutton", text: "Upload File(s)" }
|
36
|
+
$(@drop).append @uploadButton
|
37
|
+
$(@uploadButton).hide()
|
38
|
+
$(@uploadButton).click (evt) => this._uploadFiles(evt)
|
39
|
+
|
40
|
+
$(@drop).bind "dragenter", (evt) => @_dragenter(evt)
|
41
|
+
$(@drop).bind "dragover", (evt) => @_dragover(evt)
|
42
|
+
$(@drop).bind "drop", (evt) => @_drop(evt)
|
43
|
+
|
44
|
+
#----------
|
45
|
+
|
46
|
+
_dragenter: (evt) ->
|
47
|
+
evt.stopPropagation()
|
48
|
+
evt.preventDefault()
|
49
|
+
|
50
|
+
false
|
51
|
+
|
52
|
+
#----------
|
53
|
+
|
54
|
+
_dragover: (evt) ->
|
55
|
+
evt.stopPropagation()
|
56
|
+
evt.preventDefault()
|
57
|
+
false
|
58
|
+
|
59
|
+
#----------
|
60
|
+
|
61
|
+
_drop: (evt) ->
|
62
|
+
evt = evt.originalEvent
|
63
|
+
|
64
|
+
evt.stopPropagation()
|
65
|
+
evt.preventDefault()
|
66
|
+
|
67
|
+
# do something with this info
|
68
|
+
for f in evt.dataTransfer.files
|
69
|
+
@_addFileToList(f)
|
70
|
+
|
71
|
+
false
|
72
|
+
|
73
|
+
#----------
|
74
|
+
|
75
|
+
_addFileToList: (f) ->
|
76
|
+
if !this.options.allowMultiple && this.files.length
|
77
|
+
return false
|
78
|
+
|
79
|
+
if this._uploading.length
|
80
|
+
return false
|
81
|
+
|
82
|
+
|
83
|
+
li = $ "<li/>", { text: "#{f.name} (#{@readableFileSize f.size})" }
|
84
|
+
|
85
|
+
obj = {f:f,li:li,x:null}
|
86
|
+
|
87
|
+
x = $("<span/>", { text: "x" })
|
88
|
+
.bind "click", `_.bind(this._removeFile, this, obj, li)`
|
89
|
+
li.append x
|
90
|
+
|
91
|
+
obj.x = x
|
92
|
+
|
93
|
+
$(@fileUL).append li
|
94
|
+
|
95
|
+
@files.push obj
|
96
|
+
|
97
|
+
@_setFileState obj, this.options.readyClass
|
98
|
+
|
99
|
+
@_updateUploadButton()
|
100
|
+
|
101
|
+
true
|
102
|
+
|
103
|
+
#----------
|
104
|
+
|
105
|
+
_removeFile: (obj,li,evt) ->
|
106
|
+
if @_uploading.length
|
107
|
+
return false
|
108
|
+
|
109
|
+
$(li).detach()
|
110
|
+
|
111
|
+
@files = _(@files).without obj
|
112
|
+
|
113
|
+
@_updateUploadButton()
|
114
|
+
|
115
|
+
#----------
|
116
|
+
|
117
|
+
_updateUploadButton: ->
|
118
|
+
if @files.length then $(@uploadButton).show() else $(@uploadButton).hide()
|
119
|
+
|
120
|
+
#----------
|
121
|
+
|
122
|
+
_uploadFiles: (evt) ->
|
123
|
+
# disable drag/drop UI
|
124
|
+
@uploadButton.hide()
|
125
|
+
|
126
|
+
# upload files
|
127
|
+
for obj in @files
|
128
|
+
@_uploading.push(obj)
|
129
|
+
|
130
|
+
xhr = new XMLHttpRequest();
|
131
|
+
|
132
|
+
upload = xhr.upload;
|
133
|
+
|
134
|
+
$(upload).bind "progress", `_.bind(this._onUploadProgress,this,obj)`
|
135
|
+
$(upload).bind "load", `_.bind(this._onUploadComplete,this,obj)`
|
136
|
+
$(upload).bind "error", `_.bind(this._onUploadError,this,obj)`
|
137
|
+
|
138
|
+
xhr.onreadystatechange = `_.bind(this._onUploadState,this,xhr,obj)`
|
139
|
+
|
140
|
+
xhr.open('POST',this.options.url, true);
|
141
|
+
xhr.setRequestHeader('X_FILE_NAME', obj.f.fileName)
|
142
|
+
xhr.setRequestHeader('CONTENT_TYPE', obj.f.type)
|
143
|
+
xhr.setRequestHeader('HTTP_X_FILE_UPLOAD','true')
|
144
|
+
xhr.send(obj.f);
|
145
|
+
|
146
|
+
@_setFileState obj, this.options.uploadClass
|
147
|
+
|
148
|
+
#----------
|
149
|
+
|
150
|
+
_onUploadProgress: (obj,evt) ->
|
151
|
+
evt = evt.originalEvent
|
152
|
+
|
153
|
+
if evt.lengthComputable
|
154
|
+
percent = Math.floor( evt.loaded / evt.total * 100 )
|
155
|
+
$(obj.x).text "(#{percent}%)"
|
156
|
+
else
|
157
|
+
$(obj.x).text "(#{evt.loaded}%)"
|
158
|
+
|
159
|
+
#----------
|
160
|
+
|
161
|
+
_onUploadComplete: (obj,evt) ->
|
162
|
+
# turn our li green or something
|
163
|
+
@_setFileState obj, @options.pendingClass
|
164
|
+
|
165
|
+
#----------
|
166
|
+
|
167
|
+
_onUploadError: (obj,evt) ->
|
168
|
+
# turn our li red?
|
169
|
+
@_uploading = _(@_uploading).without obj
|
170
|
+
@_setFileState obj, this.options.errorClass
|
171
|
+
|
172
|
+
#----------
|
173
|
+
|
174
|
+
_onUploadState: (req,obj,evt) ->
|
175
|
+
# look for a response asset ID
|
176
|
+
if req.readyState == 4
|
177
|
+
if req.status == 200
|
178
|
+
@_setFileState obj, @options.completeClass
|
179
|
+
$(obj.li).addClass @options.completeClass
|
180
|
+
|
181
|
+
if req.responseText != "ERROR"
|
182
|
+
json = $.parseJSON req.responseText
|
183
|
+
@_ids.push json
|
184
|
+
|
185
|
+
@_uploading = _(@_uploading).without obj
|
186
|
+
|
187
|
+
if !@_uploading.length
|
188
|
+
@_uploadingComplete()
|
189
|
+
else
|
190
|
+
# error
|
191
|
+
|
192
|
+
#----------
|
193
|
+
|
194
|
+
_uploadingComplete: ->
|
195
|
+
link = $("<li/>").append(
|
196
|
+
$ "<a/>", { href: @options.posturl+"?ids="+_(@_ids).map( (k) -> k.id ).join(","), text: @options.afterText }
|
197
|
+
)
|
198
|
+
|
199
|
+
$(@drop).append link
|
200
|
+
|
201
|
+
#----------
|
202
|
+
|
203
|
+
_setFileState: (obj,classname) ->
|
204
|
+
# remove existing class(es)
|
205
|
+
|
206
|
+
for c in (obj.li.className || "").split(" ")
|
207
|
+
$(obj.li).removeClass(c)
|
208
|
+
|
209
|
+
$(obj.li).addClass classname
|
210
|
+
|
211
|
+
#----------
|
212
|
+
|
213
|
+
readableFileSize: (size) ->
|
214
|
+
units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
215
|
+
i = 0;
|
216
|
+
|
217
|
+
while size >= 1024
|
218
|
+
size /= 1024
|
219
|
+
++i
|
220
|
+
|
221
|
+
size.toFixed(1) + ' ' + units[i];
|
@@ -0,0 +1,20 @@
|
|
1
|
+
//= require ./assethost
|
2
|
+
//= require jquery
|
3
|
+
//= require jquery_ujs
|
4
|
+
//= require jquery-ui
|
5
|
+
//= require underscore.min
|
6
|
+
//= require backbone
|
7
|
+
//= require exif
|
8
|
+
|
9
|
+
//= require backbone.modelbinding
|
10
|
+
|
11
|
+
//= require spin.min
|
12
|
+
//= require spin.jquery
|
13
|
+
|
14
|
+
//= require bootstrap-transition
|
15
|
+
//= require bootstrap-tooltip
|
16
|
+
//= require bootstrap-modal
|
17
|
+
|
18
|
+
//= require_tree ./templates
|
19
|
+
|
20
|
+
//= require_tree .
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class AssetHost.AssetAdmin
|
2
|
+
DefaultOptions:
|
3
|
+
el: ""
|
4
|
+
replace: ''
|
5
|
+
replacePath: ''
|
6
|
+
|
7
|
+
constructor: (asset,options = {}) ->
|
8
|
+
@options = _.defaults options, @DefaultOptions
|
9
|
+
|
10
|
+
@asset = new AssetHost.Models.Asset asset
|
11
|
+
@preview = new AssetAdmin.PreviewView model: @asset
|
12
|
+
@form = new AssetAdmin.FormView model: @asset
|
13
|
+
|
14
|
+
$( @options.el ).html @preview.el
|
15
|
+
|
16
|
+
if @options.replace
|
17
|
+
# set up replace image uploader
|
18
|
+
@chooser = new AssetHost.ChooserUI
|
19
|
+
dropEl: @options.replace
|
20
|
+
assets: false
|
21
|
+
uploads: true
|
22
|
+
limit: 1
|
23
|
+
uploadPath: @options.replacePath
|
24
|
+
saveButton: false
|
25
|
+
afterUploadText: "Refresh",
|
26
|
+
afterUploadURL: window.location
|
27
|
+
|
28
|
+
#----------
|
29
|
+
|
30
|
+
class @FormView extends Backbone.View
|
31
|
+
el: "#editform"
|
32
|
+
|
33
|
+
#----------
|
34
|
+
|
35
|
+
class @PreviewView extends Backbone.View
|
36
|
+
template: JST['asset_host_core/templates/asset_preview']
|
37
|
+
events:
|
38
|
+
'click .asset_sizes li': '_sizeClick'
|
39
|
+
|
40
|
+
initialize: ->
|
41
|
+
@size = AssetHost.SIZES.detail
|
42
|
+
@render()
|
43
|
+
|
44
|
+
_sizeClick: (evt) ->
|
45
|
+
size = $(evt.currentTarget).attr("data-size")
|
46
|
+
|
47
|
+
if size != @size
|
48
|
+
@size = size
|
49
|
+
@render()
|
50
|
+
|
51
|
+
render: ->
|
52
|
+
$(@el).html @template
|
53
|
+
asset: @model.toJSON()
|
54
|
+
tag: @size
|
55
|
+
|
56
|
+
@
|