##// END OF EJS Templates
Display the bulk edit form with error messages when some issues can not be saved (#13943)....
Jean-Philippe Lang -
r11556:1269e6c7d3f5
parent child
Show More
@@ -555,21 +555,6 class ApplicationController < ActionController::Base
555 flash[:warning] = l(:warning_attachments_not_saved, obj.unsaved_attachments.size) if obj.unsaved_attachments.present?
555 flash[:warning] = l(:warning_attachments_not_saved, obj.unsaved_attachments.size) if obj.unsaved_attachments.present?
556 end
556 end
557
557
558 # Sets the `flash` notice or error based the number of issues that did not save
559 #
560 # @param [Array, Issue] issues all of the saved and unsaved Issues
561 # @param [Array, Integer] unsaved_issue_ids the issue ids that were not saved
562 def set_flash_from_bulk_issue_save(issues, unsaved_issue_ids)
563 if unsaved_issue_ids.empty?
564 flash[:notice] = l(:notice_successful_update) unless issues.empty?
565 else
566 flash[:error] = l(:notice_failed_to_save_issues,
567 :count => unsaved_issue_ids.size,
568 :total => issues.size,
569 :ids => '#' + unsaved_issue_ids.join(', #'))
570 end
571 end
572
573 # Rescues an invalid query statement. Just in case...
558 # Rescues an invalid query statement. Just in case...
574 def query_statement_invalid(exception)
559 def query_statement_invalid(exception)
575 logger.error "Query::StatementInvalid: #{exception.message}" if logger
560 logger.error "Query::StatementInvalid: #{exception.message}" if logger
@@ -241,7 +241,6 class IssuesController < ApplicationController
241 end
241 end
242
242
243 @safe_attributes = @issues.map(&:safe_attribute_names).reduce(:&)
243 @safe_attributes = @issues.map(&:safe_attribute_names).reduce(:&)
244 render :layout => false if request.xhr?
245 end
244 end
246
245
247 def bulk_update
246 def bulk_update
@@ -249,8 +248,8 class IssuesController < ApplicationController
249 @copy = params[:copy].present?
248 @copy = params[:copy].present?
250 attributes = parse_params_for_bulk_issue_attributes(params)
249 attributes = parse_params_for_bulk_issue_attributes(params)
251
250
252 unsaved_issue_ids = []
251 unsaved_issues = []
253 moved_issues = []
252 saved_issues = []
254
253
255 if @copy && params[:copy_subtasks].present?
254 if @copy && params[:copy_subtasks].present?
256 # Descendant issues will be copied with the parent task
255 # Descendant issues will be copied with the parent task
@@ -270,24 +269,30 class IssuesController < ApplicationController
270 issue.safe_attributes = attributes
269 issue.safe_attributes = attributes
271 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
270 call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
272 if issue.save
271 if issue.save
273 moved_issues << issue
272 saved_issues << issue
274 else
273 else
275 logger.info "issue could not be updated or copied: #{issue.errors.full_messages}" if logger && logger.info
274 unsaved_issues << issue
276 # Keep unsaved issue ids to display them in flash error
277 unsaved_issue_ids << issue.id
278 end
275 end
279 end
276 end
280 set_flash_from_bulk_issue_save(@issues, unsaved_issue_ids)
281
277
278 if unsaved_issues.empty?
279 flash[:notice] = l(:notice_successful_update) unless saved_issues.empty?
282 if params[:follow]
280 if params[:follow]
283 if @issues.size == 1 && moved_issues.size == 1
281 if @issues.size == 1 && saved_issues.size == 1
284 redirect_to issue_path(moved_issues.first)
282 redirect_to issue_path(saved_issues.first)
285 elsif moved_issues.map(&:project).uniq.size == 1
283 elsif saved_issues.map(&:project).uniq.size == 1
286 redirect_to project_issues_path(moved_issues.map(&:project).first)
284 redirect_to project_issues_path(saved_issues.map(&:project).first)
287 end
285 end
288 else
286 else
289 redirect_back_or_default _project_issues_path(@project)
287 redirect_back_or_default _project_issues_path(@project)
290 end
288 end
289 else
290 @saved_issues = @issues
291 @unsaved_issues = unsaved_issues
292 @issues = Issue.visible.find_all_by_id(@unsaved_issues.map(&:id))
293 bulk_edit
294 render :action => 'bulk_edit'
295 end
291 end
296 end
292
297
293 def destroy
298 def destroy
@@ -94,6 +94,20 module IssuesHelper
94 s.html_safe
94 s.html_safe
95 end
95 end
96
96
97 # Returns an array of error messages for bulk edited issues
98 def bulk_edit_error_messages(issues)
99 messages = {}
100 issues.each do |issue|
101 issue.errors.full_messages.each do |message|
102 messages[message] ||= []
103 messages[message] << issue
104 end
105 end
106 messages.map { |message, issues|
107 "#{message}: " + issues.map {|i| "##{i.id}"}.join(', ')
108 }
109 end
110
97 # Returns a link for adding a new subtask to the given issue
111 # Returns a link for adding a new subtask to the given issue
98 def link_to_new_subtask(issue)
112 def link_to_new_subtask(issue)
99 attrs = {
113 attrs = {
@@ -1,5 +1,21
1 <h2><%= @copy ? l(:button_copy) : l(:label_bulk_edit_selected_issues) %></h2>
1 <h2><%= @copy ? l(:button_copy) : l(:label_bulk_edit_selected_issues) %></h2>
2
2
3 <% if @saved_issues && @unsaved_issues.present? %>
4 <div id="errorExplanation">
5 <span>
6 <%= l(:notice_failed_to_save_issues,
7 :count => @unsaved_issues.size,
8 :total => @saved_issues.size,
9 :ids => @unsaved_issues.map {|i| "##{i.id}"}.join(', ')) %>
10 </span>
11 <ul>
12 <% bulk_edit_error_messages(@unsaved_issues).each do |message| %>
13 <li><%= message %></li>
14 <% end %>
15 </ul>
16 </div>
17 <% end %>
18
3 <ul id="bulk-selection">
19 <ul id="bulk-selection">
4 <% @issues.each do |issue| %>
20 <% @issues.each do |issue| %>
5 <%= content_tag 'li', link_to_issue(issue) %>
21 <%= content_tag 'li', link_to_issue(issue) %>
@@ -3588,13 +3588,32 class IssuesControllerTest < ActionController::TestCase
3588 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
3588 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
3589 end
3589 end
3590
3590
3591 def test_bulk_update_with_failure_should_set_flash
3591 def test_bulk_update_with_all_failures_should_show_errors
3592 @request.session[:user_id] = 2
3592 @request.session[:user_id] = 2
3593 Issue.update_all("subject = ''", "id = 2") # Make it invalid
3593 post :bulk_update, :ids => [1, 2], :issue => {:start_date => 'foo'}
3594 post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
3595
3594
3596 assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
3595 assert_response :success
3597 assert_equal 'Failed to save 1 issue(s) on 2 selected: #2.', flash[:error]
3596 assert_template 'bulk_edit'
3597 assert_select '#errorExplanation span', :text => 'Failed to save 2 issue(s) on 2 selected: #1, #2.'
3598 assert_select '#errorExplanation ul li', :text => 'Start date is not a valid date: #1, #2'
3599
3600 assert_equal [1, 2], assigns[:issues].map(&:id)
3601 end
3602
3603 def test_bulk_update_with_some_failures_should_show_errors
3604 issue1 = Issue.generate!(:start_date => '2013-05-12')
3605 issue2 = Issue.generate!(:start_date => '2013-05-15')
3606 issue3 = Issue.generate!
3607
3608 @request.session[:user_id] = 2
3609 post :bulk_update, :ids => [issue1.id, issue2.id, issue3.id], :issue => {:due_date => '2013-05-01'}
3610
3611 assert_response :success
3612 assert_template 'bulk_edit'
3613 assert_select '#errorExplanation span', :text => "Failed to save 2 issue(s) on 3 selected: ##{issue1.id}, ##{issue2.id}."
3614 assert_select '#errorExplanation ul li', :text => "Due date must be greater than start date: ##{issue1.id}, ##{issue2.id}"
3615
3616 assert_equal [issue1.id, issue2.id], assigns[:issues].map(&:id)
3598 end
3617 end
3599
3618
3600 def test_get_bulk_copy
3619 def test_get_bulk_copy
General Comments 0
You need to be logged in to leave comments. Login now