Ensure that we only have one task per issue/mr

parent 44656136
......@@ -6,6 +6,11 @@ module Issues
def handle_changes(issue, options = {})
if have_changes?(issue, options)
task_service.mark_pending_tasks_as_done(issue, current_user)
end
if issue.previous_changes.include?('title') ||
issue.previous_changes.include?('description')
task_service.update_issue(issue, current_user)
end
......
......@@ -16,6 +16,11 @@ module MergeRequests
def handle_changes(merge_request, options = {})
if have_changes?(merge_request, options)
task_service.mark_pending_tasks_as_done(merge_request, current_user)
end
if merge_request.previous_changes.include?('title') ||
merge_request.previous_changes.include?('description')
task_service.update_merge_request(merge_request, current_user)
end
......
......@@ -18,10 +18,9 @@ class TaskService
# When update an issue we should:
#
# * mark all pending tasks related to the issue for the current user as done
# * create a task for each new user mentioned on issue
#
def update_issue(issue, current_user)
update_issuable(issue, current_user)
create_mention_tasks(issue.project, issue, current_user)
end
# When close an issue we should:
......@@ -37,7 +36,7 @@ class TaskService
# * create a pending task for new assignee if issue is assigned
#
def reassigned_issue(issue, current_user)
reassigned_issuable(issue, current_user)
create_assignment_task(issue, current_user)
end
# When create a merge request we should:
......@@ -51,11 +50,10 @@ class TaskService
# When update a merge request we should:
#
# * mark all pending tasks related to the merge request for the current user as done
# * create a task for each new user mentioned on merge request
# * create a task for each mentioned user on merge request
#
def update_merge_request(merge_request, current_user)
update_issuable(merge_request, current_user)
create_mention_tasks(merge_request.project, merge_request, current_user)
end
# When close a merge request we should:
......@@ -71,7 +69,7 @@ class TaskService
# * creates a pending task for new assignee if merge request is assigned
#
def reassigned_merge_request(merge_request, current_user)
reassigned_issuable(merge_request, current_user)
create_assignment_task(merge_request, current_user)
end
# When merge a merge request we should:
......@@ -87,21 +85,8 @@ class TaskService
# * mark all pending tasks related to the noteable for the note author as done
# * create a task for each mentioned user on note
#
def new_note(note)
# Skip system notes, like status changes and cross-references
return if note.system
project = note.project
target = note.noteable
author = note.author
mark_pending_tasks_as_done(target, author)
mentioned_users = build_mentioned_users(project, note, author)
mentioned_users.each do |user|
create_task(project, target, author, user, Task::MENTIONED, note)
end
def new_note(note, current_user)
handle_note(note, current_user)
end
# When update a note we should:
......@@ -110,41 +95,63 @@ class TaskService
# * create a task for each new user mentioned on note
#
def update_note(note, current_user)
handle_note(note, current_user)
end
# When marking pending tasks as done we should:
#
# * mark all pending tasks related to the target for the current user as done
#
def mark_pending_tasks_as_done(target, user)
pending_tasks(user, target.project, target).update_all(state: :done)
end
private
def create_tasks(project, target, author, users, action, note = nil)
Array(users).each do |user|
next if pending_tasks(user, project, target).exists?
Task.create(
project: project,
user_id: user.id,
author_id: author.id,
target_id: target.id,
target_type: target.class.name,
action: action,
note: note
)
end
end
def new_issuable(issuable, author)
create_assignment_task(issuable, author)
create_mention_tasks(issuable.project, issuable, author)
end
def handle_note(note, author)
# Skip system notes, like status changes and cross-references
return if note.system
project = note.project
target = note.noteable
author = current_user
mark_pending_tasks_as_done(target, author)
create_mention_tasks(project, target, author, note)
end
mentioned_users = build_mentioned_users(project, note, author)
mentioned_users.each do |user|
unless pending_tasks(mentioned_user, project, target, note: note, action: Task::MENTIONED).exists?
create_task(project, target, author, user, Task::MENTIONED, note)
end
def create_assignment_task(issuable, author)
if issuable.assignee && issuable.assignee != author
create_tasks(issuable.project, issuable, author, issuable.assignee, Task::ASSIGNED)
end
end
private
def create_task(project, target, author, user, action, note = nil)
attributes = {
project: project,
user_id: user.id,
author_id: author.id,
target_id: target.id,
target_type: target.class.name,
action: action,
note: note
}
Task.create(attributes)
def create_mention_tasks(project, issuable, author, note = nil)
mentioned_users = filter_mentioned_users(project, note || issuable, author)
create_tasks(project, issuable, author, mentioned_users, Task::MENTIONED, note)
end
def build_mentioned_users(project, target, author)
def filter_mentioned_users(project, target, author)
mentioned_users = target.mentioned_users.select do |user|
user.can?(:read_project, project)
end
......@@ -153,54 +160,11 @@ class TaskService
mentioned_users.uniq
end
def mark_pending_tasks_as_done(target, user)
pending_tasks(user, target.project, target).update_all(state: :done)
end
def pending_tasks(user, project, target, options = {})
options.reverse_merge(
project: project,
target: target
def pending_tasks(user, project, target)
user.tasks.pending.where(
project_id: project.id,
target_id: target.id,
target_type: target.class.name
)
user.tasks.pending.where(options)
end
def new_issuable(issuable, current_user)
project = issuable.project
target = issuable
author = issuable.author
if target.is_assigned? && target.assignee != current_user
create_task(project, target, author, target.assignee, Task::ASSIGNED)
end
mentioned_users = build_mentioned_users(project, target, author)
mentioned_users.delete(issuable.assignee)
mentioned_users.each do |mentioned_user|
create_task(project, target, author, mentioned_user, Task::MENTIONED)
end
end
def update_issuable(issuable, current_user)
project = issuable.project
author = current_user
mark_pending_tasks_as_done(issuable, author)
mentioned_users = build_mentioned_users(project, issuable, author)
mentioned_users.each do |mentioned_user|
unless pending_tasks(mentioned_user, project, issuable, action: Task::MENTIONED).exists?
create_task(project, issuable, author, mentioned_user, Task::MENTIONED)
end
end
end
def reassigned_issuable(issuable, current_user)
if issuable.assignee && issuable.assignee != current_user
create_task(issuable.project, issuable, current_user, issuable.assignee, Task::ASSIGNED)
end
end
end
......@@ -45,13 +45,6 @@ describe TaskService, services: true do
end
describe '#update_issue' do
it 'marks pending tasks to the issue for the user as done' do
pending_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author)
service.update_issue(issue, john_doe)
expect(pending_task.reload).to be_done
end
it 'creates a task for each valid mentioned user' do
service.update_issue(issue, author)
......@@ -101,6 +94,18 @@ describe TaskService, services: true do
end
end
describe '#mark_pending_tasks_as_done' do
it 'marks related pending tasks to the target for the user as done' do
first_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author)
second_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author)
service.mark_pending_tasks_as_done(issue, john_doe)
expect(first_task.reload).to be_done
expect(second_task.reload).to be_done
end
end
describe '#new_note' do
let!(:first_task) { create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) }
let!(:second_task) { create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) }
......@@ -112,28 +117,28 @@ describe TaskService, services: true do
first_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author)
second_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author)
service.new_note(note)
service.new_note(note, john_doe)
expect(first_task.reload).to be_done
expect(second_task.reload).to be_done
end
it 'mark related pending tasks to the noteable for the award note author as done' do
service.new_note(award_note)
service.new_note(award_note, john_doe)
expect(first_task.reload).to be_done
expect(second_task.reload).to be_done
end
it 'does not mark related pending tasks it is a system note' do
service.new_note(system_note)
service.new_note(system_note, john_doe)
expect(first_task.reload).to be_pending
expect(second_task.reload).to be_pending
end
it 'creates a task for each valid mentioned user' do
service.new_note(note)
service.new_note(note, john_doe)
should_create_task(user: michael, target: issue, author: john_doe, action: Task::MENTIONED, note: note)
should_create_task(user: author, target: issue, author: john_doe, action: Task::MENTIONED, note: note)
......@@ -173,13 +178,6 @@ describe TaskService, services: true do
end
describe '#update_merge_request' do
it 'marks pending tasks to the merge request for the user as done' do
pending_task = create(:task, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
service.update_merge_request(mr_assigned, john_doe)
expect(pending_task.reload).to be_done
end
it 'creates a task for each valid mentioned user' do
service.update_merge_request(mr_assigned, author)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment