2016-07-20 18:18:18 -04:00
|
|
|
class Discussion
|
2017-03-30 20:38:21 -04:00
|
|
|
cattr_accessor :memoized_values, instance_accessor: false do
|
|
|
|
[]
|
|
|
|
end
|
|
|
|
|
|
|
|
include ResolvableDiscussion
|
2016-07-20 18:18:18 -04:00
|
|
|
|
2017-03-17 15:25:52 -04:00
|
|
|
attr_reader :notes, :noteable
|
2016-07-20 18:18:18 -04:00
|
|
|
|
|
|
|
delegate :created_at,
|
|
|
|
:project,
|
|
|
|
:author,
|
|
|
|
|
|
|
|
:noteable,
|
|
|
|
:for_commit?,
|
|
|
|
:for_merge_request?,
|
|
|
|
|
|
|
|
to: :first_note
|
|
|
|
|
2017-03-09 20:29:11 -05:00
|
|
|
def self.build(notes, noteable = nil)
|
|
|
|
notes.first.discussion_class(noteable).new(notes, noteable)
|
|
|
|
end
|
Change diff highlight/truncate for reusability
Previously the `truncated_diff_lines` method for outputting a discussion diff took in already highlighted lines, which meant it wasn't reuseable for truncating ANY lines. In the way it was used, it also meant that for any email truncation, the whole diff was being highlighted before being truncated, meaning wasted time highlighting lines that wouldn't even be used (granted, they were being memoized, so perhaps this wasn't that great of an issue). I refactored truncation away from highlighting, in order to truncate formatted diffs for text templates in email, using `>`s to designate each line, but otherwise retaining the parsing already done to create `diff_lines`.
Additionally, while notes on merge requests or commits had already been tested, there was no existing test for notes on a diff on an MR or commit. Added mailer tests for such, and a unit test for truncating diff lines.
2016-08-25 12:38:07 -04:00
|
|
|
|
2017-03-09 20:29:11 -05:00
|
|
|
def self.build_collection(notes, noteable = nil)
|
|
|
|
notes.group_by { |n| n.discussion_id(noteable) }.values.map { |notes| build(notes, noteable) }
|
|
|
|
end
|
2016-07-20 18:18:18 -04:00
|
|
|
|
2017-03-09 20:29:11 -05:00
|
|
|
def self.discussion_id(note)
|
|
|
|
Digest::SHA1.hexdigest(build_discussion_id(note).join("-"))
|
2016-07-20 18:18:18 -04:00
|
|
|
end
|
|
|
|
|
2017-03-09 20:29:11 -05:00
|
|
|
# Optionally override the discussion ID at runtime depending on circumstances
|
|
|
|
def self.override_discussion_id(note)
|
|
|
|
nil
|
2016-07-20 18:18:18 -04:00
|
|
|
end
|
|
|
|
|
2017-03-09 20:29:11 -05:00
|
|
|
def self.build_discussion_id(note)
|
|
|
|
noteable_id = note.noteable_id || note.commit_id
|
|
|
|
[:discussion, note.noteable_type.try(:underscore), noteable_id]
|
2016-07-20 18:18:18 -04:00
|
|
|
end
|
|
|
|
|
2017-03-09 20:29:11 -05:00
|
|
|
def self.original_discussion_id(note)
|
|
|
|
original_discussion_id = build_original_discussion_id(note)
|
|
|
|
if original_discussion_id
|
|
|
|
Digest::SHA1.hexdigest(original_discussion_id.join("-"))
|
|
|
|
else
|
|
|
|
note.discussion_id
|
|
|
|
end
|
|
|
|
end
|
2016-07-28 23:14:45 -04:00
|
|
|
|
2017-03-09 20:29:11 -05:00
|
|
|
# Optionally build a separate original discussion ID that will never change,
|
|
|
|
# if the main discussion ID _can_ change, like in the case of DiffDiscussion.
|
|
|
|
def self.build_original_discussion_id(note)
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(notes, noteable = nil)
|
|
|
|
@notes = notes
|
|
|
|
@noteable = noteable
|
2016-07-28 23:14:45 -04:00
|
|
|
end
|
|
|
|
|
2017-03-17 15:25:52 -04:00
|
|
|
def ==(other)
|
|
|
|
other.class == self.class &&
|
|
|
|
other.noteable == self.noteable &&
|
|
|
|
other.id == self.id &&
|
|
|
|
other.notes == self.notes
|
|
|
|
end
|
|
|
|
|
2016-07-26 00:49:21 -04:00
|
|
|
def last_updated_at
|
|
|
|
last_note.created_at
|
|
|
|
end
|
|
|
|
|
|
|
|
def last_updated_by
|
|
|
|
last_note.author
|
|
|
|
end
|
|
|
|
|
2016-07-20 18:18:18 -04:00
|
|
|
def id
|
2017-03-09 20:29:11 -05:00
|
|
|
first_note.discussion_id(noteable)
|
2016-07-20 18:18:18 -04:00
|
|
|
end
|
2016-08-17 13:14:44 -04:00
|
|
|
|
2016-08-15 19:45:23 -04:00
|
|
|
alias_method :to_param, :id
|
2016-07-20 18:18:18 -04:00
|
|
|
|
2017-03-09 20:29:11 -05:00
|
|
|
def original_id
|
|
|
|
first_note.original_discussion_id
|
|
|
|
end
|
|
|
|
|
2016-07-20 18:18:18 -04:00
|
|
|
def diff_discussion?
|
2017-03-09 20:29:11 -05:00
|
|
|
false
|
|
|
|
end
|
|
|
|
|
2017-03-17 15:25:52 -04:00
|
|
|
def individual_note?
|
2017-03-09 20:29:11 -05:00
|
|
|
false
|
2016-07-20 18:18:18 -04:00
|
|
|
end
|
|
|
|
|
2017-03-15 20:14:58 -04:00
|
|
|
def new_discussion?
|
|
|
|
notes.length == 1
|
|
|
|
end
|
|
|
|
|
2016-09-02 16:29:47 -04:00
|
|
|
def last_note
|
2017-03-09 20:29:11 -05:00
|
|
|
@last_note ||= notes.last
|
2016-09-02 16:29:47 -04:00
|
|
|
end
|
2016-07-26 00:37:22 -04:00
|
|
|
|
2016-07-26 00:46:13 -04:00
|
|
|
def collapsed?
|
2017-03-17 15:25:52 -04:00
|
|
|
resolved?
|
2016-07-26 00:46:13 -04:00
|
|
|
end
|
|
|
|
|
2016-07-20 18:18:18 -04:00
|
|
|
def expanded?
|
2016-07-26 00:46:13 -04:00
|
|
|
!collapsed?
|
2016-07-20 18:18:18 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def reply_attributes
|
2017-03-09 20:29:11 -05:00
|
|
|
first_note.slice(:type, :noteable_type, :noteable_id, :commit_id)
|
2016-07-20 18:18:18 -04:00
|
|
|
end
|
2016-09-02 16:29:47 -04:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def update
|
2017-03-09 20:29:11 -05:00
|
|
|
# Do not select `Note.resolvable`, so that system notes remain in the collection
|
|
|
|
notes_relation = Note.where(id: notes.map(&:id))
|
|
|
|
|
2016-09-02 16:29:47 -04:00
|
|
|
yield(notes_relation)
|
|
|
|
|
|
|
|
# Set the notes array to the updated notes
|
2017-03-09 20:29:11 -05:00
|
|
|
@notes = notes_relation.fresh.to_a
|
2016-09-02 16:29:47 -04:00
|
|
|
|
2017-03-30 20:38:21 -04:00
|
|
|
self.class.memoized_values.each do |var|
|
2017-03-09 20:29:11 -05:00
|
|
|
instance_variable_set(:"@#{var}", nil)
|
|
|
|
end
|
2016-09-02 16:29:47 -04:00
|
|
|
end
|
2016-07-20 18:18:18 -04:00
|
|
|
end
|