effective_assets 0.1

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.
Files changed (89) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +228 -0
  3. data/Rakefile +23 -0
  4. data/app/assets/images/effective_assets/icon_close.png +0 -0
  5. data/app/assets/images/effective_assets/s3_down_button.gif +0 -0
  6. data/app/assets/images/effective_assets/s3_over_button.gif +0 -0
  7. data/app/assets/images/effective_assets/s3_up_button.gif +0 -0
  8. data/app/assets/images/effective_assets/s3_upload.swf +0 -0
  9. data/app/assets/images/effective_assets/spinner.gif +0 -0
  10. data/app/assets/images/mime-types/excel.jpg +0 -0
  11. data/app/assets/images/mime-types/file.png +0 -0
  12. data/app/assets/images/mime-types/mp3.png +0 -0
  13. data/app/assets/images/mime-types/pdf.png +0 -0
  14. data/app/assets/images/mime-types/video.png +0 -0
  15. data/app/assets/images/mime-types/word.jpg +0 -0
  16. data/app/assets/images/mime-types/zip.png +0 -0
  17. data/app/assets/javascripts/effective_assets.js +1 -0
  18. data/app/assets/javascripts/effective_assets/asset_box_input.js.coffee +71 -0
  19. data/app/assets/javascripts/effective_assets/asset_box_uploader.js +122 -0
  20. data/app/assets/javascripts/effective_assets/asset_box_uploader_customization.js +166 -0
  21. data/app/assets/javascripts/effective_assets/jquery_ui_sortable.js +2106 -0
  22. data/app/assets/stylesheets/effective_assets.css.scss +1 -0
  23. data/app/assets/stylesheets/effective_assets/_asset_box_input.scss +206 -0
  24. data/app/controllers/effective/attachments_controller.rb +14 -0
  25. data/app/controllers/effective/s3_uploads_controller.rb +98 -0
  26. data/app/helpers/effective_assets_helper.rb +55 -0
  27. data/app/models/concerns/acts_as_asset_box.rb +97 -0
  28. data/app/models/effective/asset.rb +224 -0
  29. data/app/models/effective/attachment.rb +25 -0
  30. data/app/models/effective/delayed_job.rb +99 -0
  31. data/app/models/inputs/asset_box_input.rb +87 -0
  32. data/app/models/validators/asset_box_length_validator.rb +11 -0
  33. data/app/models/validators/asset_box_presence_validator.rb +6 -0
  34. data/app/uploaders/asset_uploader.rb +26 -0
  35. data/app/uploaders/effective_assets_uploader.rb +63 -0
  36. data/app/views/active_admin/effective_assets/_edit.html.haml +35 -0
  37. data/app/views/active_admin/effective_assets/_form.html.haml +4 -0
  38. data/app/views/active_admin/effective_assets/_new.html.haml +3 -0
  39. data/app/views/asset_box_input/_attachment_fields.html.haml +14 -0
  40. data/app/views/asset_box_input/_uploader.html.haml +119 -0
  41. data/app/views/assets/_video.html.erb +4 -0
  42. data/config/routes.rb +6 -0
  43. data/db/migrate/01_create_effective_assets.rb.erb +42 -0
  44. data/lib/effective_assets.rb +31 -0
  45. data/lib/effective_assets/engine.rb +38 -0
  46. data/lib/effective_assets/version.rb +3 -0
  47. data/lib/generators/effective_assets/install_generator.rb +41 -0
  48. data/lib/generators/templates/README +1 -0
  49. data/lib/generators/templates/asset_uploader.rb +25 -0
  50. data/lib/generators/templates/effective_assets.rb +19 -0
  51. data/lib/tasks/effective_assets_tasks.rake +4 -0
  52. data/spec/dummy/README.rdoc +261 -0
  53. data/spec/dummy/Rakefile +7 -0
  54. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  55. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  56. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  57. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  58. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  59. data/spec/dummy/config.ru +4 -0
  60. data/spec/dummy/config/application.rb +65 -0
  61. data/spec/dummy/config/boot.rb +10 -0
  62. data/spec/dummy/config/database.yml +25 -0
  63. data/spec/dummy/config/environment.rb +5 -0
  64. data/spec/dummy/config/environments/development.rb +37 -0
  65. data/spec/dummy/config/environments/production.rb +67 -0
  66. data/spec/dummy/config/environments/test.rb +37 -0
  67. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  68. data/spec/dummy/config/initializers/inflections.rb +15 -0
  69. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  70. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  71. data/spec/dummy/config/initializers/session_store.rb +8 -0
  72. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  73. data/spec/dummy/config/locales/en.yml +5 -0
  74. data/spec/dummy/config/routes.rb +58 -0
  75. data/spec/dummy/db/development.sqlite3 +0 -0
  76. data/spec/dummy/db/schema.rb +16 -0
  77. data/spec/dummy/db/test.sqlite3 +0 -0
  78. data/spec/dummy/log/development.log +71 -0
  79. data/spec/dummy/log/test.log +33 -0
  80. data/spec/dummy/public/404.html +26 -0
  81. data/spec/dummy/public/422.html +26 -0
  82. data/spec/dummy/public/500.html +25 -0
  83. data/spec/dummy/public/favicon.ico +0 -0
  84. data/spec/dummy/script/rails +6 -0
  85. data/spec/dummy/spec_link +3 -0
  86. data/spec/models/asset_spec.rb +46 -0
  87. data/spec/spec_helper.rb +34 -0
  88. data/spec/support/factories.rb +28 -0
  89. metadata +431 -0
