@@ -1011,11 +1011,20 class Issue < ActiveRecord::Base | |||
|
1011 | 1011 | end |
|
1012 | 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 | 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 | 1028 | @copied_from.children.each do |child| |
|
1020 | 1029 | unless child.visible? |
|
1021 | 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 | 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 | 1041 | end |
|
1033 | 1042 | end |
|
1034 | @subtasks_copied = true | |
|
1035 | 1043 | end |
|
1044 | @after_create_from_copy_handled = true | |
|
1036 | 1045 | end |
|
1037 | 1046 | |
|
1038 | 1047 | def update_nested_set_attributes |
@@ -26,6 +26,8 class IssueRelation < ActiveRecord::Base | |||
|
26 | 26 | TYPE_BLOCKED = "blocked" |
|
27 | 27 | TYPE_PRECEDES = "precedes" |
|
28 | 28 | TYPE_FOLLOWS = "follows" |
|
29 | TYPE_COPIED_TO = "copied_to" | |
|
30 | TYPE_COPIED_FROM = "copied_from" | |
|
29 | 31 | |
|
30 | 32 | TYPES = { TYPE_RELATES => { :name => :label_relates_to, :sym_name => :label_relates_to, :order => 1, :sym => TYPE_RELATES }, |
|
31 | 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 | 35 | TYPE_BLOCKS => { :name => :label_blocks, :sym_name => :label_blocked_by, :order => 4, :sym => TYPE_BLOCKED }, |
|
34 | 36 | TYPE_BLOCKED => { :name => :label_blocked_by, :sym_name => :label_blocks, :order => 5, :sym => TYPE_BLOCKS, :reverse => TYPE_BLOCKS }, |
|
35 | 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 | 41 | }.freeze |
|
38 | 42 | |
|
39 | 43 | validates_presence_of :issue_from, :issue_to, :relation_type |
@@ -744,6 +744,8 en: | |||
|
744 | 744 | label_blocked_by: blocked by |
|
745 | 745 | label_precedes: precedes |
|
746 | 746 | label_follows: follows |
|
747 | label_copied_to: copied to | |
|
748 | label_copied_from: copied from | |
|
747 | 749 | label_end_to_start: end to start |
|
748 | 750 | label_end_to_end: end to end |
|
749 | 751 | label_start_to_start: start to start |
@@ -728,6 +728,8 fr: | |||
|
728 | 728 | label_blocked_by: bloqué par |
|
729 | 729 | label_precedes: précède |
|
730 | 730 | label_follows: suit |
|
731 | label_copied_to: copié vers | |
|
732 | label_copied_from: copié depuis | |
|
731 | 733 | label_end_to_start: fin à début |
|
732 | 734 | label_end_to_end: fin à fin |
|
733 | 735 | label_start_to_start: début à début |
@@ -2357,6 +2357,19 class IssuesControllerTest < ActionController::TestCase | |||
|
2357 | 2357 | assert_equal count + 1, copy.attachments.count |
|
2358 | 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 | 2373 | def test_create_as_copy_should_copy_subtasks |
|
2361 | 2374 | @request.session[:user_id] = 2 |
|
2362 | 2375 | issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent') |
@@ -3512,6 +3525,19 class IssuesControllerTest < ActionController::TestCase | |||
|
3512 | 3525 | end |
|
3513 | 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 | 3541 | def test_bulk_copy_should_allow_not_copying_the_subtasks |
|
3516 | 3542 | issue = Issue.generate_with_descendants!(Project.find(1), :subject => 'Parent') |
|
3517 | 3543 | @request.session[:user_id] = 2 |
@@ -636,6 +636,19 class IssueTest < ActiveSupport::TestCase | |||
|
636 | 636 | assert_equal orig.status, issue.status |
|
637 | 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 | 652 | def test_copy_should_copy_subtasks |
|
640 | 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