Feature #31322 » 20200609-series.diff
config/locales/en.yml | ||
---|---|---|
1201 | 1201 |
text_time_logged_by_changeset: "Applied in changeset %{value}." |
1202 | 1202 |
text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?' |
1203 | 1203 |
text_issues_destroy_descendants_confirmation: "This will also delete %{count} subtask(s)." |
1204 |
text_close_parent_issue_with_open_subtasks_confirmation: Are you sure you want to close parent issue with open subtasks? |
|
1204 | 1205 |
text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies)?' |
1205 | 1206 |
text_select_project_modules: 'Select modules to enable for this project:' |
1206 | 1207 |
text_default_administrator_account_changed: Default administrator account changed |
app/views/issues/_edit.html.erb | ||
---|---|---|
82 | 82 |
<%= hidden_field_tag 'issue_position', @issue_position if @issue_position %> |
83 | 83 |
<%= hidden_field_tag 'issue_count', @issue_count if @issue_count %> |
84 | 84 |
<% end %> |
85 |
<%= javascript_tag do %> |
|
86 |
$('#issue-form').submit(function(){ |
|
87 |
var closedIssueStatusIds = |
|
88 |
<%= @allowed_statuses.select{|i| i.is_closed?}.map{|i| i.id.to_s}.to_json.html_safe %> ; |
|
89 |
var children = $("#issue_tree").find("tr.issue.child"); |
|
90 |
if (($.inArray($("#issue_status_id").val(), closedIssueStatusIds) > -1) && |
|
91 |
(children.length > 0) && |
|
92 |
((children.length - $("#issue_tree").find("tr.issue.child.closed").length) > 0)) { |
|
93 |
if (!confirm( |
|
94 |
"<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>" |
|
95 |
)){ |
|
96 |
return false; |
|
97 |
} |
|
98 |
} |
|
99 |
$("#issue-form").off('submit'); |
|
100 |
$("#issue-form").submit(); |
|
101 |
}); |
|
102 |
<% end %> |
test/system/issues_test.rb | ||
---|---|---|
234 | 234 |
assert_equal 5, issue.reload.status.id |
235 | 235 |
end |
236 | 236 | |
237 |
test "add confirm dialog to issue submit button" do |
|
238 |
parent = Issue.generate!(:project_id => 1) |
|
239 |
child = Issue.generate!(:project_id => 1, :parent_issue_id => parent.id) |
|
240 |
with_settings :closed_parent_issues_with_open_subtasks => 1 do |
|
241 |
log_user('dlopper', 'foo') |
|
242 |
visit "/issues/#{parent.id}" |
|
243 | ||
244 |
page.first(:link, 'Edit').click |
|
245 |
assert page.has_select?("issue_status_id", {:selected => "New"}) |
|
246 |
page.find("#issue_status_id").select("Closed") |
|
247 |
assert_no_difference ['Issue.count', 'child.journals.count'] do |
|
248 |
assert_no_difference 'parent.journals.count' do |
|
249 |
page.dismiss_confirm /Are you sure/ do |
|
250 |
page.first(:button, 'Submit').click |
|
251 |
end |
|
252 |
assert_equal 1, parent.reload.status.id |
|
253 |
end |
|
254 |
assert_difference 'parent.journals.count' do |
|
255 |
page.accept_confirm /Are you sure/ do |
|
256 |
page.first(:button, 'Submit').click |
|
257 |
end |
|
258 |
assert page.has_css?('#flash_notice') |
|
259 |
assert_equal 5, parent.reload.status.id |
|
260 |
end |
|
261 |
end |
|
262 | ||
263 |
page.first(:link, 'Edit').click |
|
264 |
assert page.has_select?("issue_status_id", {:selected => "Closed"}) |
|
265 |
fill_in 'Subject', :with => 'test of confirm dialog' |
|
266 |
assert_no_difference ['Issue.count', 'child.journals.count'] do |
|
267 |
assert_no_difference 'parent.journals.count' do |
|
268 |
page.dismiss_confirm /Are you sure/ do |
|
269 |
page.first(:button, 'Submit').click |
|
270 |
end |
|
271 |
assert_equal 5, parent.reload.status.id |
|
272 |
end |
|
273 |
assert_difference 'parent.journals.count' do |
|
274 |
page.accept_confirm /Are you sure/ do |
|
275 |
page.first(:button, 'Submit').click |
|
276 |
end |
|
277 |
assert page.has_css?('#flash_notice') |
|
278 |
assert_equal 5, parent.reload.status.id |
|
279 |
assert_equal 'test of confirm dialog', parent.reload.subject |
|
280 |
end |
|
281 |
end |
|
282 | ||
283 |
page.first(:link, 'Edit').click |
|
284 |
assert page.has_select?("issue_status_id", {:selected => "Closed"}) |
|
285 |
page.find("#issue_status_id").select("New") |
|
286 |
assert_no_difference ['Issue.count', 'child.journals.count'] do |
|
287 |
assert_difference 'parent.journals.count' do |
|
288 |
page.first(:button, 'Submit').click |
|
289 |
assert page.has_css?('#flash_notice') |
|
290 |
assert_equal 1, parent.reload.status.id |
|
291 |
end |
|
292 |
end |
|
293 | ||
294 |
visit "/issues/#{child.id}" |
|
295 |
page.first(:link, 'Edit').click |
|
296 |
assert page.has_select?("issue_status_id", {:selected => "New"}) |
|
297 |
page.find("#issue_status_id").select("Closed") |
|
298 |
assert_no_difference ['Issue.count', 'parent.journals.count'] do |
|
299 |
assert_difference 'child.journals.count' do |
|
300 |
page.first(:button, 'Submit').click |
|
301 |
assert page.has_css?('#flash_notice') |
|
302 |
assert_equal 5, child.reload.status.id |
|
303 |
end |
|
304 |
end |
|
305 | ||
306 |
visit "/issues/#{parent.id}" |
|
307 |
page.first(:link, 'Edit').click |
|
308 |
assert page.has_select?("issue_status_id", {:selected => "New"}) |
|
309 |
page.find("#issue_status_id").select("Closed") |
|
310 |
assert_no_difference ['Issue.count', 'child.journals.count'] do |
|
311 |
assert_difference 'parent.journals.count' do |
|
312 |
page.first(:button, 'Submit').click |
|
313 |
assert page.has_css?('#flash_notice') |
|
314 |
assert_equal 5, parent.reload.status.id |
|
315 |
end |
|
316 |
end |
|
317 |
end |
|
318 |
end |
|
319 | ||
237 | 320 |
test "removing issue shows confirm dialog" do |
238 | 321 |
log_user('jsmith', 'jsmith') |
239 | 322 |
visit '/issues/1' |
app/controllers/issues_controller.rb | ||
---|---|---|
181 | 181 |
end |
182 | 182 | |
183 | 183 |
def update |
184 |
if request.xhr? |
|
185 |
if params[:check_go_to_close_confirm] |
|
186 |
result = true |
|
187 |
status_id = params[:status_id].to_i |
|
188 |
if status_id <= 0 |
|
189 |
result = false |
|
190 |
else |
|
191 |
status = IssueStatus.find(status_id) |
|
192 |
if !status.is_closed |
|
193 |
result = false |
|
194 |
else |
|
195 |
result = !@issue.descendants.open.empty? |
|
196 |
end |
|
197 |
end |
|
198 |
render :json => {:result => result} |
|
199 |
return |
|
200 |
end |
|
201 | ||
202 |
return |
|
203 |
end |
|
204 | ||
184 | 205 |
return unless update_issue_from_params |
185 | 206 | |
186 | 207 |
@issue.save_attachments(params[:attachments] || |
app/views/issues/_edit.html.erb | ||
---|---|---|
84 | 84 |
<% end %> |
85 | 85 |
<%= javascript_tag do %> |
86 | 86 |
$('#issue-form').submit(function(){ |
87 |
var closedIssueStatusIds = |
|
88 |
<%= @allowed_statuses.select{|i| i.is_closed?}.map{|i| i.id.to_s}.to_json.html_safe %> ; |
|
89 |
var children = $("#issue_tree").find("tr.issue.child"); |
|
90 |
if (($.inArray($("#issue_status_id").val(), closedIssueStatusIds) > -1) && |
|
91 |
(children.length > 0) && |
|
92 |
((children.length - $("#issue_tree").find("tr.issue.child.closed").length) > 0)) { |
|
93 |
if (!confirm( |
|
94 |
"<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>" |
|
95 |
)){ |
|
96 |
return false; |
|
97 |
} |
|
87 |
var status_id = 0; |
|
88 |
if ($("#issue_status_id").length > 0) { |
|
89 |
status_id = $("#issue_status_id").val(); |
|
98 | 90 |
} |
99 |
$("#issue-form").off('submit'); |
|
100 |
$("#issue-form").submit(); |
|
91 |
$.ajax({ |
|
92 |
url: $("#issue-form").attr('action'), |
|
93 |
type: 'patch', |
|
94 |
data: { |
|
95 |
"check_go_to_close_confirm": "", |
|
96 |
"status_id": status_id |
|
97 |
}, |
|
98 |
}) |
|
99 |
.then( |
|
100 |
function(data){ |
|
101 |
var goto_submit = true; |
|
102 |
if (data["result"]) { |
|
103 |
if (!confirm( |
|
104 |
"<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>" |
|
105 |
)){ |
|
106 |
goto_submit = false; |
|
107 |
} |
|
108 |
} |
|
109 |
if (goto_submit) { |
|
110 |
$("#issue-form").off('submit'); |
|
111 |
$("#issue-form").submit(); |
|
112 |
} |
|
113 |
} |
|
114 |
); |
|
115 |
return false; |
|
101 | 116 |
}); |
102 | 117 |
<% end %> |
test/functional/issues_controller_test.rb | ||
---|---|---|
6370 | 6370 |
assert_equal 2, issue.reload.assigned_to_id |
6371 | 6371 |
end |
6372 | 6372 | |
6373 |
test "check_go_to_close_confirm returns false if status_id is not close" do |
|
6374 |
issue = Issue.find(1) |
|
6375 |
user = User.find(2) |
|
6376 |
assert issue.visible?(user) |
|
6377 |
assert_not issue.closed? |
|
6378 |
@request.session[:user_id] = user.id |
|
6379 |
put( |
|
6380 |
:update, |
|
6381 |
:params => { |
|
6382 |
:id => issue.id, |
|
6383 |
:check_go_to_close_confirm => "", |
|
6384 |
:status_id => 1 |
|
6385 |
}, |
|
6386 |
:xhr => true |
|
6387 |
) |
|
6388 |
assert_response :success |
|
6389 |
assert_equal 'application/json', response.content_type |
|
6390 |
json = ActiveSupport::JSON.decode(response.body) |
|
6391 |
assert_equal({"result" => false}, json) |
|
6392 |
end |
|
6393 | ||
6394 |
test "check_go_to_close_confirm returns false if status_id is 0" do |
|
6395 |
issue = Issue.find(1) |
|
6396 |
user = User.find(2) |
|
6397 |
assert issue.visible?(user) |
|
6398 |
assert_not issue.closed? |
|
6399 |
@request.session[:user_id] = user.id |
|
6400 |
put( |
|
6401 |
:update, |
|
6402 |
:params => { |
|
6403 |
:id => issue.id, |
|
6404 |
:check_go_to_close_confirm => "", |
|
6405 |
:status_id => 0 |
|
6406 |
}, |
|
6407 |
:xhr => true |
|
6408 |
) |
|
6409 |
assert_response :success |
|
6410 |
assert_equal 'application/json', response.content_type |
|
6411 |
json = ActiveSupport::JSON.decode(response.body) |
|
6412 |
assert_equal({"result" => false}, json) |
|
6413 |
end |
|
6414 | ||
6415 |
test "check_go_to_close_confirm returns false if issue does not have child" do |
|
6416 |
issue = Issue.generate! |
|
6417 |
user = User.find(2) |
|
6418 |
assert issue.visible?(user) |
|
6419 |
assert_not issue.closed? |
|
6420 |
@request.session[:user_id] = user.id |
|
6421 |
put( |
|
6422 |
:update, |
|
6423 |
:params => { |
|
6424 |
:id => issue.id, |
|
6425 |
:check_go_to_close_confirm => "", |
|
6426 |
:status_id => 5 |
|
6427 |
}, |
|
6428 |
:xhr => true |
|
6429 |
) |
|
6430 |
assert_response :success |
|
6431 |
assert_equal 'application/json', response.content_type |
|
6432 |
json = ActiveSupport::JSON.decode(response.body) |
|
6433 | ||
6434 |
assert_equal 1, issue.reload.status.id |
|
6435 |
assert_equal({"result" => false}, json) |
|
6436 |
end |
|
6437 | ||
6438 |
test "check_go_to_close_confirm returns true if issue have open child" do |
|
6439 |
parent = Issue.generate! |
|
6440 |
child = Issue.generate!(:parent_issue_id => parent.id) |
|
6441 |
user = User.find(2) |
|
6442 |
assert parent.reload.visible?(user) |
|
6443 |
assert_not parent.closed? |
|
6444 |
assert child.reload.visible?(user) |
|
6445 |
assert_not child.closed? |
|
6446 | ||
6447 |
@request.session[:user_id] = user.id |
|
6448 |
put( |
|
6449 |
:update, |
|
6450 |
:params => { |
|
6451 |
:id => parent.id, |
|
6452 |
:check_go_to_close_confirm => "", |
|
6453 |
:status_id => 5 |
|
6454 |
}, |
|
6455 |
:xhr => true |
|
6456 |
) |
|
6457 |
assert_response :success |
|
6458 |
assert_equal 'application/json', response.content_type |
|
6459 |
json = ActiveSupport::JSON.decode(response.body) |
|
6460 | ||
6461 |
assert_equal 1, parent.reload.status.id |
|
6462 |
assert_equal({"result" => true}, json) |
|
6463 |
end |
|
6464 | ||
6465 |
test "check_go_to_close_confirm returns false if child is closed" do |
|
6466 |
parent = Issue.generate! |
|
6467 |
child = Issue. |
|
6468 |
generate!( |
|
6469 |
:parent_issue_id => parent.id, |
|
6470 |
:status_id => 5 |
|
6471 |
) |
|
6472 |
user = User.find(2) |
|
6473 |
assert parent.reload.visible?(user) |
|
6474 |
assert_not parent.closed? |
|
6475 |
assert child.reload.visible?(user) |
|
6476 |
assert child.closed? |
|
6477 | ||
6478 |
@request.session[:user_id] = user.id |
|
6479 |
put( |
|
6480 |
:update, |
|
6481 |
:params => { |
|
6482 |
:id => parent.id, |
|
6483 |
:check_go_to_close_confirm => "", |
|
6484 |
:status_id => 5 |
|
6485 |
}, |
|
6486 |
:xhr => true |
|
6487 |
) |
|
6488 |
assert_response :success |
|
6489 |
assert_equal 'application/json', response.content_type |
|
6490 |
json = ActiveSupport::JSON.decode(response.body) |
|
6491 | ||
6492 |
assert_equal 1, parent.reload.status.id |
|
6493 |
assert_equal({"result" => false}, json) |
|
6494 |
end |
|
6495 | ||
6496 |
test "check_go_to_close_confirm returns true if child is open and not visible" do |
|
6497 |
user = User.generate! |
|
6498 |
project = Project.generate! |
|
6499 |
role = Role.generate! |
|
6500 |
role.add_permission! :view_issues, :edit_issues |
|
6501 |
role.set_permission_trackers :view_issues, [2] |
|
6502 |
role.set_permission_trackers :edit_issues, [2] |
|
6503 |
role.save! |
|
6504 |
User.add_to_project(user, project, role) |
|
6505 |
parent = Issue. |
|
6506 |
generate!( |
|
6507 |
:project => project, |
|
6508 |
:tracker_id => 2, |
|
6509 |
:status_id => 1 |
|
6510 |
) |
|
6511 |
child = Issue. |
|
6512 |
generate!( |
|
6513 |
:project => project, |
|
6514 |
:tracker_id => 1, |
|
6515 |
:parent_issue_id => parent.id, |
|
6516 |
:status_id => 1 |
|
6517 |
) |
|
6518 |
assert parent.reload.visible?(user) |
|
6519 |
assert_not parent.closed? |
|
6520 |
assert_not child.reload.visible?(user) |
|
6521 |
assert_not child.closed? |
|
6522 | ||
6523 |
@request.session[:user_id] = user.id |
|
6524 |
put( |
|
6525 |
:update, |
|
6526 |
:params => { |
|
6527 |
:id => parent.id, |
|
6528 |
:check_go_to_close_confirm => "", |
|
6529 |
:status_id => 5 |
|
6530 |
}, |
|
6531 |
:xhr => true |
|
6532 |
) |
|
6533 |
assert_response :success |
|
6534 |
assert_equal 'application/json', response.content_type |
|
6535 |
json = ActiveSupport::JSON.decode(response.body) |
|
6536 | ||
6537 |
assert_equal 1, parent.reload.status.id |
|
6538 |
assert_equal({"result" => true}, json) |
|
6539 |
end |
|
6540 | ||
6373 | 6541 |
def test_get_bulk_edit |
6374 | 6542 |
@request.session[:user_id] = 2 |
6375 | 6543 |
get(:bulk_edit, :params => {:ids => [1, 3]}) |
app/controllers/issues_controller.rb | ||
---|---|---|
199 | 199 |
return |
200 | 200 |
end |
201 | 201 | |
202 |
render( |
|
203 |
:partial => 'close_confirm', |
|
204 |
:layout => false, |
|
205 |
:locals => {} |
|
206 |
) |
|
202 | 207 |
return |
203 | 208 |
end |
204 | 209 |
app/views/issues/_close_confirm.js.erb | ||
---|---|---|
1 |
$('#ajax-modal').html( |
|
2 |
'<%= escape_javascript( |
|
3 |
render( |
|
4 |
:partial => 'close_confirm_dialog', |
|
5 |
:locals => {} |
|
6 |
) |
|
7 |
) |
|
8 |
%>' |
|
9 |
); |
|
10 |
showModal('ajax-modal', '400px'); |
app/views/issues/_close_confirm_dialog.html.erb | ||
---|---|---|
1 |
<h3 class="title"> </h3> |
|
2 |
<p> |
|
3 |
<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %> |
|
4 |
</p> |
|
5 |
<p class="buttons"> |
|
6 |
<%= button_tag l(:button_apply), :type => "button", :onclick => "run_submit();" %> |
|
7 |
<%= link_to_function l(:button_cancel), "hideModal(this);" %> |
|
8 |
</p> |
|
9 | ||
10 |
<%= javascript_tag do %> |
|
11 |
function run_submit() { |
|
12 |
$("#issue-form").off('submit'); |
|
13 |
$("#issue-form").submit(); |
|
14 |
} |
|
15 |
<% end %> |
app/views/issues/_edit.html.erb | ||
---|---|---|
98 | 98 |
}) |
99 | 99 |
.then( |
100 | 100 |
function(data){ |
101 |
var goto_submit = true; |
|
102 | 101 |
if (data["result"]) { |
103 |
if (!confirm( |
|
104 |
"<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %>" |
|
105 |
)){ |
|
106 |
goto_submit = false; |
|
107 |
} |
|
108 |
} |
|
109 |
if (goto_submit) { |
|
102 |
$.ajax({ |
|
103 |
url: $("#issue-form").attr('action'), |
|
104 |
type: 'patch', |
|
105 |
data: {} |
|
106 |
}); |
|
107 |
} else { |
|
110 | 108 |
$("#issue-form").off('submit'); |
111 | 109 |
$("#issue-form").submit(); |
112 | 110 |
} |
test/system/issues_test.rb | ||
---|---|---|
246 | 246 |
page.find("#issue_status_id").select("Closed") |
247 | 247 |
assert_no_difference ['Issue.count', 'child.journals.count'] do |
248 | 248 |
assert_no_difference 'parent.journals.count' do |
249 |
page.dismiss_confirm /Are you sure/ do |
|
250 |
page.first(:button, 'Submit').click |
|
249 |
page.first(:button, 'Submit').click |
|
250 |
within('#ajax-modal') do |
|
251 |
assert page.has_text?(/Are you sure/) |
|
252 |
page.first(:link, 'Cancel').click |
|
251 | 253 |
end |
252 | 254 |
assert_equal 1, parent.reload.status.id |
253 | 255 |
end |
254 | 256 |
assert_difference 'parent.journals.count' do |
255 |
page.accept_confirm /Are you sure/ do |
|
256 |
page.first(:button, 'Submit').click |
|
257 |
page.first(:button, 'Submit').click |
|
258 |
within('#ajax-modal') do |
|
259 |
assert page.has_text?(/Are you sure/) |
|
260 |
page.first(:button, 'Apply').click |
|
257 | 261 |
end |
258 | 262 |
assert page.has_css?('#flash_notice') |
259 | 263 |
assert_equal 5, parent.reload.status.id |
... | ... | |
265 | 269 |
fill_in 'Subject', :with => 'test of confirm dialog' |
266 | 270 |
assert_no_difference ['Issue.count', 'child.journals.count'] do |
267 | 271 |
assert_no_difference 'parent.journals.count' do |
268 |
page.dismiss_confirm /Are you sure/ do |
|
269 |
page.first(:button, 'Submit').click |
|
272 |
page.first(:button, 'Submit').click |
|
273 |
within('#ajax-modal') do |
|
274 |
assert page.has_text?(/Are you sure/) |
|
275 |
page.first(:link, 'Cancel').click |
|
270 | 276 |
end |
271 | 277 |
assert_equal 5, parent.reload.status.id |
272 | 278 |
end |
273 | 279 |
assert_difference 'parent.journals.count' do |
274 |
page.accept_confirm /Are you sure/ do |
|
275 |
page.first(:button, 'Submit').click |
|
280 |
page.first(:button, 'Submit').click |
|
281 |
within('#ajax-modal') do |
|
282 |
assert page.has_text?(/Are you sure/) |
|
283 |
page.first(:button, 'Apply').click |
|
276 | 284 |
end |
277 | 285 |
assert page.has_css?('#flash_notice') |
278 | 286 |
assert_equal 5, parent.reload.status.id |
app/controllers/issues_controller.rb | ||
---|---|---|
184 | 184 |
if request.xhr? |
185 | 185 |
if params[:check_go_to_close_confirm] |
186 | 186 |
result = true |
187 |
status = nil |
|
187 | 188 |
status_id = params[:status_id].to_i |
189 |
can_close_all_descendants = true |
|
188 | 190 |
if status_id <= 0 |
189 | 191 |
result = false |
190 | 192 |
else |
... | ... | |
192 | 194 |
if !status.is_closed |
193 | 195 |
result = false |
194 | 196 |
else |
195 |
result = !@issue.descendants.open.empty? |
|
197 |
opened_descendants = [] |
|
198 |
@issue.descendants.open.sort_by(&:lft).each do |issue| |
|
199 |
unless issue.visible? |
|
200 |
can_close_all_descendants = false |
|
201 |
break |
|
202 |
end |
|
203 | ||
204 |
unless issue.new_statuses_allowed_to.map{|i| i.id}.include?(status.id) |
|
205 |
can_close_all_descendants = false |
|
206 |
break |
|
207 |
end |
|
208 | ||
209 |
opened_descendants << issue |
|
210 |
end |
|
211 |
if can_close_all_descendants && opened_descendants.empty? |
|
212 |
result = false |
|
213 |
can_close_all_descendants = false |
|
214 |
end |
|
215 |
end |
|
216 |
if result |
|
217 |
session[:can_close_descendant] = {} |
|
218 |
session[:can_close_descendant][:can_close_all] = can_close_all_descendants |
|
219 |
if can_close_all_descendants |
|
220 |
session[:can_close_descendant][:status_id] = status.id |
|
221 |
session[:can_close_descendant][:status_name] = status.name |
|
222 |
session[:can_close_descendant][:ids] = opened_descendants.map{|i| i.id} |
|
223 |
end |
|
196 | 224 |
end |
197 | 225 |
end |
198 | 226 |
render :json => {:result => result} |
199 | 227 |
return |
200 | 228 |
end |
201 | 229 | |
230 |
if !session.has_key?(:can_close_descendant) |
|
231 |
return |
|
232 |
end |
|
233 | ||
234 |
render_data = { |
|
235 |
:status_name => session[:can_close_descendant][:status_name], |
|
236 |
:can_close_all => session[:can_close_descendant][:can_close_all] |
|
237 |
} |
|
202 | 238 |
render( |
203 | 239 |
:partial => 'close_confirm', |
204 | 240 |
:layout => false, |
205 |
:locals => {}
|
|
241 |
:locals => render_data
|
|
206 | 242 |
) |
207 | 243 |
return |
208 | 244 |
end |
... | ... | |
226 | 262 | |
227 | 263 |
if saved |
228 | 264 |
render_attachment_warning_if_needed(@issue) |
265 |
if params[:close_descendants] && session.has_key?(:can_close_descendant) |
|
266 |
close_descendant_ids = session[:can_close_descendant][:ids] |
|
267 |
session.delete(:can_close_descendant) |
|
268 |
close_descendant_ids.each do |id| |
|
269 |
issue = Issue.find(id) |
|
270 |
issue.init_journal(User.current, params[:issue][:notes]) |
|
271 |
issue.safe_attributes = {'status_id' => params[:issue][:status_id].to_i} |
|
272 |
issue.save |
|
273 |
end |
|
274 |
end |
|
275 | ||
229 | 276 |
unless @issue.current_journal.new_record? || params[:no_flash] |
230 | 277 |
flash[:notice] = l(:notice_successful_update) |
231 | 278 |
end |
app/views/issues/_close_confirm.js.erb | ||
---|---|---|
2 | 2 |
'<%= escape_javascript( |
3 | 3 |
render( |
4 | 4 |
:partial => 'close_confirm_dialog', |
5 |
:locals => {} |
|
5 |
:locals => { |
|
6 |
:status_name => status_name, |
|
7 |
:can_close_all => can_close_all |
|
8 |
} |
|
6 | 9 |
) |
7 | 10 |
) |
8 | 11 |
%>' |
app/views/issues/_close_confirm_dialog.html.erb | ||
---|---|---|
1 | 1 |
<h3 class="title"> </h3> |
2 |
<p> |
|
3 |
<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %> |
|
4 |
</p> |
|
2 |
<% if can_close_all %> |
|
3 |
<p> |
|
4 |
<%= l(:text_close_parent_issue_and_open_subtasks, |
|
5 |
:issue_id => params[:id]) %> |
|
6 |
</p> |
|
7 |
<p> |
|
8 |
<label class="block"> |
|
9 |
<%= radio_button_tag 'choice', '1' %> |
|
10 |
<%= l(:text_close_parent_issue_and_open_subtasks_choice_close_also_all_subtasks, |
|
11 |
:status => status_name) %> |
|
12 |
</label> |
|
13 |
<label class="block"> |
|
14 |
<%= radio_button_tag 'choice', '2', true %> |
|
15 |
<%= l(:text_close_parent_issue_and_open_subtasks_choice_close_only_parent, |
|
16 |
:issue_id => params[:id]) %> |
|
17 |
</label> |
|
18 |
</p> |
|
19 |
<% else %> |
|
20 |
<p> |
|
21 |
<%= l(:text_close_parent_issue_with_open_subtasks_confirmation) %> |
|
22 |
</p> |
|
23 |
<% end %> |
|
5 | 24 |
<p class="buttons"> |
6 | 25 |
<%= button_tag l(:button_apply), :type => "button", :onclick => "run_submit();" %> |
7 | 26 |
<%= link_to_function l(:button_cancel), "hideModal(this);" %> |
... | ... | |
9 | 28 | |
10 | 29 |
<%= javascript_tag do %> |
11 | 30 |
function run_submit() { |
31 |
var canCloseAll = <%= can_close_all %>; |
|
32 |
if (canCloseAll) { |
|
33 |
var radioVal = $("input[name='choice']:checked").val(); |
|
34 |
if (radioVal == '1') { |
|
35 |
$('<input />').attr('type', 'hidden') |
|
36 |
.attr('name', "close_descendants") |
|
37 |
.appendTo('#issue-form'); |
|
38 |
} |
|
39 |
} |
|
12 | 40 |
$("#issue-form").off('submit'); |
13 | 41 |
$("#issue-form").submit(); |
14 | 42 |
} |
config/locales/en.yml | ||
---|---|---|
1202 | 1202 |
text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?' |
1203 | 1203 |
text_issues_destroy_descendants_confirmation: "This will also delete %{count} subtask(s)." |
1204 | 1204 |
text_close_parent_issue_with_open_subtasks_confirmation: Are you sure you want to close parent issue with open subtasks? |
1205 |
text_close_parent_issue_and_open_subtasks: Issue %{issue_id} has open subtasks. |
|
1206 |
text_close_parent_issue_and_open_subtasks_choice_close_also_all_subtasks: Close all open subtasks by "%{status}" status too |
|
1207 |
text_close_parent_issue_and_open_subtasks_choice_close_only_parent: Close only issue %{issue_id} |
|
1205 | 1208 |
text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies)?' |
1206 | 1209 |
text_select_project_modules: 'Select modules to enable for this project:' |
1207 | 1210 |
text_default_administrator_account_changed: Default administrator account changed |
test/system/issues_test.rb | ||
---|---|---|
237 | 237 |
test "add confirm dialog to issue submit button" do |
238 | 238 |
parent = Issue.generate!(:project_id => 1) |
239 | 239 |
child = Issue.generate!(:project_id => 1, :parent_issue_id => parent.id) |
240 |
hidden_child = |
|
241 |
Issue. |
|
242 |
generate!( |
|
243 |
:project_id => 1, |
|
244 |
:parent_issue_id => parent.id, |
|
245 |
:author_id => 2, |
|
246 |
:is_private => true |
|
247 |
) |
|
248 |
assert_not hidden_child.visible?(User.find(3)) |
|
240 | 249 |
with_settings :closed_parent_issues_with_open_subtasks => 1 do |
241 | 250 |
log_user('dlopper', 'foo') |
242 | 251 |
visit "/issues/#{parent.id}" |
... | ... | |
311 | 320 |
end |
312 | 321 |
end |
313 | 322 | |
323 |
hidden_child.status_id = 5 |
|
324 |
hidden_child.save! |
|
325 | ||
314 | 326 |
visit "/issues/#{parent.id}" |
315 | 327 |
page.first(:link, 'Edit').click |
316 | 328 |
assert page.has_select?("issue_status_id", {:selected => "New"}) |
test/functional/issues_controller_test.rb | ||
---|---|---|
6389 | 6389 |
assert_equal 'application/json', response.content_type |
6390 | 6390 |
json = ActiveSupport::JSON.decode(response.body) |
6391 | 6391 |
assert_equal({"result" => false}, json) |
6392 |
assert_not session.has_key?(:can_close_descendant) |
|
6392 | 6393 |
end |
6393 | 6394 | |
6394 | 6395 |
test "check_go_to_close_confirm returns false if status_id is 0" do |
... | ... | |
6410 | 6411 |
assert_equal 'application/json', response.content_type |
6411 | 6412 |
json = ActiveSupport::JSON.decode(response.body) |
6412 | 6413 |
assert_equal({"result" => false}, json) |
6414 |
assert_not session.has_key?(:can_close_descendant) |
|
6413 | 6415 |
end |
6414 | 6416 | |
6415 | 6417 |
test "check_go_to_close_confirm returns false if issue does not have child" do |
... | ... | |
6433 | 6435 | |
6434 | 6436 |
assert_equal 1, issue.reload.status.id |
6435 | 6437 |
assert_equal({"result" => false}, json) |
6438 |
assert_not session.has_key?(:can_close_descendant) |
|
6436 | 6439 |
end |
6437 | 6440 | |
6438 | 6441 |
test "check_go_to_close_confirm returns true if issue have open child" do |
... | ... | |
6460 | 6463 | |
6461 | 6464 |
assert_equal 1, parent.reload.status.id |
6462 | 6465 |
assert_equal({"result" => true}, json) |
6466 |
assert session.has_key?(:can_close_descendant) |
|
6463 | 6467 |
end |
6464 | 6468 | |
6465 | 6469 |
test "check_go_to_close_confirm returns false if child is closed" do |
... | ... | |
6491 | 6495 | |
6492 | 6496 |
assert_equal 1, parent.reload.status.id |
6493 | 6497 |
assert_equal({"result" => false}, json) |
6498 |
assert_not session.has_key?(:can_close_descendant) |
|
6494 | 6499 |
end |
6495 | 6500 | |
6496 | 6501 |
test "check_go_to_close_confirm returns true if child is open and not visible" do |
... | ... | |
6536 | 6541 | |
6537 | 6542 |
assert_equal 1, parent.reload.status.id |
6538 | 6543 |
assert_equal({"result" => true}, json) |
6544 |
assert session.has_key?(:can_close_descendant) |
|
6545 |
assert_not session[:can_close_descendant][:can_close_all] |
|
6539 | 6546 |
end |
6540 | 6547 | |
6541 | 6548 |
def test_get_bulk_edit |
test/functional/issues_controller_test.rb | ||
---|---|---|
6545 | 6545 |
assert_not session[:can_close_descendant][:can_close_all] |
6546 | 6546 |
end |
6547 | 6547 | |
6548 |
test "close all descendants which are open" do |
|
6549 |
with_settings :closed_parent_issues_with_open_subtasks => 1 do |
|
6550 |
parent = Issue.generate! |
|
6551 |
child = |
|
6552 |
Issue. |
|
6553 |
generate!( |
|
6554 |
:parent_issue_id => parent.id |
|
6555 |
) |
|
6556 |
grandchild1 = |
|
6557 |
Issue. |
|
6558 |
generate!( |
|
6559 |
:parent_issue_id => child.id |
|
6560 |
) |
|
6561 |
grandchild2 = |
|
6562 |
Issue. |
|
6563 |
generate!( |
|
6564 |
:parent_issue_id => child.id, |
|
6565 |
:status_id => 6 |
|
6566 |
) |
|
6567 |
user = User.find(2) |
|
6568 |
assert parent.reload.visible?(user) |
|
6569 |
assert_not parent.closed? |
|
6570 |
assert child.reload.visible?(user) |
|
6571 |
assert_not child.closed? |
|
6572 |
assert grandchild1.reload.visible?(user) |
|
6573 |
assert_not grandchild1.closed? |
|
6574 |
assert grandchild2.reload.visible?(user) |
|
6575 |
assert grandchild2.closed? |
|
6576 | ||
6577 |
assert [parent, child, grandchild1, grandchild2]. |
|
6578 |
map{|i| i.new_statuses_allowed_to(user)}. |
|
6579 |
reduce(:&).map{|i| i.id}.include?(5) |
|
6580 |
@request.session[:user_id] = user.id |
|
6581 |
put( |
|
6582 |
:update, |
|
6583 |
:params => { |
|
6584 |
:id => parent.id, |
|
6585 |
:check_go_to_close_confirm => "", |
|
6586 |
:status_id => 5 |
|
6587 |
}, |
|
6588 |
:xhr => true |
|
6589 |
) |
|
6590 |
assert_response :success |
|
6591 |
assert_equal 'application/json', response.content_type |
|
6592 |
json = ActiveSupport::JSON.decode(response.body) |
|
6593 | ||
6594 |
assert_equal 1, parent.reload.status.id |
|
6595 |
assert_equal({"result" => true}, json) |
|
6596 |
assert session.has_key?(:can_close_descendant) |
|
6597 |
assert session[:can_close_descendant][:can_close_all] |
|
6598 |
assert_equal [child.id, grandchild1.id], session[:can_close_descendant][:ids] |
|
6599 | ||
6600 |
notes = 'close all' |
|
6601 | ||
6602 |
assert_difference( |
|
6603 |
-> {parent.journals.count} => 1, |
|
6604 |
-> {child.journals.count} => 1, |
|
6605 |
-> {grandchild1.journals.count} => 1, |
|
6606 |
-> {grandchild2.journals.count} => 0 |
|
6607 |
) do |
|
6608 |
put( |
|
6609 |
:update, |
|
6610 |
:params => { |
|
6611 |
:id => parent.id, |
|
6612 |
:close_descendants => "", |
|
6613 |
:issue => { |
|
6614 |
:status_id => 5, |
|
6615 |
:notes => notes |
|
6616 |
} |
|
6617 |
} |
|
6618 |
) |
|
6619 |
assert_response 302 |
|
6620 |
end |
|
6621 |
assert 5, parent.reload.status.id |
|
6622 |
assert_equal notes, parent.journals.last.notes |
|
6623 |
assert 5, child.reload.status.id |
|
6624 |
assert_equal notes, child.journals.last.notes |
|
6625 |
assert 5, grandchild1.reload.status.id |
|
6626 |
assert_equal notes, grandchild1.journals.last.notes |
|
6627 |
assert 6, grandchild2.reload.status.id |
|
6628 |
end |
|
6629 |
end |
|
6630 | ||
6548 | 6631 |
def test_get_bulk_edit |
6549 | 6632 |
@request.session[:user_id] = 2 |
6550 | 6633 |
get(:bulk_edit, :params => {:ids => [1, 3]}) |
test/functional/issues_controller_test.rb | ||
---|---|---|
6628 | 6628 |
end |
6629 | 6629 |
end |
6630 | 6630 | |
6631 |
test "session generated by check_go_to_close_confirm should respect subtask statuses" do |
|
6632 |
with_settings :closed_parent_issues_with_open_subtasks => 1 do |
|
6633 |
WorkflowTransition.delete_all |
|
6634 |
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, |
|
6635 |
:old_status_id => 1, :new_status_id => 5) |
|
6636 |
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, |
|
6637 |
:old_status_id => 1, :new_status_id => 6) |
|
6638 |
WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, |
|
6639 |
:old_status_id => 1, :new_status_id => 6) |
|
6640 |
user = User.find(2) |
|
6641 |
parent = |
|
6642 |
Issue. |
|
6643 |
generate!( |
|
6644 |
:author_id => 2, |
|
6645 |
:tracker_id => 1, |
|
6646 |
:status_id => 1 |
|
6647 |
) |
|
6648 |
child1 = |
|
6649 |
Issue. |
|
6650 |
generate!( |
|
6651 |
:author_id => 2, |
|
6652 |
:parent_issue_id => parent.id, |
|
6653 |
:tracker_id => 1, |
|
6654 |
:status_id => 1 |
|
6655 |
) |
|
6656 |
child2 = |
|
6657 |
Issue. |
|
6658 |
generate!( |
|
6659 |
:author_id => 2, |
|
6660 |
:parent_issue_id => parent.id, |
|
6661 |
:tracker_id => 2, |
|
6662 |
:status_id => 1 |
|
6663 |
) |
|
6664 |
assert parent.reload.visible?(user) |
|
6665 |
assert child1.reload.visible?(user) |
|
6666 |
assert child2.reload.visible?(user) |
|
6667 | ||
6668 |
assert [5, 6].all? do |id| |
|
6669 |
parent.new_statuses_allowed_to(user).map{|s| s.id}.include?(id) |
|
6670 |
end |
|
6671 |
assert [5, 6].all? do |id| |
|
6672 |
child1.new_statuses_allowed_to(user).map{|s| s.id}.include?(id) |
|
6673 |
end |
|
6674 |
assert_not child2.new_statuses_allowed_to(user).map{|s| s.id}.include?(5) |
|
6675 |
assert child2.new_statuses_allowed_to(user).map{|s| s.id}.include?(6) |
|
6676 | ||
6677 |
@request.session[:user_id] = user.id |
|
6678 |
put( |
|
6679 |
:update, |
|
6680 |
:params => { |
|
6681 |
:id => parent.id, |
|
6682 |
:check_go_to_close_confirm => "", |
|
6683 |
:status_id => 6 |
|
6684 |
}, |
|
6685 |
:xhr => true |
|
6686 |
) |
|
6687 |
assert_response :success |
|
6688 |
assert_equal 'application/json', response.content_type |
|
6689 |
json = ActiveSupport::JSON.decode(response.body) |
|
6690 | ||
6691 |
assert_equal 1, parent.reload.status.id |
|
6692 |
assert_equal({"result" => true}, json) |
|
6693 |
assert session.has_key?(:can_close_descendant) |
|
6694 |
assert session[:can_close_descendant][:can_close_all] |
|
6695 |
assert_equal [child1.id, child2.id], session[:can_close_descendant][:ids] |
|
6696 | ||
6697 |
@request.session.delete(:can_close_descendant) |
|
6698 | ||
6699 |
@request.session[:user_id] = user.id |
|
6700 |
put( |
|
6701 |
:update, |
|
6702 |
:params => { |
|
6703 |
:id => parent.id, |
|
6704 |
:check_go_to_close_confirm => "", |
|
6705 |
:status_id => 5 |
|
6706 |
}, |
|
6707 |
:xhr => true |
|
6708 |
) |
|
6709 |
assert_response :success |
|
6710 |
assert_equal 'application/json', response.content_type |
|
6711 |
json = ActiveSupport::JSON.decode(response.body) |
|
6712 | ||
6713 |
assert_equal 1, parent.reload.status.id |
|
6714 |
assert_equal({"result" => true}, json) |
|
6715 |
assert session.has_key?(:can_close_descendant) |
|
6716 |
assert_not session[:can_close_descendant][:can_close_all] |
|
6717 |
assert_not session[:can_close_descendant].has_key?(:ids) |
|
6718 |
end |
|
6719 |
end |
|
6720 | ||
6631 | 6721 |
def test_get_bulk_edit |
6632 | 6722 |
@request.session[:user_id] = 2 |
6633 | 6723 |
get(:bulk_edit, :params => {:ids => [1, 3]}) |
test/system/issues_test.rb | ||
---|---|---|
337 | 337 |
end |
338 | 338 |
end |
339 | 339 | |
340 |
test "close all open subtasks" do |
|
341 |
parent = Issue.generate!(:project_id => 1) |
|
342 |
child = Issue.generate!(:project_id => 1, :parent_issue_id => parent.id) |
|
343 |
close_only_text = "Close only issue #{parent.id}" |
|
344 | ||
345 |
with_settings :closed_parent_issues_with_open_subtasks => 1 do |
|
346 |
log_user('dlopper', 'foo') |
|
347 |
visit "/issues/#{parent.id}" |
|
348 |
page.first(:link, 'Edit').click |
|
349 |
assert page.has_select?("issue_status_id", {:selected => "New"}) |
|
350 |
page.find("#issue_status_id").select("Closed") |
|
351 |
assert_no_difference ['Issue.count', 'child.journals.count'] do |
|
352 |
assert_no_difference 'parent.journals.count' do |
|
353 |
page.first(:button, 'Submit').click |
|
354 |
within('#ajax-modal') do |
|
355 |
assert page.has_text?(/has open subtasks/) |
|
356 |
assert page.has_checked_field?(close_only_text) |
|
357 |
page.first(:link, 'Cancel').click |
|
358 |
end |
|
359 |
assert_equal 1, parent.reload.status.id |
|
360 |
end |
|
361 |
assert_difference 'parent.journals.count' do |
|
362 |
page.first(:button, 'Submit').click |
|
363 |
within('#ajax-modal') do |
|
364 |
assert page.has_text?(/has open subtasks/) |
|
365 |
assert page.has_checked_field?(close_only_text) |
|
366 |
page.first(:button, 'Apply').click |
|
367 |
end |
|
368 |
assert page.has_css?('#flash_notice') |
|
369 |
assert_equal 5, parent.reload.status.id |
|
370 |
end |
|
371 |
end |
|
372 |
page.first(:link, 'Edit').click |
|
373 |
assert page.has_select?("issue_status_id", {:selected => "Closed"}) |
|
374 |
page.find("#issue_status_id").select("New") |
|
375 |
assert_no_difference ['Issue.count', 'child.journals.count'] do |
|
376 |
assert_difference 'parent.journals.count' do |
|
377 |
page.first(:button, 'Submit').click |
|
378 |
assert page.has_css?('#flash_notice') |
|
379 |
assert_equal 1, parent.reload.status.id |
|
380 |
end |
|
381 |
end |
|
382 |
page.first(:link, 'Edit').click |
|
383 |
assert page.has_select?("issue_status_id", {:selected => "New"}) |
|
384 |
page.find("#issue_status_id").select("Closed") |
|
385 |
assert_no_difference 'Issue.count' do |
|
386 |
assert_difference ['parent.journals.count', 'child.journals.count'] do |
|
387 |
page.first(:button, 'Submit').click |
|
388 |
within('#ajax-modal') do |
|
389 |
all_text = 'Close all open subtasks by "Closed" status' |
|
390 |
assert page.has_text?(/has open subtasks/) |
|
391 |
assert page.has_checked_field?(close_only_text) |
|
392 |
page.choose(all_text) |
|
393 |
assert page.has_checked_field?(all_text) |
|
394 |
page.first(:button, 'Apply').click |
|
395 |
end |
|
396 |
assert page.has_css?('#flash_notice') |
|
397 |
assert_equal 5, parent.reload.status.id |
|
398 |
assert_equal 5, child.reload.status.id |
|
399 |
end |
|
400 |
end |
|
401 |
end |
|
402 |
end |
|
403 | ||
340 | 404 |
test "removing issue shows confirm dialog" do |
341 | 405 |
log_user('jsmith', 'jsmith') |
342 | 406 |
visit '/issues/1' |
- « Previous
- 1
- …
- 13
- 14
- 15
- Next »