Feature #6033 » 6033_subtasks_show_in_parent_history.patch
| app/helpers/issues_helper.rb | ||
|---|---|---|
| 426 | 426 |
value = "##{detail.value}" unless detail.value.blank?
|
| 427 | 427 |
old_value = "##{detail.old_value}" unless detail.old_value.blank?
|
| 428 | 428 | |
| 429 |
when 'child_id' |
|
| 430 |
label = l(:label_subtask) |
|
| 431 |
value = "##{detail.value}" unless detail.value.blank?
|
|
| 432 |
old_value = "##{detail.old_value}" unless detail.old_value.blank?
|
|
| 433 |
multiple = true |
|
| 434 | ||
| 429 | 435 |
when 'is_private' |
| 430 | 436 |
value = l(detail.value == "0" ? :general_text_No : :general_text_Yes) unless detail.value.blank? |
| 431 | 437 |
old_value = l(detail.old_value == "0" ? :general_text_No : :general_text_Yes) unless detail.old_value.blank? |
| app/models/issue.rb | ||
|---|---|---|
| 114 | 114 |
after_save :reschedule_following_issues, :update_nested_set_attributes, |
| 115 | 115 |
:update_parent_attributes, :delete_selected_attachments, :create_journal |
| 116 | 116 |
# Should be after_create but would be called before previous after_save callbacks |
| 117 |
after_save :after_create_from_copy |
|
| 118 |
after_destroy :update_parent_attributes |
|
| 117 |
after_save :after_create_from_copy, :create_parent_issue_journal
|
|
| 118 |
after_destroy :update_parent_attributes, :create_parent_issue_journal
|
|
| 119 | 119 |
after_create_commit :send_notification |
| 120 | 120 | |
| 121 | 121 |
# Returns a SQL conditions string used to find all issues visible by the specified user |
| ... | ... | |
| 1845 | 1845 |
end |
| 1846 | 1846 |
end |
| 1847 | 1847 | |
| 1848 |
def create_parent_issue_journal |
|
| 1849 |
return if persisted? && !saved_change_to_parent_id? |
|
| 1850 |
return if destroyed? && @without_nested_set_update |
|
| 1851 | ||
| 1852 |
child_id = self.id |
|
| 1853 |
old_parent_id, new_parent_id = |
|
| 1854 |
if persisted? |
|
| 1855 |
[parent_id_before_last_save, parent_id] |
|
| 1856 |
elsif destroyed? |
|
| 1857 |
[parent_id, nil] |
|
| 1858 |
else |
|
| 1859 |
[nil, parent_id] |
|
| 1860 |
end |
|
| 1861 | ||
| 1862 |
if old_parent_id.present? && old_parent_issue = Issue.visible.find_by_id(old_parent_id) |
|
| 1863 |
old_parent_issue.init_journal(User.current) |
|
| 1864 |
old_parent_issue.current_journal.__send__(:add_attribute_detail, 'child_id', child_id, nil) |
|
| 1865 |
old_parent_issue.save |
|
| 1866 |
end |
|
| 1867 |
if new_parent_id.present? && new_parent_issue = Issue.visible.find_by_id(new_parent_id) |
|
| 1868 |
new_parent_issue.init_journal(User.current) |
|
| 1869 |
new_parent_issue.current_journal.__send__(:add_attribute_detail, 'child_id', nil, child_id) |
|
| 1870 |
new_parent_issue.save |
|
| 1871 |
end |
|
| 1872 |
end |
|
| 1873 | ||
| 1848 | 1874 |
def send_notification |
| 1849 | 1875 |
if notify? && Setting.notified_events.include?('issue_added')
|
| 1850 | 1876 |
Mailer.deliver_issue_add(self) |
| config/locales/en.yml | ||
|---|---|---|
| 950 | 950 |
label_missing_api_access_key: Missing an API access key |
| 951 | 951 |
label_api_access_key_created_on: "API access key created %{value} ago"
|
| 952 | 952 |
label_profile: Profile |
| 953 |
label_subtask: Subtask |
|
| 953 | 954 |
label_subtask_plural: Subtasks |
| 954 | 955 |
label_project_copy_notifications: Send email notifications during the project copy |
| 955 | 956 |
label_import_notifications: Send email notifications during the import |
| test/functional/issues_controller_test.rb | ||
|---|---|---|
| 1956 | 1956 |
end |
| 1957 | 1957 | |
| 1958 | 1958 |
def test_show_should_list_subtasks |
| 1959 |
Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue') |
|
| 1959 |
issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
|
|
| 1960 | 1960 | |
| 1961 | 1961 |
get :show, :params => {
|
| 1962 | 1962 |
:id => 1 |
| ... | ... | |
| 1966 | 1966 |
assert_select 'div#issue_tree' do |
| 1967 | 1967 |
assert_select 'td.subject', :text => /Child Issue/ |
| 1968 | 1968 |
end |
| 1969 |
assert_select 'div#tab-content-history' do |
|
| 1970 |
assert_select 'div[id=?]', "change-#{Issue.find(1).journals.last.id}" do
|
|
| 1971 |
assert_select 'ul.details', :text => "Subtask ##{issue.id} added"
|
|
| 1972 |
end |
|
| 1973 |
end |
|
| 1969 | 1974 |
end |
| 1970 | 1975 | |
| 1971 | 1976 |
def test_show_should_list_parents |
| ... | ... | |
| 6866 | 6871 |
assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6)) |
| 6867 | 6872 |
end |
| 6868 | 6873 | |
| 6874 |
def test_destroy_child_issue |
|
| 6875 |
parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue') |
|
| 6876 |
child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id) |
|
| 6877 |
assert child.is_descendant_of?(parent.reload) |
|
| 6878 | ||
| 6879 |
@request.session[:user_id] = 2 |
|
| 6880 |
assert_difference 'Issue.count', -1 do |
|
| 6881 |
delete :destroy, :params => {
|
|
| 6882 |
:id => child.id |
|
| 6883 |
} |
|
| 6884 |
end |
|
| 6885 |
assert_response :found |
|
| 6886 |
assert_redirected_to :action => 'index', :project_id => 'ecookbook' |
|
| 6887 | ||
| 6888 |
parent.reload |
|
| 6889 |
assert_equal 2, parent.journals.count |
|
| 6890 | ||
| 6891 |
get :show, :params => {
|
|
| 6892 |
:id => parent.id |
|
| 6893 |
} |
|
| 6894 |
assert_response :success |
|
| 6895 | ||
| 6896 |
assert_select 'div#tab-content-history' do |
|
| 6897 |
assert_select 'div[id=?]', "change-#{parent.journals.last.id}" do
|
|
| 6898 |
assert_select 'ul.details', :text => "Subtask deleted (##{child.id})"
|
|
| 6899 |
end |
|
| 6900 |
end |
|
| 6901 |
end |
|
| 6902 | ||
| 6869 | 6903 |
def test_destroy_parent_and_child_issues |
| 6870 | 6904 |
parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue') |
| 6871 | 6905 |
child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id) |
| test/unit/issue_nested_set_test.rb | ||
|---|---|---|
| 49 | 49 |
def test_create_child_issue |
| 50 | 50 |
lft = new_issue_lft |
| 51 | 51 |
parent = Issue.generate! |
| 52 |
child = parent.generate_child! |
|
| 52 |
child = nil |
|
| 53 |
assert_difference 'Journal.count', 1 do |
|
| 54 |
child = parent.generate_child! |
|
| 55 |
end |
|
| 53 | 56 |
parent.reload |
| 54 | 57 |
child.reload |
| 55 | 58 |
assert_equal [parent.id, nil, lft, lft + 3], [parent.root_id, parent.parent_id, parent.lft, parent.rgt] |
| ... | ... | |
| 58 | 61 | |
| 59 | 62 |
def test_creating_a_child_in_a_subproject_should_validate |
| 60 | 63 |
issue = Issue.generate! |
| 61 |
child = Issue.new(:project_id => 3, :tracker_id => 2, :author_id => 1, |
|
| 62 |
:subject => 'child', :parent_issue_id => issue.id) |
|
| 63 |
assert_save child |
|
| 64 |
child = nil |
|
| 65 |
assert_difference 'Journal.count', 1 do |
|
| 66 |
child = Issue.new(:project_id => 3, :tracker_id => 2, :author_id => 1, |
|
| 67 |
:subject => 'child', :parent_issue_id => issue.id) |
|
| 68 |
assert_save child |
|
| 69 |
end |
|
| 64 | 70 |
assert_equal issue, child.reload.parent |
| 65 | 71 |
end |
| 66 | 72 | |
| 67 | 73 |
def test_creating_a_child_in_an_invalid_project_should_not_validate |
| 68 | 74 |
issue = Issue.generate! |
| 69 |
child = Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1, |
|
| 70 |
:subject => 'child', :parent_issue_id => issue.id) |
|
| 71 |
assert !child.save |
|
| 75 |
child = nil |
|
| 76 |
assert_no_difference 'Journal.count' do |
|
| 77 |
child = Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1, |
|
| 78 |
:subject => 'child', :parent_issue_id => issue.id) |
|
| 79 |
assert !child.save |
|
| 80 |
end |
|
| 72 | 81 |
assert_not_equal [], child.errors[:parent_issue_id] |
| 73 | 82 |
end |
| 74 | 83 | |
| ... | ... | |
| 77 | 86 |
parent1 = Issue.generate! |
| 78 | 87 |
parent2 = Issue.generate! |
| 79 | 88 |
child = parent1.generate_child! |
| 80 |
parent2.parent_issue_id = parent1.id |
|
| 81 |
parent2.save! |
|
| 89 |
assert_difference 'Journal.count', 2 do |
|
| 90 |
parent2.init_journal(User.find(2)) |
|
| 91 |
parent2.parent_issue_id = parent1.id |
|
| 92 |
parent2.save! |
|
| 93 |
end |
|
| 82 | 94 |
child.reload |
| 83 | 95 |
parent1.reload |
| 84 | 96 |
parent2.reload |
| ... | ... | |
| 94 | 106 |
parent2 = Issue.generate! |
| 95 | 107 |
lft3 = new_issue_lft |
| 96 | 108 |
child = parent1.generate_child! |
| 97 |
child.parent_issue_id = nil |
|
| 98 |
child.save! |
|
| 109 |
assert_difference 'Journal.count', 2 do |
|
| 110 |
child.init_journal(User.find(2)) |
|
| 111 |
child.parent_issue_id = nil |
|
| 112 |
child.save! |
|
| 113 |
end |
|
| 99 | 114 |
child.reload |
| 100 | 115 |
parent1.reload |
| 101 | 116 |
parent2.reload |
| ... | ... | |
| 110 | 125 |
lft2 = new_issue_lft |
| 111 | 126 |
parent2 = Issue.generate! |
| 112 | 127 |
child = parent1.generate_child! |
| 113 |
child.parent_issue_id = parent2.id |
|
| 114 |
child.save! |
|
| 128 |
assert_difference 'Journal.count', 3 do |
|
| 129 |
child.init_journal(User.find(2)) |
|
| 130 |
child.parent_issue_id = parent2.id |
|
| 131 |
child.save! |
|
| 132 |
end |
|
| 115 | 133 |
child.reload |
| 116 | 134 |
parent1.reload |
| 117 | 135 |
parent2.reload |
| ... | ... | |
| 154 | 172 |
grandchild = child.generate_child! |
| 155 | 173 |
lft4 = new_issue_lft |
| 156 | 174 |
child.reload |
| 157 |
child.project = Project.find(2) |
|
| 158 |
assert child.save |
|
| 175 |
assert_difference 'Journal.count', 2 do |
|
| 176 |
assert_difference 'JournalDetail.count', 3 do |
|
| 177 |
child.init_journal(User.find(2)) |
|
| 178 |
child.project = Project.find(2) |
|
| 179 |
assert child.save |
|
| 180 |
end |
|
| 181 |
end |
|
| 159 | 182 |
child.reload |
| 160 | 183 |
grandchild.reload |
| 161 | 184 |
parent1.reload |
| ... | ... | |
| 173 | 196 |
grandchild = child.generate_child! |
| 174 | 197 | |
| 175 | 198 |
child.reload |
| 176 |
child.parent_issue_id = grandchild.id |
|
| 177 |
assert !child.save |
|
| 199 |
assert_no_difference 'Journal.count' do |
|
| 200 |
child.init_journal(User.find(2)) |
|
| 201 |
child.parent_issue_id = grandchild.id |
|
| 202 |
assert !child.save |
|
| 203 |
end |
|
| 178 | 204 |
assert_not_equal [], child.errors[:parent_issue_id] |
| 179 | 205 |
end |
| 180 | 206 | |
| ... | ... | |
| 223 | 249 |
issue3.subject = 'child with journal' |
| 224 | 250 |
issue3.save! |
| 225 | 251 |
assert_difference 'Issue.count', -2 do |
| 226 |
assert_difference 'Journal.count', -1 do
|
|
| 227 |
assert_difference 'JournalDetail.count', -1 do
|
|
| 252 |
assert_difference 'Journal.count', -2 do
|
|
| 253 |
assert_difference 'JournalDetail.count', -2 do
|
|
| 228 | 254 |
Issue.find(issue2.id).destroy |
| 229 | 255 |
end |
| 230 | 256 |
end |
| ... | ... | |
| 244 | 270 |
child2 = issue.generate_child! |
| 245 | 271 |
issue.reload |
| 246 | 272 |
assert_equal [issue.id, lft1, lft1 + 5], [issue.root_id, issue.lft, issue.rgt] |
| 247 |
child2.reload.destroy |
|
| 273 |
assert_difference 'Journal.count', 1 do |
|
| 274 |
child2.reload.destroy |
|
| 275 |
end |
|
| 248 | 276 |
issue.reload |
| 249 | 277 |
assert_equal [issue.id, lft1, lft1 + 3], [issue.root_id, issue.lft, issue.rgt] |
| 250 | 278 |
end |
| ... | ... | |
| 255 | 283 |
parent.generate_child!(:start_date => 2.days.from_now) |
| 256 | 284 | |
| 257 | 285 |
assert_difference 'Issue.count', -3 do |
| 258 |
Issue.find(parent.id).destroy |
|
| 286 |
assert_difference 'Journal.count', -2 do |
|
| 287 |
Issue.find(parent.id).destroy |
|
| 288 |
end |
|
| 259 | 289 |
end |
| 260 | 290 |
end |
| 261 | 291 | |
| ... | ... | |
| 287 | 317 |
grandchild1 = child.generate_child! |
| 288 | 318 |
grandchild2 = child.generate_child! |
| 289 | 319 |
assert_difference 'Issue.count', -4 do |
| 290 |
Issue.find(issue.id).destroy |
|
| 320 |
assert_difference 'Journal.count', -2 do |
|
| 321 |
Issue.find(issue.id).destroy |
|
| 322 |
end |
|
| 291 | 323 |
parent.reload |
| 292 | 324 |
assert_equal [lft1, lft1 + 1], [parent.lft, parent.rgt] |
| 293 | 325 |
end |
| test/unit/issue_subtasking_test.rb | ||
|---|---|---|
| 267 | 267 |
with_settings :issue_done_ratio => 'issue_status' do |
| 268 | 268 |
status = IssueStatus.find(4) |
| 269 | 269 |
status.update_attribute :default_done_ratio, 50 |
| 270 |
child1.reload |
|
| 270 | 271 |
child1.update_attribute :status, status |
| 271 | 272 | |
| 272 | 273 |
assert_equal 50, child1.done_ratio |
| test/unit/issue_test.rb | ||
|---|---|---|
| 1381 | 1381 |
copy = issue.reload.copy |
| 1382 | 1382 |
assert_difference 'Issue.count', 1+issue.descendants.count do |
| 1383 | 1383 |
assert copy.save |
| 1384 |
copy.reload |
|
| 1384 | 1385 |
assert copy.save |
| 1385 | 1386 |
end |
| 1386 | 1387 |
end |