From: Jean-Philippe Lang Date: Tue, 19 Feb 2013 20:41:54 +0000 (+0000) Subject: Makes all time entry columns available in the CSV export. X-Git-Tag: 2.3.0~77 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=f8c649320f849dec288407a771d446108dc40931;p=redmine.git Makes all time entry columns available in the CSV export. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@11442 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb index a6f160fa0..e90442c68 100644 --- a/app/controllers/timelog_controller.rb +++ b/app/controllers/timelog_controller.rb @@ -39,6 +39,7 @@ class TimelogController < ApplicationController helper :custom_fields include CustomFieldsHelper helper :queries + include QueriesHelper def index @query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_') @@ -86,7 +87,7 @@ class TimelogController < ApplicationController :include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :order => sort_clause ) - send_data(entries_to_csv(@entries), :type => 'text/csv; header=present', :filename => 'timelog.csv') + send_data(entries_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv') } end end diff --git a/app/helpers/timelog_helper.rb b/app/helpers/timelog_helper.rb index cc4fbff47..380c4721c 100644 --- a/app/helpers/timelog_helper.rb +++ b/app/helpers/timelog_helper.rb @@ -86,44 +86,16 @@ module TimelogHelper value) end - def entries_to_csv(entries) - decimal_separator = l(:general_csv_decimal_separator) - custom_fields = TimeEntryCustomField.all + def entries_to_csv(entries, query, options={}) + encoding = l(:general_csv_encoding) + columns = (options[:columns] == 'all' ? query.available_inline_columns : query.inline_columns) + export = FCSV.generate(:col_sep => l(:general_csv_separator)) do |csv| # csv header fields - headers = [l(:field_spent_on), - l(:field_user), - l(:field_activity), - l(:field_project), - l(:field_issue), - l(:field_tracker), - l(:field_subject), - l(:field_hours), - l(:field_comments) - ] - # Export custom fields - headers += custom_fields.collect(&:name) - - csv << headers.collect {|c| Redmine::CodesetUtil.from_utf8( - c.to_s, - l(:general_csv_encoding) ) } + csv << columns.collect {|c| Redmine::CodesetUtil.from_utf8(c.caption.to_s, encoding) } # csv lines entries.each do |entry| - fields = [format_date(entry.spent_on), - entry.user, - entry.activity, - entry.project, - (entry.issue ? entry.issue.id : nil), - (entry.issue ? entry.issue.tracker : nil), - (entry.issue ? entry.issue.subject : nil), - entry.hours.to_s.gsub('.', decimal_separator), - entry.comments - ] - fields += custom_fields.collect {|f| show_value(entry.custom_field_values.detect {|v| v.custom_field_id == f.id}) } - - csv << fields.collect {|c| Redmine::CodesetUtil.from_utf8( - c.to_s, - l(:general_csv_encoding) ) } + csv << columns.collect {|c| Redmine::CodesetUtil.from_utf8(csv_content(c, entry), encoding) } end end export diff --git a/app/views/timelog/index.html.erb b/app/views/timelog/index.html.erb index 52c9118e7..e1fa5b26e 100644 --- a/app/views/timelog/index.html.erb +++ b/app/views/timelog/index.html.erb @@ -22,8 +22,22 @@ <% other_formats_links do |f| %> <%= f.link_to 'Atom', :url => params.merge({:issue_id => @issue, :key => User.current.rss_key}) %> - <%= f.link_to 'CSV', :url => params %> + <%= f.link_to 'CSV', :url => params, :onclick => "showModal('csv-export-options', '330px'); return false;" %> <% end %> + + <% end %> <% html_title l(:label_spent_time), l(:label_details) %> diff --git a/test/functional/timelog_controller_test.rb b/test/functional/timelog_controller_test.rb index 133c809e4..021f6624c 100644 --- a/test/functional/timelog_controller_test.rb +++ b/test/functional/timelog_controller_test.rb @@ -22,7 +22,9 @@ class TimelogControllerTest < ActionController::TestCase fixtures :projects, :enabled_modules, :roles, :members, :member_roles, :issues, :time_entries, :users, :trackers, :enumerations, :issue_statuses, - :custom_fields, :custom_values + :custom_fields, :custom_values, + :projects_trackers, :custom_fields_trackers, + :custom_fields_projects include Redmine::I18n @@ -546,186 +548,17 @@ class TimelogControllerTest < ActionController::TestCase assert assigns(:items).first.is_a?(TimeEntry) end - def test_index_all_projects_csv_export + def test_index_csv_all_projects Setting.date_format = '%m/%d/%Y' get :index, :format => 'csv' assert_response :success - assert_equal 'text/csv; header=present', @response.content_type - assert @response.body.include?("Date,User,Activity,Project,Issue,Tracker,Subject,Hours,Comment,Overtime\n") - assert @response.body.include?("\n04/21/2007,Redmine Admin,Design,eCookbook,3,Bug,Error 281 when updating a recipe,1.0,\"\",\"\"\n") + assert_equal 'text/csv; header=present', response.content_type end - def test_index_csv_export + def test_index_csv Setting.date_format = '%m/%d/%Y' get :index, :project_id => 1, :format => 'csv' assert_response :success - assert_equal 'text/csv; header=present', @response.content_type - assert @response.body.include?("Date,User,Activity,Project,Issue,Tracker,Subject,Hours,Comment,Overtime\n") - assert @response.body.include?("\n04/21/2007,Redmine Admin,Design,eCookbook,3,Bug,Error 281 when updating a recipe,1.0,\"\",\"\"\n") - end - - def test_index_csv_export_with_multi_custom_field - field = TimeEntryCustomField.create!(:name => 'Test', :field_format => 'list', - :multiple => true, :possible_values => ['value1', 'value2']) - entry = TimeEntry.find(1) - entry.custom_field_values = {field.id => ['value1', 'value2']} - entry.save! - - get :index, :project_id => 1, :format => 'csv' - assert_response :success - assert_include '"value1, value2"', @response.body - end - - def test_csv_big_5 - user = User.find_by_id(3) - user.language = "zh-TW" - assert user.save - str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88" - str_big5 = "\xa4@\xa4\xeb" - if str_utf8.respond_to?(:force_encoding) - str_utf8.force_encoding('UTF-8') - str_big5.force_encoding('Big5') - end - @request.session[:user_id] = 3 - post :create, :project_id => 1, - :time_entry => {:comments => str_utf8, - # Not the default activity - :activity_id => '11', - :issue_id => '', - :spent_on => '2011-11-10', - :hours => '7.3'} - assert_redirected_to :action => 'index', :project_id => 'ecookbook' - - t = TimeEntry.find_by_comments(str_utf8) - assert_not_nil t - assert_equal 11, t.activity_id - assert_equal 7.3, t.hours - assert_equal 3, t.user_id - - get :index, :project_id => 1, :format => 'csv', - :from => '2011-11-10', :to => '2011-11-10' - assert_response :success - assert_equal 'text/csv; header=present', @response.content_type - ar = @response.body.chomp.split("\n") - s1 = "\xa4\xe9\xb4\xc1" - if str_utf8.respond_to?(:force_encoding) - s1.force_encoding('Big5') - end - assert ar[0].include?(s1) - assert ar[1].include?(str_big5) - end - - def test_csv_cannot_convert_should_be_replaced_big_5 - user = User.find_by_id(3) - user.language = "zh-TW" - assert user.save - str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85" - if str_utf8.respond_to?(:force_encoding) - str_utf8.force_encoding('UTF-8') - end - @request.session[:user_id] = 3 - post :create, :project_id => 1, - :time_entry => {:comments => str_utf8, - # Not the default activity - :activity_id => '11', - :issue_id => '', - :spent_on => '2011-11-10', - :hours => '7.3'} - assert_redirected_to :action => 'index', :project_id => 'ecookbook' - - t = TimeEntry.find_by_comments(str_utf8) - assert_not_nil t - assert_equal 11, t.activity_id - assert_equal 7.3, t.hours - assert_equal 3, t.user_id - - get :index, :project_id => 1, :format => 'csv', - :from => '2011-11-10', :to => '2011-11-10' - assert_response :success - assert_equal 'text/csv; header=present', @response.content_type - ar = @response.body.chomp.split("\n") - s1 = "\xa4\xe9\xb4\xc1" - if str_utf8.respond_to?(:force_encoding) - s1.force_encoding('Big5') - end - assert ar[0].include?(s1) - s2 = ar[1].split(",")[8] - if s2.respond_to?(:force_encoding) - s3 = "\xa5H?" - s3.force_encoding('Big5') - assert_equal s3, s2 - elsif RUBY_PLATFORM == 'java' - assert_equal "??", s2 - else - assert_equal "\xa5H???", s2 - end - end - - def test_csv_tw - with_settings :default_language => "zh-TW" do - str1 = "test_csv_tw" - user = User.find_by_id(3) - te1 = TimeEntry.create(:spent_on => '2011-11-10', - :hours => 999.9, - :project => Project.find(1), - :user => user, - :activity => TimeEntryActivity.find_by_name('Design'), - :comments => str1) - te2 = TimeEntry.find_by_comments(str1) - assert_not_nil te2 - assert_equal 999.9, te2.hours - assert_equal 3, te2.user_id - - get :index, :project_id => 1, :format => 'csv', - :from => '2011-11-10', :to => '2011-11-10' - assert_response :success - assert_equal 'text/csv; header=present', @response.content_type - - ar = @response.body.chomp.split("\n") - s2 = ar[1].split(",")[7] - assert_equal '999.9', s2 - - str_tw = "Traditional Chinese (\xe7\xb9\x81\xe9\xab\x94\xe4\xb8\xad\xe6\x96\x87)" - if str_tw.respond_to?(:force_encoding) - str_tw.force_encoding('UTF-8') - end - assert_equal str_tw, l(:general_lang_name) - assert_equal ',', l(:general_csv_separator) - assert_equal '.', l(:general_csv_decimal_separator) - end - end - - def test_csv_fr - with_settings :default_language => "fr" do - str1 = "test_csv_fr" - user = User.find_by_id(3) - te1 = TimeEntry.create(:spent_on => '2011-11-10', - :hours => 999.9, - :project => Project.find(1), - :user => user, - :activity => TimeEntryActivity.find_by_name('Design'), - :comments => str1) - te2 = TimeEntry.find_by_comments(str1) - assert_not_nil te2 - assert_equal 999.9, te2.hours - assert_equal 3, te2.user_id - - get :index, :project_id => 1, :format => 'csv', - :from => '2011-11-10', :to => '2011-11-10' - assert_response :success - assert_equal 'text/csv; header=present', @response.content_type - - ar = @response.body.chomp.split("\n") - s2 = ar[1].split(";")[7] - assert_equal '999,9', s2 - - str_fr = "Fran\xc3\xa7ais" - if str_fr.respond_to?(:force_encoding) - str_fr.force_encoding('UTF-8') - end - assert_equal str_fr, l(:general_lang_name) - assert_equal ';', l(:general_csv_separator) - assert_equal ',', l(:general_csv_decimal_separator) - end + assert_equal 'text/csv; header=present', response.content_type end end