diff options
author | Douwe Maan <douwe@selenight.nl> | 2016-05-10 17:41:46 -0500 |
---|---|---|
committer | Douwe Maan <douwe@selenight.nl> | 2016-05-13 17:31:43 -0500 |
commit | 99d3e21f19ffb5cccb58fdfeac4fb6174e7e65e2 (patch) | |
tree | 3dae33d98b9688a3f7e9a4c923f555920d86652b | |
parent | 5e130c3e39febcd577e61ebd30bd231827d41f2c (diff) | |
download | gitlab-ce-99d3e21f19ffb5cccb58fdfeac4fb6174e7e65e2.tar.gz |
Extract LegacyDiffNote out of Note
33 files changed, 386 insertions, 370 deletions
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index efb3e8e2198..6d9d6528f45 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -285,6 +285,7 @@ class @Notes form.addClass "js-main-target-form" form.find("#note_line_code").remove() + form.find("#note_type").remove() ### General note form setup. @@ -472,6 +473,7 @@ class @Notes setupDiscussionNoteForm: (dataHolder, form) => # setup note target 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("#note_commit_id").val dataHolder.data("commitId") form.find("#note_line_code").val dataHolder.data("lineCode") diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 624c8249f7e..a3e1ac13a43 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -226,8 +226,7 @@ ul.notes { } } -.note-action-button, -.discussion-action-button { +.note-action-button { display: inline-block; margin-left: 10px; line-height: 24px; diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index a202cb38692..9bcb82ef3f9 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -17,11 +17,12 @@ class Projects::CommitController < Projects::ApplicationController def show apply_diff_view_cookie! - @line_notes = commit.notes.inline + @grouped_diff_notes = commit.notes.grouped_diff_notes + @note = @project.build_commit_note(commit) - @notes = commit.notes.not_inline.fresh + @notes = commit.notes.non_diff_notes.fresh @noteable = @commit - @comments_allowed = @reply_allowed = true + @comments_allowed = true @comments_target = { noteable_type: 'Commit', commit_id: @commit.id @@ -67,10 +68,10 @@ class Projects::CommitController < Projects::ApplicationController 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) end - + def cherry_pick assign_change_commit_vars(@commit.cherry_pick_branch_name) - + return render_404 if @target_branch.blank? create_commit(Commits::CherryPickService, success_notice: "The #{@commit.change_type_title} has been successfully cherry-picked.", diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 671d5c23024..587b84fd921 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -22,7 +22,7 @@ class Projects::CompareController < Projects::ApplicationController @base_commit = @project.merge_base_commit(@base_ref, @head_ref) @diffs = compare.diffs(diff_options) @diff_refs = [@base_commit, @commit] - @line_notes = [] + @grouped_diff_notes = {} end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 9c147b3689e..e571da64e4b 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -73,12 +73,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController # but we need it for the "View file @ ..." link by deleted files @base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit - @comments_allowed = @reply_allowed = true + @comments_allowed = true @comments_target = { noteable_type: 'MergeRequest', 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| format.html @@ -300,7 +301,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController # Build a note object for comment form @note = @project.notes.new(noteable: @merge_request) @notes = @merge_request.mr_and_commit_notes.nonawards.inc_author.fresh - @discussions = Note.discussions_from_notes(@notes) + @discussions = @notes.discussions @noteable = @merge_request # Get commits from repository diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index 707a0d0e5c6..4a57cd29a20 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -96,7 +96,7 @@ class Projects::NotesController < Projects::ApplicationController end def note_to_discussion_html(note) - return unless note.for_diff_line? + return unless note.diff_note? if params[:view] == 'parallel' template = "projects/notes/_diff_notes_with_reply_parallel" @@ -120,7 +120,7 @@ class Projects::NotesController < Projects::ApplicationController end def note_to_discussion_with_diff_html(note) - return unless note.for_diff_line? + return unless note.diff_note? render_to_string( "projects/notes/_discussion", @@ -158,7 +158,7 @@ class Projects::NotesController < Projects::ApplicationController def note_params params.require(:note).permit( :note, :noteable, :noteable_id, :noteable_type, :project_id, - :attachment, :line_code, :commit_id + :attachment, :line_code, :commit_id, :type ) end diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb index fa4c635f55c..c41be333537 100644 --- a/app/finders/notes_finder.rb +++ b/app/finders/notes_finder.rb @@ -10,7 +10,7 @@ class NotesFinder notes = case target_type when "commit" - project.notes.for_commit_id(target_id).not_inline + project.notes.for_commit_id(target_id).non_diff_notes when "issue" project.issues.find(target_id).notes.nonawards.inc_author when "merge_request" diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 9f73edb4553..5f311f3780a 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -55,22 +55,18 @@ module DiffHelper end end - def line_comments - @line_comments ||= @line_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code) - end - - def organize_comments(type_left, type_right, line_code_left, line_code_right) - comments_left = comments_right = nil + def organize_comments(left, right) + notes_left = notes_right = nil - unless type_left.nil? && type_right == 'new' - comments_left = line_comments[line_code_left] + unless left[:type].nil? && right[:type] == 'new' + notes_left = @grouped_diff_notes[left[:line_code]] end - unless type_left.nil? && type_right.nil? - comments_right = line_comments[line_code_right] + unless left[:type].nil? && right[:type].nil? + notes_right = @grouped_diff_notes[right[:line_code]] end - [comments_left, comments_right] + [notes_left, notes_right] end def inline_diff_btn @@ -96,8 +92,8 @@ module DiffHelper ].join(' ').html_safe end - def commit_for_diff(diff) - if diff.deleted_file + def commit_for_diff(diff_file) + if diff_file.deleted_file @base_commit || @commit.parent || @commit else @commit diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 95072b5373f..b401c8385be 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -1,7 +1,7 @@ module NotesHelper # Helps to distinguish e.g. commit notes in mr notes list 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 def note_target_fields(note) @@ -15,16 +15,6 @@ module NotesHelper note.editable? && can?(current_user, :admin_note, note) 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) { id: noteable.id, @@ -35,7 +25,7 @@ module NotesHelper end 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_id] || @comments_target[:commit_id], line_code @@ -45,9 +35,10 @@ module NotesHelper noteable_type: @comments_target[:noteable_type], noteable_id: @comments_target[:noteable_id], commit_id: @comments_target[:commit_id], + line_type: line_type, line_code: line_code, - discussion_id: discussion_id, - line_type: line_type + note_type: LegacyDiffNote.name, + discussion_id: discussion_id } button_tag(class: 'btn add-diff-note js-add-diff-note-button', @@ -57,18 +48,24 @@ module NotesHelper end end - def link_to_reply_diff(note, line_type = nil) + def link_to_reply_discussion(note, line_type = nil) return unless current_user data = { noteable_type: note.noteable_type, noteable_id: note.noteable_id, commit_id: note.commit_id, - line_code: note.line_code, discussion_id: note.discussion_id, 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', data: data, title: 'Add a reply' end diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb new file mode 100644 index 00000000000..b5de85df99f --- /dev/null +++ b/app/models/legacy_diff_note.rb @@ -0,0 +1,182 @@ +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 diff --git a/app/models/note.rb b/app/models/note.rb index f26aa1bf63f..3bc55870704 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -1,6 +1,5 @@ -require 'carrierwave/orm/activerecord' - class Note < ActiveRecord::Base + extend ActiveModel::Naming include Gitlab::CurrentSettings include Participable include Mentionable @@ -22,12 +21,10 @@ class Note < ActiveRecord::Base delegate :name, :email, to: :author, prefix: true before_validation :set_award! - before_validation :clear_blank_line_code! validates :note, :project, presence: true 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 :line_code, line_code: true, allow_blank: true # Attachments are deprecated and are handled by Markdown uploader validates :attachment, file_size: { maximum: :max_attachment_size } @@ -41,8 +38,6 @@ class Note < ActiveRecord::Base scope :awards, ->{ where(is_award: true) } scope :nonawards, ->{ where(is_award: false) } 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 :user, ->{ where(system: false) } scope :common, ->{ where(noteable_type: ["", nil]) } @@ -50,38 +45,31 @@ class Note < ActiveRecord::Base scope :inc_author_project, ->{ includes(:project, :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 includes(:author, :noteable, :updated_by, project: [:project_members, { group: [:group_members] }]) end - serialize :st_diff - before_create :set_diff, if: ->(n) { n.line_code.present? } + before_validation :clear_blank_line_code! class << self - def discussions_from_notes(notes) - discussion_ids = [] - discussions = [] - - notes.each do |note| - next if discussion_ids.include?(note.discussion_id) - - # 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 + def model_name + ActiveModel::Name.new(self, nil, 'note') + end + + def build_discussion_id(noteable_type, noteable_id) + [:discussion, noteable_type.try(:underscore), noteable_id].join("-") + end - discussions + def discussions + all.group_by(&:discussion_id).values end - def build_discussion_id(type, id, line_code) - [:discussion, type.try(:underscore), id, line_code].join("-").to_sym + def grouped_diff_notes + legacy_diff_notes.select(&:active?).sort_by(&:created_at).group_by(&:line_code) end # Searches for notes matching the given query. @@ -116,167 +104,35 @@ class Note < ActiveRecord::Base system && SystemNoteService.cross_reference?(note) end - def max_attachment_size - current_application_settings.max_attachment_size.megabytes.to_i - 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 + def diff_note? + false 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 + def legacy_diff_note? + false 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 + def discussion_id + @discussion_id ||= + if for_merge_request? + [:discussion, :note, id].join("-") else - prev_lines << line - - break if generate_line_code(line) == self.line_code - - prev_lines.shift if prev_lines.length >= max_number_of_lines + self.class.build_discussion_id(noteable_type, noteable_id || commit_id) 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 + def max_attachment_size + current_application_settings.max_attachment_size.megabytes.to_i end - def discussion_id - @discussion_id ||= Note.build_discussion_id(noteable_type, noteable_id || commit_id, line_code) + def hook_attrs + attributes end def for_commit? noteable_type == "Commit" end - def for_commit_diff_line? - for_commit? && for_diff_line? - end - - def for_diff_line? - line_code.present? - end - def for_issue? noteable_type == "Issue" end @@ -285,10 +141,6 @@ class Note < ActiveRecord::Base noteable_type == "MergeRequest" end - def for_merge_request_diff_line? - for_merge_request? && for_diff_line? - end - def for_snippet? noteable_type == "Snippet" end @@ -361,14 +213,8 @@ class Note < ActiveRecord::Base self.line_code = nil if self.line_code.blank? 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? - (for_issue? || for_merge_request?) && !for_diff_line? + (for_issue? || for_merge_request?) && !diff_note? end def contains_emoji_only? diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml index 65f0e4c4068..27e8ea5f5a1 100644 --- a/app/views/notify/note_merge_request_email.html.haml +++ b/app/views/notify/note_merge_request_email.html.haml @@ -1,4 +1,4 @@ -- if @note.diff_file_name +- if @note.legacy_diff_note? %p.details New comment on diff for = link_to @note.diff_file_name, @target_url diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 81948513e43..3d91dc43129 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -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] }} = link_to raw(right[:number]), "##{new_line_code}", id: new_line_code - 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]) - - if @reply_allowed - - comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code]) - - if comments_left.present? || comments_right.present? - = render "projects/notes/diff_notes_with_reply_parallel", notes_left: comments_left, notes_right: comments_right + - if @comments_allowed + - notes_left, notes_right = organize_comments(left, right) + - if notes_left.present? || notes_right.present? + = 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? .file-mode-changed diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index e7169d7b599..d58444a9d5b 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -6,16 +6,15 @@ %table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' } - last_line = 0 - - raw_diff_lines = diff_file.diff_lines.to_a - diff_file.highlighted_diff_lines.each_with_index do |line, index| - line_code = generate_line_code(diff_file.file_path, line) - last_line = line.new_pos = render "projects/diffs/line", {line: line, diff_file: diff_file, line_code: line_code} - - if @reply_allowed - - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) - - unless comments.empty? - = render "projects/notes/diff_notes_with_reply", notes: comments, line: raw_diff_lines[index].text + - if @comments_allowed + - diff_notes = @grouped_diff_notes[line_code] + - if diff_notes + = render "projects/notes/diff_notes_with_reply", notes: diff_notes - if last_line > 0 = render "projects/diffs/match_line", { line: "", diff --git a/app/views/projects/notes/_commit_discussion.html.haml b/app/views/projects/notes/_commit_discussion.html.haml deleted file mode 100644 index e69de29bb2d..00000000000 --- a/app/views/projects/notes/_commit_discussion.html.haml +++ /dev/null diff --git a/app/views/projects/notes/_diff_notes_with_reply.html.haml b/app/views/projects/notes/_diff_notes_with_reply.html.haml index 39be072855a..8144c1ba49e 100644 --- a/app/views/projects/notes/_diff_notes_with_reply.html.haml +++ b/app/views/projects/notes/_diff_notes_with_reply.html.haml @@ -1,10 +1,8 @@ -- note = notes.first # example note --# Check if line want not changed since comment was left -- if !defined?(line) || line == note.diff_line - %tr.notes_holder - %td.notes_line{ colspan: 2 } - %td.notes_content - %ul.notes{ data: { discussion_id: note.discussion_id } } - = render notes - .discussion-reply-holder - = link_to_reply_diff(note) +- note = notes.first +%tr.notes_holder + %td.notes_line{ colspan: 2 } + %td.notes_content + %ul.notes{ data: { discussion_id: note.discussion_id } } + = render partial: "projects/notes/note", collection: notes, as: :note + .discussion-reply-holder + = link_to_reply_discussion(note) diff --git a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml index f8aa5e2fa7d..45986b0d1e8 100644 --- a/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml +++ b/app/views/projects/notes/_diff_notes_with_reply_parallel.html.haml @@ -1,27 +1,27 @@ -- note1 = notes_left.present? ? notes_left.first : nil -- note2 = notes_right.present? ? notes_right.first : nil +- note_left = notes_left.present? ? notes_left.first : nil +- note_right = notes_right.present? ? notes_right.first : nil %tr.notes_holder - - if note1 + - if note_left %td.notes_line.old %td.notes_content.parallel.old - %ul.notes{ data: { discussion_id: note1.discussion_id } } - = render notes_left + %ul.notes{ data: { discussion_id: note_left.discussion_id } } + = render partial: "projects/notes/note", collection: notes_left, as: :note .discussion-reply-holder - = link_to_reply_diff(note1, 'old') + = link_to_reply_discussion(note_left, 'old') - else %td.notes_line.old= "" %td.notes_content.parallel.old= "" - - if note2 + - if note_right %td.notes_line.new %td.notes_content.parallel.new - %ul.notes{ data: { discussion_id: note2.discussion_id } } - = render notes_right + %ul.notes{ data: { discussion_id: note_right.discussion_id } } + = render partial: "projects/notes/note", collection: notes_right, as: :note .discussion-reply-holder - = link_to_reply_diff(note2, 'new') + = link_to_reply_discussion(note_right, 'new') - else %td.notes_line.new= "" %td.notes_content.parallel.new= "" diff --git a/app/views/projects/notes/_discussion.html.haml b/app/views/projects/notes/_discussion.html.haml index 572b00a38c7..40e03050a7d 100644 --- a/app/views/projects/notes/_discussion.html.haml +++ b/app/views/projects/notes/_discussion.html.haml @@ -1,13 +1,46 @@ - note = discussion_notes.first +- expanded = !note.diff_note? || note.active? %li.note.note-discussion.timeline-entry .timeline-entry-inner .timeline-icon = 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 - - if note.for_merge_request? - - (active_notes, outdated_notes) = discussion_notes.partition(&:active?) - = render "projects/notes/discussions/active", discussion_notes: active_notes if active_notes.length > 0 - = render "projects/notes/discussions/outdated", discussion_notes: outdated_notes if outdated_notes.length > 0 - - else - = render "projects/notes/discussions/commit", discussion_notes: discussion_notes + .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 + + - 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 diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index d0ac380f216..67ed38a7b22 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -6,6 +6,7 @@ = f.hidden_field :line_code = f.hidden_field :noteable_id = f.hidden_field :noteable_type + = f.hidden_field :type = 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..." diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index aeb7c1d5ee4..9fbc9a45549 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -1,5 +1,8 @@ +- return unless note.author +- return if note.cross_reference_not_visible_for?(current_user) + - 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-icon %a{href: user_path(note.author)} @@ -8,8 +11,8 @@ .note-header = link_to_member(note.project, note.author, avatar: false) .inline.note-headline-light - = "#{note.author.to_reference}" - - if !note.system + = note.author.to_reference + - unless note.system commented %a{ href: "##{dom_id(note)}" } = time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago') diff --git a/app/views/projects/notes/_notes.html.haml b/app/views/projects/notes/_notes.html.haml index 62db86fb181..ebf7e8a9cb3 100644 --- a/app/views/projects/notes/_notes.html.haml +++ b/app/views/projects/notes/_notes.html.haml @@ -2,14 +2,9 @@ - @discussions.each do |discussion_notes| - note = discussion_notes.first - if note_for_main_target?(note) - - next if note.cross_reference_not_visible_for?(current_user) - - = render discussion_notes + = render partial: "projects/notes/note", object: note, as: :note - else = render 'projects/notes/discussion', discussion_notes: discussion_notes - else - @notes.each do |note| - - next unless note.author - - next if note.cross_reference_not_visible_for?(current_user) - - = render note + = render partial: "projects/notes/note", object: note, as: :note diff --git a/app/views/projects/notes/discussions/_active.html.haml b/app/views/projects/notes/discussions/_active.html.haml deleted file mode 100644 index 0ea8862a684..00000000000 --- a/app/views/projects/notes/discussions/_active.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -- 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 diff --git a/app/views/projects/notes/discussions/_commit.html.haml b/app/views/projects/notes/discussions/_commit.html.haml deleted file mode 100644 index 2a2ead58eeb..00000000000 --- a/app/views/projects/notes/discussions/_commit.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -- 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 --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml deleted file mode 100644 index d46aab000c3..00000000000 --- a/app/views/projects/notes/discussions/_diff.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -- 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" ? " ".html_safe : line.old_pos } } - %td.new_line.diff-line-num{ data: { linenumber: type == "old" ? " ".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 diff --git a/app/views/projects/notes/discussions/_legacy_diff_with_notes.html.haml b/app/views/projects/notes/discussions/_legacy_diff_with_notes.html.haml new file mode 100644 index 00000000000..3ab11f6461d --- /dev/null +++ b/app/views/projects/notes/discussions/_legacy_diff_with_notes.html.haml @@ -0,0 +1,30 @@ +- 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" ? " ".html_safe : line.old_pos } } + %td.new_line.diff-line-num{ data: { linenumber: type == "old" ? " ".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 diff --git a/app/views/projects/notes/discussions/_notes.html.haml b/app/views/projects/notes/discussions/_notes.html.haml new file mode 100644 index 00000000000..e598e3c7c63 --- /dev/null +++ b/app/views/projects/notes/discussions/_notes.html.haml @@ -0,0 +1,7 @@ +- 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) diff --git a/app/views/projects/notes/discussions/_outdated.html.haml b/app/views/projects/notes/discussions/_outdated.html.haml deleted file mode 100644 index 45141bcd1df..00000000000 --- a/app/views/projects/notes/discussions/_outdated.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -- 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 diff --git a/db/migrate/20160508215820_add_type_to_notes.rb b/db/migrate/20160508215820_add_type_to_notes.rb new file mode 100644 index 00000000000..58944d4e651 --- /dev/null +++ b/db/migrate/20160508215820_add_type_to_notes.rb @@ -0,0 +1,5 @@ +class AddTypeToNotes < ActiveRecord::Migration + def change + add_column :notes, :type, :string + end +end diff --git a/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb b/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb new file mode 100644 index 00000000000..c3f23d89d5a --- /dev/null +++ b/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb @@ -0,0 +1,5 @@ +class SetTypeOnLegacyDiffNotes < ActiveRecord::Migration + def change + execute "UPDATE notes SET type = 'LegacyDiffNote' WHERE line_code IS NOT NULL" + end +end diff --git a/db/schema.rb b/db/schema.rb index 9b5aa640cb0..e1117a0d858 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -632,10 +632,11 @@ ActiveRecord::Schema.define(version: 20160509201028) do t.string "line_code" t.string "commit_id" t.integer "noteable_id" - t.boolean "system", default: false, null: false + t.boolean "system", default: false, null: false t.text "st_diff" 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 add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 93a3a5ce089..4a11c8e3620 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -107,6 +107,8 @@ module API break if opts[:line_code] end + + opts[:type] = LegacyDiffNote.name if opts[:line_code] end note = ::Notes::CreateService.new(user_project, current_user, opts).execute diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 406f5ea9139..1619199b0a7 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -227,9 +227,9 @@ module API class CommitNote < Grape::Entity expose :note - expose(:path) { |note| note.diff_file_name } - expose(:line) { |note| note.diff_new_line } - expose(:line_type) { |note| note.diff_line_type } + expose(:path) { |note| note.diff_file_name if note.legacy_diff_note? } + expose(:line) { |note| note.diff_new_line if note.legacy_diff_note? } + expose(:line_type) { |note| note.diff_line_type if note.legacy_diff_note? } expose :author, using: Entities::UserBasic expose :created_at end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 4b788b57882..264888cb376 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -43,12 +43,8 @@ describe Note, models: true do expect(note.noteable.id).to eq(commit.id) end - it "should be recognized by #for_diff_line?" do - expect(note).to be_for_diff_line - end - - it "should be recognized by #for_commit_diff_line?" do - expect(note).to be_for_commit_diff_line + it "should be recognized by #legacy_diff_note?" do + expect(note).to be_legacy_diff_note end end |