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.
- data/.gitignore +1 -0
- data/LICENSE +19 -0
- data/README.md +41 -0
- data/Rakefile +141 -0
- data/VERSION +1 -0
- data/app/controllers/admin/images_controller.rb +50 -0
- data/app/models/image.rb +91 -0
- data/app/views/admin/images/_bottom.haml +13 -0
- data/app/views/admin/images/_fields.haml +22 -0
- data/app/views/admin/images/_fields_bottom.haml +10 -0
- data/app/views/admin/images/_fields_top.haml +7 -0
- data/app/views/admin/images/_image.haml +12 -0
- data/app/views/admin/images/edit.haml +14 -0
- data/app/views/admin/images/index.haml +16 -0
- data/app/views/admin/images/new.haml +12 -0
- data/app/views/admin/images/remove.haml +12 -0
- data/config/locales/en.yml +8 -0
- data/config/routes.rb +7 -0
- data/cucumber.yml +1 -0
- data/db/migrate/20100601042237_create_images.rb +22 -0
- data/db/migrate/20100602044124_add_position_to_images.rb +13 -0
- data/features/support/env.rb +16 -0
- data/features/support/paths.rb +14 -0
- data/images_extension.rb +53 -0
- data/lib/images/interface/admin/images.rb +37 -0
- data/lib/images/tags/image.rb +171 -0
- data/lib/tasks/images_extension_tasks.rake +77 -0
- data/public/images/extensions/images/missing_icon.png +0 -0
- data/public/images/extensions/images/missing_normal.png +0 -0
- data/public/images/extensions/images/missing_preview.png +0 -0
- data/public/javascripts/admin/extensions/images/edit.js +0 -0
- data/public/stylesheets/sass/admin/extensions/images/edit.sass +8 -0
- data/public/stylesheets/sass/admin/extensions/images/index.sass +103 -0
- data/radiant-images-extension.gemspec +99 -0
- data/spec/controllers/admin/images_controller_spec.rb +135 -0
- data/spec/datasets/images.rb +15 -0
- data/spec/lib/images/tags/image_spec.rb +240 -0
- data/spec/models/image_spec.rb +65 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +22 -0
- metadata +191 -0
@@ -0,0 +1,12 @@
|
|
1
|
+
- @page_title = 'New Image - ' + default_page_title
|
2
|
+
|
3
|
+
- render_region :top do |top|
|
4
|
+
- top.title do
|
5
|
+
%h1 New Image
|
6
|
+
|
7
|
+
- form_for :image, @image, :url => admin_images_path, :html => {:multipart => true, :id => 'new_image', 'data-onsubmit_status'=>"Creating Image…"} do |fields|
|
8
|
+
#fields
|
9
|
+
= render :partial => 'fields', :locals => { :fields => fields }
|
10
|
+
|
11
|
+
#fields_bottom
|
12
|
+
= render :partial => 'fields_bottom'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
%h1
|
2
|
+
= t('remove_image')
|
3
|
+
|
4
|
+
%p
|
5
|
+
= t('text.remove_image.warning')
|
6
|
+
|
7
|
+
- form_for [:admin, @image.becomes(Image)], :html => {:method => :delete, 'data-onsubmit_status'=>"Removing Image…"} do
|
8
|
+
|
9
|
+
%p.buttons
|
10
|
+
%input.button{:type=>"submit", :value => t('delete_image') }/
|
11
|
+
= t('or')
|
12
|
+
= link_to t('cancel'), admin_images_path
|
data/config/routes.rb
ADDED
data/cucumber.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
default: --format progress features --tags ~@proposed,~@in_progress
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class CreateImages < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :images do |t|
|
4
|
+
t.string :title
|
5
|
+
t.string :caption
|
6
|
+
|
7
|
+
t.string :asset_file_name
|
8
|
+
t.string :asset_content_type
|
9
|
+
t.string :asset_file_size
|
10
|
+
|
11
|
+
t.integer :created_by
|
12
|
+
t.integer :updated_by
|
13
|
+
t.datetime :created_at
|
14
|
+
t.datetime :updated_at
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.down
|
20
|
+
drop_table :images
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class AddPositionToImages < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :images, :position, :integer
|
4
|
+
|
5
|
+
Image.all.each_with_index do |image, i|
|
6
|
+
image.update_attribute('position', i+1)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.down
|
11
|
+
remove_column :images, :position
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Sets up the Rails environment for Cucumber
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
# Extension root
|
4
|
+
extension_env = File.expand_path(File.dirname(__FILE__) + '/../../../../../config/environment')
|
5
|
+
require extension_env+'.rb'
|
6
|
+
|
7
|
+
Dir.glob(File.join(RADIANT_ROOT, "features", "**", "*.rb")).each {|step| require step}
|
8
|
+
|
9
|
+
Cucumber::Rails::World.class_eval do
|
10
|
+
include Dataset
|
11
|
+
datasets_directory "#{RADIANT_ROOT}/spec/datasets"
|
12
|
+
Dataset::Resolver.default = Dataset::DirectoryResolver.new("#{RADIANT_ROOT}/spec/datasets", File.dirname(__FILE__) + '/../../spec/datasets', File.dirname(__FILE__) + '/../datasets')
|
13
|
+
self.datasets_database_dump_path = "#{Rails.root}/tmp/dataset"
|
14
|
+
|
15
|
+
# dataset :images
|
16
|
+
end
|
data/images_extension.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Uncomment this if you reference any of your controllers in activate
|
2
|
+
# require_dependency 'application_controller'
|
3
|
+
|
4
|
+
class ImagesExtension < Radiant::Extension
|
5
|
+
version "0.1"
|
6
|
+
description "Images stores images on s3"
|
7
|
+
url "http://github.com/squaretalent/radiant-images-extension"
|
8
|
+
|
9
|
+
extension_config do |config|
|
10
|
+
config.gem 'paperclip', :version => '~> 2.3.1.1'
|
11
|
+
config.gem 'aws-s3', :version => '>= 0.6.2', :lib => 'aws/s3'
|
12
|
+
config.gem 'acts_as_list', :version => '>= 0.1.2'
|
13
|
+
|
14
|
+
if RAILS_ENV == :test
|
15
|
+
config.gem 'rr', :version => '>= 1.0.0'
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def activate
|
21
|
+
|
22
|
+
# require the settings extension to be loaded
|
23
|
+
unless Radiant::Extension.descendants.any? { |extension| extension.extension_name == 'Settings' }
|
24
|
+
warn 'Error: The Images extension requires the Settings extension to be installed.'
|
25
|
+
warn 'Either install the Settings extension or remove Images.'
|
26
|
+
exit(1)
|
27
|
+
end
|
28
|
+
|
29
|
+
unless defined? admin.image
|
30
|
+
Radiant::AdminUI.send :include, Images::Interface::Admin::Images
|
31
|
+
admin.image = Radiant::AdminUI.load_default_image_regions
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
Page.send :include, Images::Tags::Image
|
36
|
+
|
37
|
+
UserActionObserver.instance.send :add_observer!, Image
|
38
|
+
|
39
|
+
tab 'Content' do
|
40
|
+
add_item 'Images', '/admin/images', :after => 'Pages'
|
41
|
+
end
|
42
|
+
|
43
|
+
Radiant::Config['images.styles'] ||= "icon=45x45#,preview=200x200#,normal=640x640#"
|
44
|
+
Radiant::Config['images.default'] ||= "original"
|
45
|
+
|
46
|
+
Radiant::Config['s3.host_alias'] ||= ""
|
47
|
+
Radiant::Config['s3.key'] ||= "set"
|
48
|
+
Radiant::Config['s3.secret'] ||= "set"
|
49
|
+
Radiant::Config['s3.bucket'] ||= "fs.domain.com"
|
50
|
+
Radiant::Config['s3.path'] ||= ":class/:basename-:style.:extension"
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Images
|
2
|
+
module Interface
|
3
|
+
module Admin
|
4
|
+
module Images
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.class_eval do
|
8
|
+
|
9
|
+
attr_accessor :image
|
10
|
+
alias_method :images, :image
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def load_default_image_regions
|
15
|
+
returning OpenStruct.new do |image|
|
16
|
+
image.edit = Radiant::AdminUI::RegionSet.new do |edit|
|
17
|
+
edit.top.concat %w{ title }
|
18
|
+
edit.form_top.concat %w{ asset_image }
|
19
|
+
edit.form.concat %w{ title drawer upload popups }
|
20
|
+
edit.form_bottom.concat %w{ buttons timestamps }
|
21
|
+
end
|
22
|
+
image.new = image.edit
|
23
|
+
image.index = Radiant::AdminUI::RegionSet.new do |index|
|
24
|
+
index.attributes.concat %w{thumbnail title modify }
|
25
|
+
index.bottom.concat %w{ create search }
|
26
|
+
index.paginate.concat %w{ pagination }
|
27
|
+
end
|
28
|
+
image.searchearch = image.index
|
29
|
+
image.remove = image.index
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module Images
|
2
|
+
module Tags
|
3
|
+
module Image
|
4
|
+
include Radiant::Taggable
|
5
|
+
|
6
|
+
class TagError < StandardError; end
|
7
|
+
|
8
|
+
desc %{
|
9
|
+
The namespace for referencing images. You may specify the title
|
10
|
+
attribute for this tag to use only images with the specified title.
|
11
|
+
|
12
|
+
*Usage:*
|
13
|
+
<pre><code><r:images [title="image_title"]>...</r:images></code></pre>
|
14
|
+
}
|
15
|
+
tag 'images' do |tag|
|
16
|
+
tag.locals.image = ::Image.find_by_title(tag.attr['title']) || ::Image.find(tag.attr['id']) unless tag.attr.empty?
|
17
|
+
tag.expand
|
18
|
+
end
|
19
|
+
|
20
|
+
desc %{
|
21
|
+
Goes through each of the available images.
|
22
|
+
Use the limit and offset attributes to render a specific number of images.
|
23
|
+
Use the by and order attributes to control the order of images.
|
24
|
+
|
25
|
+
*Usage:*
|
26
|
+
<pre><code><r:images:each [limit=0] [offset=0] [order="asc|desc"] [by="position|title|..."]>...</r:images:each></code></pre>
|
27
|
+
}
|
28
|
+
tag 'images:each' do |tag|
|
29
|
+
options = tag.attr.dup
|
30
|
+
result = []
|
31
|
+
images = ::Image.find(:all, images_find_options(tag))
|
32
|
+
tag.locals.images = images
|
33
|
+
images.each do |image|
|
34
|
+
tag.locals.image = image
|
35
|
+
result << tag.expand
|
36
|
+
end
|
37
|
+
result
|
38
|
+
end
|
39
|
+
|
40
|
+
desc %{
|
41
|
+
Renders the first image.
|
42
|
+
|
43
|
+
*Usage:*
|
44
|
+
<pre><code><r:images:first>...</r:images:first></code></pre>
|
45
|
+
}
|
46
|
+
tag 'images:first' do |tag|
|
47
|
+
if first = ::Image.first
|
48
|
+
tag.locals.image = first
|
49
|
+
tag.expand
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
desc %{
|
54
|
+
Renders the contained elements only if the current image is the first.
|
55
|
+
|
56
|
+
*Usage:*
|
57
|
+
<pre><code><r:if_first>...</r:if_first></code></pre>
|
58
|
+
}
|
59
|
+
tag 'images:if_first' do |tag|
|
60
|
+
images = tag.locals.images
|
61
|
+
image = tag.locals.image
|
62
|
+
if image == images.first
|
63
|
+
tag.expand
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
desc %{
|
68
|
+
Renders the contained elements only if the current image is not the first.
|
69
|
+
|
70
|
+
*Usage:*
|
71
|
+
<pre><code><r:unless_first>...</r:unless_first></code></pre>
|
72
|
+
}
|
73
|
+
tag 'images:unless_first' do |tag|
|
74
|
+
images = tag.locals.images
|
75
|
+
image = tag.locals.image
|
76
|
+
if image != images.first
|
77
|
+
tag.expand
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
desc %{
|
82
|
+
Renders the contained elements only if the current contextual page has one or
|
83
|
+
more image. The min_count attribute specifies the minimum number of required
|
84
|
+
images.
|
85
|
+
|
86
|
+
*Usage:*
|
87
|
+
<pre><code><r:if_images [min_count="n"]>...</r:if_images></code></pre>
|
88
|
+
}
|
89
|
+
tag 'if_images' do |tag|
|
90
|
+
count = tag.attr['min_count'] && tag.attr['min_count'].to_i || 1
|
91
|
+
images = ::Image.count
|
92
|
+
tag.expand if images >= count
|
93
|
+
end
|
94
|
+
|
95
|
+
desc %{
|
96
|
+
Renders the contained elements only if the current contextual page does not
|
97
|
+
have one or more image. The min_count attribute specifies the minimum number
|
98
|
+
of required images.
|
99
|
+
|
100
|
+
*Usage:*
|
101
|
+
<pre><code><r:if_images [min_count="n"]>...</r:if_images></code></pre>
|
102
|
+
}
|
103
|
+
tag 'unless_images' do |tag|
|
104
|
+
count = tag.attr['min_count'] && tag.attr['min_count'].to_i || 1
|
105
|
+
images = ::Image.count
|
106
|
+
tag.expand unless images >= count
|
107
|
+
end
|
108
|
+
|
109
|
+
desc %{
|
110
|
+
Outputs the full URL of the image including the filename. Specify the style
|
111
|
+
using the style option.
|
112
|
+
}
|
113
|
+
tag 'images:url' do |tag|
|
114
|
+
style = tag.attr['style'] || :original
|
115
|
+
image, options = image_and_options(tag)
|
116
|
+
image.asset.url(style, false) rescue nil
|
117
|
+
end
|
118
|
+
|
119
|
+
desc %{
|
120
|
+
Outputs the title of the current image
|
121
|
+
}
|
122
|
+
tag 'images:title' do |tag|
|
123
|
+
image, option = image_and_options(tag)
|
124
|
+
image.title rescue nil
|
125
|
+
end
|
126
|
+
|
127
|
+
desc %{
|
128
|
+
Outputs the image tag for the current image. Use the size option to
|
129
|
+
specify which size version of the image is to be used. Use alt to
|
130
|
+
specify alt text.
|
131
|
+
|
132
|
+
*Usage:*
|
133
|
+
<pre><code><r:images:tag [title="image_title"] [size="icon|original"] [alt="alt_text"]></code></pre>
|
134
|
+
}
|
135
|
+
tag 'images:tag' do |tag|
|
136
|
+
image, options = image_and_options(tag)
|
137
|
+
size = options['size'] ? options.delete('size') : 'original'
|
138
|
+
alt = " alt=\"#{image.title}\"" unless tag.attr['alt'] rescue nil
|
139
|
+
attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
|
140
|
+
attributes << alt unless alt.nil?
|
141
|
+
url = image.asset.url size
|
142
|
+
%{<img src=\"#{url}\" #{attributes unless attributes.empty?} />} rescue nil
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
private
|
147
|
+
def image_and_options(tag)
|
148
|
+
options = tag.attr.dup
|
149
|
+
[find_image(tag, options), options]
|
150
|
+
end
|
151
|
+
|
152
|
+
def find_image(tag, options)
|
153
|
+
raise TagError, "'title' attribute required" unless title = options.delete('title') or id = options.delete('id') or tag.locals.image
|
154
|
+
tag.locals.image || ::Image.find_by_title(title) || ::Image.find(id)
|
155
|
+
end
|
156
|
+
|
157
|
+
def images_find_options(tag)
|
158
|
+
attr = tag.attr.symbolize_keys
|
159
|
+
by = attr[:by] || 'position'
|
160
|
+
order = attr[:order] || 'asc'
|
161
|
+
|
162
|
+
options = {
|
163
|
+
:order => "#{by} #{order}",
|
164
|
+
:limit => attr[:limit] || nil,
|
165
|
+
:offset => attr[:offset] || nil
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
namespace :radiant do
|
2
|
+
namespace :extensions do
|
3
|
+
namespace :images do
|
4
|
+
|
5
|
+
desc "Runs the migration of the Images extension"
|
6
|
+
task :migrate => :environment do
|
7
|
+
require 'radiant/extension_migrator'
|
8
|
+
if ENV["VERSION"]
|
9
|
+
ImagesExtension.migrator.migrate(ENV["VERSION"].to_i)
|
10
|
+
Rake::Task['db:schema:dump'].invoke
|
11
|
+
else
|
12
|
+
ImagesExtension.migrator.migrate
|
13
|
+
Rake::Task['db:schema:dump'].invoke
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Migrates from Paperclipped to Images"
|
18
|
+
task :migrate_from_paperclipped => :environment do
|
19
|
+
Asset.all.each do |asset|
|
20
|
+
if asset.asset_type.name == :image
|
21
|
+
Image.create({
|
22
|
+
:title => asset.title,
|
23
|
+
:asset_file_name => asset.asset_file_name,
|
24
|
+
:asset_content_type => asset.asset_content_type,
|
25
|
+
:asset_file_size => asset.asset_file_size
|
26
|
+
})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Radiant::Config['s3.bucket'] = Radiant::Config['assets.s3.bucket']
|
31
|
+
Radiant::Config['s3.key'] = Radiant::Config['assets.s3.key']
|
32
|
+
Radiant::Config['s3.secret'] = Radiant::Config['assets.s3.secret']
|
33
|
+
Radiant::Config['s3.path'] = Radiant::Config['assets.s3.path'].gsub(':class', 'assets')
|
34
|
+
|
35
|
+
ENV['CLASS'] = 'Image'
|
36
|
+
Rake::Task['paperclip:refresh:thumbnails'].invoke
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Copies public assets of the Images to the instance public/ directory."
|
40
|
+
task :update => :environment do
|
41
|
+
is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
|
42
|
+
puts "Copying assets from ImagesExtension"
|
43
|
+
Dir[ImagesExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
|
44
|
+
path = file.sub(ImagesExtension.root, '')
|
45
|
+
directory = File.dirname(path)
|
46
|
+
mkdir_p RAILS_ROOT + directory, :verbose => false
|
47
|
+
cp file, RAILS_ROOT + path, :verbose => false
|
48
|
+
end
|
49
|
+
unless ImagesExtension.root.starts_with? RAILS_ROOT # don't need to copy vendored tasks
|
50
|
+
puts "Copying rake tasks from ImagesExtension"
|
51
|
+
local_tasks_path = File.join(RAILS_ROOT, %w(lib tasks))
|
52
|
+
mkdir_p local_tasks_path, :verbose => false
|
53
|
+
Dir[File.join ImagesExtension.root, %w(lib tasks *.rake)].each do |file|
|
54
|
+
cp file, local_tasks_path, :verbose => false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Syncs all available translations for this ext to the English ext master"
|
60
|
+
task :sync => :environment do
|
61
|
+
# The main translation root, basically where English is kept
|
62
|
+
language_root = ImagesExtension.root + "/config/locales"
|
63
|
+
words = TranslationSupport.get_translation_keys(language_root)
|
64
|
+
|
65
|
+
Dir["#{language_root}/*.yml"].each do |filename|
|
66
|
+
next if filename.match('_available_tags')
|
67
|
+
basename = File.basename(filename, '.yml')
|
68
|
+
puts "Syncing #{basename}"
|
69
|
+
(comments, other) = TranslationSupport.read_file(filename, basename)
|
70
|
+
words.each { |k,v| other[k] ||= words[k] } # Initializing hash variable as empty if it does not exist
|
71
|
+
other.delete_if { |k,v| !words[k] } # Remove if not defined in en.yml
|
72
|
+
TranslationSupport.write_file(filename, basename, comments, other)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|