From 15390f79e01220faaf11994dcc83122f4e711930 Mon Sep 17 00:00:00 2001 From: Daniela Soares Feitosa Date: Wed, 18 Feb 2009 14:41:43 -0300 Subject: [PATCH] ActionItem774: allowing upload of more than one file at once --- app/controllers/my_profile/cms_controller.rb | 40 ++++++++++++++++++++++++++++++++++------ app/helpers/cms_helper.rb | 6 ++++++ app/models/uploaded_file.rb | 4 +++- app/views/cms/_upload_file.rhtml | 1 + app/views/cms/_uploaded_file.rhtml | 4 ---- app/views/cms/upload_files.rhtml | 34 ++++++++++++++++++++++++++++++++++ app/views/cms/view.rhtml | 2 +- public/designs/icons/default/style.css | 1 + test/functional/cms_controller_test.rb | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- test/unit/uploaded_file_test.rb | 12 ++++++++++++ 10 files changed, 150 insertions(+), 15 deletions(-) create mode 100644 app/views/cms/_upload_file.rhtml create mode 100644 app/views/cms/upload_files.rhtml diff --git a/app/controllers/my_profile/cms_controller.rb b/app/controllers/my_profile/cms_controller.rb index c8cef89..043368b 100644 --- a/app/controllers/my_profile/cms_controller.rb +++ b/app/controllers/my_profile/cms_controller.rb @@ -101,12 +101,8 @@ class CmsController < MyProfileController klass = @type.constantize @article = klass.new(params[:article]) - - if params[:parent_id] - parent = profile.articles.find(params[:parent_id]) - if ! parent.allow_children? - raise ArgumentError.new("cannot create child of article which does not accept children") - end + parent = check_parent(params[:parent_id]) + if parent @article.parent = parent @parent_id = parent.id end @@ -134,6 +130,26 @@ class CmsController < MyProfileController redirect_to :action => 'view', :id => @article.id end + def upload_files + @uploaded_files = [] + @parent = check_parent(params[:parent_id]) + if request.post? && params[:uploaded_files] + params[:uploaded_files].each do |file| + @uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent) unless file == '' + end + @errors = @uploaded_files.select { |f| f.errors.any? } + if @errors.any? + render :action => 'upload_files', :parent_id => @parent_id + else + redirect_to( if @parent + {:action => 'view', :id => @parent.id} + else + {:action => 'index'} + end) + end + end + end + def destroy @article = profile.articles.find(params[:id]) if request.post? @@ -215,5 +231,17 @@ class CmsController < MyProfileController (available_article_types + special_article_types).map {|item| item.name}.include?(type) end + def check_parent(id) + if id + parent = profile.articles.find(id) + if ! parent.allow_children? + raise ArgumentError.new("cannot create child of article which does not accept children") + end + parent + else + nil + end + end + end diff --git a/app/helpers/cms_helper.rb b/app/helpers/cms_helper.rb index 6d74b4b..cabf995 100644 --- a/app/helpers/cms_helper.rb +++ b/app/helpers/cms_helper.rb @@ -9,6 +9,12 @@ module CmsHelper mime_type.gsub('/', '_').gsub('-', '') end + def add_upload_file_field(name) + button_to_function :add, name, nil do |page| + page.insert_html :bottom, :uploaded_files, :partial => 'upload_file', :object => UploadedFile.new + end + end + attr_reader :environment def options_for_article(article) diff --git a/app/models/uploaded_file.rb b/app/models/uploaded_file.rb index 326b513..75303ec 100644 --- a/app/models/uploaded_file.rb +++ b/app/models/uploaded_file.rb @@ -11,7 +11,9 @@ class UploadedFile < Article # :max_size => 5.megabytes has_attachment :storage => :file_system, :thumbnails => { :icon => [24,24] }, - :thumbnail_class => Thumbnail + :thumbnail_class => Thumbnail, + :max_size => 5.megabytes, + :resize_to => '640x480>' def self.max_size UploadedFile.attachment_options[:max_size] diff --git a/app/views/cms/_upload_file.rhtml b/app/views/cms/_upload_file.rhtml new file mode 100644 index 0000000..f0018f4 --- /dev/null +++ b/app/views/cms/_upload_file.rhtml @@ -0,0 +1 @@ +

