Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
415f388f020b
Unverified
Commit
c319f211
authored
Apr 04, 2017
by
Douwe Maan
Committed by
Luke "Jared" Bennett
Apr 05, 2017
Browse files
Address review comments
parent
96c7ccef5d00
Changes
40
Hide whitespace changes
Inline
Side-by-side
app/helpers/notes_helper.rb
View file @
415f388f
...
...
@@ -51,7 +51,6 @@ def link_to_reply_discussion(discussion, line_type = nil)
return
unless
current_user
data
=
{
discussion_id:
discussion
.
id
,
line_type:
line_type
}
data
[
:line_code
]
=
discussion
.
line_code
if
discussion
.
respond_to?
(
:line_code
)
button_tag
'Reply...'
,
class:
'btn btn-text-field js-discussion-reply-button'
,
data:
data
,
title:
'Add a reply'
...
...
app/mailers/emails/notes.rb
View file @
415f388f
...
...
@@ -5,11 +5,7 @@ def note_commit_email(recipient_id, note_id)
@commit
=
@note
.
noteable
@target_url
=
namespace_project_commit_url
(
*
note_target_url_options
)
mail_answer_thread
(
@commit
,
from:
sender
(
@note
.
author_id
),
to:
recipient
(
recipient_id
),
subject:
subject
(
"
#{
@commit
.
title
}
(
#{
@commit
.
short_id
}
)"
))
mail_answer_thread
(
@commit
,
note_thread_options
(
recipient_id
))
end
def
note_issue_email
(
recipient_id
,
note_id
)
...
...
@@ -54,16 +50,18 @@ def note_thread_options(recipient_id)
{
from:
sender
(
@note
.
author_id
),
to:
recipient
(
recipient_id
),
subject:
subject
(
"
#{
@note
.
noteable
.
title
}
(
#{
@note
.
noteable
.
to_
reference
}
)"
)
subject:
subject
(
"
#{
@note
.
noteable
.
title
}
(
#{
@note
.
noteable
.
reference
_link_text
}
)"
)
}
end
def
setup_note_mail
(
note_id
,
recipient_id
)
@note
=
Note
.
find
(
note_id
)
# `note_id` is a `Note` when originating in `NotifyPreview`
@note
=
note_id
.
is_a?
(
Note
)
?
note_id
:
Note
.
find
(
note_id
)
@project
=
@note
.
project
return
unless
@project
@sent_notification
=
SentNotification
.
record_note
(
@note
,
recipient_id
,
reply_key
)
if
@project
&&
@note
.
persisted?
@sent_notification
=
SentNotification
.
record_note
(
@note
,
recipient_id
,
reply_key
)
end
end
end
end
app/models/concerns/discussion_on_diff.rb
View file @
415f388f
# Contains functionality shared between `DiffDiscussion` and `LegacyDiffDiscussion`.
module
DiscussionOnDiff
extend
ActiveSupport
::
Concern
...
...
app/models/concerns/note_on_diff.rb
View file @
415f388f
# Contains functionality shared between `DiffNote` and `LegacyDiffNote`.
module
NoteOnDiff
extend
ActiveSupport
::
Concern
...
...
app/models/concerns/noteable.rb
View file @
415f388f
...
...
@@ -12,6 +12,32 @@ def discussions
end
def
grouped_diff_discussions
# Doesn't use `discussion_notes`, because this may include commit diff notes
# besides MR diff notes, that we do no want to display on the MR Changes tab.
notes
.
inc_relations_for_view
.
grouped_diff_discussions
end
def
resolvable_discussions
@resolvable_discussions
||=
discussion_notes
.
resolvable
.
discussions
(
self
)
end
def
discussions_resolvable?
resolvable_discussions
.
any?
(
&
:resolvable?
)
end
def
discussions_resolved?
discussions_resolvable?
&&
resolvable_discussions
.
none?
(
&
:to_be_resolved?
)
end
def
discussions_to_be_resolved?
discussions_resolvable?
&&
!
discussions_resolved?
end
def
discussions_to_be_resolved
@discussions_to_be_resolved
||=
resolvable_discussions
.
select
(
&
:to_be_resolved?
)
end
def
discussions_can_be_resolved_by?
(
user
)
discussions_to_be_resolved
.
all?
{
|
discussion
|
discussion
.
can_resolve?
(
user
)
}
end
end
app/models/concerns/resolvable_discussion.rb
View file @
415f388f
...
...
@@ -2,6 +2,15 @@ module ResolvableDiscussion
extend
ActiveSupport
::
Concern
included
do
# A number of properties of this `Discussion`, like `first_note` and `resolvable?`, are memoized.
# When this discussion is resolved or unresolved, the values of these properties potentially change.
# To make sure all memoized values are reset when this happens, `update` resets all instance variables with names in
# `memoized_variables`. If you add a memoized method in `ResolvableDiscussion` or any `Discussion` subclass,
# please make sure the instance variable name is added to `memoized_values`, like below.
cattr_accessor
:memoized_values
,
instance_accessor:
false
do
[]
end
memoized_values
.
push
(
:resolvable
,
:resolved
,
...
...
@@ -78,4 +87,20 @@ def unresolve!
update
{
|
notes
|
notes
.
unresolve!
}
end
private
def
update
# Do not select `Note.resolvable`, so that system notes remain in the collection
notes_relation
=
Note
.
where
(
id:
notes
.
map
(
&
:id
))
yield
(
notes_relation
)
# Set the notes array to the updated notes
@notes
=
notes_relation
.
fresh
.
to_a
self
.
class
.
memoized_values
.
each
do
|
var
|
instance_variable_set
(
:"@
#{
var
}
"
,
nil
)
end
end
end
app/models/concerns/resolvable_note.rb
View file @
415f388f
...
...
@@ -8,7 +8,7 @@ module ResolvableNote
validates
:resolved_by
,
presence:
true
,
if: :resolved?
# Keep this scope in sync with the logic in `#potentially_resolvable?` in `Discussion`
subclasses
that are resolvable.
# Keep this scope in sync with the logic in `#potentially_resolvable?` in
subclasses of
`Discussion` that are resolvable.
# `RESOLVABLE_TYPES` should include names of all subclasses that are resolvable (where the method can return true), and
# the scope should also match the criteria `ResolvableDiscussion#potentially_resolvable?` puts on resolvability.
scope
:potentially_resolvable
,
->
{
where
(
type:
RESOLVABLE_TYPES
).
where
(
noteable_type:
'MergeRequest'
)
}
...
...
app/models/diff_discussion.rb
View file @
415f388f
# A discussion on merge request or commit diffs consisting of `DiffNote` notes
# A discussion on merge request or commit diffs consisting of `DiffNote` notes
.
class
DiffDiscussion
<
Discussion
include
DiscussionOnDiff
...
...
app/models/discussion.rb
View file @
415f388f
# A non-diff discussion on an issue, merge request, commit, or snippet, consisting of `DiscussionNote` notes.
class
Discussion
cattr_accessor
:memoized_values
,
instance_accessor:
false
do
[]
end
include
ResolvableDiscussion
attr_reader
:notes
,
:noteable
...
...
@@ -25,23 +22,34 @@ def self.build_collection(notes, noteable = nil)
notes
.
group_by
{
|
n
|
n
.
discussion_id
(
noteable
)
}.
values
.
map
{
|
notes
|
build
(
notes
,
noteable
)
}
end
# Returns an alphanumeric discussion ID based on `build_discussion_id`
def
self
.
discussion_id
(
note
)
Digest
::
SHA1
.
hexdigest
(
build_discussion_id
(
note
).
join
(
"-"
))
end
#
Optionally override the discussion ID at runtime depending on circumstance
s
def
self
.
override
_discussion_id
(
note
)
nil
#
Returns an array of discussion ID component
s
def
self
.
build
_discussion_id
(
note
)
[
*
base_discussion_id
(
note
),
SecureRandom
.
hex
]
end
def
self
.
b
uild
_discussion_id
_base
(
note
)
def
self
.
b
ase
_discussion_id
(
note
)
noteable_id
=
note
.
noteable_id
||
note
.
commit_id
[
:discussion
,
note
.
noteable_type
.
try
(
:underscore
),
noteable_id
]
end
# Returns an array of discussion ID components
def
self
.
build_discussion_id
(
note
)
[
*
build_discussion_id_base
(
note
),
SecureRandom
.
hex
]
# To turn a list of notes into a list of discussions, they are grouped by discussion ID.
# When notes on a commit are displayed in context of a merge request that contains that commit,
# these notes are to be displayed as if they were part of one discussion, even though they were actually
# individual notes on the commit with different discussion IDs, so that it's clear that these are not
# notes on the merge request itself.
# To get these out-of-context notes to end up in the same discussion, we need to get them to return the same
# `discussion_id` when this grouping happens. To enable this, `Note#discussion_id` calls out
# to the `override_discussion_id` method on the appropriate `Discussion` subclass, as determined by
# the `discussion_class` method on `Note` or a subclass of `Note`.
# If no override is necessary, return `nil`.
# For the case described above, see `OutOfContextDiscussion.override_discussion_id`.
def
self
.
override_discussion_id
(
note
)
nil
end
def
initialize
(
notes
,
noteable
=
nil
)
...
...
@@ -97,20 +105,4 @@ def expanded?
def
reply_attributes
first_note
.
slice
(
:type
,
:noteable_type
,
:noteable_id
,
:commit_id
,
:discussion_id
)
end
private
def
update
# Do not select `Note.resolvable`, so that system notes remain in the collection
notes_relation
=
Note
.
where
(
id:
notes
.
map
(
&
:id
))
yield
(
notes_relation
)
# Set the notes array to the updated notes
@notes
=
notes_relation
.
fresh
.
to_a
self
.
class
.
memoized_values
.
each
do
|
var
|
instance_variable_set
(
:"@
#{
var
}
"
,
nil
)
end
end
end
app/models/discussion_note.rb
View file @
415f388f
...
...
@@ -5,6 +5,6 @@ class DiscussionNote < Note
validates
:noteable_type
,
inclusion:
{
in:
NOTEABLE_TYPES
}
def
discussion_class
(
*
)
Simple
Discussion
Discussion
end
end
app/models/individual_note_discussion.rb
View file @
415f388f
# A discussion to wrap a single `Note` note on the root of an issue, merge request,
# commit, or snippet, that is not displayed as a discussion
# commit, or snippet, that is not displayed as a discussion
.
class
IndividualNoteDiscussion
<
Discussion
# Keep this method in sync with the `potentially_resolvable` scope on `ResolvableNote`
def
potentially_resolvable?
false
end
...
...
app/models/legacy_diff_discussion.rb
View file @
415f388f
# A discussion on merge request or commit diffs consisting of `LegacyDiffNote` notes
# A discussion on merge request or commit diffs consisting of `LegacyDiffNote` notes.
# All new diff discussions are of the type `DiffDiscussion`, but any diff discussions created
# before the introduction of the new implementation still use `LegacyDiffDiscussion`.
class
LegacyDiffDiscussion
<
Discussion
include
DiscussionOnDiff
...
...
@@ -6,7 +8,6 @@ def legacy_diff_discussion?
true
end
# Keep this method in sync with the `potentially_resolvable` scope on `ResolvableNote`
def
potentially_resolvable?
false
end
...
...
app/models/legacy_diff_note.rb
View file @
415f388f
# A note on merge request or commit diffs, using the legacy implementation
# A note on merge request or commit diffs, using the legacy implementation.
# All new diff notes are of the type `DiffNote`, but any diff notes created
# before the introduction of the new implementation still use `LegacyDiffNote`.
class
LegacyDiffNote
<
Note
include
NoteOnDiff
...
...
app/models/merge_request.rb
View file @
415f388f
...
...
@@ -478,30 +478,6 @@ def related_notes
alias_method
:discussion_notes
,
:related_notes
def
resolvable_discussions
@resolvable_discussions
||=
notes
.
resolvable
.
discussions
end
def
discussions_resolvable?
resolvable_discussions
.
any?
(
&
:resolvable?
)
end
def
discussions_resolved?
discussions_resolvable?
&&
resolvable_discussions
.
none?
(
&
:to_be_resolved?
)
end
def
discussions_to_be_resolved?
discussions_resolvable?
&&
!
discussions_resolved?
end
def
discussions_to_be_resolved
@discussions_to_be_resolved
||=
resolvable_discussions
.
select
(
&
:to_be_resolved?
)
end
def
discussions_can_be_resolved_by?
(
user
)
discussions_to_be_resolved
.
all?
{
|
discussion
|
discussion
.
can_resolve?
(
user
)
}
end
def
mergeable_discussions_state?
return
true
unless
project
.
only_allow_merge_if_all_discussions_are_resolved?
...
...
app/models/note.rb
View file @
415f388f
...
...
@@ -227,7 +227,8 @@ def can_be_discussion_note?
def
discussion_class
(
noteable
=
nil
)
# When commit notes are rendered on an MR's Discussion page, they are
# displayed in one discussion instead of individually
# displayed in one discussion instead of individually.
# See also `#discussion_id` and `Discussion.override_discussion_id`.
if
noteable
&&
noteable
!=
self
.
noteable
OutOfContextDiscussion
else
...
...
@@ -235,6 +236,7 @@ def discussion_class(noteable = nil)
end
end
# See `Discussion.override_discussion_id` for details.
def
discussion_id
(
noteable
=
nil
)
discussion_class
(
noteable
).
override_discussion_id
(
self
)
||
super
()
end
...
...
app/models/out_of_context_discussion.rb
View file @
415f388f
# A discussion to wrap a number of `Note` notes on the root of a commit when they
# are displayed in context of a merge request as if they were part of a discussion.
# When notes on a commit are displayed in the context of a merge request that contains that commit,
# they are displayed as if they were a discussion.
# This represents one of those discussions, consisting of `Note` notes.
class
OutOfContextDiscussion
<
Discussion
# To make sure all out-of-context notes are displayed in one discussion,
# Returns an array of discussion ID components
def
self
.
build_discussion_id
(
note
)
base_discussion_id
(
note
)
end
# To make sure all out-of-context notes end up grouped as one discussion,
# we override the discussion ID to be a newly generated but consistent ID.
def
self
.
override_discussion_id
(
note
)
Digest
::
SHA1
.
hexdigest
(
build_
discussion_id
_base
(
note
)
.
join
(
"-"
))
discussion_id
(
note
)
end
# Keep this method in sync with the `potentially_resolvable` scope on `ResolvableNote`
def
potentially_resolvable?
false
end
...
...
app/models/sent_notification.rb
View file @
415f388f
...
...
@@ -102,6 +102,8 @@ def reply_params
if
self
.
in_reply_to_discussion_id
.
present?
attrs
[
:in_reply_to_discussion_id
]
=
self
.
in_reply_to_discussion_id
else
# Remove in GitLab 10.0, when we will not support replying to SentNotifications
# that don't have `in_reply_to_discussion_id` anymore.
attrs
.
merge!
(
type:
self
.
note_type
,
...
...
app/models/simple_discussion.rb
deleted
100644 → 0
View file @
96c7ccef
# A non-diff discussion on an issue, merge request, commit, or snippet, consisting of `DiscussionNote` notes
class
SimpleDiscussion
<
Discussion
end
app/services/notes/build_service.rb
View file @
415f388f
module
Notes
class
BuildService
<
BaseService
class
BuildService
<
::
BaseService
def
execute
in_reply_to_discussion_id
=
params
.
delete
(
:in_reply_to_discussion_id
)
new_discussion
=
params
.
delete
(
:new_discussion
)
...
...
app/services/notes/create_service.rb
View file @
415f388f
module
Notes
class
CreateService
<
BaseService
class
CreateService
<
::
BaseService
def
execute
merge_request_diff_head_sha
=
params
.
delete
(
:merge_request_diff_head_sha
)
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment