Commit 15390f79e01220faaf11994dcc83122f4e711930
Committed by
Antonio Terceiro
1 parent
483065d8
Exists in
master
and in
23 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 | ... | ... |