radiant-images-extension 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. data/.gitignore +1 -0
  2. data/LICENSE +19 -0
  3. data/README.md +41 -0
  4. data/Rakefile +141 -0
  5. data/VERSION +1 -0
  6. data/app/controllers/admin/images_controller.rb +50 -0
  7. data/app/models/image.rb +91 -0
  8. data/app/views/admin/images/_bottom.haml +13 -0
  9. data/app/views/admin/images/_fields.haml +22 -0
  10. data/app/views/admin/images/_fields_bottom.haml +10 -0
  11. data/app/views/admin/images/_fields_top.haml +7 -0
  12. data/app/views/admin/images/_image.haml +12 -0
  13. data/app/views/admin/images/edit.haml +14 -0
  14. data/app/views/admin/images/index.haml +16 -0
  15. data/app/views/admin/images/new.haml +12 -0
  16. data/app/views/admin/images/remove.haml +12 -0
  17. data/config/locales/en.yml +8 -0
  18. data/config/routes.rb +7 -0
  19. data/cucumber.yml +1 -0
  20. data/db/migrate/20100601042237_create_images.rb +22 -0
  21. data/db/migrate/20100602044124_add_position_to_images.rb +13 -0
  22. data/features/support/env.rb +16 -0
  23. data/features/support/paths.rb +14 -0
  24. data/images_extension.rb +53 -0
  25. data/lib/images/interface/admin/images.rb +37 -0
  26. data/lib/images/tags/image.rb +171 -0
  27. data/lib/tasks/images_extension_tasks.rake +77 -0
  28. data/public/images/extensions/images/missing_icon.png +0 -0
  29. data/public/images/extensions/images/missing_normal.png +0 -0
  30. data/public/images/extensions/images/missing_preview.png +0 -0
  31. data/public/javascripts/admin/extensions/images/edit.js +0 -0
  32. data/public/stylesheets/sass/admin/extensions/images/edit.sass +8 -0
  33. data/public/stylesheets/sass/admin/extensions/images/index.sass +103 -0
  34. data/radiant-images-extension.gemspec +99 -0
  35. data/spec/controllers/admin/images_controller_spec.rb +135 -0
  36. data/spec/datasets/images.rb +15 -0
  37. data/spec/lib/images/tags/image_spec.rb +240 -0
  38. data/spec/models/image_spec.rb +65 -0
  39. data/spec/spec.opts +4 -0
  40. data/spec/spec_helper.rb +22 -0
  41. metadata +191 -0
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .DS_Store
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 SquareTalent
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Radiant Images
2
+
3
+ Radiant Images is an IMAGE management tool, meant only to be useful to pages and extensions that need to require images.
4
+
5
+ ## Primary (only) Goals
6
+
7
+ ### Light Weight
8
+
9
+ > We're not replacing paperclipped, we're just building a simple image manager extension.
10
+
11
+ ### Uncomplicated
12
+
13
+ > People need to be able to look at the model and instantly know what it's doing, being able to do so means they can easily extend it
14
+
15
+ ### Easily Extendable
16
+
17
+ > Images is a base for things like galleries and shop, where they don't need additional assets
18
+
19
+ ### Strictly aws and paperclip
20
+
21
+ > We don't work with images locally because we use Heroku. So we're not going to give you the option to start locally
22
+
23
+ ### Migrate from paperclipped easily
24
+
25
+ > paperclipped is freakin' awesome, we use it and we need to be able to migrate the images over
26
+
27
+ rake radiant:extensions:images:migrate_from_paperclipped
28
+
29
+ ## Host Alias Settings
30
+
31
+ By default the images extension uses the following url for images:
32
+
33
+ http://s3.amazonaws.com/bucketname/images/name_of_image-style.(png|jpg|gif)
34
+
35
+ There is a radiant configuration option called s3.host_alias. By default it is blank, if you give it a value, the images extension will use the FQDN method to access your images. Setting your host alias to domain.name.com for example would produce a URL like this:
36
+
37
+ http://domain.name.com/images/name_of_image-style.(png|jpg|gif)
38
+
39
+ ## License
40
+
41
+ Radiant Images is licensed under the MIT standard license. See LICENSE for further information.
data/Rakefile ADDED
@@ -0,0 +1,141 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "radiant-images-extension"
5
+ gem.summary = 'Images Extension for Radiant CMS'
6
+ gem.description = 'Image Radiant Extension management tool, meant only to be useful to pages and extensions that need to require images.'
7
+ gem.email = "info@squaretalent.com"
8
+ gem.homepage = "http://github.com/squaretalent/radiant-images-extension"
9
+ gem.authors = ['squaretalent']
10
+ gem.add_dependency 'paperclip', '~> 2.3.1.1'
11
+ gem.add_dependency 'aws-s3', '>= 0.6.2'
12
+ gem.add_dependency 'acts_as_list', '>= 0.1.2'
13
+ gem.add_development_dependency 'rspec', '>= 1.3.0'
14
+ gem.add_development_dependency 'rr', '>= 1.0.0'
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. This is only required if you plan to package images as a gem."
19
+ end
20
+
21
+ # In rails 1.2, plugins aren't available in the path until they're loaded.
22
+ # Check to see if the rspec plugin is installed first and require
23
+ # it if it is. If not, use the gem version.
24
+
25
+ # Determine where the RSpec plugin is by loading the boot
26
+ unless defined? RADIANT_ROOT
27
+ ENV["RAILS_ENV"] = "test"
28
+ case
29
+ when ENV["RADIANT_ENV_FILE"]
30
+ require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
31
+ when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
32
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
33
+ else
34
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
35
+ end
36
+ end
37
+
38
+ require 'rake'
39
+ require 'rake/rdoctask'
40
+ require 'rake/testtask'
41
+
42
+ rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
43
+ $LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
44
+ require 'spec/rake/spectask'
45
+ require 'cucumber'
46
+ require 'cucumber/rake/task'
47
+
48
+ # Cleanup the RADIANT_ROOT constant so specs will load the environment
49
+ Object.send(:remove_const, :RADIANT_ROOT)
50
+
51
+ extension_root = File.expand_path(File.dirname(__FILE__))
52
+
53
+ task :default => :spec
54
+ task :stats => "spec:statsetup"
55
+
56
+ desc "Run all specs in spec directory"
57
+ Spec::Rake::SpecTask.new(:spec) do |t|
58
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
59
+ t.spec_files = FileList['spec/**/*_spec.rb']
60
+ end
61
+
62
+ task :features => 'spec:integration'
63
+
64
+ namespace :spec do
65
+ desc "Run all specs in spec directory with RCov"
66
+ Spec::Rake::SpecTask.new(:rcov) do |t|
67
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
68
+ t.spec_files = FileList['spec/**/*_spec.rb']
69
+ t.rcov = true
70
+ t.rcov_opts = ['--exclude', 'spec', '--rails']
71
+ end
72
+
73
+ desc "Print Specdoc for all specs"
74
+ Spec::Rake::SpecTask.new(:doc) do |t|
75
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
76
+ t.spec_files = FileList['spec/**/*_spec.rb']
77
+ end
78
+
79
+ [:models, :controllers, :views, :helpers].each do |sub|
80
+ desc "Run the specs under spec/#{sub}"
81
+ Spec::Rake::SpecTask.new(sub) do |t|
82
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
83
+ t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
84
+ end
85
+ end
86
+
87
+ desc "Run the Cucumber features"
88
+ Cucumber::Rake::Task.new(:integration) do |t|
89
+ t.fork = true
90
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
91
+ # t.feature_pattern = "#{extension_root}/features/**/*.feature"
92
+ t.profile = "default"
93
+ end
94
+
95
+ # Setup specs for stats
96
+ task :statsetup do
97
+ require 'code_statistics'
98
+ ::STATS_DIRECTORIES << %w(Model\ specs spec/models)
99
+ ::STATS_DIRECTORIES << %w(View\ specs spec/views)
100
+ ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
101
+ ::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
102
+ ::CodeStatistics::TEST_TYPES << "Model specs"
103
+ ::CodeStatistics::TEST_TYPES << "View specs"
104
+ ::CodeStatistics::TEST_TYPES << "Controller specs"
105
+ ::CodeStatistics::TEST_TYPES << "Helper specs"
106
+ ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
107
+ end
108
+
109
+ namespace :db do
110
+ namespace :fixtures do
111
+ desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
112
+ task :load => :environment do
113
+ require 'active_record/fixtures'
114
+ ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
115
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
116
+ Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ desc 'Generate documentation for the images extension.'
124
+ Rake::RDocTask.new(:rdoc) do |rdoc|
125
+ rdoc.rdoc_dir = 'rdoc'
126
+ rdoc.title = 'ImagesExtension'
127
+ rdoc.options << '--line-numbers' << '--inline-source'
128
+ rdoc.rdoc_files.include('README')
129
+ rdoc.rdoc_files.include('lib/**/*.rb')
130
+ end
131
+
132
+ # For extensions that are in transition
133
+ desc 'Test the images extension.'
134
+ Rake::TestTask.new(:test) do |t|
135
+ t.libs << 'lib'
136
+ t.pattern = 'test/**/*_test.rb'
137
+ t.verbose = true
138
+ end
139
+
140
+ # Load any custom rakefiles for extension
141
+ Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,50 @@
1
+ class Admin::ImagesController < Admin::ResourceController
2
+
3
+ before_filter :index_assets, :only => [ :index ]
4
+ before_filter :edit_assets, :only => [ :show, :edit ]
5
+ around_filter :rescue_exceptions, :only => [:create, :edit, :destroy]
6
+
7
+ # GET /admin/images
8
+ # GET /admin/images.js
9
+ # GET /admin/images.xml
10
+ # GET /admin/images.json AJAX and HTML
11
+ #----------------------------------------------------------------------------
12
+
13
+ def index
14
+ @images = Image.paginate :page => params[:page], :per_page => 20
15
+ end
16
+
17
+
18
+ def search
19
+ @images = Image.search params[:search], params[:p]
20
+
21
+ respond_to do |format|
22
+ format.html { render }
23
+ format.js { render @images }
24
+ format.xml { render :xml => @images.to_xml }
25
+ format.json { render :json => @images.to_json }
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def index_assets
32
+ include_javascript 'admin/extensions/images/index'
33
+ include_stylesheet 'admin/extensions/images/index'
34
+ end
35
+
36
+ def edit_assets
37
+ include_javascript 'admin/extensions/images/edit'
38
+ include_stylesheet 'admin/extensions/images/edit'
39
+ end
40
+
41
+ def rescue_exceptions
42
+ begin
43
+ yield
44
+ rescue AWS::S3::ResponseError => e
45
+ flash[:error] = e.to_s
46
+ redirect_to admin_images_url
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,91 @@
1
+ class Image < ActiveRecord::Base
2
+
3
+ belongs_to :created_by, :class_name => 'User'
4
+ belongs_to :updated_by, :class_name => 'User'
5
+
6
+ before_save :assign_title
7
+ validates_uniqueness_of :asset_file_name, :message => 'This file already exists', :allow_nil => true
8
+ validates_uniqueness_of :title
9
+
10
+ default_scope :order => 'position ASC'
11
+ acts_as_list
12
+
13
+ has_attached_file :asset,
14
+ :styles => lambda { Image.config_styles },
15
+ :whiny_thumbnails => false,
16
+ :default_url => '/images/extensions/images/missing_:style.png',
17
+
18
+ :storage => :s3,
19
+ :s3_credentials => {
20
+ :access_key_id => Radiant::Config['s3.key'],
21
+ :secret_access_key => Radiant::Config['s3.secret']
22
+ },
23
+ :bucket => Radiant::Config['s3.bucket'],
24
+ :path => Radiant::Config['s3.path']
25
+
26
+ validates_attachment_presence :asset
27
+ validates_attachment_content_type :asset, :content_type => ['image/jpeg', 'image/png', 'image/gif']
28
+
29
+ def assign_title
30
+ self.title = self.asset_file_name if title.blank?
31
+ end
32
+
33
+
34
+ # We need to ovveried the url method for our attachment so
35
+ # we can dynamically swap between aliased and non aliased domain names
36
+ module ::Paperclip
37
+ class Attachment
38
+
39
+ def url(style = :original, include_updated_timestamp = true, secure = false)
40
+ style = style.to_s
41
+ prefix = secure ? 'https://' : 'http://'
42
+ domain = Radiant::Config['s3.host_alias'].empty? ? 's3.amazonaws.com' : Radiant::Config['s3.host_alias']
43
+ bucket = Radiant::Config['s3.host_alias'].empty? ? '/' + Radiant::Config['s3.bucket'] : ''
44
+
45
+ url = prefix + domain + bucket + '/images/' + basename + '-' + style + '.' + extension
46
+ include_updated_timestamp && updated_at ? [url, updated_at].compact.join(url.include?("?") ? "&" : "?") : url
47
+ end
48
+
49
+ def basename
50
+ File.basename(instance.asset_file_name, ".*") if instance.asset_file_name
51
+ end
52
+
53
+ def extension
54
+ instance.asset_file_name.split('.').last.downcase if instance.asset_file_name
55
+ end
56
+
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ class << self
63
+ def search(search, page)
64
+ unless search.blank?
65
+ queries = []
66
+ queries << 'LOWER(title) LIKE (:term)'
67
+ queries << 'LOWER(caption) LIKE (:term)'
68
+ queries << 'LOWER(asset_file_name) LIKE (:term)'
69
+
70
+ sql = queries.join(' OR ')
71
+ @conditions = [sql, {:term => "%#{search.downcase}%" }]
72
+ else
73
+ @conditions = []
74
+ end
75
+
76
+ self.all :conditions => @conditions
77
+
78
+ end
79
+
80
+ def config_styles
81
+ styles = []
82
+
83
+ if Radiant::Config['images.styles']
84
+ styles = Radiant::Config['images.styles'].gsub(/\s+/,'').split(',')
85
+ styles = styles.collect{|s| s.split('=')}.inject({}) {|ha, (k, v)| ha[k.to_sym] = v; ha}
86
+ end
87
+ styles
88
+ end
89
+ end
90
+
91
+ end
@@ -0,0 +1,13 @@
1
+ %ul{ :style =>'float: left'}
2
+ - render_region :bottom do |bottom|
3
+ - bottom.create do
4
+ %li
5
+ = link_to image('plus') + " " + t("new_image"), new_admin_image_path
6
+ - bottom.search do
7
+ %li
8
+ - form_tag nil, :method => 'get' do
9
+ = text_field_tag 'search', params[:search], :type => 'search'
10
+ = observe_field 'search', :frequency => 2, :update => 'images', :url => { :controller => 'images', :action=> 'search' }, :method => 'get', :with => "'search=' + escape(value)"
11
+ - render_region :paginate do |paginate|
12
+ - paginate.pagination do
13
+ = will_paginate(@images)
@@ -0,0 +1,22 @@
1
+ - render_region :form do |form|
2
+ - form.title do
3
+ %p.title
4
+ = fields.label :title
5
+ = fields.text_field :title, :class => 'textbox'
6
+ - form.drawer do
7
+ .drawer
8
+ .drawer_contents#attributes
9
+ %table.fieldset
10
+ %tr
11
+ %th.label
12
+ = fields.label :caption
13
+ %td.field
14
+ = fields.text_field :caption, :class => 'textbox'
15
+ .drawer_handle
16
+ = link_to 'More', '#attributes', { :class => 'more toggle', :rel => 'toggle[attributes]' }
17
+ - form.upload do
18
+ %p.update
19
+ = fields.label :asset
20
+ = fields.file_field :asset
21
+ - form.popups do
22
+ - nil
@@ -0,0 +1,10 @@
1
+ - render_region :form_bottom do |form_bottom|
2
+ - form_bottom.buttons do
3
+ %p.buttons
4
+ = save_model_button(@image)
5
+ = save_model_and_continue_editing_button(@image)
6
+ = t('or')
7
+ = link_to t('cancel'), admin_images_url
8
+
9
+ - form_bottom.timestamps do
10
+ = updated_stamp @image
@@ -0,0 +1,7 @@
1
+ - render_region :form_top do |form_top|
2
+ - form_top.asset_image do
3
+ - unless @image.new_record?
4
+ = link_to image_tag(@image.asset.url(:preview)), @image.asset.url(:original)
5
+ - @image.asset.styles.each do |style, attrs|
6
+ - unless style.to_sym == :preview
7
+ = link_to style.to_s, @image.asset.url(style.to_sym)
@@ -0,0 +1,12 @@
1
+ %li.image{:id => "image#{image.id}", :'data-id' => image.id}
2
+ .attributes
3
+ - render_region :attributes do |attributes|
4
+ - attributes.thumbnail do
5
+ .image.attribute
6
+ %a{ :href => edit_admin_image_path(image), :title => image.title }
7
+ %img.icon{ :src => image.asset.url(:icon) }
8
+ - attributes.title do
9
+ %span.title.attribute= link_to image.title, edit_admin_image_path(image)
10
+ - attributes.modify do
11
+ .modify.attribute
12
+ %span.remove= link_to t('remove'), remove_admin_image_path(image)
@@ -0,0 +1,14 @@
1
+ - @page_title = @image.title.titleize + ' - ' + default_page_title
2
+
3
+ - render_region :top do |top|
4
+ - top.title do
5
+ %h1 Edit Image
6
+
7
+ - form_for :image, @image, :url => admin_image_path(@image), :html => {:method => :put, :multipart => true, :id => 'edit_image', 'data-onsubmit_status'=>"Saving Changes&#8230;"} do |fields|
8
+ #asset
9
+ = render :partial => 'fields_top', :locals => { :fields => fields }
10
+ #fields
11
+ = render :partial => 'fields', :locals => { :fields => fields }
12
+
13
+ #fields_bottom
14
+ = render :partial => 'fields_bottom'
@@ -0,0 +1,16 @@
1
+ - @page_title = t('images') + ' - ' + default_page_title
2
+
3
+ .outset
4
+
5
+ #images_map
6
+
7
+ #images_headings
8
+ %h2.images Image
9
+
10
+ %h2.modify Modify
11
+
12
+ %ul#images
13
+ = render @images
14
+
15
+ #actions
16
+ = render 'bottom'