Feature #44015 » 0001-Add-groups_then_users_by_group-to-Assignee-List-Disp.patch
| app/helpers/application_helper.rb | ||
|---|---|---|
| 687 | 687 |
s << content_tag('option', "<< #{l(:label_me)} >>", :value => User.current.id)
|
| 688 | 688 |
end |
| 689 | 689 | |
| 690 |
involved_principals_html = +''
|
|
| 690 |
involved_principals = []
|
|
| 691 | 691 |
# This optgroup is displayed only when editing a single issue |
| 692 | 692 |
if @issue.present? && !@issue.new_record? |
| 693 |
involved_principals = [@issue.author, @issue.prior_assigned_to].uniq.compact
|
|
| 694 |
involved_principals_html = involved_principals.map do |p|
|
|
| 695 |
content_tag('option', p.name, value: p.id, disabled: !collection.include?(p))
|
|
| 696 |
end.join
|
|
| 693 |
involved_principals = |
|
| 694 |
[@issue.author, @issue.prior_assigned_to].uniq.compact.map do |principal|
|
|
| 695 |
[principal, {:disabled => !collection.include?(principal)}]
|
|
| 696 |
end
|
|
| 697 | 697 |
end |
| 698 | 698 | |
| 699 |
users_html = +'' |
|
| 700 |
groups_html = +'' |
|
| 701 |
collection.sort.each do |element| |
|
| 702 |
if option_value_selected?(element, selected) || element.id.to_s == selected |
|
| 703 |
selected_attribute = ' selected="selected"' |
|
| 704 |
end |
|
| 705 |
(element.is_a?(Group) ? groups_html : users_html) << |
|
| 706 |
%(<option value="#{element.id}"#{selected_attribute}>#{h element.name}</option>)
|
|
| 707 |
end |
|
| 708 |
if involved_principals_html.blank? && groups_html.blank? |
|
| 709 |
s << users_html |
|
| 699 |
users, groups = collection.sort.partition {|principal| principal.is_a?(User)}
|
|
| 700 |
if involved_principals.blank? && groups.blank? |
|
| 701 |
s << principals_option_tags(users, selected) |
|
| 710 | 702 |
else |
| 711 |
principal_optgroups = case Setting.assignee_dropdown_display_format.to_s |
|
| 712 |
when 'groups_then_users' |
|
| 713 |
[ |
|
| 714 |
[l(:label_group_plural), groups_html], |
|
| 715 |
[l(:label_user_plural), users_html] |
|
| 716 |
] |
|
| 717 |
else |
|
| 718 |
[ |
|
| 719 |
[l(:label_user_plural), users_html], |
|
| 720 |
[l(:label_group_plural), groups_html] |
|
| 721 |
] |
|
| 722 |
end |
|
| 723 |
([[l(:label_involved_principals), involved_principals_html]] + principal_optgroups).each do |label, options_html| |
|
| 703 |
optgroups = [[l(:label_involved_principals), involved_principals]] |
|
| 704 |
optgroups.concat( |
|
| 705 |
case Setting.assignee_dropdown_display_format.to_s |
|
| 706 |
when 'groups_then_users' |
|
| 707 |
[ |
|
| 708 |
[l(:label_group_plural), groups], |
|
| 709 |
[l(:label_user_plural), users] |
|
| 710 |
] |
|
| 711 |
when 'users_by_group' |
|
| 712 |
principal_users_by_group_optgroups_for_select(users, groups) |
|
| 713 |
else |
|
| 714 |
# Default to 'users_then_groups' |
|
| 715 |
[ |
|
| 716 |
[l(:label_user_plural), users], |
|
| 717 |
[l(:label_group_plural), groups] |
|
| 718 |
] |
|
| 719 |
end |
|
| 720 |
) |
|
| 721 | ||
| 722 |
optgroups.each do |label, principals| |
|
| 723 |
options_html = principals_option_tags(principals, selected) |
|
| 724 | 724 |
s << %(<optgroup label="#{h(label)}">#{options_html}</optgroup>) if options_html.present?
|
| 725 | 725 |
end |
| 726 | 726 |
end |
| 727 | 727 |
s.html_safe |
| 728 | 728 |
end |
| 729 | 729 | |
| 730 |
# Renders option tags for users and groups, preserving per-option attributes. |
|
| 731 |
def principals_option_tags(principals, selected) |
|
| 732 |
principals.map do |principal, options| |
|
| 733 |
options ||= {}
|
|
| 734 |
selected_attribute = %( selected="selected") if option_value_selected?(principal, selected) || principal.id.to_s == selected |
|
| 735 |
disabled_attribute = %( disabled="disabled") if options[:disabled] |
|
| 736 | ||
| 737 |
%(<option value="#{principal.id}"#{selected_attribute}#{disabled_attribute}>#{h principal.name}</option>)
|
|
| 738 |
end.join |
|
| 739 |
end |
|
| 740 | ||
| 741 |
# Builds optgroups that list groups first, then each group's users, then ungrouped users. |
|
| 742 |
def principal_users_by_group_optgroups_for_select(users, groups) |
|
| 743 |
users_by_group_optgroups = |
|
| 744 |
groups.filter_map do |group| |
|
| 745 |
group_user_ids = group.users.ids |
|
| 746 |
group_users = users.select {|user| group_user_ids.include?(user.id)}
|
|
| 747 |
[group, group_users] if group_users.present? |
|
| 748 |
end |
|
| 749 | ||
| 750 |
users_by_group_ids = users_by_group_optgroups.flat_map {|_, principals| principals.map(&:id)}.uniq
|
|
| 751 |
ungrouped_users = users.reject {|user| users_by_group_ids.include?(user.id)}
|
|
| 752 | ||
| 753 |
[[l(:label_group_plural), groups]] + |
|
| 754 |
users_by_group_optgroups.map {|group, principals| [group.name, principals]} +
|
|
| 755 |
[[l(:label_user_plural), ungrouped_users]] |
|
| 756 |
end |
|
| 757 | ||
| 730 | 758 |
def option_tag(name, text, value, selected=nil, options={})
|
| 731 | 759 |
content_tag 'option', value, options.merge(:value => value, :selected => (value == selected)) |
| 732 | 760 |
end |
| app/helpers/settings_helper.rb | ||
|---|---|---|
| 203 | 203 |
def assignee_dropdown_display_format_options |
| 204 | 204 |
options = [ |
| 205 | 205 |
[:label_assignee_dropdown_display_format_users_then_groups, 'users_then_groups'], |
| 206 |
[:label_assignee_dropdown_display_format_groups_then_users, 'groups_then_users'] |
|
| 206 |
[:label_assignee_dropdown_display_format_groups_then_users, 'groups_then_users'], |
|
| 207 |
[:label_assignee_dropdown_display_format_users_by_group, 'users_by_group'] |
|
| 207 | 208 |
] |
| 208 | 209 | |
| 209 | 210 |
options.map {|label, value| [l(label), value.to_s]}
|
| config/locales/en.yml | ||
|---|---|---|
| 1175 | 1175 |
label_involved_principals: Author / Previous assignee |
| 1176 | 1176 |
label_assignee_dropdown_display_format_users_then_groups: Users then groups |
| 1177 | 1177 |
label_assignee_dropdown_display_format_groups_then_users: Groups then users |
| 1178 |
label_assignee_dropdown_display_format_users_by_group: Users by group |
|
| 1178 | 1179 |
label_progressbar: Progress bar |
| 1179 | 1180 |
label_oauth_permission_admin: Administrate this Redmine |
| 1180 | 1181 |
label_oauth_admin_access: Administration |
| test/functional/issues_controller_test.rb | ||
|---|---|---|
| 4369 | 4369 |
end |
| 4370 | 4370 |
end |
| 4371 | 4371 | |
| 4372 |
def test_new_should_render_users_by_group_in_assignee_select_when_configured |
|
| 4373 |
project = Project.find(1) |
|
| 4374 |
group_a = Group.find(10) |
|
| 4375 |
group_b = Group.find(11) |
|
| 4376 |
project.members << Member.new(:principal => group_a, :roles => [Role.givable.first]) |
|
| 4377 |
project.members << Member.new(:principal => group_b, :roles => [Role.givable.first]) |
|
| 4378 | ||
| 4379 |
with_settings :issue_group_assignment => '1', :assignee_dropdown_display_format => 'users_by_group' do |
|
| 4380 |
@request.session[:user_id] = 2 |
|
| 4381 |
get :new, :params => {:project_id => project.id}
|
|
| 4382 |
assert_response :success |
|
| 4383 |
end |
|
| 4384 | ||
| 4385 |
assert_select 'select[name=?]', 'issue[assigned_to_id]' do |
|
| 4386 |
assert_select %(optgroup:nth-of-type(1)[label="#{l(:label_group_plural)}"]) do
|
|
| 4387 |
assert_select 'option[value="10"]', text: 'A Team' |
|
| 4388 |
assert_select 'option[value="11"]', text: 'B Team' |
|
| 4389 |
end |
|
| 4390 |
assert_select 'optgroup:nth-of-type(2)[label="A Team"]' do |
|
| 4391 |
assert_select 'option[value="8"]', text: 'User Misc' |
|
| 4392 |
end |
|
| 4393 |
assert_select 'optgroup:nth-of-type(3)[label="B Team"]' do |
|
| 4394 |
assert_select 'option[value="8"]', text: 'User Misc' |
|
| 4395 |
end |
|
| 4396 |
assert_select %(optgroup:nth-of-type(4)[label="#{l(:label_user_plural)}"]) do
|
|
| 4397 |
assert_select 'option[value="2"]', text: 'John Smith' |
|
| 4398 |
assert_select 'option[value="8"]', 0 |
|
| 4399 |
end |
|
| 4400 |
end |
|
| 4401 |
end |
|
| 4402 | ||
| 4372 | 4403 |
def test_post_create_without_start_date_and_default_start_date_is_not_creation_date |
| 4373 | 4404 |
with_settings :default_issue_start_date_to_creation_date => 0 do |
| 4374 | 4405 |
@request.session[:user_id] = 2 |
| test/helpers/application_helper_test.rb | ||
|---|---|---|
| 1956 | 1956 |
end |
| 1957 | 1957 |
end |
| 1958 | 1958 | |
| 1959 |
def test_principals_options_for_select_with_users_and_groups_with_users_by_group |
|
| 1960 |
User.current = nil |
|
| 1961 |
set_language_if_valid 'en' |
|
| 1962 |
principals = [User.find(2), User.find(8), Group.find(11), Group.find(10)] |
|
| 1963 | ||
| 1964 |
with_settings :assignee_dropdown_display_format => 'users_by_group' do |
|
| 1965 |
result = principals_options_for_select(principals) |
|
| 1966 | ||
| 1967 |
assert_select_in result, 'optgroup:nth-of-type(1)[label="Groups"]' do |
|
| 1968 |
assert_select 'option[value="10"]', text: 'A Team' |
|
| 1969 |
assert_select 'option[value="11"]', text: 'B Team' |
|
| 1970 |
end |
|
| 1971 |
assert_select_in result, 'optgroup:nth-of-type(2)[label="A Team"]' do |
|
| 1972 |
assert_select 'option[value="8"]', text: 'User Misc' |
|
| 1973 |
end |
|
| 1974 |
assert_select_in result, 'optgroup:nth-of-type(3)[label="B Team"]' do |
|
| 1975 |
assert_select 'option[value="8"]', text: 'User Misc' |
|
| 1976 |
end |
|
| 1977 |
assert_select_in result, 'optgroup:nth-of-type(4)[label="Users"]' do |
|
| 1978 |
assert_select 'option[value="2"]', text: 'John Smith' |
|
| 1979 |
assert_select 'option[value="8"]', 0 |
|
| 1980 |
end |
|
| 1981 |
end |
|
| 1982 |
end |
|
| 1983 | ||
| 1959 | 1984 |
def test_principals_options_for_select_with_empty_collection |
| 1960 | 1985 |
assert_equal '', principals_options_for_select([]) |
| 1961 | 1986 |
end |
- « Previous
- 1
- 2
- 3
- Next »