Add field separator option to CSV export dialog (#37621).

Patch by Karel Pičman.


git-svn-id: https://svn.redmine.org/redmine/trunk@22359 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Go MAEDA
2023-10-21 06:19:13 +00:00
parent a69b43d580
commit 6a7f2536b5
12 changed files with 56 additions and 2 deletions

View File

@@ -1805,6 +1805,23 @@ module ApplicationHelper
end end
end end
def export_csv_separator_select_tag
options = [[l(:label_comma_char), ','], [l(:label_semi_colon_char), ';']]
# Add the separator from translations if it is missing
general_csv_separator = l(:general_csv_separator)
unless options.index { |option| option.last == general_csv_separator }
options << Array.new(2, general_csv_separator)
end
content_tag(:p) do
concat(
content_tag(:label) do
concat l(:label_fields_separator) + ' '
concat select_tag('field_separator', options_for_select(options, general_csv_separator))
end
)
end
end
# Returns an array of error messages for bulk edited items (issues, time entries) # Returns an array of error messages for bulk edited items (issues, time entries)
def bulk_edit_error_messages(items) def bulk_edit_error_messages(items)
messages = {} messages = {}

View File

@@ -323,7 +323,7 @@ module QueriesHelper
def query_to_csv(items, query, options={}) def query_to_csv(items, query, options={})
columns = query.columns columns = query.columns
Redmine::Export::CSV.generate(:encoding => params[:encoding]) do |csv| Redmine::Export::CSV.generate(encoding: params[:encoding], field_separator: params[:field_separator]) do |csv|
# csv header fields # csv header fields
csv << columns.map {|c| c.caption.to_s} csv << columns.map {|c| c.caption.to_s}
# csv lines # csv lines

View File

@@ -59,6 +59,7 @@
</fieldset> </fieldset>
<% end %> <% end %>
<%= export_csv_encoding_select_tag %> <%= export_csv_encoding_select_tag %>
<%= export_csv_separator_select_tag %>
<% if @issue_count > Setting.issues_export_limit.to_i %> <% if @issue_count > Setting.issues_export_limit.to_i %>
<p class="icon icon-warning"> <p class="icon icon-warning">
<%= l(:setting_issues_export_limit) %>: <%= Setting.issues_export_limit.to_i %> <%= l(:setting_issues_export_limit) %>: <%= Setting.issues_export_limit.to_i %>

View File

@@ -66,6 +66,7 @@
<label><%= radio_button_tag 'c[]', 'all_inline' %> <%= l(:description_all_columns) %></label> <label><%= radio_button_tag 'c[]', 'all_inline' %> <%= l(:description_all_columns) %></label>
</p> </p>
<%= export_csv_encoding_select_tag %> <%= export_csv_encoding_select_tag %>
<%= export_csv_separator_select_tag %>
<p class="buttons"> <p class="buttons">
<%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);", :data => { :disable_with => false } %> <%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);", :data => { :disable_with => false } %>
<%= link_to_function l(:button_cancel), "hideModal(this);" %> <%= link_to_function l(:button_cancel), "hideModal(this);" %>

View File

@@ -32,6 +32,7 @@
<h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3> <h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
<%= form_tag(project_issues_report_details_path(@project, :detail => params[:detail], :format => 'csv'), :method => :get, :id => 'csv-export-form') do %> <%= form_tag(project_issues_report_details_path(@project, :detail => params[:detail], :format => 'csv'), :method => :get, :id => 'csv-export-form') do %>
<%= export_csv_encoding_select_tag %> <%= export_csv_encoding_select_tag %>
<%= export_csv_separator_select_tag %>
<p class="buttons"> <p class="buttons">
<%= submit_tag l(:button_export), :name => nil, :onclick => 'hideModal(this);', :data => {:disable_with => false} %> <%= submit_tag l(:button_export), :name => nil, :onclick => 'hideModal(this);', :data => {:disable_with => false} %>
<%= link_to_function l(:button_cancel), 'hideModal(this);' %> <%= link_to_function l(:button_cancel), 'hideModal(this);' %>

View File

