171 lines
4.8 KiB
Ruby
171 lines
4.8 KiB
Ruby
|
# TodoService class
|
||
|
#
|
||
|
# Used for creating todos after certain user actions
|
||
|
#
|
||
|
# Ex.
|
||
|
# TodoService.new.new_issue(issue, current_user)
|
||
|
#
|
||
|
class TodoService
|
||
|
# When create an issue we should:
|
||
|
#
|
||
|
# * create a todo for assignee if issue is assigned
|
||
|
# * create a todo for each mentioned user on issue
|
||
|
#
|
||
|
def new_issue(issue, current_user)
|
||
|
new_issuable(issue, current_user)
|
||
|
end
|
||
|
|
||
|
# When update an issue we should:
|
||
|
#
|
||
|
# * mark all pending todos related to the issue for the current user as done
|
||
|
#
|
||
|
def update_issue(issue, current_user)
|
||
|
create_mention_todos(issue.project, issue, current_user)
|
||
|
end
|
||
|
|
||
|
# When close an issue we should:
|
||
|
#
|
||
|
# * mark all pending todos related to the target for the current user as done
|
||
|
#
|
||
|
def close_issue(issue, current_user)
|
||
|
mark_pending_todos_as_done(issue, current_user)
|
||
|
end
|
||
|
|
||
|
# When we reassign an issue we should:
|
||
|
#
|
||
|
# * create a pending todo for new assignee if issue is assigned
|
||
|
#
|
||
|
def reassigned_issue(issue, current_user)
|
||
|
create_assignment_todo(issue, current_user)
|
||
|
end
|
||
|
|
||
|
# When create a merge request we should:
|
||
|
#
|
||
|
# * creates a pending todo for assignee if merge request is assigned
|
||
|
# * create a todo for each mentioned user on merge request
|
||
|
#
|
||
|
def new_merge_request(merge_request, current_user)
|
||
|
new_issuable(merge_request, current_user)
|
||
|
end
|
||
|
|
||
|
# When update a merge request we should:
|
||
|
#
|
||
|
# * create a todo for each mentioned user on merge request
|
||
|
#
|
||
|
def update_merge_request(merge_request, current_user)
|
||
|
create_mention_todos(merge_request.project, merge_request, current_user)
|
||
|
end
|
||
|
|
||
|
# When close a merge request we should:
|
||
|
#
|
||
|
# * mark all pending todos related to the target for the current user as done
|
||
|
#
|
||
|
def close_merge_request(merge_request, current_user)
|
||
|
mark_pending_todos_as_done(merge_request, current_user)
|
||
|
end
|
||
|
|
||
|
# When we reassign a merge request we should:
|
||
|
#
|
||
|
# * creates a pending todo for new assignee if merge request is assigned
|
||
|
#
|
||
|
def reassigned_merge_request(merge_request, current_user)
|
||
|
create_assignment_todo(merge_request, current_user)
|
||
|
end
|
||
|
|
||
|
# When merge a merge request we should:
|
||
|
#
|
||
|
# * mark all pending todos related to the target for the current user as done
|
||
|
#
|
||
|
def merge_merge_request(merge_request, current_user)
|
||
|
mark_pending_todos_as_done(merge_request, current_user)
|
||
|
end
|
||
|
|
||
|
# When create a note we should:
|
||
|
#
|
||
|
# * mark all pending todos related to the noteable for the note author as done
|
||
|
# * create a todo for each mentioned user on note
|
||
|
#
|
||
|
def new_note(note, current_user)
|
||
|
handle_note(note, current_user)
|
||
|
end
|
||
|
|
||
|
# When update a note we should:
|
||
|
#
|
||
|
# * mark all pending todos related to the noteable for the current user as done
|
||
|
# * create a todo for each new user mentioned on note
|
||
|
#
|
||
|
def update_note(note, current_user)
|
||
|
handle_note(note, current_user)
|
||
|
end
|
||
|
|
||
|
# When marking pending todos as done we should:
|
||
|
#
|
||
|
# * mark all pending todos related to the target for the current user as done
|
||
|
#
|
||
|
def mark_pending_todos_as_done(target, user)
|
||
|
pending_todos(user, target.project, target).update_all(state: :done)
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def create_todos(project, target, author, users, action, note = nil)
|
||
|
Array(users).each do |user|
|
||
|
next if pending_todos(user, project, target).exists?
|
||
|
|
||
|
Todo.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_todo(issuable, author)
|
||
|
create_mention_todos(issuable.project, issuable, author)
|
||
|
end
|
||
|
|
||
|
def handle_note(note, author)
|
||
|
# Skip system notes, notes on commit, and notes on project snippet
|
||
|
return if note.system? || ['Commit', 'Snippet'].include?(note.noteable_type)
|
||
|
|
||
|
project = note.project
|
||
|
target = note.noteable
|
||
|
|
||
|
mark_pending_todos_as_done(target, author)
|
||
|
create_mention_todos(project, target, author, note)
|
||
|
end
|
||
|
|
||
|
def create_assignment_todo(issuable, author)
|
||
|
if issuable.assignee && issuable.assignee != author
|
||
|
create_todos(issuable.project, issuable, author, issuable.assignee, Todo::ASSIGNED)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def create_mention_todos(project, issuable, author, note = nil)
|
||
|
mentioned_users = filter_mentioned_users(project, note || issuable, author)
|
||
|
create_todos(project, issuable, author, mentioned_users, Todo::MENTIONED, note)
|
||
|
end
|
||
|
|
||
|
def filter_mentioned_users(project, target, author)
|
||
|
mentioned_users = target.mentioned_users.select do |user|
|
||
|
user.can?(:read_project, project)
|
||
|
end
|
||
|
|
||
|
mentioned_users.delete(author)
|
||
|
mentioned_users.uniq
|
||
|
end
|
||
|
|
||
|
def pending_todos(user, project, target)
|
||
|
user.todos.pending.where(
|
||
|
project_id: project.id,
|
||
|
target_id: target.id,
|
||
|
target_type: target.class.name
|
||
|
)
|
||
|
end
|
||
|
end
|