papermill 1.4.3 → 2.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +12 -50
- data/TODO.txt +7 -0
- data/VERSION +1 -1
- data/app/controllers/papermill_controller.rb +19 -64
- data/app/views/papermill/_asset.html.erb +3 -2
- data/app/views/papermill/browser.html.erb +21 -0
- data/config/routes.rb +1 -1
- data/demo.txt +11 -10
- data/generators/papermill_initializer/papermill_initializer.rb +6 -55
- data/generators/papermill_table/templates/migrate/papermill_migration.rb.erb +37 -13
- data/lib/papermill/extensions.rb +10 -0
- data/lib/papermill/form_builder.rb +76 -84
- data/lib/papermill/papermill.rb +55 -43
- data/lib/papermill/papermill_asset.rb +31 -17
- data/lib/papermill/papermill_association.rb +8 -0
- data/lib/papermill/papermill_options.rb +4 -8
- data/lib/papermill.rb +3 -0
- data/public/papermill/papermill.css +0 -2
- data/public/papermill/papermill.js +22 -25
- data/test/papermill_test.rb +3 -38
- metadata +14 -9
@@ -1,130 +1,122 @@
|
|
1
1
|
class ActionView::Helpers::FormBuilder
|
2
2
|
include ActionView::Helpers::FormTagHelper
|
3
3
|
|
4
|
-
def assets_upload(
|
5
|
-
papermill_upload_tag
|
4
|
+
def assets_upload(method, options = {})
|
5
|
+
papermill_upload_tag method, { :thumbnail => false }.update(options)
|
6
6
|
end
|
7
|
-
def asset_upload(
|
8
|
-
papermill_upload_tag
|
7
|
+
def asset_upload(method, options = {})
|
8
|
+
papermill_upload_tag method, { :gallery => false, :thumbnail => false }.update(options)
|
9
9
|
end
|
10
|
-
def images_upload(
|
11
|
-
papermill_upload_tag
|
10
|
+
def images_upload(method, options = {})
|
11
|
+
papermill_upload_tag method, options
|
12
12
|
end
|
13
|
-
def image_upload(
|
14
|
-
papermill_upload_tag
|
13
|
+
def image_upload(method, options = {})
|
14
|
+
papermill_upload_tag method, { :gallery => false }.update(options)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
module ActionView::Helpers::FormTagHelper
|
19
19
|
|
20
|
-
def assets_upload_tag(assetable,
|
21
|
-
papermill_upload_tag
|
20
|
+
def assets_upload_tag(assetable, method, options = {})
|
21
|
+
papermill_upload_tag method, { :thumbnail => false, :assetable => assetable }.update(options)
|
22
22
|
end
|
23
23
|
|
24
|
-
def asset_upload_tag(assetable,
|
25
|
-
papermill_upload_tag
|
24
|
+
def asset_upload_tag(assetable, method, options = {})
|
25
|
+
papermill_upload_tag method, { :gallery => false, :thumbnail => false, :assetable => assetable }.update(options)
|
26
26
|
end
|
27
27
|
|
28
|
-
def images_upload_tag(assetable,
|
29
|
-
papermill_upload_tag
|
28
|
+
def images_upload_tag(assetable, method, options = {})
|
29
|
+
papermill_upload_tag method, { :assetable => assetable }.update(options)
|
30
30
|
end
|
31
31
|
|
32
|
-
def image_upload_tag(assetable,
|
33
|
-
papermill_upload_tag
|
32
|
+
def image_upload_tag(assetable, method, options = {})
|
33
|
+
papermill_upload_tag method, { :gallery => false, :assetable => assetable }.update(options)
|
34
34
|
end
|
35
35
|
|
36
36
|
private
|
37
37
|
|
38
|
-
def papermill_upload_tag(
|
38
|
+
def papermill_upload_tag(method, options)
|
39
|
+
assetable = options[:object] || options[:assetable] || @object || @template.instance_variable_get("@#{@object_name}")
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
options[:assetable] = nil
|
43
|
-
end
|
44
|
-
|
45
|
-
assetable = @object || options[:object] || options[:assetable] || @template.instance_variable_get("@#{@object_name}")
|
46
|
-
|
47
|
-
raise PapermillException.new("Your form instance object is not @#{@object_name}, and therefor cannot be found. \nPlease provide your object name in your form_for initialization. \nform_for :my_object_name, @my_object_name, :url => { :action => 'create'/'update'}") if @object_name && !assetable
|
41
|
+
raise PapermillException.new("Form object not found. Please provide it with :object => @assetable with the Papermill helper call") unless assetable
|
42
|
+
assetable_name = @object_name && "#{@object_name}#{(i = @options[:index]) ? "[#{i}]" : ""}"
|
48
43
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
44
|
+
sanitized_method = method.to_s.gsub(/[\?\/\-]$/, '')
|
45
|
+
sanitized_object_name = @object_name.to_s.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
|
46
|
+
field_id = @object_name && "#{sanitized_object_name}#{(i = @options[:index]) ? "_#{i}" : ""}_#{sanitized_method}"
|
47
|
+
assetable.class.papermill(method)
|
48
|
+
association_options = assetable.class.papermill_options[method.to_sym]
|
49
|
+
|
50
|
+
raise PapermillException.new("Papermill association #{method} failed to be generated dynamically for #{assetable.class.name}") unless association_options
|
51
|
+
options = association_options.deep_merge(options)
|
52
|
+
field_name = "#{assetable_name}[papermill_#{method}_ids][]"
|
55
53
|
|
56
54
|
if ot = options[:thumbnail]
|
57
55
|
w = ot[:width] || ot[:height] && ot[:aspect_ratio] && (ot[:height] * ot[:aspect_ratio]).to_i || nil
|
58
|
-
h = ot[:height] || ot[:width] && ot[:aspect_ratio] && (ot[:width]
|
59
|
-
|
56
|
+
h = ot[:height] || ot[:width] && ot[:aspect_ratio] && (ot[:width] / ot[:aspect_ratio]).to_i || nil
|
60
57
|
computed_style = ot[:style] || (w || h) && "#{w}x#{h}>" || "original"
|
61
|
-
set_papermill_inline_css(
|
58
|
+
set_papermill_inline_css(field_id, w, h, options)
|
62
59
|
end
|
63
60
|
|
64
|
-
set_papermill_inline_js(
|
61
|
+
set_papermill_inline_js(field_id, compute_papermill_url(:create, computed_style, field_name, field_id, options), options)
|
65
62
|
|
66
63
|
html = {}
|
67
|
-
html[:upload_button] = %{
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
@template.render :partial => "papermill/asset", :collection => PapermillAsset.all(:conditions => conditions), :locals => { :thumbnail_style => computed_style, :targetted_size => options[:targetted_size] }
|
72
|
-
end
|
64
|
+
html[:upload_button] = %{\
|
65
|
+
<div id="#{field_id}-button-wrapper" class="papermill-button-wrapper" style="height: #{options[:swfupload][:button_height]}px;">
|
66
|
+
<span id="browse_for_#{field_id}" class="swf_button"></span>
|
67
|
+
</div>}
|
73
68
|
|
74
|
-
if
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
html[:dashboard] = @template.content_tag(:ul, options[:dashboard].map{|action| @template.content_tag(:li, html[:dashboard][action], :class => action.to_s) }.join("\n"), :class => "dashboard")
|
69
|
+
# I don't use the full :through association that is not updated if assetable.new_record?.
|
70
|
+
collection = association_options[:through] ? assetable.send("#{method}_associations").map(&:papermill_asset) : assetable.send(method)
|
71
|
+
locals = { :thumbnail_style => computed_style, :targetted_size => options[:targetted_size], :field_name => field_name, :field_id => field_id }
|
72
|
+
html[:container] = @template.content_tag(:div, :id => field_id, :class => "papermill-#{method.to_s} #{(options[:thumbnail] ? "papermill-thumb-container" : "papermill-asset-container")} #{(options[:gallery] ? "papermill-multiple-items" : "papermill-unique-item")}") do
|
73
|
+
@template.render(:partial => "papermill/asset",
|
74
|
+
:collection => collection,
|
75
|
+
:locals => locals)
|
82
76
|
end
|
83
|
-
|
84
|
-
if
|
85
|
-
|
86
|
-
|
77
|
+
|
78
|
+
if options[:gallery] && options[:mass_edit]
|
79
|
+
html[:mass_edit] = %{\
|
80
|
+
<a onclick="Papermill.modify_all('#{field_id}'); return false;" style="cursor:pointer">#{I18n.t("papermill.modify-all")}</a>
|
81
|
+
<select id="batch_#{field_id}">#{options[:mass_editable_fields].map do |field|
|
82
|
+
%{<option value="#{field.to_s}">#{I18n.t("papermill.#{field.to_s}", :default => field.to_s)}</option>}
|
83
|
+
end.join("\n")}</select>}
|
87
84
|
end
|
88
85
|
|
89
|
-
|
86
|
+
if options[:through]
|
87
|
+
browser_url = compute_papermill_url(:browser, computed_style, field_name, field_id, options)
|
88
|
+
html[:browser] = %{<a onclick="popup('#{@template.escape_javascript(browser_url)}&list_id=#{field_id}&' + jQuery('##{field_id}').sortable('serialize')); return false;" style="cursor:pointer">Ajouter...</a>}
|
89
|
+
end
|
90
|
+
|
91
|
+
# hidden_field needed to empty a list.
|
92
|
+
%{<div class="papermill">
|
93
|
+
#{@template.hidden_field("#{assetable_name}[papermill_#{method}_ids]", nil)}
|
94
|
+
#{options[:form_helper_elements].map{|element| html[element] || ""}.join("\n")}
|
95
|
+
</div>}
|
90
96
|
end
|
91
97
|
|
92
98
|
|
93
|
-
def
|
94
|
-
|
95
|
-
:escape => false, :controller => "/papermill", :action =>
|
99
|
+
def compute_papermill_url(action, computed_style, field_name, field_id, options)
|
100
|
+
@template.url_for({
|
101
|
+
:escape => false, :controller => "/papermill", :action => action,
|
96
102
|
:asset_class => (options[:class_name] || PapermillAsset).to_s,
|
97
|
-
:gallery => !!options[:gallery], :thumbnail_style => computed_style, :targetted_size => options[:targetted_size]
|
98
|
-
|
99
|
-
|
100
|
-
create_url_options.merge!({ :assetable_key => key }) if key
|
101
|
-
@template.url_for(create_url_options)
|
103
|
+
:gallery => !!options[:gallery], :thumbnail_style => computed_style, :targetted_size => options[:targetted_size],
|
104
|
+
:field_name => field_name, :field_id => field_id
|
105
|
+
})
|
102
106
|
end
|
103
107
|
|
104
|
-
def set_papermill_inline_js(
|
108
|
+
def set_papermill_inline_js(field_id, create_url, options)
|
105
109
|
return unless options[:inline_css]
|
106
110
|
@template.content_for :papermill_inline_js do
|
107
|
-
%{
|
108
|
-
jQuery("##{dom_id}").sortable({
|
109
|
-
update:function(){
|
110
|
-
jQuery.ajax({
|
111
|
-
async: true,
|
112
|
-
data: jQuery(this).sortable('serialize'),
|
113
|
-
dataType: 'script',
|
114
|
-
type: 'post',
|
115
|
-
url: '#{@template.controller.send("sort_papermill_path")}'
|
116
|
-
})
|
117
|
-
}
|
118
|
-
})
|
119
|
-
} if options[:gallery]
|
111
|
+
%{ jQuery("##{field_id}").sortable() } if options[:gallery]
|
120
112
|
end
|
121
113
|
@template.content_for :papermill_inline_js do
|
122
114
|
%{
|
123
115
|
new SWFUpload({
|
124
|
-
post_params: {
|
116
|
+
post_params: {
|
125
117
|
"#{ ActionController::Base.session_options[:key] }": "#{ @template.cookies[ActionController::Base.session_options[:key]] }"
|
126
118
|
},
|
127
|
-
upload_id: "#{
|
119
|
+
upload_id: "#{ field_id }",
|
128
120
|
upload_url: "#{ @template.escape_javascript create_url }",
|
129
121
|
file_types: "#{ options[:images_only] ? '*.jpg;*.jpeg;*.png;*.gif' : '' }",
|
130
122
|
file_queue_limit: "#{ !options[:gallery] ? '1' : '0' }",
|
@@ -136,26 +128,26 @@ module ActionView::Helpers::FormTagHelper
|
|
136
128
|
upload_error_handler: Papermill.upload_error,
|
137
129
|
upload_success_handler: Papermill.upload_success,
|
138
130
|
upload_complete_handler: Papermill.upload_complete,
|
139
|
-
button_placeholder_id: "browse_for_#{
|
131
|
+
button_placeholder_id: "browse_for_#{field_id}",
|
140
132
|
#{ options[:swfupload].map { |key, value| "#{key}: #{value}" if value }.compact.join(",\n") }
|
141
133
|
});
|
142
134
|
}
|
143
135
|
end
|
144
136
|
end
|
145
137
|
|
146
|
-
def set_papermill_inline_css(
|
138
|
+
def set_papermill_inline_css(field_id, width, height, options)
|
147
139
|
html = ["\n"]
|
148
140
|
size = [width && "width:#{width}px", height && "height:#{height}px"].compact.join("; ")
|
149
141
|
if og = options[:gallery]
|
150
142
|
vp, hp, vm, hm, b = [og[:vpadding], og[:hpadding], og[:vmargin], og[:hmargin], og[:border_thickness]].map &:to_i
|
151
143
|
gallery_width = (og[:width] || width) && "width:#{og[:width] || og[:columns]*(width.to_i+(hp+hm+b)*2)}px;" || ""
|
152
144
|
gallery_height = (og[:height] || height) && "min-height:#{og[:height] || og[:lines]*(height.to_i+(vp+vm+b)*2)}px;" || ""
|
153
|
-
html << %{##{
|
154
|
-
html << %{##{
|
145
|
+
html << %{##{field_id} { #{gallery_width} #{gallery_height} }}
|
146
|
+
html << %{##{field_id} .asset { margin:#{vm}px #{hm}px; border-width:#{b}px; padding:#{vp}px #{hp}px; #{size}; }}
|
155
147
|
else
|
156
|
-
html << %{##{
|
148
|
+
html << %{##{field_id}, ##{field_id} .asset { #{size} }}
|
157
149
|
end
|
158
|
-
html << %{##{
|
150
|
+
html << %{##{field_id} .name { width:#{width || "100"}px; }}
|
159
151
|
@template.content_for :papermill_inline_css do
|
160
152
|
html.join("\n")
|
161
153
|
end
|
data/lib/papermill/papermill.rb
CHANGED
@@ -1,15 +1,10 @@
|
|
1
1
|
module Papermill
|
2
|
-
|
3
|
-
def self.included(base)
|
4
|
-
base.extend(ClassMethods)
|
5
|
-
end
|
2
|
+
MSWIN = (Config::CONFIG['host_os'] =~ /mswin|mingw/)
|
6
3
|
|
7
4
|
def self.options
|
8
5
|
@options ||= BASE_OPTIONS.deep_merge(defined?(OPTIONS) ? OPTIONS : {})
|
9
6
|
end
|
10
7
|
|
11
|
-
MSWIN = (Config::CONFIG['host_os'] =~ /mswin|mingw/)
|
12
|
-
|
13
8
|
def self.compute_paperclip_path
|
14
9
|
path = []
|
15
10
|
path << (options[:use_id_partition] ? ":id_partition" : ":id")
|
@@ -19,52 +14,69 @@ module Papermill
|
|
19
14
|
path.compact.join("/")
|
20
15
|
end
|
21
16
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
(@papermill_associations ||= {}).merge!( assoc_name => Papermill::options.deep_merge(local_options) )
|
17
|
+
def self.included(base)
|
18
|
+
base.extend(ClassMethods)
|
19
|
+
base.class_eval do
|
20
|
+
def papermill(key, through = ((po = self.class.papermill_options) && (po[key.to_sym] || po[:default]) || Papermill::options)[:through])
|
21
|
+
PapermillAsset.papermill(self.class.base_class.name, self.id, key.to_s, through)
|
22
|
+
end
|
30
23
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
scope = scope.scoped(:conditions => { :assetable_key => options.shift.to_s.nie })
|
42
|
-
end
|
43
|
-
scope = scope.scoped(options.shift) if options.first
|
44
|
-
scope
|
24
|
+
def respond_to_with_papermill?(method, *args, &block)
|
25
|
+
respond_to_without_papermill?(method, *args, &block) || (method.to_s =~ /^papermill_.+_ids=$/) == 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing_with_papermill(method, *args, &block)
|
29
|
+
if method.to_s =~ /^papermill_.+_ids=$/
|
30
|
+
self.class.papermill(method.to_s[10..-6])
|
31
|
+
self.send(method, *args, &block)
|
32
|
+
else
|
33
|
+
method_missing_without_papermill(method, *args, &block)
|
45
34
|
end
|
46
35
|
end
|
47
|
-
ActionController::Dispatcher.middleware.delete(FlashSessionCookieMiddleware) rescue true
|
48
|
-
ActionController::Dispatcher.middleware.insert_before(ActionController::Base.session_store, FlashSessionCookieMiddleware, ActionController::Base.session_options[:key]) rescue true
|
49
36
|
end
|
37
|
+
base.send :alias_method_chain, :method_missing, :papermill
|
38
|
+
base.send :alias_method_chain, :respond_to?, :papermill
|
39
|
+
ActionController::Dispatcher.middleware.insert_before(ActionController::Base.session_store, FlashSessionCookieMiddleware, ActionController::Base.session_options[:key]) unless ActionController::Dispatcher.middleware.include?(FlashSessionCookieMiddleware)
|
40
|
+
end
|
41
|
+
|
42
|
+
module ClassMethods
|
43
|
+
attr_reader :papermill_options
|
50
44
|
|
51
45
|
def inherited(subclass)
|
52
|
-
subclass.instance_variable_set("@
|
46
|
+
subclass.instance_variable_set("@papermill_options", @papermill_options)
|
53
47
|
super
|
54
48
|
end
|
55
|
-
end
|
56
|
-
|
57
|
-
module InstanceMethods
|
58
|
-
attr_writer :timestamp
|
59
|
-
def timestamp
|
60
|
-
@timestamp ||= "-#{(Time.now.to_f * 1000).to_i.to_s[4..-1]}"
|
61
|
-
end
|
62
49
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
50
|
+
def papermill(assoc_key, assoc_options = (@papermill_options && @papermill_options[:default] || {}))
|
51
|
+
return if @papermill_options && @papermill_options[assoc_key.to_sym] # already defined
|
52
|
+
raise PapermillException.new("Can't use '#{assoc_key}' association : #{self.name} instances already responds to it !") if self.new.respond_to?(assoc_key)
|
53
|
+
(@papermill_options ||= {}).merge!( { assoc_key.to_sym => Papermill::options.deep_merge(assoc_options) } )
|
54
|
+
return if assoc_key.to_sym == :default
|
55
|
+
unless papermill_options[assoc_key.to_sym][:through]
|
56
|
+
self.class_eval %{
|
57
|
+
has_many :#{assoc_key}, :as => "assetable", :dependent => :delete_all, :order => :position, :class_name => "PapermillAsset", :conditions => {:assetable_key => '#{assoc_key}'}, :before_add => Proc.new{|a, asset| asset.assetable_key = '#{assoc_key}'}
|
58
|
+
def papermill_#{assoc_key}_ids=(ids)
|
59
|
+
unless (assets_ids = ids.map(&:to_i).select{|i|i>0}) == self.#{assoc_key}.map(&:id)
|
60
|
+
assets = PapermillAsset.find(assets_ids)
|
61
|
+
self.#{assoc_key} = assets_ids.map{|asset_id| assets.select{|asset|asset.id==asset_id}.first}
|
62
|
+
PapermillAsset.update_all("position = CASE id " + assets_ids.map_with_index{|asset_id, index| " WHEN " + asset_id.to_s + " THEN " + (index+1).to_s }.join + " END",
|
63
|
+
:id => assets_ids) unless assets_ids.empty?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
}
|
67
|
+
else
|
68
|
+
self.class_eval %{
|
69
|
+
has_many(:#{assoc_key}_associations, :as => "assetable", :class_name => "PapermillAssociation", :include => :papermill_asset, :dependent => :delete_all, :order => :position, :conditions => {:assetable_key => '#{assoc_key}'}, :before_add => Proc.new{|a, assoc| assoc.assetable_key = '#{assoc_key}'})
|
70
|
+
has_many(:#{assoc_key}, :through => :#{assoc_key}_associations, :source => :papermill_asset)
|
71
|
+
def papermill_#{assoc_key}_ids=(ids)
|
72
|
+
unless (assets_ids = ids.map(&:to_i).select{|i|i>0}) == self.#{assoc_key}_associations.map(&:papermill_asset_id)
|
73
|
+
self.#{assoc_key}_associations.delete_all
|
74
|
+
self.#{assoc_key}_associations = assets_ids.map_with_index do |asset_id, index|
|
75
|
+
PapermillAssociation.new(:papermill_asset_id => asset_id, :position => (index+1))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
}
|
68
80
|
end
|
69
81
|
end
|
70
82
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
class PapermillAsset < ActiveRecord::Base
|
2
|
-
|
3
2
|
before_destroy :destroy_files
|
4
|
-
|
5
|
-
|
3
|
+
|
6
4
|
has_attached_file :file,
|
7
5
|
:processors => [:papermill_paperclip_processor],
|
8
6
|
:url => "#{Papermill::options[:papermill_url_prefix]}/#{Papermill::compute_paperclip_path.gsub(':style', ':escape_style_in_url')}",
|
@@ -12,10 +10,26 @@ class PapermillAsset < ActiveRecord::Base
|
|
12
10
|
|
13
11
|
validates_attachment_presence :file
|
14
12
|
|
15
|
-
belongs_to :assetable, :polymorphic => true
|
16
|
-
|
17
|
-
|
18
|
-
named_scope :
|
13
|
+
belongs_to :assetable, :polymorphic => true
|
14
|
+
has_many :papermill_associations, :dependent => :delete_all
|
15
|
+
|
16
|
+
named_scope :papermill, lambda { |assetable_type, assetable_id, assetable_key, through|
|
17
|
+
through ?
|
18
|
+
{ :joins => "INNER JOIN papermill_associations ON papermill_assets.id = papermill_associations.papermill_asset_id \
|
19
|
+
AND papermill_associations.assetable_type = #{connection.quote assetable_type} \
|
20
|
+
AND papermill_associations.assetable_id = #{assetable_id.to_i} \
|
21
|
+
AND papermill_associations.assetable_key = #{connection.quote assetable_key}",
|
22
|
+
:order => "papermill_associations.position" } :
|
23
|
+
{ :conditions => {
|
24
|
+
:assetable_type => assetable_type,
|
25
|
+
:assetable_id => assetable_id,
|
26
|
+
:assetable_key => assetable_key.to_s },
|
27
|
+
:order => "papermill_assets.position" }
|
28
|
+
}
|
29
|
+
|
30
|
+
def assetable_type=(sType)
|
31
|
+
super(sType.to_s.classify.constantize.base_class.to_s)
|
32
|
+
end
|
19
33
|
|
20
34
|
Paperclip.interpolates :url_key do |attachment, style|
|
21
35
|
attachment.instance.compute_url_key((style || "original").to_s)
|
@@ -103,10 +117,10 @@ class PapermillAsset < ActiveRecord::Base
|
|
103
117
|
style.is_a?(Hash) ? (style[:name] || style.hash).to_s : (style || "original").to_s
|
104
118
|
end
|
105
119
|
|
106
|
-
def self.papermill_options(
|
107
|
-
if
|
108
|
-
assoc =
|
109
|
-
assoc[assetable_key.try(:to_sym)] || assoc[Papermill::options
|
120
|
+
def self.papermill_options(assetable_type, assetable_key)
|
121
|
+
if assetable_type
|
122
|
+
assoc = assetable_type.constantize.papermill_options
|
123
|
+
assoc[assetable_key.try(:to_sym)] || assoc[:default] || Papermill::options
|
110
124
|
else
|
111
125
|
Papermill::options
|
112
126
|
end
|
@@ -121,12 +135,14 @@ class PapermillAsset < ActiveRecord::Base
|
|
121
135
|
end
|
122
136
|
|
123
137
|
def create_thumb_file(style_name, style = nil)
|
138
|
+
return false unless self.image?
|
124
139
|
destroy_thumbnails if style_name.to_s == "original"
|
125
140
|
style = self.class.compute_style(style_name) unless style.is_a?(Hash)
|
126
141
|
FileUtils.mkdir_p File.dirname(new_path = file.path(style_name))
|
127
142
|
FileUtils.cp((tmp_path = Paperclip::PapermillPaperclipProcessor.make(file, style).path), new_path)
|
128
143
|
FileUtils.chmod(0644, new_path) unless Papermill::MSWIN
|
129
144
|
File.delete(tmp_path)
|
145
|
+
return true
|
130
146
|
end
|
131
147
|
|
132
148
|
def destroy_thumbnails
|
@@ -141,7 +157,9 @@ class PapermillAsset < ActiveRecord::Base
|
|
141
157
|
end
|
142
158
|
|
143
159
|
def self.destroy_orphans
|
144
|
-
self.
|
160
|
+
self.name != self.base_class.name ?
|
161
|
+
PapermillAsset.delete_all(["created_at < ? AND assetable_id IS NULL AND type = ?", 1.hour.ago, self.name]) :
|
162
|
+
PapermillAsset.delete_all(["created_at < ? AND assetable_id IS NULL AND type IS NULL", 1.hour.ago])
|
145
163
|
end
|
146
164
|
|
147
165
|
def compute_url_key(style)
|
@@ -153,7 +171,7 @@ class PapermillAsset < ActiveRecord::Base
|
|
153
171
|
end
|
154
172
|
|
155
173
|
private
|
156
|
-
|
174
|
+
|
157
175
|
def root_directory
|
158
176
|
deepness_to_root = Papermill::options[:use_url_key] ? -3 : -2
|
159
177
|
@root_directory ||= File.dirname(path).split('/')[0..deepness_to_root].join('/')
|
@@ -165,10 +183,6 @@ class PapermillAsset < ActiveRecord::Base
|
|
165
183
|
self.file.instance_write(:file_name, "#{basename.to_url}#{extension}")
|
166
184
|
end
|
167
185
|
|
168
|
-
def set_position
|
169
|
-
self.position ||= PapermillAsset.maximum(:position, :conditions => { :assetable_type => assetable_type, :assetable_id => assetable_id, :assetable_key => assetable_key } ).to_i + 1
|
170
|
-
end
|
171
|
-
|
172
186
|
def destroy_files
|
173
187
|
FileUtils.rm_r(root_directory) rescue true
|
174
188
|
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Papermill
|
2
2
|
BASE_OPTIONS = {
|
3
3
|
:class_name => "PapermillAsset",
|
4
|
+
:through => false,
|
4
5
|
:inline_css => true,
|
5
6
|
:images_only => false,
|
6
|
-
:form_helper_elements => [:upload_button, :container, :
|
7
|
-
:
|
7
|
+
:form_helper_elements => [:upload_button, :container, :browser, :mass_edit],
|
8
|
+
:mass_edit => true,
|
8
9
|
:mass_editable_fields => ["title", "copyright", "description"],
|
9
10
|
:editable_fields => [
|
10
11
|
{:title => {:type => "string"}},
|
@@ -48,8 +49,6 @@ module Papermill
|
|
48
49
|
:copyright_im_command => %{\\( -font Arial-Bold -pointsize 9 -fill '#FFFFFFE0' -border 3 -bordercolor '#50550080' -background '#00000000' label:' %s ' \\) -gravity South-West -geometry +0+0 -composite},
|
49
50
|
:watermark => "/images/rails.png",
|
50
51
|
:watermark_im_command => %{- | composite \\( %s -resize 100% \\) - -dissolve 20% -gravity center -geometry +0+0 },
|
51
|
-
:base_association_name => :assets,
|
52
|
-
:touch => false,
|
53
52
|
:alias_only => false,
|
54
53
|
:aliases => {},
|
55
54
|
:use_url_key => false,
|
@@ -57,9 +56,6 @@ module Papermill
|
|
57
56
|
:url_key_generator => Proc.new { |style, asset| Digest::SHA512.hexdigest("#{style}#{asset.id}#{Papermill::options[:url_key_salt]}")[0..10] },
|
58
57
|
:use_id_partition => true,
|
59
58
|
:papermill_url_prefix => "/system/papermill",
|
60
|
-
:papermill_path_prefix => ":rails_root/public/system/papermill"
|
61
|
-
:authorize_create => "true",
|
62
|
-
:authorize_update_and_destroy => "true",
|
63
|
-
:authorize_multiple_modification => "true",
|
59
|
+
:papermill_path_prefix => ":rails_root/public/system/papermill"
|
64
60
|
}
|
65
61
|
end
|
data/lib/papermill.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "rbconfig"
|
2
|
+
require "acts_as_list"
|
2
3
|
begin
|
3
4
|
require "mime/types"
|
4
5
|
MIME_TYPE_LOADED = true
|
@@ -12,6 +13,7 @@ require 'papermill/flash_session_cookie_middleware.rb'
|
|
12
13
|
|
13
14
|
Object.send :include, PapermillObjectExtensions
|
14
15
|
Hash.send :include, PapermillHashExtensions
|
16
|
+
Array.send :include, PapermillArrayExtensions
|
15
17
|
String.send :include, StringToUrlNotFound unless String.instance_methods.include? "to_url"
|
16
18
|
Formtastic::SemanticFormBuilder.send(:include, PapermillFormtasticExtensions) rescue NameError
|
17
19
|
|
@@ -23,6 +25,7 @@ end
|
|
23
25
|
require 'paperclip' unless defined?(Paperclip)
|
24
26
|
require 'papermill/papermill_paperclip_processor'
|
25
27
|
require 'papermill/papermill'
|
28
|
+
require 'papermill/papermill_association'
|
26
29
|
require 'papermill/papermill_asset'
|
27
30
|
require 'papermill/form_builder'
|
28
31
|
require 'papermill/papermill_helper'
|
@@ -23,8 +23,6 @@
|
|
23
23
|
|
24
24
|
.papermill .dashboard li a { display:inline; padding-left:20px }
|
25
25
|
.papermill .dashboard li.mass_edit a { background:transparent url(/papermill/images/mass-edit.png) no-repeat top left; }
|
26
|
-
.papermill .dashboard li.mass_delete a { background:transparent url(/papermill/images/mass-delete.png) no-repeat top left; }
|
27
|
-
.papermill .dashboard li.mass_thumbnail_reset a { background:transparent url(/papermill/images/mass-thumbnail-reset.png) no-repeat top left; }
|
28
26
|
|
29
27
|
.papermill-thumb-container { position:relative; border:5px solid #EEE; padding:4px; overflow:hidden; }
|
30
28
|
.papermill-thumb-container .asset { border:0px solid transparent; min-height:25px; min-width:25px; display:block; float:left; position:relative; }
|
@@ -6,14 +6,15 @@ If you have your own popup solution, override popup and close_popup in your appl
|
|
6
6
|
popup = function(url) {
|
7
7
|
jQuery.facebox(function() {
|
8
8
|
jQuery.get(url, function(data) {
|
9
|
-
jQuery.facebox(data)
|
9
|
+
jQuery.facebox(data);
|
10
10
|
})
|
11
11
|
})
|
12
12
|
return false;
|
13
|
-
}
|
13
|
+
};
|
14
|
+
|
14
15
|
close_popup = function(source) {
|
15
16
|
jQuery(document).trigger('close.facebox');
|
16
|
-
}
|
17
|
+
};
|
17
18
|
|
18
19
|
jQuery(document).ajaxError(function(){
|
19
20
|
switch (arguments[1].status) {
|
@@ -37,10 +38,11 @@ If you have your own notification solution, override notify
|
|
37
38
|
*/
|
38
39
|
|
39
40
|
notify = function(title, message, type) {
|
40
|
-
if(type == "notice") { jQuery.jGrowl(message, { header: title, life: 4000, theme: type }) }
|
41
|
-
if(type == "warning") { jQuery.jGrowl(message, { header: title, life: 15000, theme: type }) }
|
42
|
-
if(type == "error") { jQuery.jGrowl(message, { header: title, sticky: true, theme: type }) }
|
43
|
-
}
|
41
|
+
if(type == "notice") { jQuery.jGrowl(message, { header: title, life: 4000, theme: type }) };
|
42
|
+
if(type == "warning") { jQuery.jGrowl(message, { header: title, life: 15000, theme: type }) };
|
43
|
+
if(type == "error") { jQuery.jGrowl(message, { header: title, sticky: true, theme: type }) };
|
44
|
+
};
|
45
|
+
|
44
46
|
var Papermill = {
|
45
47
|
files_queued: 0,
|
46
48
|
file_dialog_complete: function(num_selected, num_queued)
|
@@ -62,7 +64,7 @@ var Papermill = {
|
|
62
64
|
} while (file != null);
|
63
65
|
this.sorted_queue = file_queue.sort(function(a,b){
|
64
66
|
if(b.name < a.name) { return (1) } else { return (-1) }
|
65
|
-
})
|
67
|
+
});
|
66
68
|
var self = this;
|
67
69
|
jQuery(this.sorted_queue).each( function(index, file) {
|
68
70
|
div = jQuery('<div></div>').attr({ 'id': file.id, 'class': 'swfupload asset' });
|
@@ -76,7 +78,7 @@ var Papermill = {
|
|
76
78
|
}
|
77
79
|
}
|
78
80
|
jQuery("#" + self.settings.upload_id).append(div);
|
79
|
-
})
|
81
|
+
});
|
80
82
|
this.startUpload(this.sorted_queue[this.index++].id);
|
81
83
|
}
|
82
84
|
},
|
@@ -84,6 +86,12 @@ var Papermill = {
|
|
84
86
|
{
|
85
87
|
jQuery('#' + file.id + ' .status').html(SWFUPLOAD_LOADING);
|
86
88
|
this.addFileParam(file.id, "Fileid", file.id);
|
89
|
+
if(this.settings.file_queue_limit == 1) {
|
90
|
+
old_asset = jQuery("#" + this.settings.upload_id).children()[0];
|
91
|
+
if (old_asset && old_asset.id != file.id) {
|
92
|
+
this.addFileParam(file.id, "Oldfileid", old_asset.id);
|
93
|
+
}
|
94
|
+
}
|
87
95
|
},
|
88
96
|
upload_progress: function(file, bytes, total)
|
89
97
|
{
|
@@ -107,7 +115,7 @@ var Papermill = {
|
|
107
115
|
{
|
108
116
|
Papermill.files_queued -= 1;
|
109
117
|
if(this.sorted_queue[this.index]) {
|
110
|
-
this.startUpload(this.sorted_queue[this.index++].id)
|
118
|
+
this.startUpload(this.sorted_queue[this.index++].id);
|
111
119
|
}
|
112
120
|
},
|
113
121
|
file_queue_error: function(file, errorCode, message) {
|
@@ -127,23 +135,12 @@ var Papermill = {
|
|
127
135
|
},
|
128
136
|
modify_all: function(papermill_id) {
|
129
137
|
container = jQuery("#" + papermill_id)[0];
|
130
|
-
attribute_name = jQuery("#batch_" + papermill_id)[0].value
|
138
|
+
attribute_name = jQuery("#batch_" + papermill_id)[0].value;
|
131
139
|
attribute_wording = jQuery("#batch_" + papermill_id + " option:selected").text();
|
132
|
-
value = prompt(attribute_wording + ":")
|
140
|
+
value = prompt(attribute_wording + ":");
|
133
141
|
if(value != null) {
|
134
|
-
jQuery.ajax({async:true, data:jQuery(container).sortable('serialize'), dataType:'script', type:'post', url:'/papermill/mass_edit?attribute=' + attribute_name + "&value=" + value})
|
142
|
+
jQuery.ajax({async:true, data:jQuery(container).sortable('serialize') + "&list_id=" + container.id, dataType:'script', type:'post', url:'/papermill/mass_edit?attribute=' + attribute_name + "&value=" + value});
|
135
143
|
}
|
136
|
-
},
|
137
|
-
mass_delete: function(papermill_id, wording) {
|
138
|
-
if(confirm(wording)){
|
139
|
-
jQuery.ajax({async:true, data:jQuery('#' + papermill_id).sortable('serialize'), dataType:'script', type:'post', url:'/papermill/mass_delete'})
|
140
|
-
}
|
141
|
-
},
|
142
|
-
|
143
|
-
mass_thumbnail_reset: function(papermill_id, wording) {
|
144
|
-
if(confirm(wording)){
|
145
|
-
jQuery.ajax({async:true, data:jQuery('#' + papermill_id).sortable('serialize'), dataType:'script', type:'post', url:'/papermill/mass_thumbnail_reset'})
|
146
|
-
}
|
147
144
|
}
|
148
|
-
}
|
145
|
+
};
|
149
146
|
|