Commit 15390f79e01220faaf11994dcc83122f4e711930

Authored by Daniela Feitosa
Committed by Antonio Terceiro
1 parent 483065d8

ActionItem774: allowing upload of more than one file at once

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 &lt; 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 &lt; 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]
... ...
app/views/cms/_upload_file.rhtml 0 → 100644
... ... @@ -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)) %>
... ...
app/views/cms/upload_files.rhtml 0 → 100644
... ... @@ -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
... ... @@ -54,3 +54,4 @@
54 54 .icon-menu-comments { background-image: url(blog-HC.gif) }
55 55 .icon-menu-people { background-image: url(album-HC.gif) }
56 56 .icon-menu-mail { background-image: url(mail-HC.gif) }
  57 +.icon-upload-file { background-image: url(go-up-HC.gif) }
... ...
test/functional/cms_controller_test.rb
... ... @@ -209,6 +209,62 @@ class CmsControllerTest &lt; 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 &lt; 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 &lt; 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 &lt; 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
... ...