@@ -16,9 +16,9 class ContextMenusController < ApplicationController | |||
|
16 | 16 | @projects = @issues.collect(&:project).compact.uniq |
|
17 | 17 | @project = @projects.first if @projects.size == 1 |
|
18 | 18 | |
|
19 |
@can = {:edit => |
|
|
19 | @can = {:edit => User.current.allowed_to?(:edit_issues, @projects), | |
|
20 | 20 | :log_time => (@project && User.current.allowed_to?(:log_time, @project)), |
|
21 |
:update => |
|
|
21 | :update => (User.current.allowed_to?(:edit_issues, @projects) || (User.current.allowed_to?(:change_status, @projects) && !@allowed_statuses.blank?)), | |
|
22 | 22 | :move => (@project && User.current.allowed_to?(:move_issues, @project)), |
|
23 | 23 | :copy => (@issue && @project.trackers.include?(@issue.tracker) && User.current.allowed_to?(:add_issues, @project)), |
|
24 | 24 | :delete => User.current.allowed_to?(:delete_issues, @projects) |
@@ -27,6 +27,10 class ContextMenusController < ApplicationController | |||
|
27 | 27 | @assignables = @project.assignable_users |
|
28 | 28 | @assignables << @issue.assigned_to if @issue && @issue.assigned_to && !@assignables.include?(@issue.assigned_to) |
|
29 | 29 | @trackers = @project.trackers |
|
30 | else | |
|
31 | #when multiple projects, we only keep the intersection of each set | |
|
32 | @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a} | |
|
33 | @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t} | |
|
30 | 34 | end |
|
31 | 35 | |
|
32 | 36 | @priorities = IssuePriority.all.reverse |
@@ -21,7 +21,7 class IssuesController < ApplicationController | |||
|
21 | 21 | |
|
22 | 22 | before_filter :find_issue, :only => [:show, :edit, :update] |
|
23 | 23 | before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :move, :perform_move, :destroy] |
|
24 |
before_filter :check_project_uniqueness, :only => [ |
|
|
24 | before_filter :check_project_uniqueness, :only => [:move, :perform_move] | |
|
25 | 25 | before_filter :find_project, :only => [:new, :create] |
|
26 | 26 | before_filter :authorize, :except => [:index] |
|
27 | 27 | before_filter :find_optional_project, :only => [:index] |
@@ -194,8 +194,10 class IssuesController < ApplicationController | |||
|
194 | 194 | # Bulk edit a set of issues |
|
195 | 195 | def bulk_edit |
|
196 | 196 | @issues.sort! |
|
197 |
@available_statuses = Workflow.available_statuses( |
|
|
198 | @custom_fields = @project.all_issue_custom_fields | |
|
197 | @available_statuses = @projects.map{|p|Workflow.available_statuses(p)}.inject{|memo,w|memo & w} | |
|
198 | @custom_fields = @projects.map{|p|p.all_issue_custom_fields}.inject{|memo,c|memo & c} | |
|
199 | @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a} | |
|
200 | @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t} | |
|
199 | 201 | end |
|
200 | 202 | |
|
201 | 203 | def bulk_update |
@@ -33,7 +33,6 | |||
|
33 | 33 | </li> |
|
34 | 34 | <% end %> |
|
35 | 35 | |
|
36 | <% if @projects.size == 1 %> | |
|
37 | 36 | <li class="folder"> |
|
38 | 37 | <a href="#" class="submenu"><%= l(:field_priority) %></a> |
|
39 | 38 | <ul> |
@@ -43,8 +42,8 | |||
|
43 | 42 | <% end -%> |
|
44 | 43 | </ul> |
|
45 | 44 | </li> |
|
46 | <% end %> | |
|
47 | 45 | |
|
46 | <% #TODO: allow editing versions when multiple projects %> | |
|
48 | 47 | <% unless @project.nil? || @project.shared_versions.open.empty? -%> |
|
49 | 48 | <li class="folder"> |
|
50 | 49 | <a href="#" class="submenu"><%= l(:field_fixed_version) %></a> |
@@ -85,7 +84,7 | |||
|
85 | 84 | </li> |
|
86 | 85 | <% end -%> |
|
87 | 86 | |
|
88 |
<% if Issue.use_field_for_done_ratio? |
|
|
87 | <% if Issue.use_field_for_done_ratio? %> | |
|
89 | 88 | <li class="folder"> |
|
90 | 89 | <a href="#" class="submenu"><%= l(:field_done_ratio) %></a> |
|
91 | 90 | <ul> |
@@ -11,7 +11,7 | |||
|
11 | 11 | <div class="splitcontentleft"> |
|
12 | 12 | <p> |
|
13 | 13 | <label><%= l(:field_tracker) %></label> |
|
14 |
<%= select_tag('issue[tracker_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@ |
|
|
14 | <%= select_tag('issue[tracker_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@trackers, :id, :name)) %> | |
|
15 | 15 | </p> |
|
16 | 16 | <% if @available_statuses.any? %> |
|
17 | 17 | <p> |
@@ -27,20 +27,25 | |||
|
27 | 27 | <label><%= l(:field_assigned_to) %></label> |
|
28 | 28 | <%= select_tag('issue[assigned_to_id]', content_tag('option', l(:label_no_change_option), :value => '') + |
|
29 | 29 | content_tag('option', l(:label_nobody), :value => 'none') + |
|
30 |
options_from_collection_for_select(@ |
|
|
30 | options_from_collection_for_select(@assignables, :id, :name)) %> | |
|
31 | 31 | </p> |
|
32 | <% if @project %> | |
|
32 | 33 | <p> |
|
33 | 34 | <label><%= l(:field_category) %></label> |
|
34 | 35 | <%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') + |
|
35 | 36 | content_tag('option', l(:label_none), :value => 'none') + |
|
36 | 37 | options_from_collection_for_select(@project.issue_categories, :id, :name)) %> |
|
37 | 38 | </p> |
|
39 | <% end %> | |
|
40 | <% #TODO: allow editing versions when multiple projects %> | |
|
41 | <% if @project %> | |
|
38 | 42 | <p> |
|
39 | 43 | <label><%= l(:field_fixed_version) %></label> |
|
40 | 44 | <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') + |
|
41 | 45 | content_tag('option', l(:label_none), :value => 'none') + |
|
42 | 46 | version_options_for_select(@project.shared_versions.open)) %> |
|
43 | 47 | </p> |
|
48 | <% end %> | |
|
44 | 49 | |
|
45 | 50 | <% @custom_fields.each do |custom_field| %> |
|
46 | 51 | <p><label><%= h(custom_field.name) %></label> <%= custom_field_tag_for_bulk_edit('issue', custom_field) %></p> |
@@ -85,6 +85,18 class ContextMenusControllerTest < ActionController::TestCase | |||
|
85 | 85 | assert_response :success |
|
86 | 86 | assert_template 'context_menu' |
|
87 | 87 | ids = "ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=6" |
|
88 | assert_tag :tag => 'a', :content => 'Edit', | |
|
89 | :attributes => { :href => "/issues/bulk_edit?#{ids}", | |
|
90 | :class => 'icon-edit' } | |
|
91 | assert_tag :tag => 'a', :content => 'Closed', | |
|
92 | :attributes => { :href => "/issues/bulk_edit?#{ids}&issue%5Bstatus_id%5D=5", | |
|
93 | :class => '' } | |
|
94 | assert_tag :tag => 'a', :content => 'Immediate', | |
|
95 | :attributes => { :href => "/issues/bulk_edit?#{ids}&issue%5Bpriority_id%5D=8", | |
|
96 | :class => '' } | |
|
97 | assert_tag :tag => 'a', :content => 'John Smith', | |
|
98 | :attributes => { :href => "/issues/bulk_edit?#{ids}&issue%5Bassigned_to_id%5D=2", | |
|
99 | :class => '' } | |
|
88 | 100 | assert_tag :tag => 'a', :content => 'Delete', |
|
89 | 101 | :attributes => { :href => "/issues/destroy?#{ids}", |
|
90 | 102 | :class => 'icon-del' } |
@@ -911,6 +911,19 class IssuesControllerTest < ActionController::TestCase | |||
|
911 | 911 | assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'} |
|
912 | 912 | end |
|
913 | 913 | |
|
914 | def test_get_bulk_edit_on_different_projects | |
|
915 | @request.session[:user_id] = 2 | |
|
916 | get :bulk_edit, :ids => [1, 2, 6] | |
|
917 | assert_response :success | |
|
918 | assert_template 'bulk_edit' | |
|
919 | ||
|
920 | # Project specific custom field, date type | |
|
921 | field = CustomField.find(9) | |
|
922 | assert !field.is_for_all? | |
|
923 | assert !field.project_ids.include?(Issue.find(6).project_id) | |
|
924 | assert_no_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'} | |
|
925 | end | |
|
926 | ||
|
914 | 927 | def test_bulk_update |
|
915 | 928 | @request.session[:user_id] = 2 |
|
916 | 929 | # update issues priority |
@@ -930,6 +943,39 class IssuesControllerTest < ActionController::TestCase | |||
|
930 | 943 | assert_equal 1, journal.details.size |
|
931 | 944 | end |
|
932 | 945 | |
|
946 | def test_bulk_update_on_different_projects | |
|
947 | @request.session[:user_id] = 2 | |
|
948 | # update issues priority | |
|
949 | post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing', | |
|
950 | :issue => {:priority_id => 7, | |
|
951 | :assigned_to_id => '', | |
|
952 | :custom_field_values => {'2' => ''}} | |
|
953 | ||
|
954 | assert_response 302 | |
|
955 | # check that the issues were updated | |
|
956 | assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id) | |
|
957 | ||
|
958 | issue = Issue.find(1) | |
|
959 | journal = issue.journals.find(:first, :order => 'created_on DESC') | |
|
960 | assert_equal '125', issue.custom_value_for(2).value | |
|
961 | assert_equal 'Bulk editing', journal.notes | |
|
962 | assert_equal 1, journal.details.size | |
|
963 | end | |
|
964 | ||
|
965 | def test_bulk_update_on_different_projects_without_rights | |
|
966 | @request.session[:user_id] = 3 | |
|
967 | user = User.find(3) | |
|
968 | action = { :controller => "issues", :action => "bulk_update" } | |
|
969 | assert user.allowed_to?(action, Issue.find(1).project) | |
|
970 | assert ! user.allowed_to?(action, Issue.find(6).project) | |
|
971 | post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail', | |
|
972 | :issue => {:priority_id => 7, | |
|
973 | :assigned_to_id => '', | |
|
974 | :custom_field_values => {'2' => ''}} | |
|
975 | assert_response 403 | |
|
976 | assert_not_equal "Bulk should fail", Journal.last.notes | |
|
977 | end | |
|
978 | ||
|
933 | 979 | def test_bullk_update_should_send_a_notification |
|
934 | 980 | @request.session[:user_id] = 2 |
|
935 | 981 | ActionMailer::Base.deliveries.clear |
General Comments 0
You need to be logged in to leave comments.
Login now