@@ -0,0 +1 @@
1
+ @import "effective_assets/asset_box_input";
@@ -0,0 +1,206 @@
1
+ @mixin clearfix {
2
+ display: block;
3
+ &:after { content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden; }
4
+ }
5
+
6
+ @mixin border-radius ($radius) {
7
+ position: relative;
8
+ -webkit-border-radius: $radius;
9
+ -moz-border-radius: $radius;
10
+ -ms-border-radius: $radius;
11
+ -o-border-radius: $radius;
12
+ border-radius: $radius;
13
+ }
14
+
15
+ .asset_box_uploader {
16
+ width: 800px;
17
+ margin: 0px auto;
18
+ text-align: left;
19
+
20
+ .file_lists {
21
+ border: 1px solid #B7B9BB;
22
+ height: 300px;
23
+ margin-bottom: 10px;
24
+ overflow-y: scroll;
25
+ }
26
+
27
+ .file_list {
28
+ border-width: 0 0 1px 0;
29
+ list-style-type: none;
30
+ padding: 0;
31
+ margin: 0;
32
+
33
+ li {
34
+ border: 1px solid #B7B9BB;
35
+ height: 60px;
36
+ line-height: 45px;
37
+ position: relative;
38
+ padding: 0 0 25px 0;
39
+ }
40
+
41
+ .progress {
42
+ display: block;
43
+ height: 85px;
44
+ text-align: right;
45
+ background: #EFEFEF;
46
+ background: -webkit-gradient(linear, left top, left bottom, from(#EFEFEF), to(#DFE1E2));
47
+ background: -moz-linear-gradient(-90deg, #EFEFEF, #DFE1E2);
48
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#efefef, endColorstr=#dfe1e2);
49
+ -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#efefef, endColorstr=#dfe1e2);
50
+
51
+ .amount {
52
+ position: absolute;
53
+ right: 10px;
54
+ top: 15px;
55
+ color: #666;
56
+ text-shadow: 1px 1px #fff;
57
+ }
58
+ }
59
+
60
+ .file_name {
61
+ display: block;
62
+ position: absolute;
63
+ font-weight: bold;
64
+ margin: 0 0 15px 10px;
65
+ }
66
+
67
+ .file_size {
68
+ display: block;
69
+ position: absolute;
70
+ right: 10px;
71
+ bottom: 0;
72
+ line-height: 2;
73
+ color: #AEAEAE;
74
+ }
75
+
76
+ .properties {
77
+ position: absolute;
78
+ left: 10px;
79
+ bottom: 10px;
80
+ display: block;
81
+
82
+ label {
83
+ float: left !important;
84
+ line-height: 2 !important;
85
+ margin-right: 4px !important;
86
+ }
87
+
88
+ input[type="text"] {
89
+ float: left !important;
90
+ margin-right: 30px !important;
91
+ width: 130px !important;
92
+ }
93
+ }
94
+ }
95
+
96
+ .file_todo_list {
97
+ .progress { display: none; }
98
+ }
99
+
100
+ .file_done_list {
101
+ .progress { width: 100%; }
102
+ }
103
+
104
+ .overall {
105
+ border: 1px solid #B7B9BB;
106
+ height: 35px;
107
+ line-height: 35px;
108
+ position: relative;
109
+ font-size: 130%;
110
+ margin-bottom: 10px;
111
+
112
+ .progress {
113
+ display: block;
114
+ height: 35px;
115
+ background: #6A7176;
116
+ background: -webkit-gradient(linear, left top, left bottom, from(#6A7176), to(#4D5256));
117
+ background: -moz-linear-gradient(-90deg, #6A7176, #4D5256);
118
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6a7176, endColorstr=#4d5256);
119
+ -ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6a7176, endColorstr=#4d5256);
120
+
121
+ .amount {
122
+ padding-right: 0px;
123
+ color: #eaeaea;
124
+ text-shadow: 1px 1px #333;
125
+ position: absolute;
126
+ right: 10px;
127
+ }
128
+ }
129
+
130
+ .status {
131
+ text-align: center;
132
+ display: block;
133
+ width: 100%;
134
+ font-weight: bold;
135
+ color: #aaa;
136
+ position: absolute;
137
+ }
138
+
139
+ }
140
+
141
+ .progress {
142
+ display: block;
143
+ position: absolute;
144
+ text-align: right;
145
+ }
146
+
147
+ input[type="submit"] {
148
+ margin-left: 0 !important;
149
+
150
+ &.StopButton, &.ResetButton {
151
+ float: right;
152
+ margin-left: 10px !important;
153
+ }
154
+ }
155
+
156
+ label {
157
+ float: none;
158
+ width: auto !important;
159
+ text-align: left;
160
+ margin: 0 !important;
161
+ }
162
+ }
163
+
164
+ .asset-box-attachment {
165
+ position: relative;
166
+ width: 128px;
167
+ float: left;
168
+ margin-right: 20px;
169
+ height: 190px;
170
+
171
+ p.title {
172
+ font-size: 14px;
173
+ color: #818181;
174
+ padding: 10px;
175
+ margin: 0;
176
+ }
177
+ }
178
+
179
+ .asset-box-spinner {
180
+ height: 128px;
181
+ width: 128px;
182
+ background: rgba(255,255,255,0.8) image-url('effective_assets/spinner.gif') no-repeat center center;
183
+ display: block;
184
+ margin-bottom: 6px;
185
+ }
186
+
187
+ .attachments {
188
+ @include clearfix;
189
+ }
190
+
191
+ .file_to_upload .delete, .asset-box-remove {
192
+ @include border-radius(3px);
193
+ display: block;
194
+ position: absolute;
195
+ background: rgba(255,255,255,0.8) image-url('effective_assets/icon_close.png') no-repeat center center;
196
+ text-indent: -99999px !important;
197
+ height: 20px;
198
+ width: 20px;
199
+ right: 10px;
200
+ top: 10px;
201
+ cursor: pointer;
202
+ }
203
+
204
+ .assets {
205
+ clear: both;
206
+ }
@@ -0,0 +1,14 @@
1
+ module Effective
2
+ class AttachmentsController < ApplicationController
3
+ skip_authorize_resource if defined?(CanCan)
4
+ respond_to :json
5
+
6
+ def show
7
+ @asset = Asset.find(params[:id]) # This should actually search Assets
8
+
9
+ EffectiveAssets.authorized?(self, :read, @asset)
10
+
11
+ respond_with @asset
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,98 @@
1
+ require 's3_swf_upload'
2
+ require 'base64'
3
+
4
+ module Effective
5
+ class S3UploadsController < ApplicationController
6
+ skip_authorize_resource if defined?(CanCan)
7
+
8
+ respond_to :js, :xml
9
+
10
+ include S3SwfUpload::Signature
11
+
12
+ def index
13
+ # This is actually a 'new' action. Not an index. The s3 flash uploader is hardcoded to check this url as an xml request
14
+
15
+ EffectiveAssets.authorized?(self, :create, Effective::Asset)
16
+
17
+ bucket = EffectiveAssets.aws_bucket
18
+ access_key_id = EffectiveAssets.aws_access_key_id
19
+ acl = EffectiveAssets.aws_acl
20
+ secret_key = EffectiveAssets.aws_secret_access_key
21
+ key = params[:key]
22
+ content_type = params[:content_type]
23
+ https = 'false'
24
+ error_message = ''
25
+ expiration_date = 1.hours.from_now.utc.strftime('%Y-%m-%dT%H:%M:%S.000Z')
26
+
27
+ policy = Base64.encode64(
28
+ "{
29
+ 'expiration': '#{expiration_date}',
30
+ 'conditions': [
31
+ {'bucket': '#{bucket}'},
32
+ {'key': '#{key}'},
33
+ {'acl': '#{acl}'},
34
+ {'Content-Type': '#{content_type}'},
35
+ {'Content-Disposition': 'attachment'},
36
+ ['starts-with', '$Filename', ''],
37
+ ['eq', '$success_action_status', '201']
38
+ ]
39
+ }").gsub(/\n|\r/, '')
40
+
41
+ signature = b64_hmac_sha1(secret_key, policy)
42
+
43
+ respond_to do |format|
44
+ format.xml {
45
+ render :xml => {
46
+ :policy => policy,
47
+ :signature => signature,
48
+ :bucket => bucket,
49
+ :accesskeyid => access_key_id,
50
+ :acl => acl,
51
+ :expirationdate => expiration_date,
52
+ :https => https,
53
+ :errorMessage => error_message.to_s,
54
+ }.to_xml
55
+ }
56
+ end
57
+ end
58
+
59
+ def create
60
+ EffectiveAssets.authorized?(self, :create, Effective::Asset)
61
+
62
+ # If we're passed Asset information, then create an Asset
63
+ if params[:file_path].present?
64
+ asset = Asset.create_from_s3_uploader(params[:file_path],
65
+ {
66
+ :title => params[:title],
67
+ :description => params[:description],
68
+ :tags => params[:tags],
69
+ :content_type => params[:content_type],
70
+ :data_size => params[:file_size],
71
+ :user_id => current_user.try(:id)
72
+ }
73
+ )
74
+ else
75
+ asset = (Asset.find(params[:asset_id].to_i) rescue false)
76
+ end
77
+
78
+ unless asset
79
+ render :text => '', :status => :unprocessable_entity
80
+ return
81
+ end
82
+
83
+ # If the attachment information is present, then our input needs some attachment HTML
84
+ if params.key?(:attachable_type)
85
+ attachment = Attachment.new
86
+ attachment.attachable_type = params[:attachable_type].try(:classify)
87
+ attachment.attachable_id = params[:attachable_id].try(:to_i) if params[:attachable_id].present? # attachable_id can be nil if we're on a New action
88
+ attachment.asset_id = asset.try(:id)
89
+ attachment.box = params[:box]
90
+ attachment.position = 0
91
+
92
+ render :partial => 'asset_box_input/attachment_fields', :locals => {:attachment => attachment}, :status => 200, :content_type => 'text/html'
93
+ else
94
+ render :text => '', :status => 200
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,55 @@
1
+ module EffectiveAssetsHelper
2
+ # Generates an image tag based on the particular asset
3
+ def effective_asset_image_tag(asset, version = nil, options = {})
4
+ if asset.image? == false
5
+ opts = {}
6
+ elsif version.present? and asset.versions_info[version].present?
7
+ opts = { :height => asset.versions_info[version][:height], :width => asset.versions_info[version][:width] }
8
+ elsif version.present? and asset.data.respond_to?(:versions_info) and asset.data.versions_info[version].present?
9
+ opts = { :height => asset.data.versions_info[version][:height], :width => asset.data.versions_info[version][:width] }
10
+ elsif asset.height.present? and asset.width.present?
11
+ opts = { :height => asset.height, :width => asset.width }
12
+ else
13
+ opts = {}
14
+ end
15
+
16
+ opts = opts.merge({:alt => asset.description || asset.title || asset.file_name}).merge(options)
17
+ image_tag(_effective_asset_image_url(asset, version), opts).gsub('"', "'").html_safe # we need all ' quotes or it breaks Insert as functionality
18
+ end
19
+
20
+ def effective_asset_link_to(asset, version = nil, options = {})
21
+ link_title = asset.title || asset.file_name || asset.description || "Asset ##{asset.id}"
22
+
23
+ link_to(link_title, asset.url).gsub('"', "'").html_safe # we need all ' quotes or it breaks Insert as functionality
24
+ end
25
+
26
+ def effective_asset_video_tag(asset)
27
+ render(:partial => 'assets/video', :locals => { :asset => asset }).gsub('"', "'").html_safe # we need all ' quotes or it breaks Insert as functionality
28
+ end
29
+
30
+ def _effective_asset_image_url(asset, version = nil)
31
+ return '/assets/mime-types/file.png' if !asset.content_type.present? or asset.content_type == 'unknown'
32
+
33
+ if asset.icon?
34
+ asset.url
35
+ elsif asset.image?
36
+ (version == nil or asset.still_processing?) ? asset.url : asset.url.insert(asset.url.rindex('/')+1, "#{version.to_s}_")
37
+ elsif asset.audio?
38
+ '/assets/mime-types/mp3.png'
39
+ elsif asset.video?
40
+ '/assets/mime-types/video.png'
41
+ elsif asset.content_type.include? 'msword'
42
+ '/assets/mime-types/word.jpg'
43
+ elsif asset.content_type.include? 'excel'
44
+ '/assets/mime-types/excel.jpg'
45
+ elsif asset.content_type.include? 'application/pdf'
46
+ '/assets/mime-types/pdf.png'
47
+ elsif asset.content_type.include? 'application/zip'
48
+ '/assets/mime-types/zip.png'
49
+ else
50
+ '/assets/mime-types/file.png'
51
+ end
52
+ end
53
+
54
+
55
+ end
@@ -0,0 +1,97 @@
1
+ # ActsAsAssetBox
2
+ #
3
+ # Returns a set of assets or one asset as defined by the provided 'boxes' (a box is just a category) array
4
+ # Works with Formtastic::Inputs::asset_box_input
5
+ #
6
+ # Define your model with 'acts_as_asset_box' if you just need one box of assets
7
+ # You will then be able to call @my_resource.assets and @my_resource.asset
8
+ #
9
+ # or
10
+ #
11
+ # acts_as_asset_box :fav_icon, :pictures, :logos
12
+ #
13
+ # or (if you want validations)
14
+ #
15
+ # acts_as_asset_box :fav_icon => true, :pictures => false, :videos => 2, :images => 5..10
16
+ #
17
+ # Define your model with 'acts_as_asset_box :fav_icon, :pictures, :logos' for 3 different boxes of assets.
18
+ # This creates three methods, @my_resource.fav_icon, @my_resource.pictures, @my_resource.logos
19
+ #
20
+ # If you define a singular name, like :fav_icon, then calling @my_resource.fav_icon will return the 1 asset from the fav_icon box
21
+ # If you define a plural name, like :pictures, then calling @my_resource.pictures will return all assets in the pictures box
22
+ #
23
+ # This works with the lib/acts_as_asset_box_input.rb for editting boxes of assets
24
+ #
25
+
26
+ module ActsAsAssetBox
27
+ extend ActiveSupport::Concern
28
+
29
+ module ActiveRecord
30
+ def acts_as_asset_box(*options)
31
+ @acts_as_asset_box_opts = options || []
32
+ include ::ActsAsAssetBox
33
+ end
34
+ end
35
+
36
+ included do
37
+ has_many :attachments, :as => :attachable, :class_name => "Effective::Attachment", :dependent => :delete_all
38
+ has_many :assets, :through => :attachments, :class_name => "Effective::Asset"
39
+
40
+ #attr_accessible :attachments_attributes
41
+ accepts_nested_attributes_for :attachments, :reject_if => :all_blank, :allow_destroy => true
42
+
43
+ # Setup validations
44
+ boxes = @acts_as_asset_box_opts.try(:flatten) || []
45
+ if boxes.first.kind_of?(Hash) # We were passed some validation requirements
46
+ boxes = boxes.first
47
+
48
+ @@acts_as_asset_box_boxes = boxes.keys
49
+
50
+ boxes.each do |box, validation|
51
+ if validation == true
52
+ validates box, :asset_box_presence => true
53
+ elsif validation.kind_of?(Integer) or validation.kind_of?(Range)
54
+ validates box, :asset_box_length => validation
55
+ end
56
+ end
57
+ else
58
+ @@acts_as_asset_box_boxes = boxes
59
+ end
60
+
61
+ class_eval do
62
+ def attachments_attributes=(atts)
63
+ current_box = ''; position = 0
64
+
65
+ atts.each do |k, v|
66
+ (current_box = v['box'] and position = 0) if v['box'] != current_box
67
+ atts[k]['position'] = (position += 1) if atts[k]['_destroy'] != '1'
68
+ end
69
+
70
+ assign_nested_attributes_for_collection_association(:attachments, atts, {})
71
+ end
72
+ end
73
+ end
74
+
75
+ module ClassMethods
76
+ end
77
+
78
+ def assets(box = nil)
79
+ box = (box.present? ? box.to_s : 'assets')
80
+
81
+ if box == box.pluralize
82
+ attachments.select { |attachment| attachment.box == box }.map { |attachment| attachment.asset }
83
+ else
84
+ attachments.to_a.find { |attachment| attachment.box == box.pluralize }.try(:asset)
85
+ end
86
+ end
87
+
88
+ def asset
89
+ assets(:asset)
90
+ end
91
+
92
+ # This handles all the boxes type function calls
93
+ def method_missing(method_name, *args, &block)
94
+ (@@acts_as_asset_box_boxes || []).include?(method_name.to_sym) ? assets(method_name) : super
95
+ end
96
+ end
97
+