Commit 99d3e21f authored by Douwe Maan's avatar Douwe Maan

Extract LegacyDiffNote out of Note

parent 5e130c3e
...@@ -285,6 +285,7 @@ class @Notes ...@@ -285,6 +285,7 @@ class @Notes
form.addClass "js-main-target-form" form.addClass "js-main-target-form"
form.find("#note_line_code").remove() form.find("#note_line_code").remove()
form.find("#note_type").remove()
### ###
General note form setup. General note form setup.
...@@ -472,6 +473,7 @@ class @Notes ...@@ -472,6 +473,7 @@ class @Notes
setupDiscussionNoteForm: (dataHolder, form) => setupDiscussionNoteForm: (dataHolder, form) =>
# setup note target # setup note target
form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}" form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}"
form.find("#note_type").val dataHolder.data("noteType")
form.find("#line_type").val dataHolder.data("lineType") form.find("#line_type").val dataHolder.data("lineType")
form.find("#note_commit_id").val dataHolder.data("commitId") form.find("#note_commit_id").val dataHolder.data("commitId")
form.find("#note_line_code").val dataHolder.data("lineCode") form.find("#note_line_code").val dataHolder.data("lineCode")
......
...@@ -226,8 +226,7 @@ ul.notes { ...@@ -226,8 +226,7 @@ ul.notes {
} }
} }
.note-action-button, .note-action-button {
.discussion-action-button {
display: inline-block; display: inline-block;
margin-left: 10px; margin-left: 10px;
line-height: 24px; line-height: 24px;
......
...@@ -17,11 +17,12 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -17,11 +17,12 @@ class Projects::CommitController < Projects::ApplicationController
def show def show
apply_diff_view_cookie! apply_diff_view_cookie!
@line_notes = commit.notes.inline @grouped_diff_notes = commit.notes.grouped_diff_notes
@note = @project.build_commit_note(commit) @note = @project.build_commit_note(commit)
@notes = commit.notes.not_inline.fresh @notes = commit.notes.non_diff_notes.fresh
@noteable = @commit @noteable = @commit
@comments_allowed = @reply_allowed = true @comments_allowed = true
@comments_target = { @comments_target = {
noteable_type: 'Commit', noteable_type: 'Commit',
commit_id: @commit.id commit_id: @commit.id
...@@ -67,10 +68,10 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -67,10 +68,10 @@ class Projects::CommitController < Projects::ApplicationController
create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title} has been successfully reverted.", create_commit(Commits::RevertService, success_notice: "The #{@commit.change_type_title} has been successfully reverted.",
success_path: successful_change_path, failure_path: failed_change_path) success_path: successful_change_path, failure_path: failed_change_path)
end end
def cherry_pick def cherry_pick
assign_change_commit_vars(@commit.cherry_pick_branch_name) assign_change_commit_vars(@commit.cherry_pick_branch_name)
return render_404 if @target_branch.blank? return render_404 if @target_branch.blank?
create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title} has been successfully cherry-picked.", create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title} has been successfully cherry-picked.",
......
...@@ -22,7 +22,7 @@ class Projects::CompareController < Projects::ApplicationController ...@@ -22,7 +22,7 @@ class Projects::CompareController < Projects::ApplicationController
@base_commit = @project.merge_base_commit(@base_ref, @head_ref) @base_commit = @project.merge_base_commit(@base_ref, @head_ref)
@diffs = compare.diffs(diff_options) @diffs = compare.diffs(diff_options)
@diff_refs = [@base_commit, @commit] @diff_refs = [@base_commit, @commit]
@line_notes = [] @grouped_diff_notes = {}
end end
end end
......
...@@ -73,12 +73,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -73,12 +73,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# but we need it for the "View file @ ..." link by deleted files # but we need it for the "View file @ ..." link by deleted files
@base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit @base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit
@comments_allowed = @reply_allowed = true @comments_allowed = true
@comments_target = { @comments_target = {
noteable_type: 'MergeRequest', noteable_type: 'MergeRequest',
noteable_id: @merge_request.id noteable_id: @merge_request.id
} }
@line_notes = @merge_request.notes.where("line_code is not null")
@grouped_diff_notes = @merge_request.notes.grouped_diff_notes
respond_to do |format| respond_to do |format|
format.html format.html
...@@ -300,7 +301,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -300,7 +301,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
# Build a note object for comment form # Build a note object for comment form
@note = @project.notes.new(noteable: @merge_request) @note = @project.notes.new(noteable: @merge_request)
@notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh @notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh
@discussions = Note.discussions_from_notes(@notes) @discussions = @notes.discussions
@noteable = @merge_request @noteable = @merge_request
# Get commits from repository # Get commits from repository
......
...@@ -96,7 +96,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -96,7 +96,7 @@ class Projects::NotesController < Projects::ApplicationController
end end
def note_to_discussion_html(note) def note_to_discussion_html(note)
return unless note.for_diff_line? return unless note.diff_note?
if params[:view] == 'parallel' if params[:view] == 'parallel'
template = "projects/notes/_diff_notes_with_reply_parallel" template = "projects/notes/_diff_notes_with_reply_parallel"
...@@ -120,7 +120,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -120,7 +120,7 @@ class Projects::NotesController < Projects::ApplicationController
end end
def note_to_discussion_with_diff_html(note) def note_to_discussion_with_diff_html(note)
return unless note.for_diff_line? return unless note.diff_note?
render_to_string( render_to_string(
"projects/notes/_discussion", "projects/notes/_discussion",
...@@ -158,7 +158,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -158,7 +158,7 @@ class Projects::NotesController < Projects::ApplicationController
def note_params def note_params
params.require(:note).permit( params.require(:note).permit(
:note, :noteable, :noteable_id, :noteable_type, :project_id, :note, :noteable, :noteable_id, :noteable_type, :project_id,
:attachment, :line_code, :commit_id :attachment, :line_code, :commit_id, :type
) )
end end
......
...@@ -10,7 +10,7 @@ class NotesFinder ...@@ -10,7 +10,7 @@ class NotesFinder
notes = notes =
case target_type case target_type
when "commit" when "commit"
project.notes.for_commit_id(target_id).not_inline project.notes.for_commit_id(target_id).non_diff_notes
when "issue" when "issue"
project.issues.find(target_id).notes.nonawards.inc_author project.issues.find(target_id).notes.nonawards.inc_author
when "merge_request" when "merge_request"
......
...@@ -55,22 +55,18 @@ module DiffHelper ...@@ -55,22 +55,18 @@ module DiffHelper
end end
end end
def line_comments def organize_comments(left, right)
@line_comments ||= @line_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code) notes_left = notes_right = nil
end
def organize_comments(type_left, type_right, line_code_left, line_code_right)
comments_left = comments_right = nil
unless type_left.nil? && type_right == 'new' unless left[:type].nil? && right[:type] == 'new'
comments_left = line_comments[line_code_left] notes_left = @grouped_diff_notes[left[:line_code]]
end end
unless type_left.nil? && type_right.nil? unless left[:type].nil? && right[:type].nil?
comments_right = line_comments[line_code_right] notes_right = @grouped_diff_notes[right[:line_code]]
end end
[comments_left, comments_right] [notes_left, notes_right]
end end
def inline_diff_btn def inline_diff_btn
...@@ -96,8 +92,8 @@ module DiffHelper ...@@ -96,8 +92,8 @@ module DiffHelper
].join(' ').html_safe ].join(' ').html_safe
end end
def commit_for_diff(diff) def commit_for_diff(diff_file)
if diff.deleted_file if diff_file.deleted_file
@base_commit || @commit.parent || @commit @base_commit || @commit.parent || @commit
else else
@commit @commit
......
module NotesHelper module NotesHelper
# Helps to distinguish e.g. commit notes in mr notes list # Helps to distinguish e.g. commit notes in mr notes list
def note_for_main_target?(note) def note_for_main_target?(note)
(@noteable.class.name == note.noteable_type && !note.for_diff_line?) @noteable.class.name == note.noteable_type && !note.diff_note?
end end
def note_target_fields(note) def note_target_fields(note)
...@@ -15,16 +15,6 @@ module NotesHelper ...@@ -15,16 +15,6 @@ module NotesHelper
note.editable? && can?(current_user, :admin_note, note) note.editable? && can?(current_user, :admin_note, note)
end end
def link_to_commit_diff_line_note(note)
if note.for_commit_diff_line?
link_to(
"#{note.diff_file_name}:L#{note.diff_new_line}",
namespace_project_commit_path(@project.namespace, @project,
note.noteable, anchor: note.line_code)
)
end
end
def noteable_json(noteable) def noteable_json(noteable)
{ {
id: noteable.id, id: noteable.id,
...@@ -35,7 +25,7 @@ module NotesHelper ...@@ -35,7 +25,7 @@ module NotesHelper
end end
def link_to_new_diff_note(line_code, line_type = nil) def link_to_new_diff_note(line_code, line_type = nil)
discussion_id = Note.build_discussion_id( discussion_id = LegacyDiffNote.build_discussion_id(
@comments_target[:noteable_type], @comments_target[:noteable_type],
@comments_target[:noteable_id] || @comments_target[:commit_id], @comments_target[:noteable_id] || @comments_target[:commit_id],
line_code line_code
...@@ -45,9 +35,10 @@ module NotesHelper ...@@ -45,9 +35,10 @@ module NotesHelper
noteable_type: @comments_target[:noteable_type], noteable_type: @comments_target[:noteable_type],
noteable_id: @comments_target[:noteable_id], noteable_id: @comments_target[:noteable_id],
commit_id: @comments_target[:commit_id], commit_id: @comments_target[:commit_id],
line_type: line_type,
line_code: line_code, line_code: line_code,
discussion_id: discussion_id, note_type: LegacyDiffNote.name,
line_type: line_type discussion_id: discussion_id
} }
button_tag(class: 'btn add-diff-note js-add-diff-note-button', button_tag(class: 'btn add-diff-note js-add-diff-note-button',
...@@ -57,18 +48,24 @@ module NotesHelper ...@@ -57,18 +48,24 @@ module NotesHelper
end end
end end
def link_to_reply_diff(note, line_type = nil) def link_to_reply_discussion(note, line_type = nil)
return unless current_user return unless current_user
data = { data = {
noteable_type: note.noteable_type, noteable_type: note.noteable_type,
noteable_id: note.noteable_id, noteable_id: note.noteable_id,
commit_id: note.commit_id, commit_id: note.commit_id,
line_code: note.line_code,
discussion_id: note.discussion_id, discussion_id: note.discussion_id,
line_type: line_type line_type: line_type
} }
if note.diff_note?
data.merge!(
line_code: note.line_code,
note_type: LegacyDiffNote.name
)
end
button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button', button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
data: data, title: 'Add a reply' data: data, title: 'Add a reply'
end end
......
class LegacyDiffNote < Note
serialize :st_diff
validates :line_code, presence: true, line_code: true
before_create :set_diff
class << self
def build_discussion_id(noteable_type, noteable_id, line_code, active = true)
[super(noteable_type, noteable_id), line_code, active].join("-")
end
end
def diff_note?
true
end
def legacy_diff_note?
true
end
def discussion_id
@discussion_id ||= self.class.build_discussion_id(noteable_type, noteable_id || commit_id, line_code, active?)
end
def find_diff
return nil unless noteable
return @diff if defined?(@diff)
# Don't use ||= because nil is a valid value for @diff
@diff = noteable.diffs(Commit.max_diff_options).find do |d|
Digest::SHA1.hexdigest(d.new_path) == diff_file_index if d.new_path
end
end
def set_diff
# First lets find notes with same diff
# before iterating over all mr diffs
diff = diff_for_line_code unless for_merge_request?
diff ||= find_diff
self.st_diff = diff.to_hash if diff
end
def diff
@diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map)
end
def diff_for_line_code
attributes = {
noteable_type: noteable_type,
line_code: line_code
}
if for_commit?
attributes[:commit_id] = commit_id
else
attributes[:noteable_id] = noteable_id
end
self.class.where(attributes).last.try(:diff)
end
# Check if this note is part of an "active" discussion
#
# This will always return true for anything except MergeRequest noteables,
# which have special logic.
#
# If the note's current diff cannot be matched in the MergeRequest's current
# diff, it's considered inactive.
def active?
return true if for_commit?
return true unless self.diff
return false unless noteable
return @active if defined?(@active)
noteable_diff = find_noteable_diff
if noteable_diff
parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line)
@active = parsed_lines.any? { |line_obj| line_obj.text == diff_line }
else
@active = false
end
@active
end
def diff_file_index
line_code.split('_')[0] if line_code
end
def diff_file_name
diff.new_path if diff
end
def file_path
if diff.new_path.present?
diff.new_path
elsif diff.old_path.present?
diff.old_path
end
end
def diff_old_line
line_code.split('_')[1].to_i if line_code
end
def diff_new_line
line_code.split('_')[2].to_i if line_code
end
def generate_line_code(line)
Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
end
def diff_line
return @diff_line if @diff_line
if diff
diff_lines.each do |line|
if generate_line_code(line) == self.line_code
@diff_line = line.text
end
end
end
@diff_line
end
def diff_line_type
return @diff_line_type if @diff_line_type
if diff
diff_lines.each do |line|
if generate_line_code(line) == self.line_code
@diff_line_type = line.type
end
end
end
@diff_line_type
end
def truncated_diff_lines
max_number_of_lines = 16
prev_match_line = nil
prev_lines = []
highlighted_diff_lines.each do |line|
if line.type == "match"
prev_lines.clear
prev_match_line = line
else
prev_lines << line
break if generate_line_code(line) == self.line_code
prev_lines.shift if prev_lines.length >= max_number_of_lines
end
end
prev_lines
end
def diff_lines
@diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.each_line)
end
def highlighted_diff_lines
Gitlab::Diff::Highlight.new(diff_lines).highlight
end
private
# Find the diff on noteable that matches our own
def find_noteable_diff
diffs = noteable.diffs(Commit.max_diff_options)
diffs.find { |d| d.new_path == self.diff.new_path }
end
end
require 'carrierwave/orm/activerecord'
class Note < ActiveRecord::Base class Note < ActiveRecord::Base
extend ActiveModel::Naming
include Gitlab::CurrentSettings include Gitlab::CurrentSettings
include Participable include Participable
include Mentionable include Mentionable
...@@ -22,12 +21,10 @@ class Note < ActiveRecord::Base ...@@ -22,12 +21,10 @@ class Note < ActiveRecord::Base
delegate :name, :email, to: :author, prefix: true delegate :name, :email, to: :author, prefix: true
before_validation :set_award! before_validation :set_award!
before_validation :clear_blank_line_code!
validates :note, :project, presence: true validates :note, :project, presence: true
validates :note, uniqueness: { scope: [:author, :noteable_type, :noteable_id] }, if: ->(n) { n.is_award } validates :note, uniqueness: { scope: [:author, :noteable_type, :noteable_id] }, if: ->(n) { n.is_award }
validates :note, inclusion: { in: Emoji.emojis_names }, if: ->(n) { n.is_award } validates :note, inclusion: { in: Emoji.emojis_names }, if: ->(n) { n.is_award }
validates :line_code, line_code: true, allow_blank: true
# Attachments are deprecated and are handled by Markdown uploader # Attachments are deprecated and are handled by Markdown uploader
validates :attachment, file_size: { maximum: :max_attachment_size } validates :attachment, file_size: { maximum: :max_attachment_size }
...@@ -41,8 +38,6 @@ class Note < ActiveRecord::Base ...@@ -41,8 +38,6 @@ class Note < ActiveRecord::Base
scope :awards, ->{ where(is_award: true) } scope :awards, ->{ where(is_award: true) }
scope :nonawards, ->{ where(is_award: false) } scope :nonawards, ->{ where(is_award: false) }
scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) }
scope :inline, ->{ where("line_code IS NOT NULL") }
scope :not_inline, ->{ where(line_code: nil) }
scope :system, ->{ where(system: true) } scope :system, ->{ where(system: true) }
scope :user, ->{ where(system: false) } scope :user, ->{ where(system: false) }
scope :common, ->{ where(noteable_type: ["", nil]) } scope :common, ->{ where(noteable_type: ["", nil]) }
...@@ -50,38 +45,31 @@ class Note < ActiveRecord::Base ...@@ -50,38 +45,31 @@ class Note < ActiveRecord::Base
scope :inc_author_project, ->{ includes(:project, :author) } scope :inc_author_project, ->{ includes(:project, :author) }
scope :inc_author, ->{ includes(:author) } scope :inc_author, ->{ includes(:author) }
scope :legacy_diff_notes, ->{ where(type: 'LegacyDiffNote') }
scope :non_diff_notes, ->{ where(type: ['Note', nil]) }
scope :with_associations, -> do scope :with_associations, -> do
includes(:author, :noteable, :updated_by, includes(:author, :noteable, :updated_by,
project: [:project_members, { group: [:group_members] }]) project: [:project_members, { group: [:group_members] }])
end end
serialize :st_diff before_validation :clear_blank_line_code!
before_create :set_diff, if: ->(n) { n.line_code.present? }
class << self class << self
def discussions_from_notes(notes) def model_name
discussion_ids = [] ActiveModel::Name.new(self, nil, 'note')
discussions = [] end
notes.each do |note| def build_discussion_id(noteable_type, noteable_id)
next if discussion_ids.include?(note.discussion_id) [:discussion, noteable_type.try(:underscore), noteable_id].join("-")
end
# don't group notes for the main target
if !note.for_diff_line? && note.for_merge_request?
discussions << [note]
else
discussions << notes.select do |other_note|
note.discussion_id == other_note.discussion_id
end
discussion_ids << note.discussion_id
end
end
discussions def discussions
all.group_by(&:discussion_id).values
end end
def build_discussion_id(type, id, line_code) def grouped_diff_notes
[:discussion, type.try(:underscore), id, line_code].join("-").to_sym legacy_diff_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code)
end end
# Searches for notes matching the given query. # Searches for notes matching the given query.
...@@ -116,167 +104,35 @@ class Note < ActiveRecord::Base ...@@ -116,167 +104,35 @@ class Note < ActiveRecord::Base
system && SystemNoteService.cross_reference?(note) system && SystemNoteService.cross_reference?(note)
end end
def max_attachment_size def diff_note?
current_application_settings.max_attachment_size.megabytes.to_i false
end
def find_diff
return nil unless noteable
return @diff if defined?(@diff)
# Don't use ||= because nil is a valid value for @diff
@diff = noteable.diffs(Commit.max_diff_options).find do |d|
Digest::SHA1.hexdigest(d.new_path) == diff_file_index if d.new_path
end
end
def hook_attrs
attributes
end
def set_diff
# First lets find notes with same diff
# before iterating over all mr diffs
diff = diff_for_line_code unless for_merge_request?
diff ||= find_diff
self.st_diff = diff.to_hash if diff
end
def diff
@diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map)
end
def diff_for_line_code
Note.where(noteable_id: noteable_id, noteable_type: noteable_type, line_code: line_code).last.try(:diff)
end
# Check if this note is part of an "active" discussion
#
# This will always return true for anything except MergeRequest noteables,
# which have special logic.
#
# If the note's current diff cannot be matched in the MergeRequest's current
# diff, it's considered inactive.
def active?
return true unless self.diff
return false unless noteable
return @active if defined?(@active)
noteable_diff = find_noteable_diff
if noteable_diff
parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line)
@active = parsed_lines.any? { |line_obj| line_obj.text == diff_line }
else
@active = false
end
@active
end end
def diff_file_index def legacy_diff_note?
line_code.split('_')[0] if line_code false
end
def diff_file_name
diff.new_path if diff
end
def file_path
if diff.new_path.present?
diff.new_path
elsif diff.old_path.present?
diff.old_path
end
end end
def diff_old_line def discussion_id
line_code.split('_')[1].to_i if line_code @discussion_id ||=
end if for_merge_request?
[:discussion, :note, id].join("-")
def diff_new_line
line_code.split('_')[2].to_i if line_code
end
def generate_line_code(line)
Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
end
def diff_line
return @diff_line if @diff_line
if diff
diff_lines.each do |line|
if generate_line_code(line) == self.line_code
@diff_line = line.text
end
end
end
@diff_line
end
def diff_line_type
return @diff_line_type if @diff_line_type
if diff
diff_lines.each do |line|
if generate_line_code(line) == self.line_code
@diff_line_type = line.type
end
end
end
@diff_line_type
end
def truncated_diff_lines
max_number_of_lines = 16
prev_match_line = nil
prev_lines = []
highlighted_diff_lines.each do |line|
if line.type == "match"
prev_lines.clear
prev_match_line = line
else else
prev_lines << line self.class.build_discussion_id(noteable_type, noteable_id || commit_id)
break if generate_line_code(line) == self.line_code
prev_lines.shift if prev_lines.length >= max_number_of_lines
end end
end
prev_lines
end
def diff_lines
@diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.each_line)
end end
def highlighted_diff_lines def max_attachment_size
Gitlab::Diff::Highlight.new(diff_lines).highlight current_application_settings.max_attachment_size.megabytes.to_i
end end
def discussion_id def hook_attrs
@discussion_id ||= Note.build_discussion_id(noteable_type, noteable_id || commit_id, line_code) attributes
end end
def for_commit? def for_commit?
noteable_type == "Commit" noteable_type == "Commit"
end end
def for_commit_diff_line?
for_commit? && for_diff_line?
end
def for_diff_line?
line_code.present?
end
def for_issue? def for_issue?
noteable_type == "Issue" noteable_type == "Issue"
end end
...@@ -285,10 +141,6 @@ class Note < ActiveRecord::Base ...@@ -285,10 +141,6 @@ class Note < ActiveRecord::Base
noteable_type == "MergeRequest" noteable_type == "MergeRequest"
end end
def for_merge_request_diff_line?
for_merge_request? && for_diff_line?
end
def for_snippet? def for_snippet?
noteable_type == "Snippet" noteable_type == "Snippet"
end end
...@@ -361,14 +213,8 @@ class Note < ActiveRecord::Base ...@@ -361,14 +213,8 @@ class Note < ActiveRecord::Base
self.line_code = nil if self.line_code.blank? self.line_code = nil if self.line_code.blank?
end end
# Find the diff on noteable that matches our own
def find_noteable_diff
diffs = noteable.diffs(Commit.max_diff_options)
diffs.find { |d| d.new_path == self.diff.new_path }
end
def awards_supported? def awards_supported?
(for_issue? || for_merge_request?) && !for_diff_line? (for_issue? || for_merge_request?) && !diff_note?
end end
def contains_emoji_only? def contains_emoji_only?
......
- if @note.diff_file_name - if @note.legacy_diff_note?
%p.details %p.details
New comment on diff for New comment on diff for
= link_to @note.diff_file_name, @target_url = link_to @note.diff_file_name, @target_url
......
...@@ -30,13 +30,13 @@ ...@@ -30,13 +30,13 @@
%td.new_line.diff-line-num{id: new_line_code, class: "#{new_line_class} #{'empty-cell' if !right[:number]}", data: { linenumber: right[:number] }} %td.new_line.diff-line-num{id: new_line_code, class: "#{new_line_class} #{'empty-cell' if !right[:number]}", data: { linenumber: right[:number] }}
= link_to raw(right[:number]), "##{new_line_code}", id: new_line_code = link_to raw(right[:number]), "##{new_line_code}", id: new_line_code
- if @comments_allowed && can?(current_user, :create_note, @project) - if @comments_allowed && can?(current_user, :create_note, @project)
= link_to_new_diff_note(right[:line_code], 'new') = link_to_new_diff_note(new_line_code, 'new')
%td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code} #{'empty-cell' if right[:text].empty?}", data: { line_code: new_line_code }}= diff_line_content(right[:text]) %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code} #{'empty-cell' if right[:text].empty?}", data: { line_code: new_line_code }}= diff_line_content(right[:text])
- if @reply_allowed - if @comments_allowed
- comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code]) - notes_left, notes_right = organize_comments(left, right)
- if comments_left.present? || comments_right.present? - if notes_left.present? || notes_right.present?
= render "projects/notes/diff_notes_with_reply_parallel", notes_left: comments_left, notes_right: comments_right = render "projects/notes/diff_notes_with_reply_parallel", notes_left: notes_left, notes_right: notes_right
- if diff_file.diff.diff.blank? && diff_file.mode_changed? - if diff_file.diff.diff.blank? && diff_file.mode_changed?
.file-mode-changed .file-mode-changed
......
...@@ -6,16 +6,15 @@ ...@@ -6,16 +6,15 @@
%table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' } %table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' }
- last_line = 0 - last_line = 0
- raw_diff_lines = diff_file.diff_lines.to_a
- diff_file.highlighted_diff_lines.each_with_index do |line, index| - diff_file.highlighted_diff_lines.each_with_index do |line, index|
- line_code = generate_line_code(diff_file.file_path, line) - line_code = generate_line_code(diff_file.file_path, line)
- last_line = line.new_pos - last_line = line.new_pos
= render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: line_code} = render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: line_code}
- if @reply_allowed - if @comments_allowed
- comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) - diff_notes = @grouped_diff_notes[line_code]
- unless comments.empty? - if diff_notes
= render "projects/notes/diff_notes_with_reply", notes: comments, line: raw_diff_lines[index].text = render "projects/notes/diff_notes_with_reply", notes: diff_notes
- if last_line > 0 - if last_line > 0
= render "projects/diffs/match_line", { line: "", = render "projects/diffs/match_line", { line: "",
......
- note = notes.first # example note - note = notes.first
-# Check if line want not changed since comment was left %tr.notes_holder
- if !defined?(line) || line == note.diff_line %td.notes_line{ colspan: 2 }
%tr.notes_holder %td.notes_content
%td.notes_line{ colspan: 2 } %ul.notes{ data: { discussion_id: note.discussion_id } }
%td.notes_content = render partial: "projects/notes/note", collection: notes, as: :note
%ul.notes{ data: { discussion_id: note.discussion_id } } .discussion-reply-holder
= render notes = link_to_reply_discussion(note)
.discussion-reply-holder
= link_to_reply_diff(note)
- note1 = notes_left.present? ? notes_left.first : nil - note_left = notes_left.present? ? notes_left.first : nil
- note2 = notes_right.present? ? notes_right.first : nil - note_right = notes_right.present? ? notes_right.first : nil
%tr.notes_holder %tr.notes_holder
- if note1 - if note_left
%td.notes_line.old %td.notes_line.old
%td.notes_content.parallel.old %td.notes_content.parallel.old
%ul.notes{ data: { discussion_id: note1.discussion_id } } %ul.notes{ data: { discussion_id: note_left.discussion_id } }
= render notes_left = render partial: "projects/notes/note", collection: notes_left, as: :note
.discussion-reply-holder .discussion-reply-holder
= link_to_reply_diff(note1, 'old') = link_to_reply_discussion(note_left, 'old')
- else - else
%td.notes_line.old= "" %td.notes_line.old= ""
%td.notes_content.parallel.old= "" %td.notes_content.parallel.old= ""
- if note2 - if note_right
%td.notes_line.new %td.notes_line.new
%td.notes_content.parallel.new %td.notes_content.parallel.new
%ul.notes{ data: { discussion_id: note2.discussion_id } } %ul.notes{ data: { discussion_id: note_right.discussion_id } }
= render notes_right = render partial: "projects/notes/note", collection: notes_right, as: :note
.discussion-reply-holder .discussion-reply-holder
= link_to_reply_diff(note2, 'new') = link_to_reply_discussion(note_right, 'new')
- else - else
%td.notes_line.new= "" %td.notes_line.new= ""
%td.notes_content.parallel.new= "" %td.notes_content.parallel.new= ""
- note = discussion_notes.first - note = discussion_notes.first
- expanded = !note.diff_note? || note.active?
%li.note.note-discussion.timeline-entry %li.note.note-discussion.timeline-entry
.timeline-entry-inner .timeline-entry-inner
.timeline-icon .timeline-icon
= link_to user_path(note.author) do = link_to user_path(note.author) do
= image_tag avatar_icon(note.author_email), class: "avatar s40" = image_tag avatar_icon(note.author), class: "avatar s40"
.timeline-content .timeline-content
- if note.for_merge_request? .discussion.js-toggle-container{ class: note.discussion_id }
- (active_notes, outdated_notes) = discussion_notes.partition(&:active?) .discussion-header
= render "projects/notes/discussions/active", discussion_notes: active_notes if active_notes.length > 0 = link_to_member(@project, note.author, avatar: false)
= render "projects/notes/discussions/outdated", discussion_notes: outdated_notes if outdated_notes.length > 0
- else .inline.discussion-headline-light
= render "projects/notes/discussions/commit", discussion_notes: discussion_notes = note.author.to_reference
started a discussion on
- if note.for_commit?
- commit = note.noteable
- if commit
commit
= link_to commit.short_id, namespace_project_commit_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code), class: 'monospace'
- else
a deleted commit
- else
- if note.active?
= link_to diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code) do
the diff
- else
the outdated diff
= time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "note-created-ago")
.discussion-actions
= link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do
- if expanded
= icon("chevron-up")
- else
= icon("chevron-down")
Toggle discussion
.discussion-body.js-toggle-content{ class: ("hide" unless expanded) }
- if note.diff_note?
= render "projects/notes/discussions/legacy_diff_with_notes", discussion_notes: discussion_notes
- else
= render "projects/notes/discussions/notes", discussion_notes: discussion_notes
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
= f.hidden_field :line_code = f.hidden_field :line_code
= f.hidden_field :noteable_id = f.hidden_field :noteable_id
= f.hidden_field :noteable_type = f.hidden_field :noteable_type
= f.hidden_field :type
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', f: f, attr: :note, classes: 'note-textarea js-note-text', placeholder: "Write a comment or drag your files here..." = render 'projects/zen', f: f, attr: :note, classes: 'note-textarea js-note-text', placeholder: "Write a comment or drag your files here..."
......
- return unless note.author
- return if note.cross_reference_not_visible_for?(current_user)
- note_editable = note_editable?(note) - note_editable = note_editable?(note)
%li.timeline-entry{ id: dom_id(note), class: [dom_class(note), "note-row-#{note.id}", ('system-note' if note.system)], data: {author_id: note.author.id, editable: note_editable} } %li.timeline-entry{ id: dom_id(note), class: ["note", "note-row-#{note.id}", ('system-note' if note.system)], data: {author_id: note.author.id, editable: note_editable} }
.timeline-entry-inner .timeline-entry-inner
.timeline-icon .timeline-icon
%a{href: user_path(note.author)} %a{href: user_path(note.author)}
...@@ -8,8 +11,8 @@ ...@@ -8,8 +11,8 @@
.note-header .note-header
= link_to_member(note.project, note.author, avatar: false) = link_to_member(note.project, note.author, avatar: false)
.inline.note-headline-light .inline.note-headline-light
= "#{note.author.to_reference}" = note.author.to_reference
- if !note.system - unless note.system
commented commented
%a{ href: "##{dom_id(note)}" } %a{ href: "##{dom_id(note)}" }
= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago') = time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago')
......
...@@ -2,14 +2,9 @@ ...@@ -2,14 +2,9 @@
- @discussions.each do |discussion_notes| - @discussions.each do |discussion_notes|
- note = discussion_notes.first - note = discussion_notes.first
- if note_for_main_target?(note) - if note_for_main_target?(note)
- next if note.cross_reference_not_visible_for?(current_user) = render partial: "projects/notes/note", object: note, as: :note
= render discussion_notes
- else - else
= render 'projects/notes/discussion', discussion_notes: discussion_notes = render 'projects/notes/discussion', discussion_notes: discussion_notes
- else - else
- @notes.each do |note| - @notes.each do |note|
- next unless note.author = render partial: "projects/notes/note", object: note, as: :note
- next if note.cross_reference_not_visible_for?(current_user)
= render note
- note = discussion_notes.first
.discussion.js-toggle-container{ class: note.discussion_id }
.discussion-header
= link_to_member(@project, note.author, avatar: false)
.inline.discussion-headline-light
= "#{note.author.to_reference} started a discussion"
= link_to diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code) do
on the diff
= time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago")
.discussion-actions
= link_to "#", class: "discussion-action-button discussion-toggle-button js-toggle-button" do
%i.fa.fa-chevron-up
Show/hide discussion
.discussion-body.js-toggle-content
= render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note
- note = discussion_notes.first
- commit = note.noteable
- commit_description = commit ? 'commit' : 'a deleted commit'
.discussion.js-toggle-container{ class: note.discussion_id }
.discussion-header
= link_to_member(@project, note.author, avatar: false)
.inline.discussion-headline-light
= "#{note.author.to_reference} started a discussion on #{commit_description}"
- if commit
= link_to(commit.short_id, namespace_project_commit_path(note.project.namespace, note.project, note.noteable), class: 'monospace')
= time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago")
.discussion-actions
= link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do
%i.fa.fa-chevron-up
Show/hide discussion
.discussion-body.js-toggle-content
- if note.for_diff_line?
= render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note
- else
.panel.panel-default
.notes{ data: { discussion_id: discussion_notes.first.discussion_id } }
%ul.notes.timeline
= render discussion_notes
.discussion-reply-holder
= link_to_reply_diff(discussion_notes.first)
- diff = note.diff
- if diff
.diff-file
.diff-header
%span
- if diff.deleted_file
= diff.old_path
- else
= diff.new_path
- if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
%span.file-mode= "#{diff.a_mode}#{diff.b_mode}"
.diff-content.code.js-syntax-highlight
%table
- note.truncated_diff_lines.each do |line|
- type = line.type
- line_code = generate_line_code(note.file_path, line)
%tr.line_holder{ id: line_code, class: "#{type}" }
- if type == "match"
%td.old_line.diff-line-num= "..."
%td.new_line.diff-line-num= "..."
%td.line_content.match= line.text
- else
%td.old_line.diff-line-num{ data: { linenumber: type == "new" ? "&nbsp;".html_safe : line.old_pos } }
%td.new_line.diff-line-num{ data: { linenumber: type == "old" ? "&nbsp;".html_safe : line.new_pos } }
%td.line_content{ class: ['noteable_line', type, line_code], line_code: line_code }= diff_line_content(line.text, type)
- if line_code == note.line_code
= render "projects/notes/diff_notes_with_reply", notes: discussion_notes
- note = discussion_notes.first
- diff = note.diff
- return unless diff
.diff-file
.diff-header
%span
- if diff.deleted_file
= diff.old_path
- else
= diff.new_path
- if diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
%span.file-mode= "#{diff.a_mode}#{diff.b_mode}"
.diff-content.code.js-syntax-highlight
%table
- note.truncated_diff_lines.each do |line|
- type = line.type
- line_code = generate_line_code(note.file_path, line)
%tr.line_holder{ id: line_code, class: "#{type}" }
- if type == "match"
%td.old_line.diff-line-num= "..."
%td.new_line.diff-line-num= "..."
%td.line_content.match= line.text
- else
%td.old_line.diff-line-num{ data: { linenumber: type == "new" ? "&nbsp;".html_safe : line.old_pos } }
%td.new_line.diff-line-num{ data: { linenumber: type == "old" ? "&nbsp;".html_safe : line.new_pos } }
%td.line_content{ class: ['noteable_line', type, line_code], line_code: line_code }= diff_line_content(line.text, type)
- if line_code == note.line_code
= render "projects/notes/diff_notes_with_reply", notes: discussion_notes
- note = discussion_notes.first
.panel.panel-default
.notes{ data: { discussion_id: note.discussion_id } }
%ul.notes.timeline
= render partial: "projects/notes/note", collection: discussion_notes, as: :note
.discussion-reply-holder
= link_to_reply_discussion(note)
- note = discussion_notes.first
.discussion.js-toggle-container{ class: note.discussion_id }
.discussion-header
= link_to_member(@project, note.author, avatar: false)
.inline.discussion-headline-light
= "#{note.author.to_reference} started a discussion"
on the outdated diff
= time_ago_with_tooltip(note.created_at, placement: "bottom", html_class: "discussion_updated_ago")
.discussion-actions
= link_to "#", class: "note-action-button discussion-toggle-button js-toggle-button" do
%i.fa.fa-chevron-down
Show/hide discussion
.discussion-body.js-toggle-content.hide
= render "projects/notes/discussions/diff", discussion_notes: discussion_notes, note: note
class AddTypeToNotes < ActiveRecord::Migration
def change
add_column :notes, :type, :string
end
end
class SetTypeOnLegacyDiffNotes < ActiveRecord::Migration
def change
execute "UPDATE notes SET type = 'LegacyDiffNote' WHERE line_code IS NOT NULL"
end
end
...@@ -632,10 +632,11 @@ ActiveRecord::Schema.define(version: 20160509201028) do ...@@ -632,10 +632,11 @@ ActiveRecord::Schema.define(version: 20160509201028) do
t.string "line_code" t.string "line_code"
t.string "commit_id" t.string "commit_id"
t.integer "noteable_id" t.integer "noteable_id"
t.boolean "system", default: false, null: false t.boolean "system", default: false, null: false
t.text "st_diff" t.text "st_diff"
t.integer "updated_by_id" t.integer "updated_by_id"
t.boolean "is_award", default: false, null: false t.boolean "is_award", default: false, null: false
t.string "type"
end end
add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree
......
...@@ -107,6 +107,8 @@ module API ...@@ -107,6 +107,8 @@ module API
break if opts[:line_code] break if opts[:line_code]
end end
opts[:type] = LegacyDiffNote.name if opts[:line_code]
end end
note = ::Notes::CreateService.new(user_project, current_user, opts).execute note = ::Notes::CreateService.new(user_project, current_user, opts).execute
......
...@@ -227,9 +227,9 @@ module API ...@@ -227,9 +227,9 @@ module API
class CommitNote < Grape::Entity class CommitNote < Grape::Entity
expose :note expose :note
expose(:path) { |note| note.diff_file_name } expose(:path) { |note| note.diff_file_name if note.legacy_diff_note? }
expose(:line) { |note| note.diff_new_line } expose(:line) { |note| note.diff_new_line if note.legacy_diff_note? }
expose(:line_type) { |note| note.diff_line_type } expose(:line_type) { |note| note.diff_line_type if note.legacy_diff_note? }
expose :author, using: Entities::UserBasic expose :author, using: Entities::UserBasic
expose :created_at expose :created_at
end end
......
...@@ -43,12 +43,8 @@ describe Note, models: true do ...@@ -43,12 +43,8 @@ describe Note, models: true do
expect(note.noteable.id).to eq(commit.id) expect(note.noteable.id).to eq(commit.id)
end end
it "should be recognized by #for_diff_line?" do it "should be recognized by #legacy_diff_note?" do
expect(note).to be_for_diff_line expect(note).to be_legacy_diff_note
end
it "should be recognized by #for_commit_diff_line?" do
expect(note).to be_for_commit_diff_line
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment