BBenezech-papermill 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 +5 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +62 -0
- data/Rakefile +37 -0
- data/VERSION +1 -0
- data/app/controllers/papermill_controller.rb +80 -0
- data/app/views/papermill/_asset.html.erb +11 -0
- data/app/views/papermill/_raw_asset.html.erb +1 -0
- data/app/views/papermill/_thumbnail_asset.html.erb +6 -0
- data/config/locale/papermill.yml +30 -0
- data/config/routes.rb +4 -0
- data/generators/papermill/USAGE +3 -0
- data/generators/papermill/papermill_generator.rb +16 -0
- data/generators/papermill/templates/migrate/papermill_migration.rb.erb +22 -0
- data/init.rb +10 -0
- data/install.rb +7 -0
- data/lib/core_extensions.rb +25 -0
- data/lib/papermill.rb +4 -0
- data/lib/papermill/form_builder.rb +91 -0
- data/lib/papermill/papermill_asset.rb +67 -0
- data/lib/papermill/papermill_helper.rb +35 -0
- data/lib/papermill/papermill_module.rb +182 -0
- data/papermill.gemspec +77 -0
- data/public/flashs/swfupload.swf +0 -0
- data/public/images/papermill/background.png +0 -0
- data/public/images/papermill/container-background.jpg +0 -0
- data/public/images/papermill/delete.png +0 -0
- data/public/images/papermill/upload-blank.png +0 -0
- data/public/images/papermill/upload.png +0 -0
- data/public/javascripts/papermill.js +89 -0
- data/public/stylesheets/papermill.css +33 -0
- data/tasks/papermill_tasks.rake +1 -0
- data/test/papermill_test.rb +8 -0
- data/test/test_helper.rb +3 -0
- data/uninstall.rb +1 -0
- metadata +92 -0
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 [name of plugin creator]
|
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.rdoc
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
= Papermill
|
2
|
+
|
3
|
+
Asset management made easy.. Painfully easy.
|
4
|
+
Try the demo to see for yourself.
|
5
|
+
|
6
|
+
See papermill_module.rb for a complete list of available options.
|
7
|
+
These options can be application wide, for a class, or set at the last moment for the helper.
|
8
|
+
|
9
|
+
In your model:
|
10
|
+
|
11
|
+
papermill :assets
|
12
|
+
|
13
|
+
In your layout:
|
14
|
+
|
15
|
+
<%= papermill_stylesheet_tag %>
|
16
|
+
<%= papermill_javascript_tag :with_jquery => true %>
|
17
|
+
|
18
|
+
In your edit form:
|
19
|
+
|
20
|
+
f.images_upload(:my_image_gallery)
|
21
|
+
f.image_upload(:header_image)
|
22
|
+
|
23
|
+
Finally, in your views:
|
24
|
+
|
25
|
+
# Some template image :
|
26
|
+
<%= image_tag @article.assets(:header_image).first.url("800x>") %>
|
27
|
+
|
28
|
+
# Some image gallery:
|
29
|
+
<ul>
|
30
|
+
<% @article.assets(:my_image_gallery).each do |image| %>
|
31
|
+
<li><%= link_to(image_tag(image.url("100x100>")), image.url) %></li>
|
32
|
+
<% end %>
|
33
|
+
</ul>
|
34
|
+
|
35
|
+
Also see http://gist.github.com/177714.txt to get up-to-date installation steps.
|
36
|
+
See the API here http://rdoc.info/projects/BBenezech/papermill
|
37
|
+
|
38
|
+
== Word of caution:
|
39
|
+
|
40
|
+
Beta.
|
41
|
+
|
42
|
+
This is xNIX only (system("rm ...")).
|
43
|
+
|
44
|
+
You'll need rails 2.3, since this is an engine. Anyway, copying the controller/view/routes to your project will make it work on an older version of rails.
|
45
|
+
|
46
|
+
You'll need rails 2.2, since their are calls to I18n.t. But it shouldn't be too hard to work-around either.
|
47
|
+
|
48
|
+
== Usage :
|
49
|
+
|
50
|
+
=== Demo :
|
51
|
+
|
52
|
+
You can use the custom template generator to get an example application up and running in no time.
|
53
|
+
|
54
|
+
rails -m http://gist.github.com/177714.txt papermill-example
|
55
|
+
|
56
|
+
=== Translation:
|
57
|
+
|
58
|
+
Papermill is fully Rails 2.2 I18n-able.
|
59
|
+
|
60
|
+
Copy config/locale/papermill.yml to your root config/locale folder to modify any wording in a any locale.
|
61
|
+
|
62
|
+
Copyright (c) 2009 Benoit Bénézech, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the papermill plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.libs << 'test'
|
12
|
+
t.pattern = 'test/**/*_test.rb'
|
13
|
+
t.verbose = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generate documentation for the papermill plugin.'
|
17
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'Papermill'
|
20
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
21
|
+
rdoc.rdoc_files.include('README')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
require 'jeweler'
|
27
|
+
Jeweler::Tasks.new do |gemspec|
|
28
|
+
gemspec.name = "papermill"
|
29
|
+
gemspec.summary = "Paperclip wrapper"
|
30
|
+
gemspec.description = "Paperclip wrapper"
|
31
|
+
gemspec.email = "benoit.benezech@gmail.com"
|
32
|
+
gemspec.homepage = "http://github.com/BBenezech/papermill"
|
33
|
+
gemspec.authors = ["Benoit Bénézech"]
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
37
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class PapermillController < ApplicationController
|
2
|
+
|
3
|
+
skip_before_filter :verify_authenticity_token
|
4
|
+
|
5
|
+
def show
|
6
|
+
begin
|
7
|
+
if Papermill::PAPERMILL_DEFAULTS[:alias_only]
|
8
|
+
style = Papermill::PAPERMILL_DEFAULTS[:aliases][params[:style]]
|
9
|
+
else
|
10
|
+
style = Papermill::PAPERMILL_DEFAULTS[:aliases][params[:style]] || params[:style]
|
11
|
+
end
|
12
|
+
raise unless style
|
13
|
+
asset = PapermillAsset.find(params[:id])
|
14
|
+
temp_thumbnail = Paperclip::Thumbnail.make(asset_file = asset.file, style)
|
15
|
+
new_parent_folder_path = File.dirname(new_image_path = asset_file.path(params[:style]))
|
16
|
+
FileUtils.mkdir_p new_parent_folder_path unless File.exists? new_parent_folder_path
|
17
|
+
FileUtils.cp temp_thumbnail.path, new_image_path
|
18
|
+
redirect_to asset.url(params[:style])
|
19
|
+
rescue
|
20
|
+
render :text => t("not-processed", :scope => "papermill"), :status => "500"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy
|
25
|
+
begin
|
26
|
+
@asset = PapermillAsset.find(params[:id])
|
27
|
+
render :update do |page|
|
28
|
+
if @asset.destroy
|
29
|
+
page << "jQuery('#papermill_asset_#{params[:id]}').remove()"
|
30
|
+
else
|
31
|
+
page << "jQuery('#papermill_asset_#{params[:id]}').show()"
|
32
|
+
message = t("not-deleted", :ressource => @asset.name, :scope => "papermill")
|
33
|
+
page << %{ notify("#{message}", error) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
rescue ActiveRecord::RecordNotFound
|
37
|
+
render :update do |page|
|
38
|
+
page << "jQuery('#papermill_asset_#{params[:id]}').remove()"
|
39
|
+
message = t("not-found", :ressource => params[:id].to_s, :scope => "papermill")
|
40
|
+
page << %{ notify("#{message}", "warning") }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def update
|
46
|
+
@asset = PapermillAsset.find params[:id]
|
47
|
+
@asset.update(params)
|
48
|
+
render :update do |page|
|
49
|
+
message = t("updated", :ressource => @asset.name, :scope => "papermill")
|
50
|
+
page << %{ notify("#{message}", "notice") }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def edit
|
55
|
+
@asset = PapermillAsset.find params[:id]
|
56
|
+
end
|
57
|
+
|
58
|
+
def create
|
59
|
+
params[:assetable_type] = params[:assetable_type].camelize
|
60
|
+
asset_class = params[:assetable_type].constantize.papermill_associations[params[:association].to_sym][:class]
|
61
|
+
params[:swfupload_file] = params.delete(:Filedata)
|
62
|
+
@old_asset = asset_class.find(:first, :conditions => {:assetable_key => params[:assetable_key].to_s, :assetable_type => params[:assetable_type], :assetable_id => params[:assetable_id]}) unless params[:gallery]
|
63
|
+
@asset = asset_class.new(params.reject{|key, value| !(PapermillAsset.columns.map(&:name)+["swfupload_file"]).include?(key.to_s)})
|
64
|
+
|
65
|
+
if @asset.save
|
66
|
+
@old_asset.destroy if @old_asset
|
67
|
+
render :partial => "papermill/asset", :object => @asset, :locals => {:thumbnail => params[:thumbnail], :gallery => params[:gallery], :thumbnail_style => params[:thumbnail_style]}
|
68
|
+
else
|
69
|
+
message = t("not-created", :scope => "papermill")
|
70
|
+
render :text => message, :status => "500"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def sort
|
75
|
+
params[:papermill_asset].each_with_index do |id, index|
|
76
|
+
PapermillAsset.find(id).update_attribute(:position, index + 1)
|
77
|
+
end
|
78
|
+
render :nothing => true
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%- dom_id = dom_id(asset) -%>
|
2
|
+
<%- delete_link = %{<a onclick="if(confirm('#{escape_javascript I18n.t("delete-confirmation", :scope => :papermill, :resource => asset.name)}')){ $.ajax({async:true, beforeSend:function(request){$('##{dom_id}').hide();}, dataType:'script', error:function(request){$('##{dom_id}').show();}, type:'delete', url:'#{papermill_url(asset)}'})}; return false;" href="#" class="delete"><img title="#{escape_javascript t("delete", :scope => "papermill", :ressource => asset.name)}" src="/images/papermill/delete.png" alt="delete"/></a>} %>
|
3
|
+
|
4
|
+
<li id="<%= dom_id %>" rel="<%= edit_papermill_url(asset) %>" title="<%= t("#{thumbnail_style ? "thumbnail-" : ""}edit-title", :scope => "papermill", :ressource => asset.name) %>">
|
5
|
+
<%= delete_link %>
|
6
|
+
<%- if thumbnail_style -%>
|
7
|
+
<%= render :partial => "papermill/thumbnail_asset", :object => asset, :locals => {:thumbnail_style => thumbnail_style} %>
|
8
|
+
<%- else -%>
|
9
|
+
<%= render :partial => "papermill/raw_asset", :object => asset %>
|
10
|
+
<%- end -%>
|
11
|
+
</li>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= link_to(raw_asset.name, raw_asset.url, :class => "name") -%>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<% if thumbnail_asset.image? %>
|
2
|
+
<span class="image"><%= image_tag(thumbnail_asset.url(thumbnail_style)) %></span>
|
3
|
+
<% else %>
|
4
|
+
<span class="name" title="<%= thumbnail_asset.name %>"><%= truncate(thumbnail_asset.name, :length => 15) %></span>
|
5
|
+
<span class="infos"><%= thumbnail_asset.content_type[1] %></span>
|
6
|
+
<% end %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
en:
|
2
|
+
papermill:
|
3
|
+
not-processed: "Error/ressource not processed"
|
4
|
+
updated: "{{ressource}} updated"
|
5
|
+
not-deleted: "{{ressource}} could not be deleted"
|
6
|
+
not-created: "Ressource could not be created"
|
7
|
+
not-found: "Asset #{{ressource}} not found"
|
8
|
+
edit-title: "" # You can use {{ressource}}
|
9
|
+
thumbnail-edit-title: ""
|
10
|
+
upload-button-wording: "Upload..."
|
11
|
+
delete: "Remove {{ressource}}"
|
12
|
+
delete-confirmation: "Delete '{{resource}}'?"
|
13
|
+
SWFUPLOAD_PENDING: "Pending..."
|
14
|
+
SWFUPLOAD_LOADING: "Loading..."
|
15
|
+
SWFUPLOAD_ERROR: "Something happened while loading" # + " <file_name> (<swfupload error message> [<error code>])"
|
16
|
+
fr:
|
17
|
+
papermill:
|
18
|
+
not-processed: "Erreur/ressource non trouvée"
|
19
|
+
updated: "{{ressource}} mise à jour"
|
20
|
+
not-deleted: "{{ressource}} n'a pas pu être supprimée"
|
21
|
+
not-created: "La ressource n'a pas pu être créée"
|
22
|
+
not-found: "Asset #{{ressource}} non trouvé"
|
23
|
+
edit-title: ""
|
24
|
+
thumbnail-edit-title: ""
|
25
|
+
upload-button-wording: "Charger.."
|
26
|
+
delete: "Supprimer {{ressource}}"
|
27
|
+
delete-confirmation: "Êtes-vous sûr de vouloir supprimer '{{resource}}' ?"
|
28
|
+
SWFUPLOAD_PENDING: "En attente..."
|
29
|
+
SWFUPLOAD_LOADING: "Chargement..."
|
30
|
+
SWFUPLOAD_ERROR: "Une erreur est survenue pendant le chargement de"
|
data/config/routes.rb
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
map.resources :papermill, :collection => { :sort => :post }
|
3
|
+
map.connect "#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}", :controller => "papermill", :action => "show"
|
4
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class PapermillGenerator < Rails::Generator::NamedBase
|
2
|
+
attr_accessor :class_name, :migration_name
|
3
|
+
|
4
|
+
def initialize(args, options = {})
|
5
|
+
super
|
6
|
+
@class_name = args[0]
|
7
|
+
end
|
8
|
+
|
9
|
+
def manifest
|
10
|
+
@migration_name = file_name.camelize
|
11
|
+
record do |m|
|
12
|
+
# Migration creation
|
13
|
+
m.migration_template "migrate/papermill_migration.rb.erb", "db/migrate", :migration_file_name => migration_name.underscore
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :papermill_assets do |t|
|
4
|
+
t.string :file_file_name
|
5
|
+
t.string :file_content_type
|
6
|
+
t.integer :file_file_size
|
7
|
+
t.integer :position
|
8
|
+
t.text :description
|
9
|
+
t.string :copyright
|
10
|
+
t.string :title
|
11
|
+
t.integer :assetable_id
|
12
|
+
t.string :assetable_type
|
13
|
+
t.string :assetable_key
|
14
|
+
t.string :type
|
15
|
+
t.timestamps
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.down
|
20
|
+
drop_table :papermill_assets
|
21
|
+
end
|
22
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'core_extensions'
|
2
|
+
Object.send :include, ObjectExtensions
|
3
|
+
Hash.send :include, HashExtensions
|
4
|
+
String.send :include, StringExtensions
|
5
|
+
|
6
|
+
I18n.load_path = [File.join(File.dirname(__FILE__), 'config/locale/papermill.yml')] + I18n.load_path
|
7
|
+
|
8
|
+
require 'papermill'
|
9
|
+
ActionView::Base.send :include, PapermillHelper
|
10
|
+
ActiveRecord::Base.send :include, Papermill
|
data/install.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module HashExtensions
|
2
|
+
def deep_merge(hash)
|
3
|
+
target = dup
|
4
|
+
hash.keys.each do |key|
|
5
|
+
if hash[key].is_a? Hash and self[key].is_a? Hash
|
6
|
+
target[key] = target[key].deep_merge(hash[key])
|
7
|
+
next
|
8
|
+
end
|
9
|
+
target[key] = hash[key]
|
10
|
+
end
|
11
|
+
target
|
12
|
+
end
|
13
|
+
end
|
14
|
+
module StringExtensions
|
15
|
+
def simple_sql_sanitizer
|
16
|
+
gsub(/\\/, '\&\&').gsub(/'/, "''")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module ObjectExtensions
|
21
|
+
# Nil if empty.
|
22
|
+
def nie
|
23
|
+
self.blank? ? nil : self
|
24
|
+
end
|
25
|
+
end
|
data/lib/papermill.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
class ActionView::Helpers::FormBuilder
|
2
|
+
|
3
|
+
def assets_upload(key = nil, method = nil, options = {})
|
4
|
+
papermill_upload_field key, method, { :thumbnail => false }.update(options)
|
5
|
+
end
|
6
|
+
def asset_upload(key = nil, method = nil, options = {})
|
7
|
+
papermill_upload_field key, method, { :gallery => false, :thumbnail => false }.update(options)
|
8
|
+
end
|
9
|
+
def images_upload(key = nil, method = nil, options = {})
|
10
|
+
papermill_upload_field key, method, options
|
11
|
+
end
|
12
|
+
def image_upload(key = nil, method = nil, options = {})
|
13
|
+
papermill_upload_field key, method, { :gallery => false }.update(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def papermill_upload_field(key, method, options = {})
|
18
|
+
assetable = @template.instance_variable_get("@#{@object_name}")
|
19
|
+
method ||= options[:association] || :papermill_assets
|
20
|
+
key ||= options[:key] || nil
|
21
|
+
options = assetable.class.papermill_options.deep_merge(options)
|
22
|
+
assetable_id = assetable.id || assetable.timestamp
|
23
|
+
assetable_type = assetable.class.to_s.underscore
|
24
|
+
id = "papermill_#{assetable_type}_#{assetable_id}_#{key}_#{method}"
|
25
|
+
if options[:thumbnail]
|
26
|
+
w = options[:thumbnail][:width] || options[:thumbnail][:height] && options[:thumbnail][:aspect_ratio] && (options[:thumbnail][:height] * options[:thumbnail][:aspect_ratio]).to_i || nil
|
27
|
+
h = options[:thumbnail][:height] || options[:thumbnail][:width] && options[:thumbnail][:aspect_ratio] && (options[:thumbnail][:width] / options[:thumbnail][:aspect_ratio]).to_i || nil
|
28
|
+
options[:thumbnail][:style] ||= (w || h) && "#{w || options[:thumbnail][:max_width]}x#{h || options[:thumbnail][:max_height]}>" || "original"
|
29
|
+
if options[:thumbnail][:inline_css]
|
30
|
+
size = []
|
31
|
+
size << "width:#{w}px" if w
|
32
|
+
size << "height:#{h}px" if h
|
33
|
+
size = size.join("; ")
|
34
|
+
@template.content_for :inline_css do
|
35
|
+
inline_css = ["\n"]
|
36
|
+
if options[:gallery]
|
37
|
+
vp = options[:gallery][:vpadding].to_i
|
38
|
+
hp = options[:gallery][:hpadding].to_i
|
39
|
+
vm = options[:gallery][:vmargin].to_i
|
40
|
+
hm = options[:gallery][:hmargin].to_i
|
41
|
+
b = options[:gallery][:border_thickness].to_i
|
42
|
+
gallery_width = (options[:gallery][:width] || w) && "width:#{options[:gallery][:width] || options[:gallery][:columns]*(w+(hp+hm+b)*2)}px;" || ""
|
43
|
+
gallery_height = (options[:gallery][:height] || h) && "#{options[:gallery][:autogrow] ? "" : "min-"}height:#{options[:gallery][:height] || options[:gallery][:lines]*(h+(vp+vm+b)*2)}px;" || ""
|
44
|
+
inline_css << %{##{id} { #{gallery_width} #{gallery_height} }}
|
45
|
+
inline_css << %{##{id} li { margin:#{vm}px #{hm}px; border-width:#{b}px; padding:#{vp}px #{hp}px; #{size}; }}
|
46
|
+
else
|
47
|
+
inline_css << %{##{id}, ##{id} li { #{size} }}
|
48
|
+
end
|
49
|
+
inline_css << %{##{id} .name { width:#{w || "100"}px; }}
|
50
|
+
inline_css.join("\n")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
create_url = @template.url_for(:controller => "/papermill", :action => "create", :escape => false, :association => method.to_s, :assetable_key => key, :assetable_id => assetable_id, :assetable_type => assetable_type, :gallery => (options[:gallery] != false), :thumbnail_style => (options[:thumbnail] && options[:thumbnail][:style]))
|
55
|
+
html = []
|
56
|
+
if assetable.new_record? && !@timestamped
|
57
|
+
html << self.hidden_field(:timestamp, :value => assetable.timestamp)
|
58
|
+
@timestamped = true
|
59
|
+
end
|
60
|
+
html << %{<div style="height: #{options[:swfupload][:button_height]}px;"><span id="browse_for_#{id}" class="swf_button"></span></div>}
|
61
|
+
conditions = {:assetable_type => assetable.class.sti_name, :assetable_id => assetable_id}
|
62
|
+
conditions.merge!({:assetable_key => key.to_s}) if key
|
63
|
+
html << @template.content_tag(:ul, :id => id, :class => "papermill #{(options[:thumbnail] ? "papermill-thumb-container" : "papermill-asset-container")} #{(options[:gallery] ? "papermill-multiple-items" : "papermill-unique-item")}") {
|
64
|
+
@template.render :partial => "papermill/asset", :collection => assetable.class.papermill_associations[method][:class].find(:all, :conditions => conditions, :order => "position"), :locals => { :thumbnail_style => (options[:thumbnail] && options[:thumbnail][:style]) }
|
65
|
+
}
|
66
|
+
@template.content_for :inline_js do
|
67
|
+
%{
|
68
|
+
#{%{$("##{id}").sortable({update:function(){jQuery.ajax({async:true, data:jQuery(this).sortable('serialize'), dataType:'script', type:'post', url:'#{@template.controller.send("sort_papermill_url")}'})}})} if options[:gallery]}
|
69
|
+
new SWFUpload({
|
70
|
+
upload_id: "#{id}",
|
71
|
+
upload_url: "#{@template.escape_javascript create_url}",
|
72
|
+
file_size_limit: "#{options[:file_size_limit_mb].megabytes}",
|
73
|
+
file_types: "#{options[:images_only] ? '*.jpg;*.jpeg;*.png;*.gif' : ''}",
|
74
|
+
file_types_description: "#{options[:thumbnail] ? 'Images' : 'Files'}",
|
75
|
+
file_queue_limit: "#{!options[:gallery] ? '1' : '0'}",
|
76
|
+
file_queued_handler: Upload.file_queued,
|
77
|
+
file_dialog_complete_handler: Upload.file_dialog_complete,
|
78
|
+
upload_start_handler: Upload.upload_start,
|
79
|
+
upload_progress_handler: Upload.upload_progress,
|
80
|
+
upload_error_handler: Upload.upload_error,
|
81
|
+
upload_success_handler: Upload.upload_success,
|
82
|
+
upload_complete_handler: Upload.upload_complete,
|
83
|
+
button_placeholder_id : "browse_for_#{id}",
|
84
|
+
#{options[:swfupload].map{ |key, value| ["false", "true"].include?(value.to_s) ? "#{key.to_s}: #{value.to_s}" : "#{key.to_s}: '#{value.to_s}'" }.compact.join(", ")}
|
85
|
+
});
|
86
|
+
}
|
87
|
+
end
|
88
|
+
html.reverse! if options[:button_after_container]
|
89
|
+
html.join("\n")
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class PapermillAsset < ActiveRecord::Base
|
2
|
+
acts_as_list :scope => 'assetable_key=\'#{assetable_key.simple_sql_sanitizer}\' AND assetable_id=#{assetable_id} AND assetable_type=\'#{assetable_type}\''
|
3
|
+
|
4
|
+
belongs_to :assetable, :polymorphic => true
|
5
|
+
before_destroy :destroy_files
|
6
|
+
|
7
|
+
named_scope :key, lambda { |key| { :conditions => { :assetable_key => key } } }
|
8
|
+
|
9
|
+
Paperclip::Attachment.interpolations[:assetable_type] = proc do |attachment, style|
|
10
|
+
attachment.instance.assetable_type.underscore.pluralize
|
11
|
+
end
|
12
|
+
|
13
|
+
Paperclip::Attachment.interpolations[:assetable_id] = proc do |attachment, style|
|
14
|
+
attachment.instance.assetable_id
|
15
|
+
end
|
16
|
+
|
17
|
+
Paperclip::Attachment.interpolations[:assetable_key] = proc do |attachment, style|
|
18
|
+
attachment.instance.assetable_key.to_url
|
19
|
+
end
|
20
|
+
|
21
|
+
Paperclip::Attachment.interpolations[:escaped_basename] = proc do |attachment, style|
|
22
|
+
Paperclip::Attachment.interpolations[:basename].call(attachment, style).to_url
|
23
|
+
end
|
24
|
+
|
25
|
+
has_attached_file :file,
|
26
|
+
:path => "#{Papermill::PAPERMILL_DEFAULTS[:public_root]}/#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}",
|
27
|
+
:url => "/#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}"
|
28
|
+
validates_attachment_presence :file
|
29
|
+
|
30
|
+
#validates_attachment_content_type :file, :content_type => ['image/jpeg', 'image/pjpeg', 'image/jpg', 'image/png', 'image/gif']
|
31
|
+
|
32
|
+
# Fix the mime types. Make sure to require the mime-types gem
|
33
|
+
def swfupload_file=(data)
|
34
|
+
data.content_type = MIME::Types.type_for(data.original_filename).to_s
|
35
|
+
self.file = data
|
36
|
+
end
|
37
|
+
|
38
|
+
def name
|
39
|
+
file_file_name
|
40
|
+
end
|
41
|
+
|
42
|
+
def size
|
43
|
+
file_file_size
|
44
|
+
end
|
45
|
+
|
46
|
+
def url(style = nil)
|
47
|
+
file.url(style && CGI::escape(style.to_s))
|
48
|
+
end
|
49
|
+
|
50
|
+
def content_type
|
51
|
+
file_content_type.split("/") if file_content_type
|
52
|
+
end
|
53
|
+
|
54
|
+
def image?
|
55
|
+
content_type.first == "image" && content_type[1]
|
56
|
+
end
|
57
|
+
|
58
|
+
def interpolated_path(with = {}, up_to = nil)
|
59
|
+
Papermill::papermill_interpolated_path({":id" => self.id, ":assetable_id" => self.assetable_id, ":assetable_type" => self.assetable_type.underscore.pluralize}.merge(with), up_to)
|
60
|
+
end
|
61
|
+
|
62
|
+
# before_filter
|
63
|
+
def destroy_files
|
64
|
+
system "rm -rf #{self.interpolated_path({}, ':id')}/" if image?
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PapermillHelper
|
2
|
+
|
3
|
+
def papermill_javascript_tag(options = {})
|
4
|
+
html = []
|
5
|
+
root_folder = options[:path] || "javascripts"
|
6
|
+
if options[:with_jquery] || options[:with_jqueryui]
|
7
|
+
html << %{<script src="http://www.google.com/jsapi"></script>}
|
8
|
+
html << %{<script type="text/javascript">\n//<![CDATA[}
|
9
|
+
html << %{google.load("jquery", "1");} if options[:with_jquery]
|
10
|
+
html << %{google.load("jqueryui", "1");} if options[:with_jquery] || options[:with_jqueryui]
|
11
|
+
html << %{</script>}
|
12
|
+
end
|
13
|
+
html << %{<script src="http://swfupload.googlecode.com/svn/swfupload/tags/swfupload_v2.2.0_core/swfupload.js"></script>}
|
14
|
+
html << %{<script type="text/javascript">\n//<![CDATA[}
|
15
|
+
["SWFUPLOAD_PENDING", "SWFUPLOAD_LOADING", "SWFUPLOAD_ERROR"].each do |js_constant|
|
16
|
+
html << %{var #{js_constant} = "#{I18n.t(js_constant, :scope => "papermill")}";}
|
17
|
+
end
|
18
|
+
html << %{//]]>\n</script>}
|
19
|
+
html << javascript_include_tag("/#{root_folder}/papermill", :cache => "swfupload-papermill")
|
20
|
+
html << '<script type="text/javascript">jQuery(document).ready(function() {'
|
21
|
+
html << @content_for_inline_js
|
22
|
+
html << '});</script>'
|
23
|
+
html.join("\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
def papermill_stylesheet_tag(options = {})
|
27
|
+
html = []
|
28
|
+
root_folder = options[:path] || "stylesheets"
|
29
|
+
html << stylesheet_link_tag("/#{root_folder}/papermill")
|
30
|
+
html << %{<style type="text/css">}
|
31
|
+
html << @content_for_inline_css
|
32
|
+
html << %{</style>}
|
33
|
+
html.join("\n")
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module Papermill
|
2
|
+
|
3
|
+
# Override these defaults :
|
4
|
+
# - in your application (environment.rb, ..) => in your [environment, development, production].rb file with Papermill::OPTIONS = {thumbnails => {..}, :gallery => {..}, etc. }
|
5
|
+
# - in your class => papermill <assoc_name>, :class_name => MySTIedPapermillAssetSubClass, thumbnails => {<my_thumbnail_parameters>}, :gallery => {<my_gallery_parameters>}, etc.
|
6
|
+
# - in your helper call => images_upload :my_gallery, {thumbnails => {..}, :gallery => {..}, etc. }
|
7
|
+
# Options will cascade as you expect them to.
|
8
|
+
|
9
|
+
# sizes (widths, paddings, etc..) are CSS pixel values.
|
10
|
+
PAPERMILL_DEFAULTS = {
|
11
|
+
:thumbnail => {
|
12
|
+
# you clearly want to override these two values in your templates.
|
13
|
+
# the rest is very optionnal and will "cascade" nicely
|
14
|
+
:width => 100, # Recommended if :gallery[:width] is nil
|
15
|
+
:height => 100, # Recommended if :gallery[:height] is nil
|
16
|
+
# set :width OR :height to nil to use aspect_ratio value. Remember that 4/3 == 1 => Use : 4.0/3
|
17
|
+
:aspect_ratio => nil,
|
18
|
+
:max_width => 1000,
|
19
|
+
:max_height => 1000,
|
20
|
+
# You can override computed ImageMagick transformation strings that defaults to "#{:width}x#{:height}>"
|
21
|
+
# Note that this is required if PAPERMILL_DEFAULTS[:alias_only] is true
|
22
|
+
:style => nil,
|
23
|
+
# set to false if you don't want inline CSS
|
24
|
+
:inline_css => true
|
25
|
+
},
|
26
|
+
# gallery
|
27
|
+
:gallery => {
|
28
|
+
# if thumbnail.inline_css is true, css will be generated automagically with these values. Great for quick scaffolding, and complete enough for real use.
|
29
|
+
:width => nil, # overrides calculated width. Recommended if :thumbnail[:width] is nil.
|
30
|
+
:height => nil, # overrides calculated height. Recommended if :thumbnail[:height] is nil.
|
31
|
+
:columns => 8, # number of columns. If thumbnail.width has a value, sets a width for the gallery, calculated from thumbnails width multiplied by :columns.
|
32
|
+
:lines => 2, # number of default lines. (height will autogrow) If thumbnail.height has a value, sets a min-height for the gallery, calculated from thumbnails height multiplied by :lines
|
33
|
+
:vpadding => 0, # vertical padding around thumbnails
|
34
|
+
:hpadding => 0, # horizontal padding around thumbnails
|
35
|
+
:vmargin => 1, # vertical margin around thumbnails
|
36
|
+
:hmargin => 1, # horizontal margin around thumbnails
|
37
|
+
:border_thickness => 2, # border around thumbnails
|
38
|
+
:autogrow => false # sets a min-height instead of height for the gallery
|
39
|
+
},
|
40
|
+
# options passed on to SWFUpload. To remove an option when overriding, set it to nil.
|
41
|
+
:swfupload => {
|
42
|
+
# !!! Will only work if the swf file comes from the server to where the files are sent. (Flash same origin security policy)
|
43
|
+
:flash_url => '/flashs/swfupload.swf',
|
44
|
+
# You can use upload-blank.png with your own wording or upload.png with default "upload" wording (looks nicer)
|
45
|
+
:button_image_url => '/images/papermill/upload-blank.png',
|
46
|
+
:button_width => 61,
|
47
|
+
:button_height => 22,
|
48
|
+
# Wording and CSS processed through an Adobe Flash styler. Result is terrible. Feel free to put a CSS button overlayed directly on the SWF button. See swfupload website.
|
49
|
+
:button_text => %{<span class="button-text">#{I18n.t("upload-button-wording", :scope => :papermill)}</span>},
|
50
|
+
:button_text_style => %{.button-text { color: red; font-size: 12pt; font-weight: bold; }},
|
51
|
+
:button_disabled => "false",
|
52
|
+
:button_text_top_padding => 4,
|
53
|
+
:button_text_left_padding => 4,
|
54
|
+
:debug => "false",
|
55
|
+
:prevent_swf_caching => "false"
|
56
|
+
# See swfupload.js for details.
|
57
|
+
},
|
58
|
+
:images_only => false, # set to true to forbid upload of anything else than images
|
59
|
+
:file_size_limit_mb => 10, # file max size
|
60
|
+
:button_after_container => false, # set to true to move the upload button below the container
|
61
|
+
|
62
|
+
# DO NOT CHANGE THESE IN YOUR CLASSES. Only application wide (routes depend on it..)
|
63
|
+
:alias_only => false, # set to true so that only aliases are authorized in url/path
|
64
|
+
:aliases => {
|
65
|
+
# "example" => "100x100#",
|
66
|
+
},
|
67
|
+
# path to the root of your public directory
|
68
|
+
:public_root => ":rails_root/public",
|
69
|
+
# added to :public_root as the root folder for all papermill items
|
70
|
+
:papermill_prefix => "papermill"
|
71
|
+
}.deep_merge( Papermill.const_defined?("OPTIONS") ? Papermill::OPTIONS : {} )
|
72
|
+
|
73
|
+
|
74
|
+
PAPERCLIP_INTERPOLATION_STRING = ":assetable_type/:assetable_id/:id/:style/:escaped_basename.:extension"
|
75
|
+
|
76
|
+
def self.included(base)
|
77
|
+
base.extend(ClassMethods)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.papermill_interpolated_path(replacements_pairs, up_to)
|
81
|
+
replacements_pairs = {"other" => "*", ":rails_root" => RAILS_ROOT}.merge(replacements_pairs)
|
82
|
+
a = "#{PAPERMILL_DEFAULTS[:public_root]}/#{PAPERMILL_DEFAULTS[:papermill_prefix]}/#{PAPERCLIP_INTERPOLATION_STRING}".split("/")
|
83
|
+
"#{a[0..(up_to && a.index(up_to) || -1)].map{ |s| s.starts_with?(':') ? (replacements_pairs[s] || replacements_pairs['other'] || s) : s }.join('/')}"
|
84
|
+
end
|
85
|
+
|
86
|
+
module ClassMethods
|
87
|
+
attr_reader :papermill_options
|
88
|
+
attr_reader :papermill_associations
|
89
|
+
|
90
|
+
# Dealing with STIed Asset table in papermill declaration is dead easy, since papermill follows ActiveRecord :has_many global syntax and the Convention over configuration concept :
|
91
|
+
# papermill <association_name>, :class_name => MySTIedPapermillAssetClassName
|
92
|
+
# class MyAsset < PapermillAsset
|
93
|
+
# ...
|
94
|
+
# end
|
95
|
+
# class MyAssetableClass < ActiveRecord::Base
|
96
|
+
# 1 -> papermill :my_association, :class_name => MyAsset
|
97
|
+
# 2 -> papermill :class_name => MyAsset
|
98
|
+
# 3 -> papermill :my_assets
|
99
|
+
# 4 -> papermill :my_other_assets
|
100
|
+
# 5 -> papermill
|
101
|
+
# end
|
102
|
+
# assetable = MyAssetableClass.new
|
103
|
+
# 1 -> assetable.my_association attached MyAsset objects (no magic here, association and class_name both specified)
|
104
|
+
# 2 -> assetable.my_assets attached MyAsset objects (association infered from :class_name as expected)
|
105
|
+
# 3 -> assetable.my_assets attached MyAsset objects (class_name guessed from association name)
|
106
|
+
# 4 -> assetable.my_other_assets attached PapermillAssets objects (couldn't find MyOtherAsset class or MyOtherAsset is not a PapermillAsset subclass, use default PapermillAsset superclass)
|
107
|
+
# 5 -> assetable.papermill_assets attached PapermillAssets objects (defaults)
|
108
|
+
|
109
|
+
def papermill(assoc = nil, options = {})
|
110
|
+
@papermill_associations ||= {}
|
111
|
+
asset_class = ((klass = options.delete(:class_name)) && (klass = (klass.to_s.singularize.camelize.constantize rescue nil)) && klass.superclass == PapermillAsset && klass || assoc && (klass = (assoc.to_s.singularize.camelize.constantize rescue nil)) && klass.superclass == PapermillAsset && klass || PapermillAsset)
|
112
|
+
assoc ||= asset_class.to_s.pluralize.underscore.to_sym
|
113
|
+
|
114
|
+
@papermill_associations.merge!({assoc => {:class => asset_class}})
|
115
|
+
@papermill_options = Papermill::PAPERMILL_DEFAULTS.deep_merge(options)
|
116
|
+
association_finder = assoc.to_s + "_finder"
|
117
|
+
# using finder_sql because ActiveRecord chokes with STI on polymorphic tables. (Stupidely uses class.to_s instead of class.sti_name in association, god knows when it will get fixed, but tickets seems on the way for rails 3.0)
|
118
|
+
has_many association_finder, :finder_sql => 'SELECT * FROM papermill_assets WHERE papermill_assets.assetable_id = #{id} AND papermill_assets.assetable_type = "#{self.class.sti_name}" AND papermill_assets.type ' + (asset_class == PapermillAsset ? "IS NULL" : %{= "#{asset_class.to_s}"}) + ' ORDER BY papermill_assets.position'
|
119
|
+
after_create :rebase_assets
|
120
|
+
# reinventing the wheel because ActiveRecord chokes on :finder_sql with associations
|
121
|
+
# TODO Clean the mess
|
122
|
+
define_method assoc do |*options|
|
123
|
+
klass = self.class.papermill_associations[assoc.to_sym][:class]
|
124
|
+
options = options.first || {}
|
125
|
+
conditions = {
|
126
|
+
:assetable_type => self.class.sti_name,
|
127
|
+
:assetable_id => self.id,
|
128
|
+
}.merge(options.delete(:conditions) || {})
|
129
|
+
order = (options.delete(:order) || "position ASC")
|
130
|
+
conditions.merge!({:type => klass.to_s}) unless klass == PapermillAsset
|
131
|
+
conditions.merge!({:assetable_key => options[:key].to_s}) if options[:key]
|
132
|
+
conditions.merge!({:type => options[:class_name]}) if options[:class_name]
|
133
|
+
asset_class.find(:all, :conditions => conditions, :order => order)
|
134
|
+
end
|
135
|
+
|
136
|
+
after_destroy :remove_papermill_folder
|
137
|
+
class_eval <<-EOV
|
138
|
+
include Papermill::InstanceMethods
|
139
|
+
EOV
|
140
|
+
end
|
141
|
+
|
142
|
+
def inherited(subclass)
|
143
|
+
subclass.instance_variable_set("@papermill_options", @papermill_options)
|
144
|
+
subclass.instance_variable_set("@papermill_associations", @papermill_associations)
|
145
|
+
super
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
module InstanceMethods
|
150
|
+
attr_writer :timestamp
|
151
|
+
def timestamp
|
152
|
+
@timestamp ||= "-#{(Time.now.to_f * 1000).to_i.to_s[4..-1]}"
|
153
|
+
end
|
154
|
+
|
155
|
+
def interpolated_path(with = {}, up_to = nil)
|
156
|
+
Papermill::papermill_interpolated_path({
|
157
|
+
":assetable_type" => self.class.sti_name.underscore.pluralize,
|
158
|
+
":assetable_id" => self.id
|
159
|
+
}.merge(with), up_to)
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def rebase_assets
|
165
|
+
return true unless timestamp
|
166
|
+
PapermillAsset.find(:all, :conditions => {:assetable_id => self.timestamp}).each do |asset|
|
167
|
+
if asset.created_at < 2.hours.ago
|
168
|
+
asset.destroy
|
169
|
+
else
|
170
|
+
asset.update_attribute(:assetable_id, self.id)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
system "mv #{interpolated_path({':assetable_id' => timestamp}, ':assetable_id')}/ #{interpolated_path({}, ':assetable_id')}/"
|
174
|
+
true
|
175
|
+
end
|
176
|
+
|
177
|
+
def remove_papermill_folder
|
178
|
+
system "rm -rf #{interpolated_path({}, ':assetable_id')}/"
|
179
|
+
true
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
data/papermill.gemspec
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{papermill}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Benoit B\303\251n\303\251zech"]
|
12
|
+
s.date = %q{2009-08-30}
|
13
|
+
s.description = %q{Paperclip wrapper}
|
14
|
+
s.email = %q{benoit.benezech@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"MIT-LICENSE",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"app/controllers/papermill_controller.rb",
|
25
|
+
"app/views/papermill/_asset.html.erb",
|
26
|
+
"app/views/papermill/_raw_asset.html.erb",
|
27
|
+
"app/views/papermill/_thumbnail_asset.html.erb",
|
28
|
+
"config/locale/papermill.yml",
|
29
|
+
"config/routes.rb",
|
30
|
+
"generators/papermill/USAGE",
|
31
|
+
"generators/papermill/papermill_generator.rb",
|
32
|
+
"generators/papermill/templates/migrate/papermill_migration.rb.erb",
|
33
|
+
"init.rb",
|
34
|
+
"install.rb",
|
35
|
+
"lib/core_extensions.rb",
|
36
|
+
"lib/papermill.rb",
|
37
|
+
"lib/papermill/form_builder.rb",
|
38
|
+
"lib/papermill/papermill_asset.rb",
|
39
|
+
"lib/papermill/papermill_helper.rb",
|
40
|
+
"lib/papermill/papermill_module.rb",
|
41
|
+
"papermill.gemspec",
|
42
|
+
"public/.DS_Store",
|
43
|
+
"public/flashs/swfupload.swf",
|
44
|
+
"public/images/.DS_Store",
|
45
|
+
"public/images/papermill/.DS_Store",
|
46
|
+
"public/images/papermill/background.png",
|
47
|
+
"public/images/papermill/container-background.jpg",
|
48
|
+
"public/images/papermill/delete.png",
|
49
|
+
"public/images/papermill/upload-blank.png",
|
50
|
+
"public/images/papermill/upload.png",
|
51
|
+
"public/javascripts/papermill.js",
|
52
|
+
"public/stylesheets/papermill.css",
|
53
|
+
"tasks/papermill_tasks.rake",
|
54
|
+
"test/papermill_test.rb",
|
55
|
+
"test/test_helper.rb",
|
56
|
+
"uninstall.rb"
|
57
|
+
]
|
58
|
+
s.homepage = %q{http://github.com/BBenezech/papermill}
|
59
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
60
|
+
s.require_paths = ["lib"]
|
61
|
+
s.rubygems_version = %q{1.3.5}
|
62
|
+
s.summary = %q{Paperclip wrapper}
|
63
|
+
s.test_files = [
|
64
|
+
"test/papermill_test.rb",
|
65
|
+
"test/test_helper.rb"
|
66
|
+
]
|
67
|
+
|
68
|
+
if s.respond_to? :specification_version then
|
69
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
70
|
+
s.specification_version = 3
|
71
|
+
|
72
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
73
|
+
else
|
74
|
+
end
|
75
|
+
else
|
76
|
+
end
|
77
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,89 @@
|
|
1
|
+
/*
|
2
|
+
Papermill SWFUpload wrapper
|
3
|
+
You'll need jQuery or a **very** little bit of rewriting for native/prototype
|
4
|
+
*/
|
5
|
+
|
6
|
+
notify = function(message, type) {
|
7
|
+
// wrap with your own javascript alert system (here is the thing for jGrowl)
|
8
|
+
//if(type == "notice") { jQuery.noticeAdd({ text: message, stayTime: 4000, stay: false, type: type }) }
|
9
|
+
//if(type == "warning") { jQuery.noticeAdd({ text: message, stayTime: 9000, stay: false, type: type }) }
|
10
|
+
//if(type == "error") { jQuery.noticeAdd({ text: message, stayTime: 20000, stay: false, type: type }) }
|
11
|
+
|
12
|
+
// or simply
|
13
|
+
alert(type + ": " + message)
|
14
|
+
}
|
15
|
+
|
16
|
+
|
17
|
+
var Upload = {
|
18
|
+
// The total number of files queued with SWFUpload
|
19
|
+
files_queued: 0,
|
20
|
+
|
21
|
+
set_recipient_id: function(dom_id) {
|
22
|
+
this.recipient_id = dom_id
|
23
|
+
},
|
24
|
+
file_dialog_complete: function(num_selected, num_queued)
|
25
|
+
{
|
26
|
+
// SwfUpload doesn't order uploads by name out of the box...
|
27
|
+
this.sorted_queue = [];
|
28
|
+
this.index = 0;
|
29
|
+
if (num_queued > 0) {
|
30
|
+
file_queue = [];
|
31
|
+
global_index = 0;
|
32
|
+
index = 0;
|
33
|
+
do {
|
34
|
+
file = this.callFlash("GetFileByIndex", [global_index]);
|
35
|
+
if(file != null && file.filestatus == -1) {
|
36
|
+
file_queue[index] = file;
|
37
|
+
index++;
|
38
|
+
}
|
39
|
+
global_index++;
|
40
|
+
} while (file != null);
|
41
|
+
this.sorted_queue = file_queue.sort(function(a,b){
|
42
|
+
if(b.name < a.name){return (1)}
|
43
|
+
})
|
44
|
+
self = this;
|
45
|
+
jQuery(this.sorted_queue).each( function(index, file) {
|
46
|
+
li = jQuery('<li></li>').attr({ 'id': file.id, 'class': 'swfupload' });
|
47
|
+
li.append(jQuery('<span></span>').attr('class', 'name').html(file.name.substring(0, 10) + '...'));
|
48
|
+
li.append(jQuery('<span></span>').attr('class', 'status').html(SWFUPLOAD_PENDING));
|
49
|
+
li.append(jQuery('<span></span>').attr('class', 'progress').append('<span></span>'));
|
50
|
+
|
51
|
+
if(self.settings.file_queue_limit == 1) {
|
52
|
+
jQuery("#" + self.settings.upload_id).html(li);
|
53
|
+
} else {
|
54
|
+
jQuery("#" + self.settings.upload_id).append(li);
|
55
|
+
}
|
56
|
+
})
|
57
|
+
this.startUpload(this.sorted_queue[this.index++].id);
|
58
|
+
}
|
59
|
+
},
|
60
|
+
|
61
|
+
upload_start: function(file)
|
62
|
+
{
|
63
|
+
jQuery('#' + file.id + ' .status').html(SWFUPLOAD_LOADING);
|
64
|
+
},
|
65
|
+
upload_progress: function(file, bytes, total)
|
66
|
+
{
|
67
|
+
percent = Math.ceil((bytes / total) * 100);
|
68
|
+
jQuery('#' + file.id + ' .progress span').width(percent + '%');
|
69
|
+
},
|
70
|
+
upload_error: function(file, code, message)
|
71
|
+
{
|
72
|
+
notify(SWFUPLOAD_ERROR + " " + file.name + " (" + message + " [" + code + "])", "error");
|
73
|
+
jQuery('#' + file.id).remove();
|
74
|
+
},
|
75
|
+
upload_success: function(file, data)
|
76
|
+
{
|
77
|
+
jQuery('#' + file.id).replaceWith(jQuery(data));
|
78
|
+
},
|
79
|
+
upload_complete: function(file)
|
80
|
+
{
|
81
|
+
Upload.files_queued -= 1;
|
82
|
+
if(this.sorted_queue[this.index]) {
|
83
|
+
this.startUpload(this.sorted_queue[this.index++].id)
|
84
|
+
}
|
85
|
+
},
|
86
|
+
file_queue_error: function(file, error_code, message) {
|
87
|
+
upload_error(file, error_code, message)
|
88
|
+
}
|
89
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
.papermill a:hover { background:none; color:inherit; }
|
2
|
+
.papermill a img { border:0px; }
|
3
|
+
.papermill li:hover { border-color:blue; }
|
4
|
+
.papermill li a { display:block; }
|
5
|
+
.papermill .progress { display:block; border:1px solid #C2E3EF; text-align:left; height:6px; }
|
6
|
+
.papermill .progress span { background:#7BB963; height:6px; width:0; display:block; }
|
7
|
+
|
8
|
+
.papermill-thumb-container li { border:0px solid transparent; min-height:25px; min-width:25px; }
|
9
|
+
.papermill-thumb-container { position:relative; border:5px solid #EEE; padding:4px; overflow-x:hidden; }
|
10
|
+
.papermill-thumb-container li { display:block; float:left; position:relative; }
|
11
|
+
.papermill-thumb-container .delete { position:absolute; bottom:5px; right:5px; }
|
12
|
+
.papermill-thumb-container span { display:block; }
|
13
|
+
.papermill-thumb-container .name { font-size:10px; overflow:hidden; font-weight:bold; }
|
14
|
+
.papermill-thumb-container .infos { font-size:8px; overflow:hidden; }
|
15
|
+
.papermill-thumb-container .status { margin-bottom:10px; }
|
16
|
+
|
17
|
+
.papermill-asset-container { border:1px solid #EEE; padding:3px; }
|
18
|
+
.papermill-asset-container li { display:block; height:22px; }
|
19
|
+
.papermill-asset-container .swfupload .name { margin-left:21px; }
|
20
|
+
.papermill-asset-container .name { float:left; }
|
21
|
+
.papermill-asset-container .status { margin-left:5px; float:left; }
|
22
|
+
.papermill-asset-container .progress { float:left; margin-top:6px; margin-left:5px; width:100px; }
|
23
|
+
.papermill-asset-container .delete { float:left; margin-top:2px; margin-right:5px; }
|
24
|
+
|
25
|
+
.papermill-asset-container.papermill-multiple-items { padding-left:10px; border-left:5px solid #EEE; min-height:40px; }
|
26
|
+
.papermill-asset-container.papermill-multiple-items li { cursor:row-resize; }
|
27
|
+
.papermill-thumb-container.papermill-multiple-items li { cursor:move; }
|
28
|
+
.papermill-asset-container.papermill-unique-item { padding-left:5px; min-height:22px; }
|
29
|
+
|
30
|
+
/* Need some backgrounds?
|
31
|
+
.papermill li { background:transparent url(/images/papermill/background.png) repeat top left; }
|
32
|
+
.papermill-thumb-container { background:transparent url(/images/papermill/container-background.jpg) repeat top left; }
|
33
|
+
*/
|
@@ -0,0 +1 @@
|
|
1
|
+
|
data/test/test_helper.rb
ADDED
data/uninstall.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: BBenezech-papermill
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Benoit B\xC3\xA9n\xC3\xA9zech"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-30 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Paperclip wrapper
|
17
|
+
email: benoit.benezech@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- MIT-LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
- Rakefile
|
29
|
+
- VERSION
|
30
|
+
- app/controllers/papermill_controller.rb
|
31
|
+
- app/views/papermill/_asset.html.erb
|
32
|
+
- app/views/papermill/_raw_asset.html.erb
|
33
|
+
- app/views/papermill/_thumbnail_asset.html.erb
|
34
|
+
- config/locale/papermill.yml
|
35
|
+
- config/routes.rb
|
36
|
+
- generators/papermill/USAGE
|
37
|
+
- generators/papermill/papermill_generator.rb
|
38
|
+
- generators/papermill/templates/migrate/papermill_migration.rb.erb
|
39
|
+
- init.rb
|
40
|
+
- install.rb
|
41
|
+
- lib/core_extensions.rb
|
42
|
+
- lib/papermill.rb
|
43
|
+
- lib/papermill/form_builder.rb
|
44
|
+
- lib/papermill/papermill_asset.rb
|
45
|
+
- lib/papermill/papermill_helper.rb
|
46
|
+
- lib/papermill/papermill_module.rb
|
47
|
+
- papermill.gemspec
|
48
|
+
- public/.DS_Store
|
49
|
+
- public/flashs/swfupload.swf
|
50
|
+
- public/images/.DS_Store
|
51
|
+
- public/images/papermill/.DS_Store
|
52
|
+
- public/images/papermill/background.png
|
53
|
+
- public/images/papermill/container-background.jpg
|
54
|
+
- public/images/papermill/delete.png
|
55
|
+
- public/images/papermill/upload-blank.png
|
56
|
+
- public/images/papermill/upload.png
|
57
|
+
- public/javascripts/papermill.js
|
58
|
+
- public/stylesheets/papermill.css
|
59
|
+
- tasks/papermill_tasks.rake
|
60
|
+
- test/papermill_test.rb
|
61
|
+
- test/test_helper.rb
|
62
|
+
- uninstall.rb
|
63
|
+
has_rdoc: false
|
64
|
+
homepage: http://github.com/BBenezech/papermill
|
65
|
+
licenses:
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options:
|
68
|
+
- --charset=UTF-8
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: "0"
|
76
|
+
version:
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
version:
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.3.5
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Paperclip wrapper
|
90
|
+
test_files:
|
91
|
+
- test/papermill_test.rb
|
92
|
+
- test/test_helper.rb
|