radiant-clipped-extension-add-group 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +184 -0
  3. data/Rakefile +109 -0
  4. data/app/controllers/admin/assets_controller.rb +66 -0
  5. data/app/controllers/admin/page_attachments_controller.rb +18 -0
  6. data/app/helpers/admin/assets_helper.rb +16 -0
  7. data/app/helpers/admin/page_attachments_helper.rb +2 -0
  8. data/app/models/asset.rb +237 -0
  9. data/app/models/asset_type.rb +241 -0
  10. data/app/models/old_page_attachment.rb +26 -0
  11. data/app/models/page_attachment.rb +20 -0
  12. data/app/views/admin/assets/_asset.html.haml +12 -0
  13. data/app/views/admin/assets/_asset_table.html.haml +33 -0
  14. data/app/views/admin/assets/_errors.html.haml +3 -0
  15. data/app/views/admin/assets/_form.html.haml +25 -0
  16. data/app/views/admin/assets/_page_assets.html.haml +12 -0
  17. data/app/views/admin/assets/_search.html.haml +17 -0
  18. data/app/views/admin/assets/_search_results.html.haml +17 -0
  19. data/app/views/admin/assets/edit.html.haml +41 -0
  20. data/app/views/admin/assets/index.html.haml +19 -0
  21. data/app/views/admin/assets/new.html.haml +24 -0
  22. data/app/views/admin/assets/refresh.html.haml +14 -0
  23. data/app/views/admin/assets/remove.html.haml +16 -0
  24. data/app/views/admin/configuration/_clipped_edit.html.haml +8 -0
  25. data/app/views/admin/configuration/_clipped_show.html.haml +12 -0
  26. data/app/views/admin/page_attachments/_attachment.html.haml +25 -0
  27. data/app/views/admin/page_parts/_page_part.html.haml +21 -0
  28. data/app/views/admin/pages/_asset_popups.html.haml +42 -0
  29. data/app/views/admin/pages/_assets.html.haml +11 -0
  30. data/app/views/admin/removed/_assets_bucket.html.haml +8 -0
  31. data/app/views/admin/removed/_assets_container.html.haml +58 -0
  32. data/app/views/admin/removed/_bucket.html.haml +11 -0
  33. data/app/views/admin/removed/_bucket_asset.html.haml +9 -0
  34. data/app/views/admin/removed/_show_bucket_link.html.haml +4 -0
  35. data/app/views/admin/removed/_upload_to_page.html.haml +12 -0
  36. data/app/views/admin/removed/bucket/_iframe.html.haml +1 -0
  37. data/artwork/icons.png +0 -0
  38. data/clipped_extension.rb +52 -0
  39. data/config/initializers/interpolation.rb +6 -0
  40. data/config/initializers/processors.rb +43 -0
  41. data/config/initializers/radiant_config.rb +65 -0
  42. data/config/locales/de.yml +109 -0
  43. data/config/locales/en.yml +110 -0
  44. data/config/locales/nl.yml +107 -0
  45. data/config/locales/ru.yml +110 -0
  46. data/config/routes.rb +8 -0
  47. data/cucumber.yml +1 -0
  48. data/db/migrate/001_create_assets.rb +12 -0
  49. data/db/migrate/002_create_paperclip_attributes.rb +13 -0
  50. data/db/migrate/003_create_user_observer.rb +13 -0
  51. data/db/migrate/004_create_page_attachments.rb +19 -0
  52. data/db/migrate/005_rename_users.rb +13 -0
  53. data/db/migrate/20110513205050_asset_uuid.rb +11 -0
  54. data/db/migrate/20110606111250_update_configuration.rb +34 -0
  55. data/db/migrate/20110609101438_dimensions.rb +13 -0
  56. data/db/migrate/20121024064452_add_group_to_assets.rb +9 -0
  57. data/features/support/env.rb +11 -0
  58. data/features/support/paths.rb +22 -0
  59. data/lib/asset_tags.rb +350 -0
  60. data/lib/clipped_admin_ui.rb +32 -0
  61. data/lib/cloud.rb +41 -0
  62. data/lib/generators/templates/clipped_config.rb +53 -0
  63. data/lib/page_asset_associations.rb +13 -0
  64. data/lib/paperclip/frame_grab.rb +73 -0
  65. data/lib/paperclip/geometry_transformation.rb +80 -0
  66. data/lib/radiant-clipped-extension.rb +8 -0
  67. data/lib/tasks/clipped_extension_tasks.rake +124 -0
  68. data/lib/tasks/paperclip_tasks.rake +79 -0
  69. data/public/flash/ZeroClipboard.swf +0 -0
  70. data/public/images/admin/assets/add.png +0 -0
  71. data/public/images/admin/assets/archive_icon.png +0 -0
  72. data/public/images/admin/assets/audio_icon.png +0 -0
  73. data/public/images/admin/assets/audio_thumbnail.png +0 -0
  74. data/public/images/admin/assets/c_icon.png +0 -0
  75. data/public/images/admin/assets/copy.png +0 -0
  76. data/public/images/admin/assets/css_icon.png +0 -0
  77. data/public/images/admin/assets/database_icon.png +0 -0
  78. data/public/images/admin/assets/delete.png +0 -0
  79. data/public/images/admin/assets/document_icon.png +0 -0
  80. data/public/images/admin/assets/document_thumbnail.png +0 -0
  81. data/public/images/admin/assets/flash_icon.png +0 -0
  82. data/public/images/admin/assets/flash_thumbnail.png +0 -0
  83. data/public/images/admin/assets/font_icon.png +0 -0
  84. data/public/images/admin/assets/gzip_icon.png +0 -0
  85. data/public/images/admin/assets/html_icon.png +0 -0
  86. data/public/images/admin/assets/image_icon.png +0 -0
  87. data/public/images/admin/assets/image_thumbnail.png +0 -0
  88. data/public/images/admin/assets/java_icon.png +0 -0
  89. data/public/images/admin/assets/page_edit.png +0 -0
  90. data/public/images/admin/assets/perl_icon.png +0 -0
  91. data/public/images/admin/assets/php_icon.png +0 -0
  92. data/public/images/admin/assets/presentation_icon.png +0 -0
  93. data/public/images/admin/assets/python_icon.png +0 -0
  94. data/public/images/admin/assets/reorder_assets.png +0 -0
  95. data/public/images/admin/assets/ruby_icon.png +0 -0
  96. data/public/images/admin/assets/script_icon.png +0 -0
  97. data/public/images/admin/assets/spreadsheet_icon.png +0 -0
  98. data/public/images/admin/assets/tar_icon.png +0 -0
  99. data/public/images/admin/assets/unknown_icon.png +0 -0
  100. data/public/images/admin/assets/unknown_thumbnail.png +0 -0
  101. data/public/images/admin/assets/video_icon.png +0 -0
  102. data/public/images/admin/assets/video_thumbnail.png +0 -0
  103. data/public/images/admin/assets/xml_icon.png +0 -0
  104. data/public/images/admin/assets/zip_icon.png +0 -0
  105. data/public/javascripts/admin/assets.js +297 -0
  106. data/public/stylesheets/sass/admin/assets.sass +224 -0
  107. data/radiant-clipped-extension.gemspec +29 -0
  108. data/spec/ci/before_script +23 -0
  109. data/spec/ci/script +2 -0
  110. data/spec/controllers/admin/assets_controller_spec.rb +50 -0
  111. data/spec/controllers/admin/page_attachments_controller_spec.rb +50 -0
  112. data/spec/datasets/assets_dataset.rb +36 -0
  113. data/spec/fixtures/5k.png +0 -0
  114. data/spec/fixtures/test.flv +0 -0
  115. data/spec/lib/asset_tags_spec.rb +107 -0
  116. data/spec/lib/frame_grab_spec.rb +17 -0
  117. data/spec/lib/geometry_transformation_spec.rb +63 -0
  118. data/spec/models/asset_spec.rb +72 -0
  119. data/spec/models/asset_type_spec.rb +70 -0
  120. data/spec/models/post_processing_spec.rb +62 -0
  121. data/spec/spec.opts +7 -0
  122. data/spec/spec_helper.rb +36 -0
  123. data/wireframes/edit-page-assets-2.bmml +453 -0
  124. data/wireframes/edit-page-assets-2.png +0 -0
  125. data/wireframes/edit-page-assets-3.bmml +454 -0
  126. data/wireframes/edit-page-assets-3.png +0 -0
  127. data/wireframes/edit-page-assets.bmml +433 -0
  128. data/wireframes/edit-page-assets.png +0 -0
  129. data/wireframes/edit-page.bmml +174 -0
  130. data/wireframes/edit-page.png +0 -0
  131. metadata +281 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ == MIT License
