papermill 1.4.3 → 2.0.0.pre
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/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
|
|