discussion.rb 3.4 KB
Newer Older
D
Douwe Maan 已提交
1
# A non-diff discussion on an issue, merge request, commit, or snippet, consisting of `DiscussionNote` notes.
2 3
#
# A discussion of this type can be resolvable.
4
class Discussion
5
  include ResolvableDiscussion
6

7
  attr_reader :notes, :context_noteable
8 9 10 11 12 13

  delegate  :created_at,
            :project,
            :author,

            :noteable,
14
            :commit_id,
15 16 17 18 19
            :for_commit?,
            :for_merge_request?,

            to: :first_note

20 21
  def self.build(notes, context_noteable = nil)
    notes.first.discussion_class(context_noteable).new(notes, context_noteable)
22
  end
23

24
  def self.build_collection(notes, context_noteable = nil)
D
Douwe Maan 已提交
25
    grouped_notes = notes.group_by { |n| n.discussion_id(context_noteable) }
26
    grouped_notes.values.map { |notes| build(notes, context_noteable) }
27
  end
28

D
Douwe Maan 已提交
29
  # Returns an alphanumeric discussion ID based on `build_discussion_id`
30 31
  def self.discussion_id(note)
    Digest::SHA1.hexdigest(build_discussion_id(note).join("-"))
32 33
  end

D
Douwe Maan 已提交
34 35 36
  # Returns an array of discussion ID components
  def self.build_discussion_id(note)
    [*base_discussion_id(note), SecureRandom.hex]
37 38
  end

D
Douwe Maan 已提交
39
  def self.base_discussion_id(note)
40 41
    noteable_id = note.noteable_id || note.commit_id
    [:discussion, note.noteable_type.try(:underscore), noteable_id]
42 43
  end

D
Douwe Maan 已提交
44 45 46 47
  # 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.
D
Douwe Maan 已提交
48 49 50
  #
  # To turn a list of notes into a list of discussions, they are grouped by discussion ID, so to
  # get these out-of-context notes to end up in the same discussion, we need to get them to return the same
D
Douwe Maan 已提交
51 52 53
  # `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`.
D
Douwe Maan 已提交
54
  #
D
Douwe Maan 已提交
55 56 57 58
  # If no override is necessary, return `nil`.
  # For the case described above, see `OutOfContextDiscussion.override_discussion_id`.
  def self.override_discussion_id(note)
    nil
59 60
  end

61 62 63 64
  def self.note_class
    DiscussionNote
  end

65
  def initialize(notes, context_noteable = nil)
66
    @notes = notes
67
    @context_noteable = context_noteable
68 69
  end

F
Felipe Artur 已提交
70 71 72 73
  def on_image?
    false
  end

D
Douwe Maan 已提交
74 75
  def ==(other)
    other.class == self.class &&
76
      other.context_noteable == self.context_noteable &&
D
Douwe Maan 已提交
77 78 79 80
      other.id == self.id &&
      other.notes == self.notes
  end

81 82 83 84 85 86 87 88
  def last_updated_at
    last_note.created_at
  end

  def last_updated_by
    last_note.author
  end

89 90 91 92
  def updated?
    last_updated_at != created_at
  end

93
  def id
94
    first_note.discussion_id(context_noteable)
95
  end
96

97 98 99 100 101 102
  def reply_id
    # To reply to this discussion, we need the actual discussion_id from the database,
    # not the potentially overwritten one based on the noteable.
    first_note.discussion_id
  end

D
Douwe Maan 已提交
103
  alias_method :to_param, :id
104 105

  def diff_discussion?
106 107 108
    false
  end

D
Douwe Maan 已提交
109
  def individual_note?
110
    false
111 112
  end

113 114 115 116
  def new_discussion?
    notes.length == 1
  end

117
  def last_note
118
    @last_note ||= notes.last
119
  end
120

D
Douwe Maan 已提交
121
  def collapsed?
D
Douwe Maan 已提交
122
    resolved?
D
Douwe Maan 已提交
123 124
  end

125
  def expanded?
D
Douwe Maan 已提交
126
    !collapsed?
127 128 129
  end

  def reply_attributes
D
Douwe Maan 已提交
130
    first_note.slice(:type, :noteable_type, :noteable_id, :commit_id, :discussion_id)
131 132
  end
end