summaryrefslogtreecommitdiff
path: root/app/models/note.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/note.rb')
-rw-r--r--app/models/note.rb68
1 files changed, 50 insertions, 18 deletions
diff --git a/app/models/note.rb b/app/models/note.rb
index 5b50ca285c3..3e8aa49a601 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -8,6 +8,7 @@ class Note < ActiveRecord::Base
include FasterCacheKeys
include CacheMarkdownField
include AfterCommitQueue
+ include ResolvableNote
cache_markdown_field :note, pipeline: :note
@@ -22,6 +23,9 @@ class Note < ActiveRecord::Base
# Attribute used to store the attributes that have ben changed by slash commands.
attr_accessor :commands_changes
+ # The discussion ID for the `DiscussionNote` thread being replied to
+ attr_accessor :in_reply_to_discussion_id
+
default_value_for :system, false
attr_mentionable :note, pipeline: :note
@@ -32,9 +36,6 @@ class Note < ActiveRecord::Base
belongs_to :author, class_name: "User"
belongs_to :updated_by, class_name: "User"
- # Only used by DiffNote, but defined here so that it can be used in `Note.includes`
- belongs_to :resolved_by, class_name: "User"
-
has_many :todos, dependent: :destroy
has_many :events, as: :target, dependent: :destroy
@@ -52,6 +53,7 @@ class Note < ActiveRecord::Base
validates :noteable_id, presence: true, unless: [:for_commit?, :importing?]
validates :commit_id, presence: true, if: :for_commit?
validates :author, presence: true
+ validates :discussion_id, presence: true, format: { with: /\A\h{40}\z/ }
validate unless: [:for_commit?, :importing?] do |note|
unless note.noteable.try(:project) == note.project
@@ -71,8 +73,9 @@ class Note < ActiveRecord::Base
scope :inc_author, ->{ includes(:author) }
scope :inc_relations_for_view, ->{ includes(:project, :author, :updated_by, :resolved_by, :award_emoji) }
+ scope :discussion_notes, ->{ where(type: 'DiscussionNote') }
scope :diff_notes, ->{ where(type: ['LegacyDiffNote', 'DiffNote']) }
- scope :non_diff_notes, ->{ where(type: ['Note', nil]) }
+ scope :non_diff_notes, ->{ where(type: ['Note', 'DiscussionNote', nil]) }
scope :with_associations, -> do
# FYI noteable cannot be loaded for LegacyDiffNote for commits
@@ -98,14 +101,28 @@ class Note < ActiveRecord::Base
Digest::SHA1.hexdigest(build_discussion_id(*args))
end
+ def resolvable?
+ false
+ end
+
def discussions
- Discussion.for_notes(all)
+ Discussion.build_collection(all.fresh)
+ end
+
+ def find_discussion(discussion_id)
+ notes = where(discussion_id: discussion_id).fresh.to_a
+ return if notes.empty?
+
+ Discussion.build(notes)
end
def grouped_diff_discussions
- active_notes = diff_notes.fresh.select(&:active?)
- Discussion.for_diff_notes(active_notes).
- map { |d| [d.line_code, d] }.to_h
+ diff_notes.
+ fresh.
+ select(&:active?).
+ group_by(&:line_code).
+ map { |line_code, notes| [line_code, DiffDiscussion.build(notes)] }.
+ to_h
end
# Searches for notes matching the given query.
@@ -146,18 +163,10 @@ class Note < ActiveRecord::Base
true
end
- def resolvable?
- false
- end
-
- def resolved?
+ def part_of_discussion?
false
end
- def to_be_resolved?
- resolvable? && !resolved?
- end
-
def max_attachment_size
current_application_settings.max_attachment_size.megabytes.to_i
end
@@ -226,7 +235,7 @@ class Note < ActiveRecord::Base
end
def can_be_award_emoji?
- noteable.is_a?(Awardable)
+ noteable.is_a?(Awardable) && !part_of_discussion?
end
def contains_emoji_only?
@@ -237,6 +246,29 @@ class Note < ActiveRecord::Base
note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1]
end
+ def discussion_class
+ if for_merge_request?
+ # Notes on merge requests are always in a discussion of their own
+ SingleNoteDiscussion
+ else
+ CommitDiscussion
+ end
+ end
+
+ # Returns a discussion containing just this note
+ def to_discussion
+ Discussion.build([self])
+ end
+
+ # Returns the entire discussion this note is part of
+ def discussion
+ if part_of_discussion?
+ self.noteable.notes.find_discussion(self.discussion_id)
+ else
+ to_discussion
+ end
+ end
+
private
def keep_around_commit