Commit 15390f79e01220faaf11994dcc83122f4e711930
Committed by
Antonio Terceiro
1 parent
483065d8
Exists in
master
and in
22 other branches
ActionItem774: allowing upload of more than one file at once
Showing
10 changed files
with
150 additions
and
15 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -101,12 +101,8 @@ class CmsController < MyProfileController |
101 | 101 | klass = @type.constantize |
102 | 102 | @article = klass.new(params[:article]) |
103 | 103 | |
104 | - | |
105 | - if params[:parent_id] | |
106 | - parent = profile.articles.find(params[:parent_id]) | |
107 | - if ! parent.allow_children? | |
108 | - raise ArgumentError.new("cannot create child of article which does not accept children") | |
109 | - end | |
104 | + parent = check_parent(params[:parent_id]) | |
105 | + if parent | |
110 | 106 | @article.parent = parent |
111 | 107 | @parent_id = parent.id |
112 | 108 | end |
... | ... | @@ -134,6 +130,26 @@ class CmsController < MyProfileController |
134 | 130 | redirect_to :action => 'view', :id => @article.id |
135 | 131 | end |
136 | 132 | |
133 | + def upload_files | |
134 | + @uploaded_files = [] | |
135 | + @parent = check_parent(params[:parent_id]) | |
136 | + if request.post? && params[:uploaded_files] | |
137 | + params[:uploaded_files].each do |file| | |
138 | + @uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent) unless file == '' | |
139 | + end | |
140 | + @errors = @uploaded_files.select { |f| f.errors.any? } | |
141 | + if @errors.any? | |
142 | + render :action => 'upload_files', :parent_id => @parent_id | |
143 | + else | |
144 | + redirect_to( if @parent | |
145 | + {:action => 'view', :id => @parent.id} | |
146 | + else | |
147 | + {:action => 'index'} | |
148 | + end) | |
149 | + end | |
150 | + end | |
151 | + end | |
152 | + | |
137 | 153 | def destroy |
138 | 154 | @article = profile.articles.find(params[:id]) |
139 | 155 | if request.post? |
... | ... | @@ -215,5 +231,17 @@ class CmsController < MyProfileController |
215 | 231 | (available_article_types + special_article_types).map {|item| item.name}.include?(type) |
216 | 232 | end |
217 | 233 | |
234 | + def check_parent(id) | |
235 | + if id | |
236 | + parent = profile.articles.find(id) | |
237 | + if ! parent.allow_children? | |
238 | + raise ArgumentError.new("cannot create child of article which does not accept children") | |
239 | + end | |
240 | + parent | |
241 | + else | |
242 | + nil | |
243 | + end | |
244 | + end | |
245 | + | |
218 | 246 | end |
219 | 247 | ... | ... |
app/helpers/cms_helper.rb
... | ... | @@ -9,6 +9,12 @@ module CmsHelper |
9 | 9 | mime_type.gsub('/', '_').gsub('-', '') |
10 | 10 | end |
11 | 11 | |
12 | + def add_upload_file_field(name) | |
13 | + button_to_function :add, name, nil do |page| | |
14 | + page.insert_html :bottom, :uploaded_files, :partial => 'upload_file', :object => UploadedFile.new | |
15 | + end | |
16 | + end | |
17 | + | |
12 | 18 | attr_reader :environment |
13 | 19 | |
14 | 20 | def options_for_article(article) | ... | ... |
app/models/uploaded_file.rb
... | ... | @@ -11,7 +11,9 @@ class UploadedFile < Article |
11 | 11 | # :max_size => 5.megabytes |
12 | 12 | has_attachment :storage => :file_system, |
13 | 13 | :thumbnails => { :icon => [24,24] }, |
14 | - :thumbnail_class => Thumbnail | |
14 | + :thumbnail_class => Thumbnail, | |
15 | + :max_size => 5.megabytes, | |
16 | + :resize_to => '640x480>' | |
15 | 17 | |
16 | 18 | def self.max_size |
17 | 19 | UploadedFile.attachment_options[:max_size] | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<p><%= file_field_tag('uploaded_files[]') %></p> | ... | ... |
app/views/cms/_uploaded_file.rhtml
1 | -<%= required_fields_message %> | |
2 | - | |
3 | -<%= required labelled_form_field(_("Select the file you want to upload (max size %s).") % UploadedFile.max_size.to_humanreadable, file_field(:article, :uploaded_data)) %> | |
4 | - | |
5 | 1 | <%= labelled_form_field(_('Describe this file:'), text_area(:article, :abstract)) %> | ... | ... |
... | ... | @@ -0,0 +1,34 @@ |
1 | +<% if @errors %> | |
2 | + <div class="errorExplanation" id="errorExplanation"> | |
3 | + <h2><%= n_('This file couldn\'t be saved', 'These %{num} files couldn\'t be saved', @errors.size) % { :num => @errors.size } %></h2> | |
4 | + <p><%= _('There were problems with the following files:') %> </p> | |
5 | + <ul> | |
6 | + <% for file in @uploaded_files %> | |
7 | + <% for msg in file.errors.full_messages %> | |
8 | + <li><strong><%= file.name %></strong> : <%= msg %></li> | |
9 | + <% end %> | |
10 | + <% end %> | |
11 | + </ul> | |
12 | + </div> | |
13 | + | |
14 | +<% end %> | |
15 | + | |
16 | +<h2><%= _('Publish media') %></h2> | |
17 | + | |
18 | +<h3><%= _("Select the files you want to upload (max size %s):") % UploadedFile.max_size.to_humanreadable %></h3> | |
19 | +<h4><%= _('Photos/Videos/Audio/Documents') %></h4> | |
20 | + | |
21 | +<% form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %> | |
22 | + | |
23 | + <div id='uploaded_files'> | |
24 | + <%= render :partial => 'upload_file' %> | |
25 | + </div> | |
26 | + | |
27 | + <%= hidden_field_tag('parent_id', @parent.id) if @parent %> | |
28 | + | |
29 | + <% button_bar do %> | |
30 | + <%= add_upload_file_field _('More files') %> | |
31 | + <%= submit_button :save, _('Upload'), :cancel => {:action => (@parent ? 'view' : 'index'), :id => @parent } %> | |
32 | + <% end %> | |
33 | + | |
34 | +<% end %> | ... | ... |
app/views/cms/view.rhtml
... | ... | @@ -18,7 +18,7 @@ |
18 | 18 | <%= button :add, _('New folder'), :action => 'new', :type => 'Folder', :parent_id => parent_id %> |
19 | 19 | <% end %> |
20 | 20 | <%= lightbox_button('new', label_for_new_article(@article), :action => 'new', :parent_id => parent_id) %> |
21 | - <%= button('save', _('Upload file'), :action => 'new', :parent_id => parent_id, :type => 'UploadedFile') %> | |
21 | + <%= button('upload-file', _('Upload files'), :action => 'upload_files', :parent_id => parent_id) %> | |
22 | 22 | <% end %> |
23 | 23 | |
24 | 24 | <table class='cms-articles'> | ... | ... |
public/designs/icons/default/style.css
test/functional/cms_controller_test.rb
... | ... | @@ -209,6 +209,62 @@ class CmsControllerTest < Test::Unit::TestCase |
209 | 209 | end |
210 | 210 | end |
211 | 211 | |
212 | + should 'be able to upload more than one file at once' do | |
213 | + assert_difference UploadedFile, :count, 2 do | |
214 | + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain'), fixture_file_upload('/files/rails.png', 'text/plain')] | |
215 | + end | |
216 | + assert_not_nil profile.articles.find_by_path('test.txt') | |
217 | + assert_not_nil profile.articles.find_by_path('rails.png') | |
218 | + end | |
219 | + | |
220 | + should 'upload to rigth folder' do | |
221 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
222 | + post :upload_files, :profile => profile.identifier, :parent_id => f.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')] | |
223 | + f.reload | |
224 | + | |
225 | + assert_not_nil f.children[0] | |
226 | + assert_equal 'test.txt', f.children[0].name | |
227 | + end | |
228 | + | |
229 | + should 'not crash on empty file' do | |
230 | + assert_nothing_raised do | |
231 | + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain'), '' ] | |
232 | + end | |
233 | + assert_not_nil profile.articles.find_by_path('test.txt') | |
234 | + end | |
235 | + | |
236 | + should 'redirect to cms after uploading files' do | |
237 | + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')] | |
238 | + assert_redirected_to :action => 'index' | |
239 | + end | |
240 | + | |
241 | + should 'redirect to folder after uploading files' do | |
242 | + f = Folder.new(:name => 'f'); profile.articles << f; f.save! | |
243 | + post :upload_files, :profile => profile.identifier, :parent_id => f.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')] | |
244 | + assert_redirected_to :action => 'view', :id => f.id | |
245 | + end | |
246 | + | |
247 | + should 'display error message when file has more than max size' do | |
248 | + UploadedFile.any_instance.stubs(:size).returns(UploadedFile.attachment_options[:max_size] + 1024) | |
249 | + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/rails.png', 'image/png')] | |
250 | + assert assigns(:uploaded_files).first.size > UploadedFile.attachment_options[:max_size] | |
251 | + assert_tag :tag => 'div', :attributes => { :class => 'errorExplanation', :id => 'errorExplanation' } | |
252 | + end | |
253 | + | |
254 | + should 'not display error message when file has less than max size' do | |
255 | + UploadedFile.any_instance.stubs(:size).returns(UploadedFile.attachment_options[:max_size] - 1024) | |
256 | + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/rails.png', 'image/png')] | |
257 | + assert_no_tag :tag => 'div', :attributes => { :class => 'errorExplanation', :id => 'errorExplanation' } | |
258 | + end | |
259 | + | |
260 | + should 'not redirect when some file has errors' do | |
261 | + UploadedFile.any_instance.stubs(:size).returns(UploadedFile.attachment_options[:max_size] + 1024) | |
262 | + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/rails.png', 'image/png')] | |
263 | + assert_response :success | |
264 | + assert_template 'upload_files' | |
265 | + end | |
266 | + | |
267 | + | |
212 | 268 | should 'offer to create children' do |
213 | 269 | Article.any_instance.stubs(:allow_children?).returns(true) |
214 | 270 | |
... | ... | @@ -250,8 +306,8 @@ class CmsControllerTest < Test::Unit::TestCase |
250 | 306 | end |
251 | 307 | |
252 | 308 | should 'display max size of uploaded file' do |
253 | - get :new, :type => UploadedFile.name, :profile => profile.identifier | |
254 | - assert_tag :tag => 'label', :attributes => { :for => 'article_uploaded_data' }, :content => /max size #{UploadedFile.max_size.to_humanreadable}/ | |
309 | + get :upload_files, :profile => profile.identifier | |
310 | + assert_tag :tag => 'h3', :content => /max size #{UploadedFile.max_size.to_humanreadable}/ | |
255 | 311 | end |
256 | 312 | |
257 | 313 | should 'display link for selecting categories' do |
... | ... | @@ -766,5 +822,4 @@ class CmsControllerTest < Test::Unit::TestCase |
766 | 822 | get :edit, :profile => profile.identifier, :id => profile.blog.id |
767 | 823 | assert_tag :tag => 'a', :content => 'Cancel', :attributes => { :href => /\/myprofile\/#{profile.identifier}/ } |
768 | 824 | end |
769 | - | |
770 | 825 | end | ... | ... |
test/unit/uploaded_file_test.rb
... | ... | @@ -73,4 +73,16 @@ class UploadedFileTest < Test::Unit::TestCase |
73 | 73 | assert_equal false, file.can_display_hits? |
74 | 74 | end |
75 | 75 | |
76 | + should 'not upload files bigger than max_size' do | |
77 | + f = UploadedFile.new(:profile => @profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | |
78 | + f.expects(:size).returns(UploadedFile.attachment_options[:max_size] + 1024) | |
79 | + assert !f.valid? | |
80 | + end | |
81 | + | |
82 | + should 'upload files smaller than max_size' do | |
83 | + f = UploadedFile.new(:profile => @profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) | |
84 | + f.expects(:size).returns(UploadedFile.attachment_options[:max_size] - 1024) | |
85 | + assert f.valid? | |
86 | + end | |
87 | + | |
76 | 88 | end | ... | ... |