##// END OF EJS Templates
Bulk edit refactoring....
Jean-Philippe Lang -
r3364:e24d6cc2237d
parent child
Show More
@@ -260,29 +260,16 class IssuesController < ApplicationController
260 # Bulk edit a set of issues
260 # Bulk edit a set of issues
261 def bulk_edit
261 def bulk_edit
262 if request.post?
262 if request.post?
263 tracker = params[:tracker_id].blank? ? nil : @project.trackers.find_by_id(params[:tracker_id])
263 attributes = (params[:issue] || {}).reject {|k,v| v.blank?}
264 status = params[:status_id].blank? ? nil : IssueStatus.find_by_id(params[:status_id])
264 attributes.keys.each {|k| attributes[k] = '' if attributes[k] == 'none'}
265 priority = params[:priority_id].blank? ? nil : IssuePriority.find_by_id(params[:priority_id])
265 attributes[:custom_field_values].reject! {|k,v| v.blank?} if attributes[:custom_field_values]
266 assigned_to = (params[:assigned_to_id].blank? || params[:assigned_to_id] == 'none') ? nil : User.find_by_id(params[:assigned_to_id])
267 category = (params[:category_id].blank? || params[:category_id] == 'none') ? nil : @project.issue_categories.find_by_id(params[:category_id])
268 fixed_version = (params[:fixed_version_id].blank? || params[:fixed_version_id] == 'none') ? nil : @project.shared_versions.find_by_id(params[:fixed_version_id])
269 custom_field_values = params[:custom_field_values] ? params[:custom_field_values].reject {|k,v| v.blank?} : nil
270
271 # Need to merge in the records found above for Issue#bulk_edit.
272 # Assuming this is done so the associations are only looked up once.
273 merged_params = params.merge({
274 :tracker => tracker,
275 :status => status,
276 :priority => priority,
277 :assigned_to => assigned_to,
278 :category => category,
279 :fixed_version => fixed_version,
280 :custom_field_values => custom_field_values
281 })
282
266
283 unsaved_issue_ids = []
267 unsaved_issue_ids = []
284 @issues.each do |issue|
268 @issues.each do |issue|
285 unless issue.bulk_edit(merged_params)
269 journal = issue.init_journal(User.current, params[:notes])
270 issue.safe_attributes = attributes
271 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
272 unless issue.save
286 # Keep unsaved issue ids to display them in flash error
273 # Keep unsaved issue ids to display them in flash error
287 unsaved_issue_ids << issue.id
274 unsaved_issue_ids << issue.id
288 end
275 end
@@ -67,9 +67,9 module CustomFieldsHelper
67 custom_field_label_tag(name, custom_value) + custom_field_tag(name, custom_value)
67 custom_field_label_tag(name, custom_value) + custom_field_tag(name, custom_value)
68 end
68 end
69
69
70 def custom_field_tag_for_bulk_edit(custom_field)
70 def custom_field_tag_for_bulk_edit(name, custom_field)
71 field_name = "custom_field_values[#{custom_field.id}]"
71 field_name = "#{name}[custom_field_values][#{custom_field.id}]"
72 field_id = "custom_field_values_#{custom_field.id}"
72 field_id = "#{name}_custom_field_values_#{custom_field.id}"
73 case custom_field.field_format
73 case custom_field.field_format
74 when "date"
74 when "date"
75 text_field_tag(field_name, '', :id => field_id, :size => 10) +
75 text_field_tag(field_name, '', :id => field_id, :size => 10) +
@@ -136,24 +136,6 class Issue < ActiveRecord::Base
136 end
136 end
137 return issue
137 return issue
138 end
138 end
139
140 def bulk_edit(params)
141 journal = init_journal(User.current, params[:notes])
142 self.tracker = params[:tracker] if params[:tracker]
143 self.priority = params[:priority] if params[:priority]
144 self.assigned_to = params[:assigned_to] if params[:assigned_to] || params[:assigned_to_id] == 'none'
145 self.category = params[:category] if params[:category] || params[:category_id] == 'none'
146 self.fixed_version = params[:fixed_version] if params[:fixed_version] || params[:fixed_version_id] == 'none'
147 self.start_date = params[:start_date] unless params[:start_date].blank?
148 self.due_date = params[:due_date] unless params[:due_date].blank?
149 self.done_ratio = params[:done_ratio] unless params[:done_ratio].blank?
150 self.custom_field_values = params[:custom_field_values] if params[:custom_field_values] && !params[:custom_field_values].empty?
151 # TODO: Edit hook name
152 Redmine::Hook.call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => self })
153
154 # Don't save any change to the issue if the user is not authorized to apply the requested status
155 return (params[:status].nil? || (new_statuses_allowed_to(User.current).include?(params[:status]) && self.status = params[:status])) && save
156 end
157
139
158 def priority_id=(pid)
140 def priority_id=(pid)
159 self.priority = nil
141 self.priority = nil
@@ -206,7 +188,13 class Issue < ActiveRecord::Base
206 # TODO: move workflow/permission checks from controllers to here
188 # TODO: move workflow/permission checks from controllers to here
207 def safe_attributes=(attrs, user=User.current)
189 def safe_attributes=(attrs, user=User.current)
208 return if attrs.nil?
190 return if attrs.nil?
209 self.attributes = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)}
191 attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)}
192 if attrs['status_id']
193 unless new_statuses_allowed_to(user).collect(&:id).include?(attrs['status_id'].to_i)
194 attrs.delete('status_id')
195 end
196 end
197 self.attributes = attrs
210 end
198 end
211
199
212 def done_ratio
200 def done_ratio
@@ -11,39 +11,39
11 <div class="splitcontentleft">
11 <div class="splitcontentleft">
12 <p>
12 <p>
13 <label><%= l(:field_tracker) %></label>
13 <label><%= l(:field_tracker) %></label>
14 <%= select_tag('tracker_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@project.trackers, :id, :name)) %>
14 <%= select_tag('issue[tracker_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@project.trackers, :id, :name)) %>
15 </p>
15 </p>
16 <% if @available_statuses.any? %>
16 <% if @available_statuses.any? %>
17 <p>
17 <p>
18 <label><%= l(:field_status) %></label>
18 <label><%= l(:field_status) %></label>
19 <%= select_tag('status_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@available_statuses, :id, :name)) %>
19 <%= select_tag('issue[status_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@available_statuses, :id, :name)) %>
20 </p>
20 </p>
21 <% end %>
21 <% end %>
22 <p>
22 <p>
23 <label><%= l(:field_priority) %></label>
23 <label><%= l(:field_priority) %></label>
24 <%= select_tag('priority_id', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(IssuePriority.all, :id, :name)) %>
24 <%= select_tag('issue[priority_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(IssuePriority.all, :id, :name)) %>
25 </p>
25 </p>
26 <p>
26 <p>
27 <label><%= l(:field_assigned_to) %></label>
27 <label><%= l(:field_assigned_to) %></label>
28 <%= select_tag('assigned_to_id', content_tag('option', l(:label_no_change_option), :value => '') +
28 <%= select_tag('issue[assigned_to_id]', content_tag('option', l(:label_no_change_option), :value => '') +
29 content_tag('option', l(:label_nobody), :value => 'none') +
29 content_tag('option', l(:label_nobody), :value => 'none') +
30 options_from_collection_for_select(@project.assignable_users, :id, :name)) %>
30 options_from_collection_for_select(@project.assignable_users, :id, :name)) %>
31 </p>
31 </p>
32 <p>
32 <p>
33 <label><%= l(:field_category) %></label>
33 <label><%= l(:field_category) %></label>
34 <%= select_tag('category_id', content_tag('option', l(:label_no_change_option), :value => '') +
34 <%= select_tag('issue[category_id]', content_tag('option', l(:label_no_change_option), :value => '') +
35 content_tag('option', l(:label_none), :value => 'none') +
35 content_tag('option', l(:label_none), :value => 'none') +
36 options_from_collection_for_select(@project.issue_categories, :id, :name)) %>
36 options_from_collection_for_select(@project.issue_categories, :id, :name)) %>
37 </p>
37 </p>
38 <p>
38 <p>
39 <label><%= l(:field_fixed_version) %></label>
39 <label><%= l(:field_fixed_version) %></label>
40 <%= select_tag('fixed_version_id', content_tag('option', l(:label_no_change_option), :value => '') +
40 <%= select_tag('issue[fixed_version_id]', content_tag('option', l(:label_no_change_option), :value => '') +
41 content_tag('option', l(:label_none), :value => 'none') +
41 content_tag('option', l(:label_none), :value => 'none') +
42 version_options_for_select(@project.shared_versions.open)) %>
42 version_options_for_select(@project.shared_versions.open)) %>
43 </p>
43 </p>
44
44
45 <% @custom_fields.each do |custom_field| %>
45 <% @custom_fields.each do |custom_field| %>
46 <p><label><%= h(custom_field.name) %></label> <%= custom_field_tag_for_bulk_edit(custom_field) %></p>
46 <p><label><%= h(custom_field.name) %></label> <%= custom_field_tag_for_bulk_edit('issue', custom_field) %></p>
47 <% end %>
47 <% end %>
48
48
49 <%= call_hook(:view_issues_bulk_edit_details_bottom, { :issues => @issues }) %>
49 <%= call_hook(:view_issues_bulk_edit_details_bottom, { :issues => @issues }) %>
@@ -52,16 +52,16
52 <div class="splitcontentright">
52 <div class="splitcontentright">
53 <p>
53 <p>
54 <label><%= l(:field_start_date) %></label>
54 <label><%= l(:field_start_date) %></label>
55 <%= text_field_tag 'start_date', '', :size => 10 %><%= calendar_for('start_date') %>
55 <%= text_field_tag 'issue[start_date]', '', :size => 10 %><%= calendar_for('issue_start_date') %>
56 </p>
56 </p>
57 <p>
57 <p>
58 <label><%= l(:field_due_date) %></label>
58 <label><%= l(:field_due_date) %></label>
59 <%= text_field_tag 'due_date', '', :size => 10 %><%= calendar_for('due_date') %>
59 <%= text_field_tag 'issue[due_date]', '', :size => 10 %><%= calendar_for('issue_due_date') %>
60 </p>
60 </p>
61 <% if Issue.use_field_for_done_ratio? %>
61 <% if Issue.use_field_for_done_ratio? %>
62 <p>
62 <p>
63 <label><%= l(:field_done_ratio) %></label>
63 <label><%= l(:field_done_ratio) %></label>
64 <%= select_tag 'done_ratio', options_for_select([[l(:label_no_change_option), '']] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %>
64 <%= select_tag 'issue[done_ratio]', options_for_select([[l(:label_no_change_option), '']] + (0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %>
65 </p>
65 </p>
66 <% end %>
66 <% end %>
67 </div>
67 </div>
@@ -899,20 +899,21 class IssuesControllerTest < ActionController::TestCase
899 field = CustomField.find(9)
899 field = CustomField.find(9)
900 assert !field.is_for_all?
900 assert !field.is_for_all?
901 assert_equal 'date', field.field_format
901 assert_equal 'date', field.field_format
902 assert_tag :input, :attributes => {:name => 'custom_field_values[9]'}
902 assert_tag :input, :attributes => {:name => 'issue[custom_field_values][9]'}
903
903
904 # System wide custom field
904 # System wide custom field
905 assert CustomField.find(1).is_for_all?
905 assert CustomField.find(1).is_for_all?
906 assert_tag :select, :attributes => {:name => 'custom_field_values[1]'}
906 assert_tag :select, :attributes => {:name => 'issue[custom_field_values][1]'}
907 end
907 end
908
908
909 def test_bulk_edit
909 def test_bulk_edit
910 @request.session[:user_id] = 2
910 @request.session[:user_id] = 2
911 # update issues priority
911 # update issues priority
912 post :bulk_edit, :ids => [1, 2], :priority_id => 7,
912 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing',
913 :assigned_to_id => '',
913 :issue => {:priority_id => 7,
914 :custom_field_values => {'2' => ''},
914 :assigned_to_id => '',
915 :notes => 'Bulk editing'
915 :custom_field_values => {'2' => ''}}
916
916 assert_response 302
917 assert_response 302
917 # check that the issues were updated
918 # check that the issues were updated
918 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
919 assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
@@ -930,10 +931,12 class IssuesControllerTest < ActionController::TestCase
930 post(:bulk_edit,
931 post(:bulk_edit,
931 {
932 {
932 :ids => [1, 2],
933 :ids => [1, 2],
933 :priority_id => 7,
934 :notes => 'Bulk editing',
934 :assigned_to_id => '',
935 :issue => {
935 :custom_field_values => {'2' => ''},
936 :priority_id => 7,
936 :notes => 'Bulk editing'
937 :assigned_to_id => '',
938 :custom_field_values => {'2' => ''}
939 }
937 })
940 })
938
941
939 assert_response 302
942 assert_response 302
@@ -943,10 +946,11 class IssuesControllerTest < ActionController::TestCase
943 def test_bulk_edit_status
946 def test_bulk_edit_status
944 @request.session[:user_id] = 2
947 @request.session[:user_id] = 2
945 # update issues priority
948 # update issues priority
946 post :bulk_edit, :ids => [1, 2], :priority_id => '',
949 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing status',
947 :assigned_to_id => '',
950 :issue => {:priority_id => '',
948 :status_id => '5',
951 :assigned_to_id => '',
949 :notes => 'Bulk editing status'
952 :status_id => '5'}
953
950 assert_response 302
954 assert_response 302
951 issue = Issue.find(1)
955 issue = Issue.find(1)
952 assert issue.closed?
956 assert issue.closed?
@@ -955,10 +959,11 class IssuesControllerTest < ActionController::TestCase
955 def test_bulk_edit_custom_field
959 def test_bulk_edit_custom_field
956 @request.session[:user_id] = 2
960 @request.session[:user_id] = 2
957 # update issues priority
961 # update issues priority
958 post :bulk_edit, :ids => [1, 2], :priority_id => '',
962 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk editing custom field',
959 :assigned_to_id => '',
963 :issue => {:priority_id => '',
960 :custom_field_values => {'2' => '777'},
964 :assigned_to_id => '',
961 :notes => 'Bulk editing custom field'
965 :custom_field_values => {'2' => '777'}}
966
962 assert_response 302
967 assert_response 302
963
968
964 issue = Issue.find(1)
969 issue = Issue.find(1)
@@ -973,7 +978,7 class IssuesControllerTest < ActionController::TestCase
973 assert_not_nil Issue.find(2).assigned_to
978 assert_not_nil Issue.find(2).assigned_to
974 @request.session[:user_id] = 2
979 @request.session[:user_id] = 2
975 # unassign issues
980 # unassign issues
976 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :assigned_to_id => 'none'
981 post :bulk_edit, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
977 assert_response 302
982 assert_response 302
978 # check that the issues were updated
983 # check that the issues were updated
979 assert_nil Issue.find(2).assigned_to
984 assert_nil Issue.find(2).assigned_to
@@ -982,9 +987,7 class IssuesControllerTest < ActionController::TestCase
982 def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject
987 def test_post_bulk_edit_should_allow_fixed_version_to_be_set_to_a_subproject
983 @request.session[:user_id] = 2
988 @request.session[:user_id] = 2
984
989
985 post :bulk_edit,
990 post :bulk_edit, :ids => [1,2], :issue => {:fixed_version_id => 4}
986 :ids => [1,2],
987 :fixed_version_id => 4
988
991
989 assert_response :redirect
992 assert_response :redirect
990 issues = Issue.find([1,2])
993 issues = Issue.find([1,2])
General Comments 0
You need to be logged in to leave comments. Login now