Feature #43355 » 0002-groups-pagination.patch
| app/controllers/groups_controller.rb | ||
|---|---|---|
| 119 | 119 |
respond_to do |format| |
| 120 | 120 |
format.html do |
| 121 | 121 |
flash[:notice] = l(:notice_successful_update) |
| 122 |
redirect_back_or_default edit_group_path(@group, :tab => 'users')
|
|
| 122 |
redirect_back_or_default edit_group_path(@group, group_users_query)
|
|
| 123 | 123 |
end |
| 124 | 124 |
format.js |
| 125 | 125 |
format.api do |
| ... | ... | |
| 145 | 145 |
respond_to do |format| |
| 146 | 146 |
format.html do |
| 147 | 147 |
flash[:notice] = l(:notice_successful_delete) |
| 148 |
redirect_back_or_default edit_group_path(@group, :tab => 'users')
|
|
| 148 |
redirect_back_or_default edit_group_path(@group, group_users_query)
|
|
| 149 | 149 |
end |
| 150 | 150 |
format.api {render_api_ok}
|
| 151 | 151 |
end |
| ... | ... | |
| 174 | 174 |
def user_count_by_group_id |
| 175 | 175 |
User.joins(:groups).group(:group_id).count.transform_keys(&:to_i) |
| 176 | 176 |
end |
| 177 | ||
| 178 |
# Keeps the users tab and its pagination when redirecting after add/remove |
|
| 179 |
def group_users_query |
|
| 180 |
query = {:tab => 'users'}
|
|
| 181 |
query[:users_page] = params[:users_page] if params[:users_page].present? |
|
| 182 |
query[:per_page] = params[:per_page] if params[:per_page].present? |
|
| 183 |
query |
|
| 184 |
end |
|
| 177 | 185 |
end |
| app/helpers/groups_helper.rb | ||
|---|---|---|
| 50 | 50 |
end |
| 51 | 51 |
s + content_tag('span', links, :class => 'pagination')
|
| 52 | 52 |
end |
| 53 | ||
| 54 |
# Returns the requested page of the group's users together with its paginator |
|
| 55 |
# and the total user count, so the users tab loads only one page at a time |
|
| 56 |
# instead of rendering every user of the group. |
|
| 57 |
def paginate_group_users(group) |
|
| 58 |
scope = group.users.sorted |
|
| 59 |
user_count = scope.count |
|
| 60 |
user_pages = Redmine::Pagination::Paginator.new(user_count, per_page_option, params['users_page'], 'users_page') |
|
| 61 |
users = scope.limit(user_pages.per_page).offset(user_pages.offset).to_a |
|
| 62 |
[users, user_pages, user_count] |
|
| 63 |
end |
|
| 53 | 64 |
end |
| app/views/groups/_new_users_modal.html.erb | ||
|---|---|---|
| 1 | 1 |
<h3 class="title"><%= l(:label_user_new) %></h3> |
| 2 | 2 | |
| 3 |
<%= form_for(@group, :url => group_users_path(@group), :remote => true, :method => :post) do |f| %> |
|
| 3 |
<%= form_for(@group, :url => group_users_path(@group, :users_page => params[:users_page]), :remote => true, :method => :post) do |f| %>
|
|
| 4 | 4 |
<%= render :partial => 'new_users_form' %> |
| 5 | 5 |
<p class="buttons"> |
| 6 | 6 |
<%= submit_tag l(:button_add) %> |
| app/views/groups/_users.html.erb | ||
|---|---|---|
| 1 |
<p><%= link_to sprite_icon('add', l(:label_user_new)), new_group_users_path(@group), :remote => true, :class => "icon icon-add" %></p>
|
|
| 1 |
<% |
|
| 2 |
# A dedicated 'users_page' parameter is used so it does not clash with the |
|
| 3 |
# 'page' used by the add-user modal's principal list (render_principals_for_new_group_users). |
|
| 4 |
users, user_pages, user_count = paginate_group_users(@group) |
|
| 5 |
%> |
|
| 6 |
<p><%= link_to sprite_icon('add', l(:label_user_new)), new_group_users_path(@group, :users_page => params[:users_page]), :remote => true, :class => "icon icon-add" %></p>
|
|
| 2 | 7 | |
| 3 |
<% if @group.users.any? %>
|
|
| 8 |
<% if users.any? %> |
|
| 4 | 9 |
<table class="list users"> |
| 5 | 10 |
<thead><tr> |
| 6 | 11 |
<th><%= l(:label_user) %></th> |
| 7 | 12 |
<th style="width:15%"></th> |
| 8 | 13 |
</tr></thead> |
| 9 | 14 |
<tbody> |
| 10 |
<% @group.users.sort.each do |user| %>
|
|
| 15 |
<% users.each do |user| %>
|
|
| 11 | 16 |
<tr id="user-<%= user.id %>"> |
| 12 | 17 |
<td class="name"><%= link_to_user user %></td> |
| 13 | 18 |
<td class="buttons"> |
| 14 |
<%= link_to sprite_icon('link-break', l(:button_remove)), group_users_path(@group, :user_id => user), :method => :delete, :class => 'icon icon-link-break' %>
|
|
| 19 |
<%= link_to sprite_icon('link-break', l(:button_remove)), group_users_path(@group, :user_id => user, :users_page => params[:users_page]), :method => :delete, :class => 'icon icon-link-break' %>
|
|
| 15 | 20 |
</td> |
| 16 | 21 |
</tr> |
| 17 | 22 |
<% end %> |
| 18 | 23 |
</tbody> |
| 19 | 24 |
</table> |
| 25 |
<span class="pagination"> |
|
| 26 |
<%= pagination_links_full(user_pages, user_count) do |text, parameters, options| |
|
| 27 |
link_to text, edit_group_path(@group, request.query_parameters.merge(parameters).merge(:tab => 'users')), options |
|
| 28 |
end %> |
|
| 29 |
</span> |
|
| 20 | 30 |
<% else %> |
| 21 | 31 |
<p class="nodata"><%= l(:label_no_data) %></p> |
| 22 | 32 |
<% end %> |
| test/functional/groups_controller_test.rb | ||
|---|---|---|
| 169 | 169 |
assert_select 'div#tab-content-memberships a.icon-link-break', :text => 'Remove' |
| 170 | 170 |
end |
| 171 | 171 | |
| 172 |
def test_edit_users_tab_should_be_paginated |
|
| 173 |
group = Group.generate! |
|
| 174 |
3.times { group.users << User.generate! }
|
|
| 175 | ||
| 176 |
with_settings :per_page_options => '2,25,50' do |
|
| 177 |
get(:edit, :params => {:id => group.id, :tab => 'users'})
|
|
| 178 |
assert_response :success |
|
| 179 |
assert_select 'div#tab-content-users table.users tbody tr', :count => 2 |
|
| 180 |
assert_select 'div#tab-content-users span.pagination' |
|
| 181 |
# Pagination links keep the users tab and use the users_page parameter |
|
| 182 |
assert_select 'div#tab-content-users span.pagination a[href*=?]', 'users_page=' |
|
| 183 | ||
| 184 |
get(:edit, :params => {:id => group.id, :tab => 'users', :users_page => 2})
|
|
| 185 |
assert_response :success |
|
| 186 |
assert_select 'div#tab-content-users table.users tbody tr', :count => 1 |
|
| 187 |
end |
|
| 188 |
end |
|
| 189 | ||
| 190 |
def test_new_users_xhr_should_keep_current_page_in_form_action |
|
| 191 |
get(:new_users, :params => {:id => 10, :users_page => 2}, :xhr => true)
|
|
| 192 |
assert_response :success |
|
| 193 |
# The add-user form posts with the current page so the list stays on it after adding |
|
| 194 |
assert_match %r{/groups/10/users\?users_page=2}, response.body
|
|
| 195 |
end |
|
| 196 | ||
| 172 | 197 |
def test_update |
| 173 | 198 |
new_name = 'New name' |
| 174 | 199 |
put( |
| test/helpers/groups_helper_test.rb | ||
|---|---|---|
| 39 | 39 |
assert_select_in result, 'span.pagination li.current span', :text => '1' |
| 40 | 40 |
assert_select_in result, 'a[href=?]', "/groups/#{group.id}/autocomplete_for_user.js?page=2", :text => '2'
|
| 41 | 41 |
end |
| 42 | ||
| 43 |
def test_paginate_group_users_returns_only_the_requested_page |
|
| 44 |
# per_page_option is provided by ApplicationController in the running app |
|
| 45 |
stubs(:per_page_option).returns(2) |
|
| 46 |
group = Group.generate! |
|
| 47 |
3.times { group.users << User.generate! }
|
|
| 48 | ||
| 49 |
users, user_pages, user_count = paginate_group_users(group) |
|
| 50 | ||
| 51 |
assert_equal 2, users.size |
|
| 52 |
assert_equal 2, user_pages.per_page |
|
| 53 |
assert_equal group.users.count, user_count |
|
| 54 |
end |
|
| 42 | 55 |
end |
- « Previous
- 1
- 2
- 3
- Next »