Update notes views to support discussions
This commit is contained in:
parent
0b3df2f128
commit
5c2f6d7f05
14 changed files with 270 additions and 60 deletions
|
@ -20,7 +20,7 @@ var NoteList = {
|
|||
// get initial set of notes
|
||||
this.getContent();
|
||||
|
||||
$("#notes-list, #new-notes-list").on("ajax:success", ".delete-note", function() {
|
||||
$("#notes-list, #new-notes-list").on("ajax:success", ".js-note-delete", function() {
|
||||
$(this).closest('li').fadeOut(function() {
|
||||
$(this).remove();
|
||||
NoteList.updateVotes();
|
||||
|
@ -275,16 +275,23 @@ var NoteList = {
|
|||
var PerLineNotes = {
|
||||
init:
|
||||
function() {
|
||||
$(".per_line_form .hide-button").on("click", function(){
|
||||
$(this).closest(".per_line_form").hide();
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* Called when clicking on the "add note" or "reply" button for a diff line.
|
||||
*
|
||||
* Shows the note form below the line.
|
||||
* Sets some hidden fields in the form.
|
||||
*/
|
||||
$(".diff_file_content").on("click", ".line_note_link, .line_note_reply_link", function(e) {
|
||||
$(".diff_file_content").on("click", ".js-note-add-to-diff-line", function(e) {
|
||||
var form = $(".per_line_form");
|
||||
$(this).closest("tr").after(form);
|
||||
form.find("#note_line_code").val($(this).data("lineCode"));
|
||||
form.find("#note_noteable_type").val($(this).data("noteableType"));
|
||||
form.find("#note_noteable_id").val($(this).data("noteableId"));
|
||||
form.show();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
@ -297,7 +304,7 @@ var PerLineNotes = {
|
|||
* Removes the actual note from view.
|
||||
* Removes the reply button if the last note for that line has been removed.
|
||||
*/
|
||||
$(".diff_file_content").on("ajax:success", ".delete-note", function() {
|
||||
$(".diff_file_content").on("ajax:success", ".js-note-delete", function() {
|
||||
var trNote = $(this).closest("tr");
|
||||
trNote.fadeOut(function() {
|
||||
$(this).remove();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/**
|
||||
* Notes
|
||||
*
|
||||
*/
|
||||
#notes-list,
|
||||
#new-notes-list {
|
||||
|
@ -8,6 +7,133 @@
|
|||
list-style: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
|
||||
.discussion-header,
|
||||
.note-header {
|
||||
@extend .cgray;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 15px;
|
||||
|
||||
.avatar {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.discussion-last-update,
|
||||
.note-last-update {
|
||||
font-style: italic;
|
||||
}
|
||||
.note-author {
|
||||
color: $style_color;
|
||||
font-weight: bold;
|
||||
&:hover {
|
||||
color: $primary_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.discussion {
|
||||
padding: 8px 0;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
position:relative;
|
||||
|
||||
.discussion-body {
|
||||
margin-left: 50px;
|
||||
|
||||
.diff_file,
|
||||
.discussion-hidden,
|
||||
.notes {
|
||||
@extend .borders;
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
.diff_file .note {
|
||||
border-bottom: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
.discussion-hidden .note {
|
||||
@extend .cgray;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
.notes .note {
|
||||
border-color: #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.note {
|
||||
padding: 8px 0;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
position:relative;
|
||||
p { color: $style_color; }
|
||||
|
||||
.avatar {
|
||||
margin-top:3px;
|
||||
}
|
||||
.note-body {
|
||||
margin-left:45px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.note-header {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#notes-list:not(.reversed) .note,
|
||||
#notes-list:not(.reversed) .discussion,
|
||||
#new-notes-list:not(.reversed) .note,
|
||||
#new-notes-list:not(.reversed) .discussion {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
#notes-list.reversed .note,
|
||||
#notes-list.reversed .discussion,
|
||||
#new-notes-list.reversed .note,
|
||||
#new-notes-list.reversed .discussion {
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Discussion/Note Actions
|
||||
*/
|
||||
.discussion,
|
||||
.note {
|
||||
&.note:hover {
|
||||
.note-actions { display: block; }
|
||||
}
|
||||
.discussion-header:hover {
|
||||
.discussion-actions { display: block; }
|
||||
}
|
||||
|
||||
.discussion-actions,
|
||||
.note-actions {
|
||||
display: none;
|
||||
float: right;
|
||||
|
||||
[class^="icon-"],
|
||||
[class*="icon-"] {
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
a {
|
||||
@extend .cgray;
|
||||
|
||||
&:hover {
|
||||
color: $primary_color;
|
||||
&.danger { @extend .cred; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.diff_file .note .note-actions {
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.issue_notes,
|
||||
|
@ -18,13 +144,19 @@
|
|||
}
|
||||
}
|
||||
|
||||
/* Note textare */
|
||||
#note_note {
|
||||
height: 80px;
|
||||
width: 99%;
|
||||
font-size: 14px;
|
||||
/*
|
||||
* New Note Form
|
||||
*/
|
||||
.new_note {
|
||||
/* Note textare */
|
||||
#note_note {
|
||||
height:80px;
|
||||
width:99%;
|
||||
font-size:14px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#new_note {
|
||||
.attach_holder {
|
||||
display: none;
|
||||
|
|
|
@ -6,13 +6,15 @@ class NotesController < ProjectResourceController
|
|||
respond_to :js
|
||||
|
||||
def index
|
||||
@target_note = Note.new(noteable_type: params[:target_type].camelize,
|
||||
noteable_id: params[:target_id])
|
||||
@target = @target_note.noteable
|
||||
@notes = Notes::LoadContext.new(project, current_user, params).execute
|
||||
|
||||
if params[:target_type] == "merge_request"
|
||||
@mixed_targets = true
|
||||
@main_target_type = params[:target_type].camelize
|
||||
@discussions = discussions_from_notes
|
||||
@has_diff = true
|
||||
@has_diff = true
|
||||
@mixed_targets = true
|
||||
@discussions = discussions_from_notes
|
||||
elsif params[:target_type] == "commit"
|
||||
@has_diff = true
|
||||
end
|
||||
|
@ -72,6 +74,6 @@ class NotesController < ProjectResourceController
|
|||
|
||||
# Helps to distinguish e.g. commit notes in mr notes list
|
||||
def for_main_target?(note)
|
||||
!@mixed_targets || (@main_target_type == note.noteable_type && !note.for_diff_line?)
|
||||
!@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,13 +9,18 @@ module NotesHelper
|
|||
|
||||
# Helps to distinguish e.g. commit notes in mr notes list
|
||||
def note_for_main_target?(note)
|
||||
!@mixed_targets || (@main_target_type == note.noteable_type && !note.for_diff_line?)
|
||||
!@mixed_targets || (@target.class.name == note.noteable_type && !note.for_diff_line?)
|
||||
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}", project_commit_path(@project, note.noteable, anchor: note.line_code)
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_merge_request_diff_line_note(note)
|
||||
if note.for_merge_request_diff_line?
|
||||
link_to "#{note.diff_file_name}:L#{note.diff_new_line}", diffs_project_merge_request_path(note.project, note.noteable_id, anchor: note.line_code)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -79,7 +79,7 @@ class Note < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def discussion_id
|
||||
@discussion_id ||= [noteable_type, noteable_id, line_code].join.underscore.to_sym
|
||||
@discussion_id ||= [:discussion, noteable_type.underscore, noteable_id, line_code].join("-").to_sym
|
||||
end
|
||||
|
||||
# Returns true if this is a downvote note,
|
||||
|
|
|
@ -1,6 +1 @@
|
|||
= render "show"
|
||||
|
||||
:javascript
|
||||
$(function(){
|
||||
PerLineNotes.init();
|
||||
});
|
||||
|
|
46
app/views/notes/_discussion.html.haml
Normal file
46
app/views/notes/_discussion.html.haml
Normal file
|
@ -0,0 +1,46 @@
|
|||
- note = discussion_notes.first
|
||||
.discussion.js-details-container.js-toggler-container.open{ class: note.discussion_id }
|
||||
.discussion-header
|
||||
.discussion-actions
|
||||
= link_to "javascript:;", class: "js-details-target turn-on js-toggler-target" do
|
||||
%i.icon-eye-close
|
||||
Hide discussion
|
||||
= link_to "javascript:;", class: "js-details-target turn-off js-toggler-target" do
|
||||
%i.icon-eye-open
|
||||
Show discussion
|
||||
= image_tag gravatar_icon(note.author.email), class: "avatar s32"
|
||||
%div
|
||||
= link_to note.author_name, project_team_member_path(@project, @project.team_member_by_id(note.author)), class: "note-author"
|
||||
- if note.for_merge_request?
|
||||
started a discussion on this merge request diff
|
||||
= link_to_merge_request_diff_line_note(note)
|
||||
- elsif note.for_commit?
|
||||
started a discussion on commit
|
||||
#{link_to note.noteable.short_id, project_commit_path(@project, note.noteable)}
|
||||
= link_to_commit_diff_line_note(note) if note.for_diff_line?
|
||||
- else
|
||||
%cite.cgray started a discussion
|
||||
%div
|
||||
- if discussion_notes.size > 1
|
||||
- last_note = discussion_notes.last
|
||||
last updated by
|
||||
= link_to last_note.author_name, project_team_member_path(@project, @project.team_member_by_id(last_note.author)), class: "note-author"
|
||||
%span.discussion-last-update
|
||||
= time_ago_in_words(last_note.updated_at)
|
||||
ago
|
||||
.discussion-body
|
||||
- if note.for_diff_line?
|
||||
.diff_file.content
|
||||
= render "notes/discussion_diff", discussion_notes: discussion_notes, note: note
|
||||
- else
|
||||
.notes.content
|
||||
= render discussion_notes
|
||||
|
||||
-# will be shown when the other one is hidden
|
||||
.discussion-hidden.content.hide
|
||||
.note
|
||||
%em Hidden discussion.
|
||||
= link_to "javascript:;", class: "js-details-target js-toggler-target" do
|
||||
%i.icon-eye-open
|
||||
Show
|
||||
|
24
app/views/notes/_discussion_diff.html.haml
Normal file
24
app/views/notes/_discussion_diff.html.haml
Normal file
|
@ -0,0 +1,24 @@
|
|||
- diff = note.diff
|
||||
.diff_file_header
|
||||
%i.icon-file
|
||||
- if diff.deleted_file
|
||||
%span{id: "#{diff.a_path}"}= diff.a_path
|
||||
- else
|
||||
%span{id: "#{diff.b_path}"}= diff.b_path
|
||||
%br/
|
||||
.diff_file_content
|
||||
%table
|
||||
- each_diff_line(diff.diff.lines.to_a, note.diff_file_index) do |line, type, line_code, line_new, line_old|
|
||||
%tr.line_holder{ id: line_code }
|
||||
- if type == "match"
|
||||
%td.old_line= "..."
|
||||
%td.new_line= "..."
|
||||
%td.line_content.matched= line
|
||||
- else
|
||||
%td.old_line= raw(type == "new" ? " " : line_old)
|
||||
%td.new_line= raw(type == "old" ? " " : line_new)
|
||||
%td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line} "
|
||||
|
||||
- if line_code == note.line_code
|
||||
= render "notes/per_line_notes_with_reply", notes: discussion_notes
|
||||
- break # cut off diff after notes
|
|
@ -1,17 +1,18 @@
|
|||
%li{id: dom_id(note), class: "note"}
|
||||
= image_tag gravatar_icon(note.author.email), class: "avatar s32"
|
||||
%div.note-author
|
||||
%strong= note.author_name
|
||||
= link_to "##{dom_id(note)}", name: dom_id(note) do
|
||||
%cite.cgray
|
||||
= time_ago_in_words(note.updated_at)
|
||||
ago
|
||||
|
||||
- unless note_for_main_target?(note)
|
||||
- if note.for_commit?
|
||||
%span.cgray
|
||||
on #{link_to note.noteable.short_id, project_commit_path(@project, note.noteable)}
|
||||
= link_to_commit_diff_line_note(note) if note.for_diff_line?
|
||||
%li{ id: dom_id(note), class: dom_class(note), data: { discussion: note.discussion_id } }
|
||||
.note-header
|
||||
.note-actions
|
||||
= link_to "##{dom_id(note)}", name: dom_id(note) do
|
||||
%i.icon-link
|
||||
Link here
|
||||
|
||||
- if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
|
||||
= link_to project_note_path(@project, note), method: :delete, confirm: 'Are you sure?', remote: true, class: "danger js-note-delete" do
|
||||
%i.icon-remove-circle
|
||||
= image_tag gravatar_icon(note.author.email), class: "avatar s32"
|
||||
= link_to note.author_name, project_team_member_path(@project, @project.team_member_by_id(note.author)), class: "note-author"
|
||||
%span.note-last-update
|
||||
= time_ago_in_words(note.updated_at)
|
||||
ago
|
||||
|
||||
-# only show vote if it's a note for the main target
|
||||
- if note_for_main_target?(note)
|
||||
|
@ -24,13 +25,8 @@
|
|||
%i.icon-thumbs-down
|
||||
\-1
|
||||
|
||||
-# remove button
|
||||
- if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
|
||||
= link_to [@project, note], confirm: 'Are you sure?', method: :delete, remote: true, class: "cred delete-note btn very_small" do
|
||||
%i.icon-trash
|
||||
Remove
|
||||
|
||||
%div.note-title
|
||||
.note-body
|
||||
= preserve do
|
||||
= markdown(note.note)
|
||||
- if note.attachment.url
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
- @notes.each do |note|
|
||||
- next unless note.author
|
||||
= render "note", note: note
|
||||
|
||||
- if @discussions.present?
|
||||
- @discussions.each do |discussion_notes|
|
||||
- note = discussion_notes.first
|
||||
- if note_for_main_target?(note)
|
||||
= render discussion_notes
|
||||
- else
|
||||
= render 'discussion', discussion_notes: discussion_notes
|
||||
- else
|
||||
- @notes.each do |note|
|
||||
- next unless note.author
|
||||
= render 'note', note: note
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
.note_actions
|
||||
.buttons
|
||||
= f.submit 'Add Comment', class: "btn save-btn submit_note submit_inline_note", id: "submit_note"
|
||||
= link_to "Cancel", "#", class: "btn hide-button"
|
||||
= link_to "Cancel", "javascript:;", class: "btn hide-button"
|
||||
.options
|
||||
%h6.left Notify via email:
|
||||
.labels
|
||||
|
@ -29,11 +29,3 @@
|
|||
= label_tag :notify_author do
|
||||
= check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
|
||||
%span Commit author
|
||||
|
||||
:javascript
|
||||
$(function(){
|
||||
$(".per_line_form .hide-button").bind("click", function(){
|
||||
$('.per_line_form').hide();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
= link_to "",
|
||||
"#",
|
||||
id: "line-note-#{line_code}",
|
||||
class: "line_note_link",
|
||||
id: "add-diff-line-note-#{line_code}",
|
||||
class: "line_note_link js-note-add-to-diff-line",
|
||||
data: @comments_target.merge({ line_code: line_code }),
|
||||
title: "Add comment on line #{line_code[/[0-9]+$/]}"
|
||||
title: "Add a comment to this line"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
%tr.line_notes_row.reply
|
||||
%td{colspan: 3}
|
||||
= link_to "#",
|
||||
class: "line_note_reply_link",
|
||||
= link_to "javascript:;",
|
||||
class: "line_note_reply_link js-note-add-to-diff-line",
|
||||
data: { line_code: note.line_code,
|
||||
noteable_type: note.noteable_type,
|
||||
noteable_id: note.noteable_id },
|
||||
title: "Add note for this line" do
|
||||
title: "Add a comment to this line" do
|
||||
%i.icon-comment
|
||||
Reply
|
||||
|
|
|
@ -15,3 +15,7 @@
|
|||
- if loading_more_notes?
|
||||
:plain
|
||||
NoteList.finishedLoadingMore();
|
||||
|
||||
- if @has_diff
|
||||
:plain
|
||||
PerLineNotes.init();
|
||||
|
|
Loading…
Reference in a new issue