Commit 06ea1228 authored by Riyad Preukschas's avatar Riyad Preukschas

Refactor diff notes creation

parent 39834ec6
...@@ -17,34 +17,6 @@ var NoteList = { ...@@ -17,34 +17,6 @@ var NoteList = {
this.reversed = $("#notes-list").is(".reversed"); this.reversed = $("#notes-list").is(".reversed");
this.target_params = "target_type=" + this.target_type + "&target_id=" + this.target_id; this.target_params = "target_type=" + this.target_type + "&target_id=" + this.target_id;
// get initial set of notes
this.getContent();
$("#notes-list, #new-notes-list").on("ajax:success", ".js-note-delete", function() {
$(this).closest('li').fadeOut(function() {
$(this).remove();
NoteList.updateVotes();
});
});
$(".note-form-holder").on("ajax:before", function(){
$(".submit_note").disable();
})
$(".note-form-holder").on("ajax:complete", function(){
$(".submit_note").enable();
$('#preview-note').hide();
$('#note_note').show();
})
disableButtonIfEmptyField(".note-text", ".submit_note");
$("#note_attachment").change(function(e){
var val = $('.input-file').val();
var filename = val.replace(/^.*[\\\/]/, '');
$(".file_name").text(filename);
});
if(this.reversed) { if(this.reversed) {
var textarea = $(".note-text"); var textarea = $(".note-text");
$('.note_advanced_opts').hide(); $('.note_advanced_opts').hide();
...@@ -55,6 +27,17 @@ var NoteList = { ...@@ -55,6 +27,17 @@ var NoteList = {
}); });
} }
// get initial set of notes
this.getContent();
disableButtonIfEmptyField(".js-note-text", ".js-comment-button");
$("#note_attachment").change(function(e){
var val = $('.input-file').val();
var filename = val.replace(/^.*[\\\/]/, '');
$(".file_name").text(filename);
});
// Setup note preview // Setup note preview
$(document).on('click', '#preview-link', function(e) { $(document).on('click', '#preview-link', function(e) {
$('#preview-note').text('Loading...'); $('#preview-note').text('Loading...');
...@@ -72,11 +55,170 @@ var NoteList = { ...@@ -72,11 +55,170 @@ var NoteList = {
} }
$('#preview-note, #note_note').toggle(); $('#preview-note, #note_note').toggle();
e.preventDefault(); });+
$(document).on("click",
".js-add-diff-note-button",
NoteList.addDiffNote);
// reply to diff notes
$(document).on("click",
".js-diff-note-reply-button",
NoteList.replyToDiffNote);
// hide diff note form
$(document).on("click",
".js-hide-diff-note-form",
NoteList.removeDiffNoteForm);
// do some diff note specific housekeeping when removing a diff note
$(document).on("click",
".diff_file .js-note-delete",
NoteList.removeDiffNote);
// remove a note (in general)
$(document).on("click",
".js-note-delete",
NoteList.removeNote);
// clean up previews for forms
$(document).on("ajax:complete", ".note-form-holder", function(){
$(this).find('#preview-note').hide();
$(this).find('#note_note').show();
}); });
}, },
/**
* Event handlers
*/
/**
* Called when clicking on the "add a comment" button on the side of a diff line.
*
* Inserts a temporary row for the form below the line.
* Sets up the form and shows it.
*/
addDiffNote: function(e) {
// find the form
var form = $(".js-note-forms .js-diff-note-form");
var row = $(this).closest("tr");
var nextRow = row.next();
// does it already have notes?
if (nextRow.is(".notes_holder")) {
$.proxy(NoteList.replyToDiffNote,
nextRow.find(".js-diff-note-reply-button")
).call();
} else {
// add a notes row and insert the form
row.after('<tr class="notes_holder js-temp-notes-holder"><td class="notes_line" colspan="2"></td><td class="notes_content"></td></tr>');
form.clone().appendTo(row.next().find(".notes_content"));
// show the form
NoteList.setupDiffNoteForm($(this), row.next().find("form"));
}
e.preventDefault();
},
/**
* Called in response to deleting a note on a diff line.
*
* Removes the actual note from view.
* Removes the whole notes row if the last note for that line is being removed.
*
* Note: must be called before removeNote()
*/
removeDiffNote: function() {
var notes = $(this).closest(".notes");
// check if this is the last note for this line
if (notes.find(".note").length === 1) {
notes.closest("tr").remove();
}
},
/**
* Called in response to "cancel" on a diff note form.
*
* Shows the reply button again.
* Removes the form and if necessary it's temporary row.
*/
removeDiffNoteForm: function(e) {
var form = $(this).closest("form");
var row = form.closest("tr");
// show the reply button (will only work for replys)
form.prev(".js-diff-note-reply-button").show();
if (row.is(".js-temp-notes-holder")) {
// remove temporary row
row.remove();
} else {
// only remove the form
form.remove();
}
e.preventDefault();
},
/**
* Called in response to deleting a note of any kind.
*
* Removes the actual note from view.
*/
removeNote: function() {
$(this).closest(".note").remove();
NoteList.updateVotes();
},
/**
* Called when clicking on the "reply" button for a diff line.
*
* Shows the note form below the notes.
*/
replyToDiffNote: function() {
// find the form
var form = $(".js-note-forms .js-diff-note-form");
// hide reply button
$(this).hide();
// insert the form after the button
form.clone().insertAfter($(this));
// show the form
NoteList.setupDiffNoteForm($(this), $(this).next("form"));
},
/**
* Shows the diff line form and does some setup.
*
* Sets some hidden fields in the form.
*
* Note: "this" must have the "discussionId", "lineCode", "noteableType" and
* "noteableId" data attributes set.
*/
setupDiffNoteForm: function(data_holder, form) {
// setup note target
form.attr("rel", data_holder.data("discussionId"));
form.find("#note_line_code").val(data_holder.data("lineCode"));
form.find("#note_noteable_type").val(data_holder.data("noteableType"));
form.find("#note_noteable_id").val(data_holder.data("noteableId"));
// setup interaction
disableButtonIfEmptyField(form.find(".js-note-text"), form.find(".js-comment-button"));
setupGfmAutoComplete();
// cleanup after successfully creating a diff note
form.on("ajax:success", NoteList.removeDiffNoteForm);
form.show();
},
/** /**
* Handle loading the initial set of notes. * Handle loading the initial set of notes.
* And set up loading more notes when scrolling to the bottom of the page. * And set up loading more notes when scrolling to the bottom of the page.
...@@ -272,52 +414,3 @@ var NoteList = { ...@@ -272,52 +414,3 @@ 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", ".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();
});
disableButtonIfEmptyField(".line-note-text", ".submit_inline_note");
/**
* Called in response to successfully deleting a note on a diff line.
*
* 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", ".js-note-delete", function() {
var trNote = $(this).closest("tr");
trNote.fadeOut(function() {
$(this).remove();
});
// check if this is the last note for this line
// elements must really be removed for this to work reliably
var trLine = trNote.prev();
var trRpl = trNote.next();
if (trLine.is(".line_holder") && trRpl.is(".reply")) {
trRpl.fadeOut(function() { $(this).remove(); });
}
});
}
}
...@@ -194,12 +194,6 @@ ...@@ -194,12 +194,6 @@
-khtml-user-select: none; -khtml-user-select: none;
user-select: none; user-select: none;
&.notes_line {
border: 1px solid #ccc;
border-left: none;
text-align: center;
padding: 10px 0;
}
a { a {
float: left; float: left;
width: 35px; width: 35px;
...@@ -227,10 +221,6 @@ ...@@ -227,10 +221,6 @@
background: #fafafa; background: #fafafa;
} }
} }
.notes_content {
border: 1px solid #ccc;
border-width: 1px 0;
}
} }
/** COMMIT BLOCK **/ /** COMMIT BLOCK **/
......
...@@ -92,23 +92,58 @@ ul.notes { ...@@ -92,23 +92,58 @@ ul.notes {
} }
} }
.comment-btn {
@extend .save-btn;
}
.diff_file tr.notes_holder { .diff_file tr.notes_holder {
font-family: $sansFontFamily; font-family: $sansFontFamily;
font-size: 13px; font-size: 13px;
line-height: 18px; line-height: 18px;
td:last-child { td {
background-color: $white; border: 1px solid #ddd;
padding-top: 0; border-left: none;
&.notes_line {
text-align: center;
padding: 10px 0;
}
&.notes_content {
background-color: $white;
border-width: 1px 0;
padding-top: 0;
}
} }
.comment-btn { .comment-btn {
margin-top: 8px; margin-top: 8px;
} }
// TODO: start cleanup
form {
// hide it by default
display: none;
margin: 8px 0;
.note_actions {
margin:0;
padding-top: 10px;
.buttons {
float:left;
width:300px;
}
.options {
.labels {
float:left;
padding-left:10px;
label {
padding: 6px 0;
margin: 0;
width:120px;
}
}
}
}
}
// TODO: end cleanup
} }
/** /**
...@@ -158,74 +193,6 @@ ul.notes { ...@@ -158,74 +193,6 @@ ul.notes {
} }
} }
/*
* New Note Form
*/
.new_note {
/* Note textare */
#note_note {
height:80px;
width:99%;
font-size:14px;
}
}
#new_note {
.attach_holder {
display: none;
}
}
.preview_note {
margin: 2px;
border: 1px solid #ddd;
padding: 10px;
min-height: 60px;
background: #f5f5f5;
}
.note {
padding: 8px 0;
overflow: hidden;
display: block;
position: relative;
img {float: left; margin-right: 10px;}
img.emoji {float: none;margin: 0;}
.note-author cite{font-style: italic;}
p { color: $style_color; }
.note-author { color: $style_color;}
.note-title { margin-left: 45px; padding-top: 5px;}
.avatar {
margin-top: 3px;
}
.delete-note {
display: none;
position: absolute;
right: 0;
top: 0;
}
&:hover {
.delete-note { display: block; }
}
}
#notes-list:not(.reversed) .note,
#new-notes-list:not(.reversed) .note {
border-bottom: 1px solid #eee;
}
#notes-list.reversed .note,
#new-notes-list.reversed .note {
border-top: 1px solid #eee;
}
/* mark vote notes */
.voting_notes .note {
padding: 8px 0;
}
.notes-status { .notes-status {
margin: 18px; margin: 18px;
} }
...@@ -239,62 +206,74 @@ p.notify_controls span{ ...@@ -239,62 +206,74 @@ p.notify_controls span{
font-weight: 700; font-weight: 700;
} }
.line_notes_row, .per_line_form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } /**
* add line note button on the side of diffs
*/
.diff_file tr.line_holder {
.add-diff-note {
position:absolute;
margin-left:-70px;
margin-top:-10px;
z-index:10;
background: url("comment_add.png") no-repeat left 0;
width:32px;
height:32px;
opacity: 0.0;
filter: alpha(opacity=0);
.per_line_form { &:hover {
background: #f5f5f5; opacity: 1.0;
border-top: 1px solid #eee; filter: alpha(opacity=100);
form { margin: 0; } }
td {
border-bottom: 1px solid #ddd;
} }
.note_actions {
margin: 0;
padding-top: 10px;
.buttons { &:hover > td {
float: left; background: $hover !important;
width: 300px;
} .add-diff-note {
.options { opacity: 1.0;
.labels { filter: alpha(opacity=100);
float: left;
padding-left: 10px;
label {
padding: 6px 0;
margin: 0;
width: 120px;
}
}
} }
} }
} }
td .line_note_link { /**
position: absolute; * Note Forms
margin-left:-70px; */
margin-top:-10px;
z-index: 10; .comment-btn {
background: url("comment_add.png") no-repeat left 0; @extend .save-btn;
width: 32px; }
height: 32px; .new_note {
textarea {
opacity: 0.0; height:80px;
filter: alpha(opacity=0); width:99%;
font-size:14px;
&:hover { }
opacity: 1.0; }
filter: alpha(opacity=100); .note-forms {
.new_diff_note {
display: none;
}
}
#new_note {
.attach_holder {
display:none;
} }
} }
.diff_file_content tr.line_holder:hover > td { background: $hover !important; } .preview_note {
.diff_file_content tr.line_holder:hover > td .line_note_link { margin: 2px;
opacity: 1.0; border: 1px solid #ddd;
filter: alpha(opacity=100); padding: 10px;
min-height: 60px;
background:#f5f5f5;
} }
.new_note { form.new_note {
.input-file { .input-file {
font: 500px monospace; font: 500px monospace;
opacity: 0; opacity: 0;
......
...@@ -12,11 +12,8 @@ class NotesController < ProjectResourceController ...@@ -12,11 +12,8 @@ class NotesController < ProjectResourceController
@notes = Notes::LoadContext.new(project, current_user, params).execute @notes = Notes::LoadContext.new(project, current_user, params).execute
if params[:target_type] == "merge_request" if params[:target_type] == "merge_request"
@has_diff = true
@mixed_targets = true @mixed_targets = true
@discussions = discussions_from_notes @discussions = discussions_from_notes
elsif params[:target_type] == "commit"
@has_diff = true
end end
respond_with(@notes) respond_with(@notes)
......
= render "commits/commit_box" = render "commits/commit_box"
= render "commits/diffs", diffs: @commit.diffs = render "commits/diffs", diffs: @commit.diffs
= render "notes/notes_with_form", tid: @commit.id, tt: "commit" = render "notes/notes_with_form", tid: @commit.id, tt: "commit"
= render "notes/diff_note_form"
:javascript :javascript
$(function(){ $(function(){
PerLineNotes.init();
var w, h; var w, h;
$('.diff_file').each(function(){ $('.diff_file').each(function(){
$('.image.diff_removed img', this).on('load', $.proxy(function(event){ $('.image.diff_removed img', this).on('load', $.proxy(function(event){
...@@ -19,7 +16,5 @@ ...@@ -19,7 +16,5 @@
, h = event.currentTarget.naturalHeight; , h = event.currentTarget.naturalHeight;
$('.image.diff_added .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px'); $('.image.diff_added .image-info', this).append(' | <b>W:</b> ' + w + 'px | <b>H:</b> ' + h + 'px');
}, this)); }, this));
}); });
}); });
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
= render "merge_requests/show/diffs" if @diffs = render "merge_requests/show/diffs" if @diffs
.status .status
= render "notes/diff_note_form"
:javascript :javascript
$(function(){ $(function(){
MergeRequest.init({ MergeRequest.init({
......
:plain :plain
$(".merge-request-diffs").html("#{escape_javascript(render(partial: "merge_requests/show/diffs"))}"); $(".merge-request-diffs").html("#{escape_javascript(render(partial: "merge_requests/show/diffs"))}");
$(function(){
PerLineNotes.init();
});
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
= f.hidden_field :noteable_id = f.hidden_field :noteable_id
= f.hidden_field :noteable_type = f.hidden_field :noteable_type
= f.text_area :note, size: 255, class: 'note-text js-gfm-input' = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input'
#preview-note.preview_note.hide #preview-note.preview_note.hide
.hint .hint
.right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}. .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
.row.note_advanced_opts .row.note_advanced_opts
.span3 .span3
= f.submit 'Add Comment', class: "btn comment-btn submit_note grouped", id: "submit_note" = f.submit 'Add Comment', class: "btn comment-btn grouped js-comment-button"
= link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link' = link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link'
.span4.notify_opts .span4.notify_opts
%h6.left Notify via email: %h6.left Notify via email:
......
- if note.valid? - if note.valid?
:plain :plain
// hide and reset the form // hide and reset the form
$(".per_line_form").hide(); var form = $("form[rel='#{note.discussion_id}']");
$('.line-note-form-holder textarea').val(""); var row = form.closest("tr");
// find the reply button for this line // is this the first note?
// (might not be there if this is the first note) if (row.is(".js-temp-notes-holder")) {
var trRpl = $(".js-note-add-to-diff-line[data-noteable-type='#{note.noteable_type}'][data-noteable-id='#{note.noteable_id}'][data-line-code='#{note.line_code}']").closest("tr"); // insert the note and the reply button after it
if (trRpl.size() == 0) { row.after("#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}");
// find the commented line ...
var trEl = $(".#{note.line_code}").parent();
// ... and insert the note and the reply button after it
trEl.after("#{escape_javascript(render "notes/diff_notes_with_reply", notes: [note])}");
} else { } else {
// instert new note before reply button // instert new note before reply button
trRpl.before("#{escape_javascript(render "notes/diff_note", note: note)}"); row.find(".notes").append("#{escape_javascript(render "notes/note", note: note)}");
} }
%table{style: "display:none;"} = form_for [@project, @note], remote: true, html: { multipart: true, class: "new_note new_diff_note js-diff-note-form" } do |f|
%tr.per_line_form .span10
%td{colspan: 3 } -if @note.errors.any?
.line-note-form-holder .alert-message.block-message.error
= form_for [@project, @note], remote: "true", multipart: true do |f| - @note.errors.full_messages.each do |msg|
%h3.page_title Leave a comment %div= msg
%div.span10
-if @note.errors.any?
.alert-message.block-message.error
- @note.errors.full_messages.each do |msg|
%div= msg
= f.hidden_field :noteable_id = f.hidden_field :noteable_id
= f.hidden_field :noteable_type = f.hidden_field :noteable_type
= f.hidden_field :line_code = f.hidden_field :line_code
= f.text_area :note, size: 255, class: 'line-note-text js-gfm-input' = f.text_area :note, size: 255, class: 'js-note-text js-gfm-input'
.note_actions .note_actions
.buttons .buttons
= f.submit 'Add Comment', class: "btn save-btn submit_note submit_inline_note", id: "submit_note" = f.submit 'Add Comment', class: "btn save-btn js-comment-button"
= link_to "Cancel", "javascript:;", class: "btn hide-button" %button.btn.js-hide-diff-note-form Cancel
.options .options
%h6.left Notify via email: %h6.left Notify via email:
.labels .labels
= label_tag :notify do = label_tag :notify do
= check_box_tag :notify, 1, @note.noteable_type != "Commit" = check_box_tag :notify, 1, @note.noteable_type != "Commit"
%span Project team %span Project team
- if @note.notify_only_author?(current_user) - if @note.notify_only_author?(current_user)
= label_tag :notify_author do = label_tag :notify_author do
= check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
%span Commit author %span Commit author
- note = @project.notes.new(@comments_target.merge({ line_code: line_code }))
= link_to "", = link_to "",
"#", "javascript:;",
id: "add-diff-line-note-#{line_code}", class: "add-diff-note js-add-diff-note-button",
class: "line_note_link js-note-add-to-diff-line", data: { noteable_type: note.noteable_type,
data: @comments_target.merge({ line_code: line_code }), noteable_id: note.noteable_id,
line_code: note.line_code,
discussion_id: note.discussion_id },
title: "Add a comment to this line" title: "Add a comment to this line"
%tr.notes_holder - note = notes.first # example note
%tr.notes_holder{ data: { :'discussion-id' => note.discussion_id } }
%td.notes_line{ colspan: 2 } %td.notes_line{ colspan: 2 }
%span.btn.disabled %span.btn.disabled
%i.icon-comment %i.icon-comment
...@@ -8,11 +9,12 @@ ...@@ -8,11 +9,12 @@
= render notes = render notes
-# reply button -# reply button
- note = notes.first # example note = link_to "javascript:;",
%button{ class: "btn comment-btn js-note-add-to-diff-line", class: "btn comment-btn js-diff-note-reply-button",
data: { line_code: note.line_code, data: { noteable_type: note.noteable_type,
noteable_type: note.noteable_type, noteable_id: note.noteable_id,
noteable_id: note.noteable_id }, line_code: note.line_code,
title: "Add a comment to this line" } discussion_id: note.discussion_id },
title: "Add a comment to this line" do
%i.icon-comment %i.icon-comment
Reply Reply
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
.notes-status .notes-status
- if can? current_user, :write_note, @project - if can? current_user, :write_note, @project
= render "notes/common_form" .note-forms.js-note-forms
= render "notes/common_form"
= render "notes/diff_note_form"
:javascript :javascript
$(function(){ $(function(){
......
...@@ -2,7 +2,3 @@ ...@@ -2,7 +2,3 @@
= render "create_diff_note", note: @note = render "create_diff_note", note: @note
- else - else
= render "create_common_note", note: @note = render "create_common_note", note: @note
-# Enable submit button
:plain
$("#submit_note").removeAttr("disabled");
...@@ -16,7 +16,3 @@ ...@@ -16,7 +16,3 @@
- if loading_more_notes? - if loading_more_notes?
:plain :plain
NoteList.finishedLoadingMore(); NoteList.finishedLoadingMore();
- if @has_diff
:plain
PerLineNotes.init();
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