@@ -1011,11 +1011,20 class Issue < ActiveRecord::Base | |||||
1011 | end |
|
1011 | end | |
1012 | end |
|
1012 | end | |
1013 |
|
1013 | |||
1014 | # Copies subtasks from the copied issue |
|
1014 | # Callback for after the creation of an issue by copy | |
|
1015 | # * adds a "copied to" relation with the copied issue | |||
|
1016 | # * copies subtasks from the copied issue | |||
1015 | def after_create_from_copy |
|
1017 | def after_create_from_copy | |
1016 | return unless copy? |
|
1018 | return unless copy? && !@after_create_from_copy_handled | |
1017 |
|
1019 | |||
1018 | unless @copied_from.leaf? || @copy_options[:subtasks] == false || @subtasks_copied |
|
1020 | if @copied_from.project_id == project_id || Setting.cross_project_issue_relations? | |
|
1021 | relation = IssueRelation.new(:issue_from => @copied_from, :issue_to => self, :relation_type => IssueRelation::TYPE_COPIED_TO) | |||
|
1022 | unless relation.save | |||
|
1023 | logger.error "Could not create relation while copying ##{@copied_from.id} to ##{id} due to validation errors: #{relation.errors.full_messages.join(', ')}" if logger | |||
|
1024 | end | |||
|
1025 | end | |||
|
1026 | ||||
|
1027 | unless @copied_from.leaf? || @copy_options[:subtasks] == false | |||
1019 | @copied_from.children.each do |child| |
|
1028 | @copied_from.children.each do |child| | |
1020 | unless child.visible? |
|
1029 | unless child.visible? | |
1021 | # Do not copy subtasks that are not visible to avoid potential disclosure of private data |
|
1030 | # Do not copy subtasks that are not visible to avoid potential disclosure of private data | |
@@ -1031,8 +1040,8 class Issue < ActiveRecord::Base | |||||
1031 | logger.error "Could not copy subtask ##{child.id} while copying ##{@copied_from.id} to ##{id} due to validation errors: #{copy.errors.full_messages.join(', ')}" if logger |
|
1040 | logger.error "Could not copy subtask ##{child.id} while copying ##{@copied_from.id} to ##{id} due to validation errors: #{copy.errors.full_messages.join(', ')}" if logger | |
1032 | end |
|
1041 | end | |
1033 | end |
|
1042 | end | |
1034 | @subtasks_copied = true |
|
|||
1035 | end |
|
1043 | end | |
|
1044 | @after_create_from_copy_handled = true | |||
1036 | end |
|
1045 | end | |
1037 |
|
1046 | |||
1038 | def update_nested_set_attributes |
|
1047 | def update_nested_set_attributes |
@@ -26,6 +26,8 class IssueRelation < ActiveRecord::Base | |||||
26 | TYPE_BLOCKED = "blocked" |
|
26 | TYPE_BLOCKED = "blocked" | |
27 | TYPE_PRECEDES = "precedes" |
|
27 | TYPE_PRECEDES = "precedes" | |
28 | TYPE_FOLLOWS = "follows" |
|
28 | TYPE_FOLLOWS = "follows" | |
|
29 | TYPE_COPIED_TO = "copied_to" | |||
|
30 | TYPE_COPIED_FROM = "copied_from" | |||
29 |
|
31 | |||
30 | TYPES = { TYPE_RELATES => { :name => :label_relates_to, :sym_name => :label_relates_to, :order => 1, :sym => TYPE_RELATES }, |
|
32 | TYPES = { TYPE_RELATES => { :name => :label_relates_to, :sym_name => :label_relates_to, :order => 1, :sym => TYPE_RELATES }, | |
31 | TYPE_DUPLICATES => { :name => :label_duplicates, :sym_name => :label_duplicated_by, :order => 2, :sym => TYPE_DUPLICATED }, |
|
33 | TYPE_DUPLICATES => { :name => :label_duplicates, :sym_name => :label_duplicated_by, :order => 2, :sym => TYPE_DUPLICATED }, | |
@@ -33,7 +35,9 class IssueRelation < ActiveRecord::Base | |||||
33 | TYPE_BLOCKS => { :name => :label_blocks, :sym_name => :label_blocked_by, :order => 4, :sym => TYPE_BLOCKED }, |
|
35 | TYPE_BLOCKS => { :name => :label_blocks, :sym_name => :label_blocked_by, :order => 4, :sym => TYPE_BLOCKED }, | |
34 | TYPE_BLOCKED => { :name => :label_blocked_by, :sym_name => :label_blocks, :order => 5, :sym => TYPE_BLOCKS, :reverse => TYPE_BLOCKS }, |
|
36 | TYPE_BLOCKED => { :name => :label_blocked_by, :sym_name => :label_blocks, :order => 5, :sym => TYPE_BLOCKS, :reverse => TYPE_BLOCKS }, | |
35 | TYPE_PRECEDES => { :name => :label_precedes, :sym_name => :label_follows, :order => 6, :sym => TYPE_FOLLOWS }, |
|
37 | TYPE_PRECEDES => { :name => :label_precedes, :sym_name => :label_follows, :order => 6, :sym => TYPE_FOLLOWS }, | |
36 | TYPE_FOLLOWS => { :name => :label_follows, :sym_name => :label_precedes, :order => 7, :sym => TYPE_PRECEDES, :reverse => TYPE_PRECEDES } |
|
38 | TYPE_FOLLOWS => { :name => :label_follows, :sym_name => :label_precedes, :order => 7, :sym => TYPE_PRECEDES, :reverse => TYPE_PRECEDES }, | |
|
39 | TYPE_COPIED_TO => { :name => :label_copied_to, :sym_name => :label_copied_from, :order => 8, :sym => TYPE_COPIED_FROM }, | |||
|
40 | TYPE_COPIED_FROM => { :name => :label_copied_from, :sym_name => :label_copied_to, :order => 9, :sym => TYPE_COPIED_TO, :reverse => TYPE_COPIED_TO } | |||
37 | }.freeze |
|
41 | }.freeze | |
38 |
|
42 | |||
39 | validates_presence_of :issue_from, :issue_to, :relation_type |
|
43 | validates_presence_of :issue_from, :issue_to, :relation_type |
@@ -744,6 +744,8 en: | |||||
744 | label_blocked_by: blocked by |
|
744 | label_blocked_by: blocked by | |
745 | label_precedes: precedes |
|
745 | label_precedes: precedes | |
746 | label_follows: follows |
|
746 | label_follows: follows | |
|
747 | label_copied_to: copied to | |||
|
748 | label_copied_from: copied from | |||
747 | label_end_to_start: end to start |
|
749 | label_end_to_start: end to start | |
748 | label_end_to_end: end to end |
|
750 | label_end_to_end: end to end | |
749 | label_start_to_start: start to start |
|
751 | label_start_to_start: start to start |
@@ -728,6 +728,8 fr: | |||||
728 | label_blocked_by: bloqué par |
|
728 | label_blocked_by: bloqué par | |
729 | label_precedes: précède |
|
729 | label_precedes: précède | |
730 | label_follows: suit |
|
730 | label_follows: suit | |
|
731 | label_copied_to: copié vers | |||
|
732 | label_copied_from: copié depuis | |||
731 | label_end_to_start: fin à début |
|
733 | label_end_to_start: fin à début | |
732 | label_end_to_end: fin à fin |
|
734 | label_end_to_end: fin à fin | |
733 | label_start_to_start: début à début |
|
735 | label_start_to_start: début à début |
@@ -2357,6 +2357,19 class IssuesControllerTest < ActionController::TestCase | |||||
2357 | assert_equal count + 1, copy.attachments.count |
|
2357 | assert_equal count + 1, copy.attachments.count | |
2358 | end |
|
2358 | end | |
2359 |
|
2359 | |||
|
2360 | def test_create_as_copy_should_add_relation_with_copied_issue | |||
|
2361 | @request.session[:user_id] = 2 | |||
|
2362 | ||||
|
2363 | assert_difference 'Issue.count' do | |||
|
2364 | assert_difference 'IssueRelation.count' do | |||
|
2365 | post :create, :project_id => 1, :copy_from => 1, | |||
|
2366 | :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy'} | |||
|
2367 | end | |||
|
2368 | end | |||
|
2369 | copy = Issue.first(:order => 'id DESC') | |||
|
2370 | assert_equal 1, copy.relations.size | |||
|
2371 | end | |||
|
2372 | ||||
2360 | def test_create_as_copy_should_copy_subtasks |
|
2373 | def test_create_as_copy_should_copy_subtasks | |
2361 | @request.session[:user_id] = 2 |
|
2374 | @request.session[:user_id] = 2 | |
2362 | issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent') |
|
2375 | issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent') | |
@@ -3512,6 +3525,19 class IssuesControllerTest < ActionController::TestCase | |||||
3512 | end |
|
3525 | end | |
3513 | end |
|
3526 | end | |
3514 |
|
3527 | |||
|
3528 | def test_bulk_copy_should_add_relations_with_copied_issues | |||
|
3529 | @request.session[:user_id] = 2 | |||
|
3530 | ||||
|
3531 | assert_difference 'Issue.count', 2 do | |||
|
3532 | assert_difference 'IssueRelation.count', 2 do | |||
|
3533 | post :bulk_update, :ids => [1, 3], :copy => '1', | |||
|
3534 | :issue => { | |||
|
3535 | :project_id => '1' | |||
|
3536 | } | |||
|
3537 | end | |||
|
3538 | end | |||
|
3539 | end | |||
|
3540 | ||||
3515 | def test_bulk_copy_should_allow_not_copying_the_subtasks |
|
3541 | def test_bulk_copy_should_allow_not_copying_the_subtasks | |
3516 | issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent') |
|
3542 | issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent') | |
3517 | @request.session[:user_id] = 2 |
|
3543 | @request.session[:user_id] = 2 |
@@ -636,6 +636,19 class IssueTest < ActiveSupport::TestCase | |||||
636 | assert_equal orig.status, issue.status |
|
636 | assert_equal orig.status, issue.status | |
637 | end |
|
637 | end | |
638 |
|
638 | |||
|
639 | def test_copy_should_add_relation_with_copied_issue | |||
|
640 | copied = Issue.find(1) | |||
|
641 | issue = Issue.new.copy_from(copied) | |||
|
642 | assert issue.save | |||
|
643 | issue.reload | |||
|
644 | ||||
|
645 | assert_equal 1, issue.relations.size | |||
|
646 | relation = issue.relations.first | |||
|
647 | assert_equal 'copied_to', relation.relation_type | |||
|
648 | assert_equal copied, relation.issue_from | |||
|
649 | assert_equal issue, relation.issue_to | |||
|
650 | end | |||
|
651 | ||||
639 | def test_copy_should_copy_subtasks |
|
652 | def test_copy_should_copy_subtasks | |
640 | issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent') |
|
653 | issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent') | |
641 |
|
654 |
General Comments 0
You need to be logged in to leave comments.
Login now