Commit 638a6ba7 authored by Mayra Cabrera's avatar Mayra Cabrera

Merge branch 'issue_227691' into 'master'

Mark pending todos as done when resolving design discussions

See merge request gitlab-org/gitlab!62951
parents 6db91f09 0a27c129
...@@ -26,6 +26,7 @@ class PendingTodosFinder ...@@ -26,6 +26,7 @@ class PendingTodosFinder
todos = by_project(todos) todos = by_project(todos)
todos = by_target_id(todos) todos = by_target_id(todos)
todos = by_target_type(todos) todos = by_target_type(todos)
todos = by_discussion(todos)
by_commit_id(todos) by_commit_id(todos)
end end
...@@ -60,4 +61,12 @@ class PendingTodosFinder ...@@ -60,4 +61,12 @@ class PendingTodosFinder
todos todos
end end
end end
def by_discussion(todos)
if (discussion = params[:discussion])
todos.for_note(discussion.notes)
else
todos
end
end
end end
...@@ -61,6 +61,7 @@ class Todo < ApplicationRecord ...@@ -61,6 +61,7 @@ class Todo < ApplicationRecord
scope :for_author, -> (author) { where(author: author) } scope :for_author, -> (author) { where(author: author) }
scope :for_user, -> (user) { where(user: user) } scope :for_user, -> (user) { where(user: user) }
scope :for_project, -> (projects) { where(project: projects) } scope :for_project, -> (projects) { where(project: projects) }
scope :for_note, -> (notes) { where(note: notes) }
scope :for_undeleted_projects, -> { joins(:project).merge(Project.without_deleted) } scope :for_undeleted_projects, -> { joins(:project).merge(Project.without_deleted) }
scope :for_group, -> (group) { where(group: group) } scope :for_group, -> (group) { where(group: group) }
scope :for_type, -> (type) { where(target_type: type) } scope :for_type, -> (type) { where(target_type: type) }
......
...@@ -47,9 +47,16 @@ module Discussions ...@@ -47,9 +47,16 @@ module Discussions
MergeRequests::ResolvedDiscussionNotificationService.new(project: project, current_user: current_user).execute(merge_request) MergeRequests::ResolvedDiscussionNotificationService.new(project: project, current_user: current_user).execute(merge_request)
end end
resolve_user_todos_for(discussion)
SystemNoteService.discussion_continued_in_issue(discussion, project, current_user, follow_up_issue) if follow_up_issue SystemNoteService.discussion_continued_in_issue(discussion, project, current_user, follow_up_issue) if follow_up_issue
end end
def resolve_user_todos_for(discussion)
return unless discussion.for_design?
TodoService.new.resolve_todos_for_target(discussion, current_user)
end
def first_discussion def first_discussion
@first_discussion ||= discussions.first @first_discussion ||= discussions.first
end end
......
...@@ -316,6 +316,8 @@ class TodoService ...@@ -316,6 +316,8 @@ class TodoService
attributes.merge!(target_id: nil, commit_id: target.id) attributes.merge!(target_id: nil, commit_id: target.id)
elsif target.is_a?(Issue) elsif target.is_a?(Issue)
attributes[:issue_type] = target.issue_type attributes[:issue_type] = target.issue_type
elsif target.is_a?(Discussion)
attributes.merge!(target_type: nil, target_id: nil, discussion: target)
end end
attributes attributes
......
...@@ -219,6 +219,9 @@ There are two ways to resolve/unresolve a Design thread: ...@@ -219,6 +219,9 @@ There are two ways to resolve/unresolve a Design thread:
![Resolve checkbox](img/resolve_design-discussion_checkbox_v13_1.png) ![Resolve checkbox](img/resolve_design-discussion_checkbox_v13_1.png)
Resolving a discussion thread will also mark any pending to-do related to notes
inside the thread as done. This is applicable only for to-dos owned by the user triggering the action.
Note that your resolved comment pins disappear from the Design to free up space for new discussions. Note that your resolved comment pins disappear from the Design to free up space for new discussions.
However, if you need to revisit or find a resolved discussion, all of your resolved threads are However, if you need to revisit or find a resolved discussion, all of your resolved threads are
available in the **Resolved Comment** area at the bottom of the right sidebar. available in the **Resolved Comment** area at the bottom of the right sidebar.
......
...@@ -112,6 +112,7 @@ Actions that dismiss to-do items include: ...@@ -112,6 +112,7 @@ Actions that dismiss to-do items include:
- Changing the milestone - Changing the milestone
- Adding/removing a label - Adding/removing a label
- Commenting on the issue - Commenting on the issue
- Resolving a [design discussion thread](project/issues/design_management.md#resolve-design-threads)
Your To-Do List is personal, and items are only marked as done if you take Your To-Do List is personal, and items are only marked as done if you take
action. If you close the issue or merge request, your to-do item is marked as action. If you close the issue or merge request, your to-do item is marked as
......
...@@ -3,8 +3,11 @@ ...@@ -3,8 +3,11 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe PendingTodosFinder do RSpec.describe PendingTodosFinder do
let(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:user2) { create(:user) } let_it_be(:user2) { create(:user) }
let_it_be(:issue) { create(:issue) }
let_it_be(:note) { create(:note) }
let(:users) { [user, user2] } let(:users) { [user, user2] }
describe '#execute' do describe '#execute' do
...@@ -30,20 +33,16 @@ RSpec.describe PendingTodosFinder do ...@@ -30,20 +33,16 @@ RSpec.describe PendingTodosFinder do
end end
it 'supports retrieving of todos for a specific todo target' do it 'supports retrieving of todos for a specific todo target' do
issue = create(:issue)
note = create(:note)
todo = create(:todo, :pending, user: user, target: issue) todo = create(:todo, :pending, user: user, target: issue)
create(:todo, :pending, user: user, target: note) create(:todo, :pending, user: user, target: note)
todos = described_class.new(users, target_id: issue.id).execute todos = described_class.new(users, target_id: issue.id, target_type: 'Issue').execute
expect(todos).to eq([todo]) expect(todos).to eq([todo])
end end
it 'supports retrieving of todos for a specific target type' do it 'supports retrieving of todos for a specific target type' do
issue = create(:issue)
note = create(:note)
todo = create(:todo, :pending, user: user, target: issue) todo = create(:todo, :pending, user: user, target: issue)
create(:todo, :pending, user: user, target: note) create(:todo, :pending, user: user, target: note)
...@@ -61,5 +60,20 @@ RSpec.describe PendingTodosFinder do ...@@ -61,5 +60,20 @@ RSpec.describe PendingTodosFinder do
expect(todos).to eq([todo]) expect(todos).to eq([todo])
end end
it 'supports retrieving of todos for specific discussion' do
first_discussion_note = create(:discussion_note_on_issue, noteable: issue, project: issue.project)
note_2 = create(:note, discussion_id: first_discussion_note.discussion_id)
note_3 = create(:note, discussion_id: first_discussion_note.discussion_id)
todo1 = create(:todo, :pending, target: issue, note: note_2, user: note_2.author)
todo2 = create(:todo, :pending, target: issue, note: note_3, user: note_3.author)
create(:todo, :pending, note: note, user: user)
discussion = Discussion.lazy_find(first_discussion_note.discussion_id)
users = [note_2.author, note_3.author, user]
todos = described_class.new(users, discussion: discussion).execute
expect(todos).to contain_exactly(todo1, todo2)
end
end end
end end
...@@ -376,6 +376,18 @@ RSpec.describe Todo do ...@@ -376,6 +376,18 @@ RSpec.describe Todo do
end end
end end
describe '.for_note' do
it 'returns todos that belongs to notes' do
note_1 = create(:note, noteable: issue, project: issue.project)
note_2 = create(:note, noteable: issue, project: issue.project)
todo_1 = create(:todo, note: note_1)
todo_2 = create(:todo, note: note_2)
create(:todo, note: create(:note))
expect(described_class.for_note([note_1, note_2])).to contain_exactly(todo_1, todo_2)
end
end
describe '.group_by_user_id_and_state' do describe '.group_by_user_id_and_state' do
let_it_be(:user1) { create(:user) } let_it_be(:user1) { create(:user) }
let_it_be(:user2) { create(:user) } let_it_be(:user2) { create(:user) }
......
...@@ -121,5 +121,50 @@ RSpec.describe Discussions::ResolveService do ...@@ -121,5 +121,50 @@ RSpec.describe Discussions::ResolveService do
service.execute service.execute
end end
end end
context 'when resolving a discussion' do
def resolve_discussion(discussion, user)
described_class.new(project, user, one_or_more_discussions: discussion).execute
end
context 'in a design' do
let_it_be(:design) { create(:design, :with_file, issue: create(:issue, project: project)) }
let_it_be(:user_1) { create(:user) }
let_it_be(:user_2) { create(:user) }
let_it_be(:discussion_1) { create(:diff_note_on_design, noteable: design, project: project, author: user_1).to_discussion }
let_it_be(:discussion_2) { create(:diff_note_on_design, noteable: design, project: project, author: user_2).to_discussion }
before do
project.add_developer(user_1)
project.add_developer(user_2)
end
context 'when user resolving discussion has open todos' do
let!(:user_1_todo_for_discussion_1) { create(:todo, :pending, user: user_1, target: design, note: discussion_1.notes.first, project: project) }
let!(:user_1_todo_2_for_discussion_1) { create(:todo, :pending, user: user_1, target: design, note: discussion_1.notes.first, project: project) }
let!(:user_1_todo_for_discussion_2) { create(:todo, :pending, user: user_1, target: design, note: discussion_2.notes.first, project: project) }
let!(:user_2_todo_for_discussion_1) { create(:todo, :pending, user: user_2, target: design, note: discussion_1.notes.first, project: project) }
it 'marks user todos for given discussion as done' do
resolve_discussion(discussion_1, user_1)
expect(user_1_todo_for_discussion_1.reload).to be_done
expect(user_1_todo_2_for_discussion_1.reload).to be_done
expect(user_1_todo_for_discussion_2.reload).to be_pending
expect(user_2_todo_for_discussion_1.reload).to be_pending
end
end
end
context 'in a merge request' do
let!(:user_todo_for_discussion) { create(:todo, :pending, user: user, target: merge_request, note: discussion.notes.first, project: project) }
it 'does not mark user todo as done' do
resolve_discussion(discussion, user)
expect(user_todo_for_discussion).to be_pending
end
end
end
end end
end end
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