##// END OF EJS Templates
Adds a "Copied from/to" relation when copying issue(s) (#6899)....
Jean-Philippe Lang -
r10282:cc4cff9f11b4
parent child
Show More
@@ -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