2
+
3
+ Copyright (c) 2011 Keith Bingman, Benny Degezelle, William Ross, and John W. Long
4
+ Copyright (c) 2008-2010, Keith Bingman
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # Radiant Clipped Extension
2
+
3
+ [![Build Status](https://secure.travis-ci.org/radiant/radiant-clipped-extension.png)](http://travis-ci.org/radiant/radiant-clipped-extension)
4
+
5
+ Asset management for Radiant CMS.
6
+
7
+ The Clipped extension comes bundled with the Radiant gem but may be updated separately. Only Radiant versions 1.0 or newer are supported.
8
+
9
+ Please file bugs and feature requests on [Github][issues]. If you have questions regarding usage ask on the [mailing list][mailing-list].
10
+
11
+ [issues]: https://github.com/radiant/radiant-clipped-extension/issues
12
+ [mailing-list]: https://groups.google.com/forum/?hl=en#!forum/radiantcms
13
+
14
+ ## Features
15
+
16
+ * Concurrent uploads
17
+ * Automatic thumbnail generation
18
+ * requiers ImageMagick for images
19
+ * requiers FFmpeg for videos
20
+ * requiers Ghostscript for PDFs
21
+ * In-page and dedicated management interfaces
22
+ * Easily to extended with new asset types and processors
23
+
24
+ ## Installation
25
+
26
+ If you installed the Radiant gem then you already have Clipped installed. You can upgrade to a newer version using `bundle update radiant-clipped-extension`.
27
+
28
+ Installation of the optional post-processors varies by system but are likely available through your package manager.
29
+
30
+ ### Mac OSX
31
+
32
+ brew install ghostscript imagemagick ffmpeg
33
+ # or
34
+ port install ghostscript imagemagick ffmpeg
35
+
36
+ ### Debian
37
+
38
+ apt-get install ghostscript imagemagick ffmpeg
39
+
40
+ ### Windows
41
+
42
+ [Ghostscript][ghostscript], [ImageMagick][imagemagick] and [FFmpeg][ffmpeg] all
43
+ offer Windows installers that you can install in the usual way.
44
+
45
+ [ghostscript]: http://sourceforge.net/projects/ghostscript/
46
+ [imagemagick]: http://www.imagemagick.org/script/binary-releases.php
47
+ [ffmpeg]: http://ffmpeg.zeranoe.com/builds/
48
+
49
+ If the post-processors are not in your `PATH` or you're running Passenger you might need to set `Paperclip.options[:command_path]` to the location where the binaries are installed.
50
+
51
+ ## Configuration
52
+
53
+ The clipped extension is configured in the usual way, but only its minor settings are exposed in the admin interface. The more architectural settings shouldn't be changed at runtime and some of them will require a lot of sorting out if they're changed at all, so those are only accessible through the console or by editing the database. Eventually they will be made part of the initial radiant installation process.
54
+
55
+ ### Structural settings
56
+
57
+ * `paperclip.url` sets the url scheme for attached files. Paperclip interpolations are applied. You probably don't want to change this.
58
+ * `paperclip.path` sets the path scheme for attached files. Paperclip interpolations are applied. You might conceivably want to change this.
59
+ * `paperclip.additional_thumbnails` is a string of comma-separated style definitions that is passed to paperclip for any asset type that has a post-processor (that is, currently, images, pdfs and video clips). The definitions are in the format name=geometry and when assembled the string will look something like `preview=640x640>,square=#260x260`. Thumbnail and icon styles are already defined and don't need to be configured this way.
60
+ * `paperclip.storage` can be 'filesystem' (the default) or 'fog' for cloud storage (such as s3).
61
+ * `paperclip.skip_filetype_validation` is true by default and allows uploads of any mime type.
62
+
63
+ ### Cloud Storage
64
+
65
+ Set `paperclip.storage` to 'fog' and add the following line to your `Gemfile`
66
+
67
+ `gem "fog", "~> 1.0"`
68
+
69
+ You also have to provide the following settings:
70
+
71
+ * `paperclip.fog.provider` # set to one of "AWS", "Google" or "Rackspace"
72
+
73
+ If set to AWS, provide the following:
74
+
75
+ * `paperclip.s3.bucket`
76
+ * `paperclip.s3.key`
77
+ * `paperclip.s3.secret`
78
+ * `paperclip.s3.region`
79
+
80
+ If set to "Google", provide the following:
81
+
82
+ * `paperclip.fog.directory`
83
+ * `paperclip.google_storage.access_key_id`
84
+ * `paperclip.google_storage.secret_access_key`
85
+
86
+ If set to "Rackspace", provide the following:
87
+
88
+ * `paperclip.fog.directory`
89
+ * `paperclip.rackspace.username`
90
+ * `paperclip.rackspace.api_key`
91
+
92
+ And optionally:
93
+
94
+ * `paperclip.fog.host`
95
+ * `paperclip.fog.public?`
96
+
97
+ ### Configurable settings
98
+
99
+ If you want to disable a whole category of post-processing, set one of these options to false:
100
+
101
+ * `assets.create_image_thumbnails?`
102
+ * `assets.create_video_thumbnails?`
103
+ * `assets.create_pdf_thumbnails?`
104
+
105
+ If we can't find ffmpeg on initialization, video thumbnailing will be disabled automatically by setting `assets.create_video_thumbnails?` to false.
106
+
107
+ To set a threshold for the size of uploads permitted:
108
+
109
+ * `assets.max_asset_size` which should be an integer number of MB
110
+
111
+ And you can set some defaults:
112
+
113
+ * `assets.insertion_size` is the name of the style that's used when you click on 'insert' to add a radius asset tag to your text. You can edit it after insertion, of course.
114
+ * `assets.display_size` is the name of the style that's shows when you edit a single asset in the admin interface.
115
+
116
+ ## Usage
117
+
118
+ For most purposes you will probably work with assets while you're working on pages. Click on one of the 'assets' links and a panel will pop up allowing you to find, insert and attach existing assets or upload new ones.
119
+
120
+ For tidying up, replacing files and other admin, click on the 'assets' tab to get a larger version of the same list. Here again you can search for assets and filter the results by type, but the options are 'edit' and 'remove' and on editing you can change name, file and caption while keeping page associations intact.
121
+
122
+ ## Radius Tags
123
+
124
+ The asset manager has its own family of radius tags. The basic tag is `<r:asset/>`, which can be used either alone or as a double tag. This tag requires a `name` or `id` attribute, which references the asset. The `<r:asset/>` tag can be combined with other tags for a variety of uses:
125
+
126
+ <r:asset:image name="image.png"/> #=> <img src="/path/to/image.png" />
127
+ <r:asset:link name="image.png"/> #=> <a href="/path/to/image.png">image.png</a>
128
+
129
+ You could also use:
130
+
131
+ <r:asset:link name="bar.pdf">Download PDF</r:asset:link>
132
+
133
+ Asset links are also available, such as content_type, file_size, and url.
134
+
135
+ Another important tag is the `<r:assets:each>...</r:assets:each>` (note the plural namespace tag "assets"). If a page has attached assets, the `<r:assets:each>` tag will cycle through each asset. You can then use an image, `link` or `url` tag to display and connect your assets. Usage:
136
+
137
+ <r:assets:each [limit=0] [offset=0] [order="asc|desc"] [by="position|title|..."]>
138
+ ...
139
+ </r:assets:each>
140
+
141
+ This tag uses the following parameters:
142
+
143
+ * `limit` and `offset` let you specify a range of assets
144
+ * `order` and `by` lets you control sorting
145
+
146
+ The conditional tags `<r:if_assets [min_count="0"]>` and `<r:unless_assets [min_count="0"]>` allow you to optionally render content based on the existence of tags. They accept the same options as `<r:assets:each>`.
147
+
148
+ Thumbnails are automatically generated for images when the images are uploaded. By default, two sizes are made for use within the extension itself. These are "icon" 42px by 42px and "thumbnail" which is 100px square.
149
+
150
+ You can access sizes of image assets for various versions with tags like `<r:asset:width [size="original"]/>` and `<r:asset:height [size="original"]/>`.
151
+
152
+ Also, for vertical centering of images, you have the handy `<r:asset:top_padding container="<container height>" [size="icon"]/>` tag. Working example:
153
+
154
+ <ul>
155
+ <r:assets:each>
156
+ <li style="height:140px">
157
+ <img style="padding-top:<r:top_padding size='category' container='140'/>px" src="<r:url/>" alt="<r:caption/>">
158
+ </li>
159
+ </r:assets:each>
160
+ </ul>
161
+
162
+ ## Contributions
163
+
164
+ If you would like to contribute, please [fork the project][fork] and submit a [pull request][pull-request].
165
+
166
+ [fork]: http://help.github.com/fork-a-repo/
167
+ [pull-request]: http://help.github.com/send-pull-requests/
168
+
169
+ Pull requests with working tests are preferred and have a greater chance of being merged.
170
+
171
+ ## TODO
172
+
173
+ * Progress bars while uploading assets
174
+ * Warning if you try and save a page while assets are still uploading
175
+ * Radius tags for the HTML video and audio elements
176
+ * Auxiliary extension to add video transcoding support
177
+
178
+ ## Authors
179
+
180
+ * Keith Bingman
181
+ * John Long
182
+ * William Ross
183
+
184
+ Copyright 2011 the Radiant team. Released under the same terms as Radiant.
data/Rakefile ADDED
@@ -0,0 +1,109 @@
1
+ # Determine where the RSpec plugin is by loading the boot
2
+ unless defined? RADIANT_ROOT
3
+ ENV["RAILS_ENV"] = "test"
4
+ case
5
+ when ENV["RADIANT_ENV_FILE"]
6
+ require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
7
+ when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
8
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
9
+ else
10
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
11
+ end
12
+ end
13
+
14
+ require 'rake'
15
+ require 'rdoc/task'
16
+ require 'rake/testtask'
17
+
18
+ rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
19
+ $LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
20
+ require 'spec/rake/spectask'
21
+ require 'cucumber'
22
+ require 'cucumber/rake/task'
23
+
24
+ # Cleanup the RADIANT_ROOT constant so specs will load the environment
25
+ Object.send(:remove_const, :RADIANT_ROOT)
26
+
27
+ extension_root = File.expand_path(File.dirname(__FILE__))
28
+
29
+ task :default => [:spec, :features]
30
+ task :stats => "spec:statsetup"
31
+
32
+ desc "Run all specs in spec directory"
33
+ Spec::Rake::SpecTask.new(:spec) do |t|
34
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
35
+ t.spec_files = FileList['spec/**/*_spec.rb']
36
+ end
37
+
38
+ task :features => 'spec:integration'
39
+
40
+ namespace :spec do
41
+ desc "Run all specs in spec directory with RCov"
42
+ Spec::Rake::SpecTask.new(:rcov) do |t|
43
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
44
+ t.spec_files = FileList['spec/**/*_spec.rb']
45
+ t.rcov = true
46
+ t.rcov_opts = ['--exclude', 'spec', '--rails']
47
+ end
48
+
49
+ desc "Print Specdoc for all specs"
50
+ Spec::Rake::SpecTask.new(:doc) do |t|
51
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
52
+ t.spec_files = FileList['spec/**/*_spec.rb']
53
+ end
54
+
55
+ [:models, :controllers, :views, :helpers].each do |sub|
56
+ desc "Run the specs under spec/#{sub}"
57
+ Spec::Rake::SpecTask.new(sub) do |t|
58
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
59
+ t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
60
+ end
61
+ end
62
+
63
+ desc "Run the Cucumber features"
64
+ Cucumber::Rake::Task.new(:integration) do |t|
65
+ t.fork = true
66
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
67
+ # t.feature_pattern = "#{extension_root}/features/**/*.feature"
68
+ t.profile = "default"
69
+ end
70
+
71
+ # Setup specs for stats
72
+ task :statsetup do
73
+ require 'code_statistics'
74
+ ::STATS_DIRECTORIES << %w(Model\ specs spec/models)
75
+ ::STATS_DIRECTORIES << %w(View\ specs spec/views)
76
+ ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
77
+ ::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
78
+ ::CodeStatistics::TEST_TYPES << "Model specs"
79
+ ::CodeStatistics::TEST_TYPES << "View specs"
80
+ ::CodeStatistics::TEST_TYPES << "Controller specs"
81
+ ::CodeStatistics::TEST_TYPES << "Helper specs"
82
+ ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
83
+ end
84
+
85
+ namespace :db do
86
+ namespace :fixtures do
87
+ desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
88
+ task :load => :environment do
89
+ require 'active_record/fixtures'
90
+ ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
91
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
92
+ Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ desc 'Generate documentation for the clipped extension.'
100
+ RDoc::Task.new(:rdoc) do |rdoc|
101
+ rdoc.rdoc_dir = 'rdoc'
102
+ rdoc.title = 'ClippedExtension'
103
+ rdoc.options << '--line-numbers' << '--inline-source'
104
+ rdoc.rdoc_files.include('README')
105
+ rdoc.rdoc_files.include('lib/**/*.rb')
106
+ end
107
+
108
+ # Load any custom rakefiles for extension
109
+ Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
@@ -0,0 +1,66 @@
1
+ class Admin::AssetsController < Admin::ResourceController
2
+ paginate_models(:per_page => 50)
3
+
4
+ def index
5
+ assets = Asset.scoped({:order => "created_at DESC"})
6
+
7
+ @term = params[:search] || ''
8
+ assets = assets.matching(@term) if @term && !@term.blank?
9
+
10
+ @types = params[:filter] || []
11
+ if @types.include?('all')
12
+ params[:filter] = nil
13
+ elsif @types.any?
14
+ assets = assets.of_types(@types)
15
+ end
16
+
17
+ @assets = paginated? ? assets.paginate(pagination_parameters) : assets.all
18
+ respond_to do |format|
19
+ format.html { render }
20
+ format.js {
21
+ @page = Page.find_by_id(params[:page_id])
22
+ render :partial => 'asset_table', :locals => {:with_pagination => !!@page}
23
+ }
24
+ end
25
+ end
26
+
27
+ def create
28
+ @assets, @page_attachments = [], []
29
+ params[:asset][:asset].to_a.each do |uploaded_asset|
30
+ @asset = Asset.create(:group => params[:asset][:group], :asset => uploaded_asset, :title => params[:asset][:title], :caption => params[:asset][:caption])
31
+ if params[:for_attachment]
32
+ @page = Page.find_by_id(params[:page_id]) || Page.new
33
+ @page_attachments << @page_attachment = @asset.page_attachments.build(:page => @page)
34
+ end
35
+ @assets << @asset
36
+ end
37
+ if params[:for_attachment]
38
+ render :partial => 'admin/page_attachments/attachment', :collection => @page_attachments
39
+ else
40
+ response_for :create
41
+ end
42
+ end
43
+
44
+ def refresh
45
+ if params[:id]
46
+ @asset = Asset.find(params[:id])
47
+ @asset.asset.reprocess!
48
+ flash[:notice] = t('clipped_extension.thumbnails_refreshed')
49
+ redirect_to edit_admin_asset_path(@asset)
50
+ else
51
+ render
52
+ end
53
+ end
54
+
55
+ only_allow_access_to :regenerate,
56
+ :when => [:admin],
57
+ :denied_url => { :controller => 'admin/assets', :action => 'index' },
58
+ :denied_message => 'You must have admin privileges to refresh the whole asset set.'
59
+
60
+ def regenerate
61
+ Asset.all.each { |asset| asset.asset.reprocess! }
62
+ flash[:notice] = t('clipped_extension.all_thumbnails_refreshed')
63
+ redirect_to admin_assets_path
64
+ end
65
+
66
+ end
@@ -0,0 +1,18 @@
1
+ class Admin::PageAttachmentsController < Admin::ResourceController
2
+ helper 'admin/assets'
3
+
4
+ def new
5
+ render :partial => 'attachment', :object => model
6
+ end
7
+
8
+ def load_model
9
+ begin
10
+ @asset = Asset.find(params[:asset_id])
11
+ @page = params[:page_id].blank? ? Page.new : Page.find_by_id(params[:page_id])
12
+ rescue ActiveRecord::RecordNotFound
13
+ render :nothing => true, :layout => false
14
+ end
15
+ self.model = PageAttachment.new(:asset => @asset, :page => @page)
16
+ end
17
+
18
+ end
@@ -0,0 +1,16 @@
1
+ module Admin::AssetsHelper
2
+
3
+ def automatic_size_descriptions
4
+ Asset.thumbnail_sizes.collect{|k,v| "#{k} (#{(v.to_s).match(/\d+x\d+/)})"}.join(', ')
5
+ end
6
+
7
+ def asset_insertion_link(asset)
8
+ radius_tag = asset.asset_type.default_radius_tag || 'link';
9
+ link_to t('clipped_extension.insert'), '#', :class => 'insert_asset', :rel => "#{radius_tag}_#{Radiant.config['assets.insertion_size']}_#{asset.id}"
10
+ end
11
+
12
+ def asset_attachment_link(asset)
13
+ link_to t("clipped_extension.attach"), new_admin_page_attachment_path(:asset_id => asset.id), :class => 'attach_asset', :rel => "attach_#{asset.id}"
14
+ end
15
+
16
+ end
@@ -0,0 +1,2 @@
1
+ module Admin::PageAttachmentsHelper
2
+ end
@@ -0,0 +1,237 @@
1
+ class Asset < ActiveRecord::Base
2
+ has_many :page_attachments, :dependent => :destroy
3
+ has_many :pages, :through => :page_attachments
4
+ has_site if respond_to? :has_site
5
+
6
+ belongs_to :created_by, :class_name => 'User'
7
+ belongs_to :updated_by, :class_name => 'User'
8
+
9
+ default_scope :order => "created_at DESC"
10
+
11
+ named_scope :latest, lambda { |limit|
12
+ { :order => "created_at DESC", :limit => limit }
13
+ }
14
+
15
+ named_scope :of_types, lambda { |types|
16
+ mimes = AssetType.slice(*types).map(&:mime_types).flatten
17
+ { :conditions => ["asset_content_type IN (#{mimes.map{'?'}.join(',')})", *mimes] }
18
+ }
19
+
20
+ named_scope :matching, lambda { |term|
21
+ { :conditions => ["LOWER(assets.asset_file_name) LIKE (:term) OR LOWER(title) LIKE (:term) OR LOWER(caption) LIKE (:term)", {:term => "%#{term.downcase}%" }] }
22
+ }
23
+
24
+ named_scope :except, lambda { |assets|
25
+ if assets.any?
26
+ assets = assets.split(',') if assets.is_a?(String)
27
+ asset_ids = assets.first.is_a?(Asset) ? assets.map(&:id) : assets
28
+ { :conditions => ["assets.id NOT IN(#{asset_ids.map{ '?' }.join(',')})", *asset_ids] }
29
+ else
30
+ {}
31
+ end
32
+ }
33
+
34
+ has_attached_file :asset,
35
+ :styles => lambda { |attachment|
36
+ AssetType.for(attachment).paperclip_styles
37
+ },
38
+ :processors => lambda { |asset|
39
+ asset.paperclip_processors
40
+ },
41
+ :whiny => false,
42
+ :storage => Radiant.config["paperclip.storage"],
43
+ :path => Radiant.config["paperclip.path"],
44
+ :url => Radiant.config["paperclip.url"],
45
+ :fog_credentials => RadiantClippedExtension::Cloud.credentials,
46
+ :fog_directory => Radiant.config["paperclip.fog.directory"],
47
+ :fog_public => Radiant.config["paperclip.fog.public?"] || true,
48
+ :fog_host => RadiantClippedExtension::Cloud.host
49
+
50
+ before_save :assign_title
51
+ before_save :assign_uuid
52
+
53
+ after_post_process :read_dimensions
54
+
55
+ validates_attachment_presence :asset, :message => "You must choose a file to upload!"
56
+ if Radiant.config["paperclip.skip_filetype_validation"] != "true" && Radiant.config['paperclip.content_types']
57
+ validates_attachment_content_type :asset, :content_type => Radiant.config["paperclip.content_types"].gsub(' ','').split(',')
58
+ end
59
+ validates_attachment_size :asset, :less_than => ( Radiant.config["assets.max_asset_size"] || 5 ).to_i.megabytes
60
+
61
+ def asset_type
62
+ AssetType.for(asset)
63
+ end
64
+ delegate :paperclip_processors, :paperclip_styles, :style_dimensions, :style_format, :to => :asset_type
65
+
66
+ def thumbnail(style_name='original')
67
+ return asset.url if style_name.to_sym == :original
68
+ return asset.url(style_name.to_sym) if has_style?(style_name)
69
+ return asset_type.icon(style_name)
70
+ end
71
+
72
+ def has_style?(style_name='original')
73
+ style_name == 'original' || paperclip_styles.keys.include?(style_name.to_sym)
74
+ end
75
+
76
+ def basename
77
+ File.basename(asset_file_name, ".*") if asset_file_name
78
+ end
79
+
80
+ def extension(style_name='original')
81
+ if style_name == 'original'
82
+ return original_extension
83
+ elsif style = paperclip_styles[style_name.to_sym]
84
+ return style.format
85
+ else
86
+ return original_extension
87
+ end
88
+ end
89
+
90
+ def original_extension
91
+ return asset_file_name.split('.').last.downcase if asset_file_name
92
+ end
93
+
94
+ def attached_to?(page)
95
+ pages.include?(page)
96
+ end
97
+
98
+ def original_geometry
99
+ @original_geometry ||= Paperclip::Geometry.new(original_width, original_height)
100
+ end
101
+
102
+ def geometry(style_name='original')
103
+ raise Paperclip::StyleError, "Requested style #{style_name} is not defined for this asset." unless has_style?(style_name)
104
+ @geometry ||= {}
105
+ begin
106
+ @geometry[style_name] ||= if style_name.to_s == 'original'
107
+ original_geometry
108
+ else
109
+ style = self.asset.styles[style_name.to_sym]
110
+ original_geometry.transformed_by(style.geometry) # this can return dimensions for fully specified style sizes but not for relative sizes when there are no original dimensions
111
+ end
112
+ rescue Paperclip::TransformationError => e
113
+ Rails.logger.warn "geometry transformation error: #{e}"
114
+ original_geometry # returns a blank geometry if the real geometry cannot be calculated
115
+ end
116
+ end
117
+
118
+ def aspect(style_name='original')
119
+ geometry(style_name).aspect
120
+ end
121
+
122
+ def orientation(style_name='original')
123
+ a = aspect(style_name)
124
+ case
125
+ when a == nil?
126
+ 'unknown'
127
+ when a < 1.0
128
+ 'vertical'
129
+ when a > 1.0
130
+ 'horizontal'
131
+ else
132
+ 'square'
133
+ end
134
+ end
135
+
136
+ def width(style_name='original')
137
+ geometry(style_name).width.to_i
138
+ end
139
+
140
+ def height(style_name='original')
141
+ geometry(style_name).height.to_i
142
+ end
143
+
144
+ def square?(style_name='original')
145
+ geometry(style_name).square?
146
+ end
147
+
148
+ def vertical?(style_name='original')
149
+ geometry(style_name).vertical?
150
+ end
151
+
152
+ def horizontal?(style_name='original')
153
+ geometry(style_name).horizontal?
154
+ end
155
+
156
+ def dimensions_known?
157
+ original_width? && original_height?
158
+ end
159
+
160
+ private
161
+
162
+ # at this point the file queue will not have been written
163
+ # but the upload should be in place. We read dimensions from the
164
+ # original file and calculate thumbnail dimensions later, on demand.
165
+
166
+ def read_dimensions
167
+ if image?
168
+ if file = asset.queued_for_write[:original]
169
+ geometry = Paperclip::Geometry.from_file(file)
170
+ self.original_width = geometry.width
171
+ self.original_height = geometry.height
172
+ self.original_extension = File.extname(file.path)
173
+ end
174
+ end
175
+ true
176
+ end
177
+
178
+ def assign_title
179
+ self.title = basename unless title?
180
+ end
181
+
182
+ def assign_uuid
183
+ self.uuid = UUIDTools::UUID.timestamp_create.to_s unless uuid?
184
+ end
185
+
186
+ class << self
187
+ def known_types
188
+ AssetType.known_types
189
+ end
190
+
191
+ # searching and pagination moved to the controller
192
+
193
+ def find_all_by_asset_types(asset_types, *args)
194
+ with_asset_types(asset_types) { find *args }
195
+ end
196
+
197
+ def count_with_asset_types(asset_types, *args)
198
+ with_asset_types(asset_types) { count *args }
199
+ end
200
+
201
+ def with_asset_types(asset_types, &block)
202
+ with_scope(:find => { :conditions => AssetType.conditions_for(asset_types) }, &block)
203
+ end
204
+ end
205
+
206
+ # called from AssetType to set type_condition? methods on Asset
207
+ def self.define_class_method(name, &block)
208
+ eigenclass.send :define_method, name, &block
209
+ end
210
+
211
+ # returns the return value of class << self block, which is self (as defined within that block)
212
+ def self.eigenclass
213
+ class << self; self; end
214
+ end
215
+
216
+ # for backwards compatibility
217
+ def self.thumbnail_sizes
218
+ AssetType.find(:image).paperclip_styles
219
+ end
220
+
221
+ def self.thumbnail_names
222
+ thumbnail_sizes.keys
223
+ end
224
+
225
+ # this is a convenience for image-pickers
226
+ def self.thumbnail_options
227
+ asset_sizes = thumbnail_sizes.collect{|k,v|
228
+ size_id = k
229
+ size_description = "#{k}: "
230
+ size_description << (v.is_a?(Array) ? v.join(' as ') : v)
231
+ [size_description, size_id]
232
+ }.sort_by{|pair| pair.last.to_s}
233
+ asset_sizes.unshift ['Original (as uploaded)', 'original']
234
+ asset_sizes
235
+ end
236
+
237
+ end