<%= file_field_tag('uploaded_files[]') %>

diff --git a/app/views/cms/_uploaded_file.rhtml b/app/views/cms/_uploaded_file.rhtml index c3fd36d..b7969fc 100644 --- a/app/views/cms/_uploaded_file.rhtml +++ b/app/views/cms/_uploaded_file.rhtml @@ -1,5 +1 @@ -<%= required_fields_message %> - -<%= required labelled_form_field(_("Select the file you want to upload (max size %s).") % UploadedFile.max_size.to_humanreadable, file_field(:article, :uploaded_data)) %> - <%= labelled_form_field(_('Describe this file:'), text_area(:article, :abstract)) %> diff --git a/app/views/cms/upload_files.rhtml b/app/views/cms/upload_files.rhtml new file mode 100644 index 0000000..12d79c3 --- /dev/null +++ b/app/views/cms/upload_files.rhtml @@ -0,0 +1,34 @@ +<% if @errors %> +
+

<%= n_('This file couldn\'t be saved', 'These %{num} files couldn\'t be saved', @errors.size) % { :num => @errors.size } %>

+

<%= _('There were problems with the following files:') %>

+ +
+ +<% end %> + +

<%= _('Publish media') %>

+ +

<%= _("Select the files you want to upload (max size %s):") % UploadedFile.max_size.to_humanreadable %>

+

<%= _('Photos/Videos/Audio/Documents') %>

