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 |