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
acfe1480aedc
Unverified
Commit
21e10888
authored
Mar 30, 2017
by
Douwe Maan
Committed by
Luke "Jared" Bennett
Apr 05, 2017
Browse files
Address review comments
parent
1bc5e35ded6d
Changes
28
Hide whitespace changes
Inline
Side-by-side
app/controllers/concerns/renders_notes.rb
0 → 100644
View file @
acfe1480
module
RendersNotes
def
prepare_notes_for_rendering
(
notes
)
preload_noteable_for_regular_notes
(
notes
)
preload_max_access_for_authors
(
notes
,
@project
)
Banzai
::
NoteRenderer
.
render
(
notes
,
@project
,
current_user
)
notes
end
private
def
preload_max_access_for_authors
(
notes
,
project
)
user_ids
=
notes
.
map
(
&
:author_id
)
project
.
team
.
max_member_access_for_user_ids
(
user_ids
)
end
def
preload_noteable_for_regular_notes
(
notes
)
ActiveRecord
::
Associations
::
Preloader
.
new
.
preload
(
notes
.
reject
(
&
:for_commit?
),
:noteable
)
end
end
app/controllers/projects/commit_controller.rb
View file @
acfe1480
...
...
@@ -2,7 +2,7 @@
#
# Not to be confused with CommitsController, plural.
class
Projects::CommitController
<
Projects
::
ApplicationController
include
NotesHelper
include
RendersNotes
include
CreatesCommit
include
DiffForPath
include
DiffHelper
...
...
app/controllers/projects/issues_controller.rb
View file @
acfe1480
class
Projects::IssuesController
<
Projects
::
ApplicationController
include
NotesHelper
include
RendersNotes
include
ToggleSubscriptionAction
include
IssuableActions
include
ToggleAwardEmoji
...
...
app/controllers/projects/merge_requests_controller.rb
View file @
acfe1480
...
...
@@ -3,7 +3,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
include
DiffForPath
include
DiffHelper
include
IssuableActions
include
NotesHelper
include
RendersNotes
include
ToggleAwardEmoji
include
IssuableCollections
...
...
app/controllers/projects/notes_controller.rb
View file @
acfe1480
class
Projects::NotesController
<
Projects
::
ApplicationController
include
NotesHelper
include
RendersNotes
include
ToggleAwardEmoji
# Authorize
...
...
app/controllers/projects/snippets_controller.rb
View file @
acfe1480
class
Projects::SnippetsController
<
Projects
::
ApplicationController
include
NotesHelper
include
RendersNotes
include
ToggleAwardEmoji
include
SpammableActions
include
SnippetsActions
...
...
app/finders/notes_finder.rb
View file @
acfe1480
...
...
@@ -20,9 +20,9 @@ def initialize(project, current_user, params = {})
end
def
execute
@
notes
=
init_collection
@
notes
=
since_fetch_at
(
@params
[
:last_fetched_at
],
@notes
)
if
@params
[
:last_fetched_at
]
@
notes
notes
=
init_collection
notes
=
since_fetch_at
(
notes
)
notes
.
fresh
end
def
target
...
...
@@ -56,7 +56,7 @@ def init_collection
def
notes_of_any_type
types
=
%w(commit issue merge_request snippet)
note_relations
=
types
.
map
{
|
t
|
notes_for_type
(
t
)
}
note_relations
.
map!
{
|
notes
|
search
(
@params
[
:search
],
notes
)
}
if
@params
[
:search
]
note_relations
.
map!
{
|
notes
|
search
(
notes
)
}
UnionFinder
.
new
.
find_union
(
note_relations
,
Note
)
end
...
...
@@ -98,16 +98,21 @@ def notes_on_target
#
# This method uses ILIKE on PostgreSQL and LIKE on MySQL.
#
def
search
(
query
,
notes_relation
=
@notes
)
def
search
(
query
,
notes
)
query
=
@params
[
:search
]
return
unless
query
pattern
=
"%
#{
query
}
%"
notes
_relation
.
where
(
Note
.
arel_table
[
:note
].
matches
(
pattern
))
notes
.
where
(
Note
.
arel_table
[
:note
].
matches
(
pattern
))
end
# Notes changed since last fetch
# Uses overlapping intervals to avoid worrying about race conditions
def
since_fetch_at
(
fetch_time
,
notes_relation
=
@notes
)
def
since_fetch_at
(
notes
)
return
notes
unless
@params
[
:last_fetched_at
]
# Default to 0 to remain compatible with old clients
last_fetched_at
=
Time
.
at
(
@params
.
fetch
(
:last_fetched_at
,
0
).
to_i
)
notes
_relation
.
where
(
'
updated_a
t > ?'
,
last_fetched_at
-
FETCH_OVERLAP
)
.
fresh
notes
.
updated_a
fter
(
last_fetched_at
-
FETCH_OVERLAP
)
end
end
app/helpers/notes_helper.rb
View file @
acfe1480
...
...
@@ -57,23 +57,6 @@ def link_to_reply_discussion(discussion, line_type = nil)
data:
data
,
title:
'Add a reply'
end
def
preload_max_access_for_authors
(
notes
,
project
)
user_ids
=
notes
.
map
(
&
:author_id
)
project
.
team
.
max_member_access_for_user_ids
(
user_ids
)
end
def
preload_noteable_for_regular_notes
(
notes
)
ActiveRecord
::
Associations
::
Preloader
.
new
.
preload
(
notes
.
reject
(
&
:for_commit?
),
:noteable
)
end
def
prepare_notes_for_rendering
(
notes
)
preload_noteable_for_regular_notes
(
notes
)
preload_max_access_for_authors
(
notes
,
@project
)
Banzai
::
NoteRenderer
.
render
(
notes
,
@project
,
current_user
)
notes
end
def
note_max_access_for_user
(
note
)
note
.
project
.
team
.
human_max_access
(
note
.
author_id
)
end
...
...
app/mailers/emails/notes.rb
View file @
acfe1480
...
...
@@ -4,7 +4,6 @@ def note_commit_email(recipient_id, note_id)
setup_note_mail
(
note_id
,
recipient_id
)
@commit
=
@note
.
noteable
@discussion
=
@note
.
discussion
if
@note
.
part_of_discussion?
@target_url
=
namespace_project_commit_url
(
*
note_target_url_options
)
mail_answer_thread
(
@commit
,
...
...
@@ -17,7 +16,6 @@ def note_issue_email(recipient_id, note_id)
setup_note_mail
(
note_id
,
recipient_id
)
@issue
=
@note
.
noteable
@discussion
=
@note
.
discussion
if
@note
.
part_of_discussion?
@target_url
=
namespace_project_issue_url
(
*
note_target_url_options
)
mail_answer_thread
(
@issue
,
note_thread_options
(
recipient_id
))
end
...
...
@@ -26,7 +24,6 @@ def note_merge_request_email(recipient_id, note_id)
setup_note_mail
(
note_id
,
recipient_id
)
@merge_request
=
@note
.
noteable
@discussion
=
@note
.
discussion
if
@note
.
part_of_discussion?
@target_url
=
namespace_project_merge_request_url
(
*
note_target_url_options
)
mail_answer_thread
(
@merge_request
,
note_thread_options
(
recipient_id
))
end
...
...
@@ -35,7 +32,6 @@ def note_snippet_email(recipient_id, note_id)
setup_note_mail
(
note_id
,
recipient_id
)
@snippet
=
@note
.
noteable
@discussion
=
@note
.
discussion
if
@note
.
part_of_discussion?
@target_url
=
namespace_project_snippet_url
(
*
note_target_url_options
)
mail_answer_thread
(
@snippet
,
note_thread_options
(
recipient_id
))
end
...
...
@@ -44,7 +40,6 @@ def note_personal_snippet_email(recipient_id, note_id)
setup_note_mail
(
note_id
,
recipient_id
)
@snippet
=
@note
.
noteable
@discussion
=
@note
.
discussion
if
@note
.
part_of_discussion?
@target_url
=
snippet_url
(
@note
.
noteable
)
mail_answer_thread
(
@snippet
,
note_thread_options
(
recipient_id
))
end
...
...
app/models/concerns/resolvable_discussion.rb
View file @
acfe1480
...
...
@@ -2,12 +2,14 @@ module ResolvableDiscussion
extend
ActiveSupport
::
Concern
included
do
memoized_values
<<
:resolvable
memoized_values
<<
:resolved
memoized_values
<<
:first_note
memoized_values
<<
:first_note_to_resolve
memoized_values
<<
:last_resolved_note
memoized_values
<<
:last_note
memoized_values
.
push
(
:resolvable
,
:resolved
,
:first_note
,
:first_note_to_resolve
,
:last_resolved_note
,
:last_note
)
delegate
:resolved_at
,
:resolved_by
,
...
...
app/models/concerns/resolvable_note.rb
View file @
acfe1480
...
...
@@ -8,7 +8,9 @@ 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 `Discussion` subclasses 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'
)
}
# Keep this scope in sync with `#resolvable?`
scope
:resolvable
,
->
{
potentially_resolvable
.
user
}
...
...
app/models/diff_discussion.rb
View file @
acfe1480
# A discussion on merge request or commit diffs consisting of `DiffNote` notes
class
DiffDiscussion
<
Discussion
include
DiscussionOnDiff
...
...
app/models/diff_note.rb
View file @
acfe1480
# A note on merge request or commit diffs
class
DiffNote
<
Note
include
NoteOnDiff
...
...
app/models/discussion.rb
View file @
acfe1480
...
...
@@ -39,6 +39,7 @@ def self.build_discussion_id_base(note)
[
: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
]
end
...
...
app/models/discussion_note.rb
View file @
acfe1480
# A note in a non-diff discussion on an issue, merge request, commit, or snippet
class
DiscussionNote
<
Note
NOTEABLE_TYPES
=
%w(MergeRequest Issue Commit Snippet)
.
freeze
...
...
app/models/individual_note_discussion.rb
View file @
acfe1480
# 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
class
IndividualNoteDiscussion
<
Discussion
# Keep this method in sync with the `potentially_resolvable` scope on `ResolvableNote`
def
potentially_resolvable?
...
...
app/models/legacy_diff_discussion.rb
View file @
acfe1480
# A discussion on merge request or commit diffs consisting of `LegacyDiffNote` notes
class
LegacyDiffDiscussion
<
Discussion
include
DiscussionOnDiff
...
...
app/models/legacy_diff_note.rb
View file @
acfe1480
# A note on merge request or commit diffs, using the legacy implementation
class
LegacyDiffNote
<
Note
include
NoteOnDiff
...
...
app/models/note.rb
View file @
acfe1480
...
...
@@ -68,6 +68,7 @@ class Note < ActiveRecord::Base
scope
:user
,
->
{
where
(
system:
false
)
}
scope
:common
,
->
{
where
(
noteable_type:
[
""
,
nil
])
}
scope
:fresh
,
->
{
order
(
created_at: :asc
,
id: :asc
)
}
scope
:updated_after
,
->
(
time
){
where
(
'updated_at > ?'
,
time
)
}
scope
:inc_author_project
,
->
{
includes
(
:project
,
:author
)
}
scope
:inc_author
,
->
{
includes
(
:author
)
}
scope
:inc_relations_for_view
,
->
do
...
...
@@ -238,18 +239,20 @@ def discussion_id(noteable = nil)
discussion_class
(
noteable
).
override_discussion_id
(
self
)
||
super
()
end
# Returns a discussion containing just this note
# Returns a discussion containing just this note.
# This method exists as an alternative to `#discussion` to use when the methods
# we intend to call on the Discussion object don't require it to have all of its notes,
# and just depend on the first note or the type of discussion. This saves us a DB query.
def
to_discussion
(
noteable
=
nil
)
Discussion
.
build
([
self
],
noteable
)
end
# Returns the entire discussion this note is part of
# Returns the entire discussion this note is part of.
# Consider using `#to_discussion` if we do not need to render the discussion
# and all its notes and if we don't care about the discussion's resolvability status.
def
discussion
if
part_of_discussion?
self
.
noteable
.
notes
.
find_discussion
(
self
.
discussion_id
)
||
to_discussion
else
to_discussion
end
full_discussion
=
self
.
noteable
.
notes
.
find_discussion
(
self
.
discussion_id
)
if
part_of_discussion?
full_discussion
||
to_discussion
end
def
part_of_discussion?
...
...
app/models/out_of_context_discussion.rb
View file @
acfe1480
# 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.
class
OutOfContextDiscussion
<
Discussion
# To make sure all out-of-context notes are displayed in one discussion,
# we override the discussion ID to be a newly generated but consistent ID.
...
...
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