@@ -92,6 +92,7 @@
<h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3> <h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
<%= form_tag(permissions_roles_path(:format => 'csv'), :method => :get, :id => 'csv-export-form') do %> <%= form_tag(permissions_roles_path(:format => 'csv'), :method => :get, :id => 'csv-export-form') do %>
<%= export_csv_encoding_select_tag %> <%= export_csv_encoding_select_tag %>
<%= export_csv_separator_select_tag %>
<p class="buttons"> <p class="buttons">
<%= submit_tag l(:button_export), :name => nil, :onclick => 'hideModal(this);', :data => {:disable_with => false} %> <%= submit_tag l(:button_export), :name => nil, :onclick => 'hideModal(this);', :data => {:disable_with => false} %>
<%= link_to_function l(:button_cancel), 'hideModal(this);' %> <%= link_to_function l(:button_cancel), 'hideModal(this);' %>

View File

@@ -52,6 +52,7 @@
</fieldset> </fieldset>
<% end %> <% end %>
<%= export_csv_encoding_select_tag %> <%= export_csv_encoding_select_tag %>
<%= export_csv_separator_select_tag %>
<p class="buttons"> <p class="buttons">
<%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);", :data => { :disable_with => false } %> <%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);", :data => { :disable_with => false } %>
<%= link_to_function l(:button_cancel), "hideModal(this);" %> <%= link_to_function l(:button_cancel), "hideModal(this);" %>

View File

@@ -72,6 +72,7 @@
<div id="csv-export-options" style="display: none;"> <div id="csv-export-options" style="display: none;">
<h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3> <h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
<%= export_csv_encoding_select_tag %> <%= export_csv_encoding_select_tag %>
<%= export_csv_separator_select_tag %>
<p class="buttons"> <p class="buttons">
<%= submit_tag l(:button_export), :name => nil, :id => 'csv-export-button' %> <%= submit_tag l(:button_export), :name => nil, :id => 'csv-export-button' %>
<%= submit_tag l(:button_cancel), :name => nil, :onclick => 'hideModal(this);', :type => 'button' %> <%= submit_tag l(:button_cancel), :name => nil, :onclick => 'hideModal(this);', :type => 'button' %>

View File

@@ -45,6 +45,7 @@
</fieldset> </fieldset>
<% end %> <% end %>
<%= export_csv_encoding_select_tag %> <%= export_csv_encoding_select_tag %>
<%= export_csv_separator_select_tag %>
<p class="buttons"> <p class="buttons">
<%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);", :data => { :disable_with => false } %> <%= submit_tag l(:button_export), :name => nil, :onclick => "hideModal(this);", :data => { :disable_with => false } %>
<%= link_to_function l(:button_cancel), "hideModal(this);" %> <%= link_to_function l(:button_cancel), "hideModal(this);" %>

View File

@@ -31,7 +31,7 @@ module Redmine
class << self class << self
def generate(options = {}, &block) def generate(options = {}, &block)
col_sep = l(:general_csv_separator) col_sep = (options[:field_separator].presence || l(:general_csv_separator))
encoding = Encoding.find(options[:encoding]) rescue Encoding.find(l(:general_csv_encoding)) encoding = Encoding.find(options[:encoding]) rescue Encoding.find(l(:general_csv_encoding))
str = str =

View File

@@ -2244,6 +2244,20 @@ class ApplicationHelperTest < Redmine::HelperTest
end end
end end
def test_export_csv_separator_select_tag
with_locale 'en' do
result = export_csv_separator_select_tag
assert_equal ',', l(:general_csv_separator)
assert_select_in result, 'option[value=?][selected=selected]', ',', text: 'Comma'
assert_select_in result, 'option[value=?]', ';', text: 'Semicolon'
end
with_locale 'fr' do
result = export_csv_separator_select_tag
assert_equal ';', l(:general_csv_separator)
assert_select_in result, 'option[value=?][selected=selected]', ';'
end
end
private private
def wiki_links_with_special_characters def wiki_links_with_special_characters

View File

@@ -44,4 +44,20 @@ class CsvTest < ActiveSupport::TestCase
assert_equal l(:general_csv_encoding), string.encoding.name assert_equal l(:general_csv_encoding), string.encoding.name
end end
end end
def test_generate_should_use_general_csv_separator_by_default
with_locale 'fr' do
string = Redmine::Export::CSV.generate {|csv| csv << %w(Foo Bar)}
assert_equal ';', l(:general_csv_separator)
assert 'Foo;Bar', string
end
end
def test_generate_should_use_given_separator
with_locale 'fr' do
string = Redmine::Export::CSV.generate({field_separator: ','}) {|csv| csv << %w(Foo Bar)}
assert_equal ';', l(:general_csv_separator)
assert 'Foo,Bar', string
end
end
end end