@@ -209,10 +209,25 class IssuesController < ApplicationController | |||
|
209 | 209 | # Bulk edit a set of issues |
|
210 | 210 | def bulk_edit |
|
211 | 211 | @issues.sort! |
|
212 | @available_statuses = @projects.map{|p|Workflow.available_statuses(p)}.inject{|memo,w|memo & w} | |
|
213 | @custom_fields = @projects.map{|p|p.all_issue_custom_fields}.inject{|memo,c|memo & c} | |
|
214 | @assignables = @projects.map(&:assignable_users).inject{|memo,a| memo & a} | |
|
215 | @trackers = @projects.map(&:trackers).inject{|memo,t| memo & t} | |
|
212 | ||
|
213 | if User.current.allowed_to?(:move_issues, @projects) | |
|
214 | @allowed_projects = Issue.allowed_target_projects_on_move | |
|
215 | if params[:issue] | |
|
216 | @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:issue][:project_id]} | |
|
217 | if @target_project | |
|
218 | target_projects = [@target_project] | |
|
219 | end | |
|
220 | end | |
|
221 | end | |
|
222 | target_projects ||= @projects | |
|
223 | ||
|
224 | @available_statuses = target_projects.map{|p|Workflow.available_statuses(p)}.inject{|memo,w|memo & w} | |
|
225 | @custom_fields = target_projects.map{|p|p.all_issue_custom_fields}.inject{|memo,c|memo & c} | |
|
226 | @assignables = target_projects.map(&:assignable_users).inject{|memo,a| memo & a} | |
|
227 | @trackers = target_projects.map(&:trackers).inject{|memo,t| memo & t} | |
|
228 | ||
|
229 | @notes = params[:notes] | |
|
230 | render :layout => false if request.xhr? | |
|
216 | 231 | end |
|
217 | 232 | |
|
218 | 233 | def bulk_update |
@@ -220,18 +235,30 class IssuesController < ApplicationController | |||
|
220 | 235 | attributes = parse_params_for_bulk_issue_attributes(params) |
|
221 | 236 | |
|
222 | 237 | unsaved_issue_ids = [] |
|
238 | moved_issues = [] | |
|
223 | 239 | @issues.each do |issue| |
|
224 | 240 | issue.reload |
|
225 | 241 | journal = issue.init_journal(User.current, params[:notes]) |
|
226 | 242 | issue.safe_attributes = attributes |
|
227 | 243 | call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue }) |
|
228 |
|
|
|
244 | if issue.save | |
|
245 | moved_issues << issue | |
|
246 | else | |
|
229 | 247 | # Keep unsaved issue ids to display them in flash error |
|
230 | 248 | unsaved_issue_ids << issue.id |
|
231 | 249 | end |
|
232 | 250 | end |
|
233 | 251 | set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids) |
|
234 | redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project}) | |
|
252 | ||
|
253 | if params[:follow] | |
|
254 | if @issues.size == 1 && moved_issues.size == 1 | |
|
255 | redirect_to :controller => 'issues', :action => 'show', :id => moved_issues.first | |
|
256 | elsif moved_issues.map(&:project).uniq.size == 1 | |
|
257 | redirect_to :controller => 'issues', :action => 'index', :project_id => moved_issues.map(&:project).first | |
|
258 | end | |
|
259 | else | |
|
260 | redirect_back_or_default({:controller => 'issues', :action => 'index', :project_id => @project}) | |
|
261 | end | |
|
235 | 262 | end |
|
236 | 263 | |
|
237 | 264 | verify :method => :delete, :only => :destroy, :render => { :nothing => true, :status => :method_not_allowed } |
@@ -7,13 +7,22 | |||
|
7 | 7 | ) + h(": #{i.subject}")) |
|
8 | 8 | }.join("\n").html_safe %></ul> |
|
9 | 9 | |
|
10 | <% form_tag(:action => 'bulk_update') do %> | |
|
10 | <% form_tag({:action => 'bulk_update'}, :id => 'bulk_edit_form') do %> | |
|
11 | 11 | <%= @issues.collect {|i| hidden_field_tag('ids[]', i.id)}.join("\n").html_safe %> |
|
12 | 12 | <div class="box tabular"> |
|
13 | 13 | <fieldset class="attributes"> |
|
14 | 14 | <legend><%= l(:label_change_properties) %></legend> |
|
15 | 15 | |
|
16 | 16 | <div class="splitcontentleft"> |
|
17 | <% if @allowed_projects.present? %> | |
|
18 | <p> | |
|
19 | <label for="issue_project_id"><%= l(:field_project) %></label> | |
|
20 | <%= select_tag('issue[project_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + project_tree_options_for_select(@allowed_projects, :selected => @target_project)) %> | |
|
21 | </p> | |
|
22 | <%= observe_field :issue_project_id, :url => {:action => 'bulk_edit'}, | |
|
23 | :update => 'content', | |
|
24 | :with => "Form.serialize('bulk_edit_form')" %> | |
|
25 | <% end %> | |
|
17 | 26 | <p> |
|
18 | 27 | <label for="issue_tracker_id"><%= l(:field_tracker) %></label> |
|
19 | 28 | <%= select_tag('issue[tracker_id]', "<option value=\"\">#{l(:label_no_change_option)}</option>" + options_from_collection_for_select(@trackers, :id, :name)) %> |
@@ -92,5 +101,13 | |||
|
92 | 101 | </fieldset> |
|
93 | 102 | </div> |
|
94 | 103 | |
|
95 | <p><%= submit_tag l(:button_submit) %></p> | |
|
104 | <p> | |
|
105 | <% if @target_project %> | |
|
106 | <%= submit_tag l(:button_move) %> | |
|
107 | <%= submit_tag l(:button_move_and_follow), :name => 'follow' %> | |
|
108 | <% else %> | |
|
109 | <%= submit_tag l(:button_submit) %> | |
|
110 | <% end %> | |
|
111 | </p> | |
|
112 | ||
|
96 | 113 | <% end %> |
@@ -198,7 +198,7 ActionController::Routing::Routes.draw do |map| | |||
|
198 | 198 | |
|
199 | 199 | map.resources :queries, :except => [:show] |
|
200 | 200 | map.resources :issues, |
|
201 | :collection => {:bulk_edit => :get, :bulk_update => :post} do |issues| | |
|
201 | :collection => {:bulk_edit => [:get, :post], :bulk_update => :post} do |issues| | |
|
202 | 202 | issues.resources :time_entries, :controller => 'timelog', |
|
203 | 203 | :collection => {:report => :get} |
|
204 | 204 | issues.resources :relations, :shallow => true, |
@@ -2033,6 +2033,7 class IssuesControllerTest < ActionController::TestCase | |||
|
2033 | 2033 | assert_response :success |
|
2034 | 2034 | assert_template 'bulk_edit' |
|
2035 | 2035 | |
|
2036 | assert_tag :select, :attributes => {:name => 'issue[project_id]'} | |
|
2036 | 2037 | assert_tag :input, :attributes => {:name => 'issue[parent_issue_id]'} |
|
2037 | 2038 | |
|
2038 | 2039 | # Project specific custom field, date type |
@@ -2185,6 +2186,38 class IssuesControllerTest < ActionController::TestCase | |||
|
2185 | 2186 | assert_equal 2, ActionMailer::Base.deliveries.size |
|
2186 | 2187 | end |
|
2187 | 2188 | |
|
2189 | def test_bulk_update_project | |
|
2190 | @request.session[:user_id] = 2 | |
|
2191 | post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'} | |
|
2192 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook' | |
|
2193 | # Issues moved to project 2 | |
|
2194 | assert_equal 2, Issue.find(1).project_id | |
|
2195 | assert_equal 2, Issue.find(2).project_id | |
|
2196 | # No tracker change | |
|
2197 | assert_equal 1, Issue.find(1).tracker_id | |
|
2198 | assert_equal 2, Issue.find(2).tracker_id | |
|
2199 | end | |
|
2200 | ||
|
2201 | def test_bulk_update_project_on_single_issue_should_follow_when_needed | |
|
2202 | @request.session[:user_id] = 2 | |
|
2203 | post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1' | |
|
2204 | assert_redirected_to '/issues/1' | |
|
2205 | end | |
|
2206 | ||
|
2207 | def test_bulk_update_project_on_multiple_issues_should_follow_when_needed | |
|
2208 | @request.session[:user_id] = 2 | |
|
2209 | post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1' | |
|
2210 | assert_redirected_to '/projects/onlinestore/issues' | |
|
2211 | end | |
|
2212 | ||
|
2213 | def test_bulk_update_tracker | |
|
2214 | @request.session[:user_id] = 2 | |
|
2215 | post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'} | |
|
2216 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook' | |
|
2217 | assert_equal 2, Issue.find(1).tracker_id | |
|
2218 | assert_equal 2, Issue.find(2).tracker_id | |
|
2219 | end | |
|
2220 | ||
|
2188 | 2221 | def test_bulk_update_status |
|
2189 | 2222 | @request.session[:user_id] = 2 |
|
2190 | 2223 | # update issues priority |
@@ -2198,6 +2231,24 class IssuesControllerTest < ActionController::TestCase | |||
|
2198 | 2231 | assert issue.closed? |
|
2199 | 2232 | end |
|
2200 | 2233 | |
|
2234 | def test_bulk_update_priority | |
|
2235 | @request.session[:user_id] = 2 | |
|
2236 | post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6} | |
|
2237 | ||
|
2238 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook' | |
|
2239 | assert_equal 6, Issue.find(1).priority_id | |
|
2240 | assert_equal 6, Issue.find(2).priority_id | |
|
2241 | end | |
|
2242 | ||
|
2243 | def test_bulk_update_with_notes | |
|
2244 | @request.session[:user_id] = 2 | |
|
2245 | post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues' | |
|
2246 | ||
|
2247 | assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook' | |
|
2248 | assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes | |
|
2249 | assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes | |
|
2250 | end | |
|
2251 | ||
|
2201 | 2252 | def test_bulk_update_parent_id |
|
2202 | 2253 | @request.session[:user_id] = 2 |
|
2203 | 2254 | post :bulk_update, :ids => [1, 3], |
@@ -123,6 +123,11 class RoutingIssuesTest < ActionController::IntegrationTest | |||
|
123 | 123 | { :method => 'get', :path => "/issues/bulk_edit" }, |
|
124 | 124 | { :controller => 'issues', :action => 'bulk_edit' } |
|
125 | 125 | ) |
|
126 | # For updating the bulk edit form | |
|
127 | assert_routing( | |
|
128 | { :method => 'post', :path => "/issues/bulk_edit" }, | |
|
129 | { :controller => 'issues', :action => 'bulk_edit' } | |
|
130 | ) | |
|
126 | 131 | assert_routing( |
|
127 | 132 | { :method => 'post', :path => "/issues/bulk_update" }, |
|
128 | 133 | { :controller => 'issues', :action => 'bulk_update' } |
General Comments 0
You need to be logged in to leave comments.
Login now