mirror of
https://github.com/redmine/redmine.git
synced 2026-04-02 02:31:17 +02:00
CSV export of project memberships (#37480).
Patch by Mizuki ISHIKAWA (user:ishikawa999). git-svn-id: https://svn.redmine.org/redmine/trunk@24487 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
@@ -28,17 +28,24 @@ class MembersController < ApplicationController
|
||||
|
||||
require_sudo_mode :create, :update, :destroy
|
||||
|
||||
include MembersHelper
|
||||
|
||||
def index
|
||||
scope = @project.memberships
|
||||
@offset, @limit = api_offset_and_limit
|
||||
@member_count = scope.count
|
||||
@member_pages = Paginator.new @member_count, @limit, params['page']
|
||||
@offset ||= @member_pages.offset
|
||||
@members = scope.includes(:principal, :roles).order(:id).limit(@limit).offset(@offset).to_a
|
||||
@members = scope.includes(:principal, :roles).order(:id)
|
||||
|
||||
respond_to do |format|
|
||||
format.html {head :not_acceptable}
|
||||
format.api
|
||||
format.api do
|
||||
@offset, @limit = api_offset_and_limit
|
||||
@member_count = scope.count
|
||||
@member_pages = Paginator.new @member_count, @limit, params['page']
|
||||
@offset ||= @member_pages.offset
|
||||
@members = @members.limit(@limit).offset(@offset).to_a
|
||||
end
|
||||
format.csv do
|
||||
send_data(members_to_csv(@members), type: 'text/csv; header=present', filename: "#{@project.identifier}-members.csv")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -62,4 +62,23 @@ module MembersHelper
|
||||
content_tag('em', content.join(", "), :class => "info")
|
||||
end
|
||||
end
|
||||
|
||||
def members_to_csv(members)
|
||||
Redmine::Export::CSV.generate(encoding: params[:encoding]) do |csv|
|
||||
# csv headers
|
||||
csv << [l(:label_name), l(:label_role), l(:field_principal), l(:label_project)]
|
||||
|
||||
# csv lines
|
||||
members.each do |member|
|
||||
member.roles.each do |role|
|
||||
csv << [
|
||||
member.principal.name,
|
||||
role.name,
|
||||
member.principal.is_a?(Group) ? l(:label_group) : l(:label_user),
|
||||
member.project.name
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -45,6 +45,19 @@
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% other_formats_links do |f| %>
|
||||
<%= f.link_to_with_query_parameters "CSV", {}, :onclick => "showModal('csv-export-options', '330px'); return false;" %>
|
||||
<% end %>
|
||||
<div id="csv-export-options" style="display: none;">
|
||||
<h3 class="title"><%= l(:label_export_options, :export_format => 'CSV') %></h3>
|
||||
<%= form_tag(project_memberships_path(project_id: @project.id, format: 'csv'), :method => :get, :id => 'csv-export-form') do %>
|
||||
<%= export_csv_encoding_select_tag %>
|
||||
<p class="buttons">
|
||||
<%= submit_tag l(:button_export), :name => nil, :onclick => 'hideModal(this);', :data => {:disable_with => false} %>
|
||||
<%= link_to_function l(:button_cancel), 'hideModal(this);' %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<p class="nodata"><%= l(:label_no_data) %></p>
|
||||
<% end %>
|
||||
|
||||
@@ -657,6 +657,7 @@ en:
|
||||
label_document_new: New document
|
||||
label_document_plural: Documents
|
||||
label_document_added: Document added
|
||||
label_name: Name
|
||||
label_role: Role
|
||||
label_role_plural: Roles
|
||||
label_role_new: New role
|
||||
|
||||
@@ -493,6 +493,7 @@ ja:
|
||||
label_document_new: 新しい文書
|
||||
label_document_plural: 文書
|
||||
label_document_added: 文書の追加
|
||||
label_name: 名前
|
||||
label_role: ロール
|
||||
label_role_plural: ロール
|
||||
label_role_new: 新しいロール
|
||||
|
||||
@@ -25,6 +25,37 @@ class MembersControllerTest < Redmine::ControllerTest
|
||||
@request.session[:user_id] = 2
|
||||
end
|
||||
|
||||
def test_index_with_csv_format_should_export_csv
|
||||
project = Project.find(5)
|
||||
get(
|
||||
:index,
|
||||
params: {
|
||||
project_id: project.id,
|
||||
format: 'csv'
|
||||
}
|
||||
)
|
||||
assert_response :success
|
||||
assert_equal 'text/csv; header=present', response.media_type
|
||||
|
||||
lines = response.body.chomp.split("\n")
|
||||
# Number of lines
|
||||
assert_equal project.memberships.sum{|m| m.roles.count } + 1, lines.size
|
||||
# Header
|
||||
assert_equal "Name,Role,User or Group,Project", lines.first
|
||||
# Details
|
||||
to_test = [
|
||||
'John Smith,Manager,User,Private child of eCookbook',
|
||||
'A Team,Manager,Group,Private child of eCookbook',
|
||||
'A Team,Developer,Group,Private child of eCookbook',
|
||||
'User Misc,Manager,User,Private child of eCookbook',
|
||||
'User Misc,Developer,User,Private child of eCookbook',
|
||||
'Redmine Admin,Manager,User,Private child of eCookbook'
|
||||
]
|
||||
to_test.each do |expected|
|
||||
assert_includes lines, expected
|
||||
end
|
||||
end
|
||||
|
||||
def test_new
|
||||
get(:new, :params => {:project_id => 1})
|
||||
assert_response :success
|
||||
|
||||
Reference in New Issue
Block a user