+ +<% form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %> + +
+ <%= render :partial => 'upload_file' %> +
+ + <%= hidden_field_tag('parent_id', @parent.id) if @parent %> + + <% button_bar do %> + <%= add_upload_file_field _('More files') %> + <%= submit_button :save, _('Upload'), :cancel => {:action => (@parent ? 'view' : 'index'), :id => @parent } %> + <% end %> + +<% end %> diff --git a/app/views/cms/view.rhtml b/app/views/cms/view.rhtml index 3460ff2..0e00b95 100644 --- a/app/views/cms/view.rhtml +++ b/app/views/cms/view.rhtml @@ -18,7 +18,7 @@ <%= button :add, _('New folder'), :action => 'new', :type => 'Folder', :parent_id => parent_id %> <% end %> <%= lightbox_button('new', label_for_new_article(@article), :action => 'new', :parent_id => parent_id) %> - <%= button('save', _('Upload file'), :action => 'new', :parent_id => parent_id, :type => 'UploadedFile') %> + <%= button('upload-file', _('Upload files'), :action => 'upload_files', :parent_id => parent_id) %> <% end %> diff --git a/public/designs/icons/default/style.css b/public/designs/icons/default/style.css index e85723b..530f2e7 100644 --- a/public/designs/icons/default/style.css +++ b/public/designs/icons/default/style.css @@ -54,3 +54,4 @@ .icon-menu-comments { background-image: url(blog-HC.gif) } .icon-menu-people { background-image: url(album-HC.gif) } .icon-menu-mail { background-image: url(mail-HC.gif) } +.icon-upload-file { background-image: url(go-up-HC.gif) } diff --git a/test/functional/cms_controller_test.rb b/test/functional/cms_controller_test.rb index 7cd5f17..d4fbed0 100644 --- a/test/functional/cms_controller_test.rb +++ b/test/functional/cms_controller_test.rb @@ -209,6 +209,62 @@ class CmsControllerTest < Test::Unit::TestCase end end + should 'be able to upload more than one file at once' do + assert_difference UploadedFile, :count, 2 do + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain'), fixture_file_upload('/files/rails.png', 'text/plain')] + end + assert_not_nil profile.articles.find_by_path('test.txt') + assert_not_nil profile.articles.find_by_path('rails.png') + end + + should 'upload to rigth folder' do + f = Folder.new(:name => 'f'); profile.articles << f; f.save! + post :upload_files, :profile => profile.identifier, :parent_id => f.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')] + f.reload + + assert_not_nil f.children[0] + assert_equal 'test.txt', f.children[0].name + end + + should 'not crash on empty file' do + assert_nothing_raised do + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain'), '' ] + end + assert_not_nil profile.articles.find_by_path('test.txt') + end + + should 'redirect to cms after uploading files' do + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')] + assert_redirected_to :action => 'index' + end + + should 'redirect to folder after uploading files' do + f = Folder.new(:name => 'f'); profile.articles << f; f.save! + post :upload_files, :profile => profile.identifier, :parent_id => f.id, :uploaded_files => [fixture_file_upload('/files/test.txt', 'text/plain')] + assert_redirected_to :action => 'view', :id => f.id + end + + should 'display error message when file has more than max size' do + UploadedFile.any_instance.stubs(:size).returns(UploadedFile.attachment_options[:max_size] + 1024) + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/rails.png', 'image/png')] + assert assigns(:uploaded_files).first.size > UploadedFile.attachment_options[:max_size] + assert_tag :tag => 'div', :attributes => { :class => 'errorExplanation', :id => 'errorExplanation' } + end + + should 'not display error message when file has less than max size' do + UploadedFile.any_instance.stubs(:size).returns(UploadedFile.attachment_options[:max_size] - 1024) + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/rails.png', 'image/png')] + assert_no_tag :tag => 'div', :attributes => { :class => 'errorExplanation', :id => 'errorExplanation' } + end + + should 'not redirect when some file has errors' do + UploadedFile.any_instance.stubs(:size).returns(UploadedFile.attachment_options[:max_size] + 1024) + post :upload_files, :profile => profile.identifier, :uploaded_files => [fixture_file_upload('/files/rails.png', 'image/png')] + assert_response :success + assert_template 'upload_files' + end + + should 'offer to create children' do Article.any_instance.stubs(:allow_children?).returns(true) @@ -250,8 +306,8 @@ class CmsControllerTest < Test::Unit::TestCase end should 'display max size of uploaded file' do - get :new, :type => UploadedFile.name, :profile => profile.identifier - assert_tag :tag => 'label', :attributes => { :for => 'article_uploaded_data' }, :content => /max size #{UploadedFile.max_size.to_humanreadable}/ + get :upload_files, :profile => profile.identifier + assert_tag :tag => 'h3', :content => /max size #{UploadedFile.max_size.to_humanreadable}/ end should 'display link for selecting categories' do @@ -766,5 +822,4 @@ class CmsControllerTest < Test::Unit::TestCase get :edit, :profile => profile.identifier, :id => profile.blog.id assert_tag :tag => 'a', :content => 'Cancel', :attributes => { :href => /\/myprofile\/#{profile.identifier}/ } end - end diff --git a/test/unit/uploaded_file_test.rb b/test/unit/uploaded_file_test.rb index 67ec8fe..080cbe0 100644 --- a/test/unit/uploaded_file_test.rb +++ b/test/unit/uploaded_file_test.rb @@ -73,4 +73,16 @@ class UploadedFileTest < Test::Unit::TestCase assert_equal false, file.can_display_hits? end + should 'not upload files bigger than max_size' do + f = UploadedFile.new(:profile => @profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) + f.expects(:size).returns(UploadedFile.attachment_options[:max_size] + 1024) + assert !f.valid? + end + + should 'upload files smaller than max_size' do + f = UploadedFile.new(:profile => @profile, :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png')) + f.expects(:size).returns(UploadedFile.attachment_options[:max_size] - 1024) + assert f.valid? + end + end -- libgit2 0.21.2