Write new Notes coffee class to handle comments
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
This commit is contained in:
parent
f7e7dc7ebb
commit
923bd2ecd2
1 changed files with 397 additions and 0 deletions
397
app/assets/javascripts/notes.js.coffee
Normal file
397
app/assets/javascripts/notes.js.coffee
Normal file
|
@ -0,0 +1,397 @@
|
|||
class Notes
|
||||
constructor: (notes_url, note_ids) ->
|
||||
@notes_url = notes_url
|
||||
@notes_url = gon.relative_url_root + @notes_url if gon.relative_url_root?
|
||||
@note_ids = note_ids
|
||||
@initRefresh()
|
||||
@setupMainTargetNoteForm()
|
||||
@cleanBinding()
|
||||
@addBinding()
|
||||
|
||||
addBinding: ->
|
||||
# add note to UI after creation
|
||||
$(document).on "ajax:success", ".js-main-target-form", @addNote
|
||||
$(document).on "ajax:success", ".js-discussion-note-form", @addDiscussionNote
|
||||
|
||||
# change note in UI after update
|
||||
$(document).on "ajax:success", "form.edit_note", @updateNote
|
||||
|
||||
# Edit note link
|
||||
$(document).on "click", ".js-note-edit", @showEditForm
|
||||
$(document).on "click", ".note-edit-cancel", @cancelEdit
|
||||
|
||||
# remove a note (in general)
|
||||
$(document).on "click", ".js-note-delete", @removeNote
|
||||
|
||||
# delete note attachment
|
||||
$(document).on "click", ".js-note-attachment-delete", @removeAttachment
|
||||
|
||||
# Preview button
|
||||
$(document).on "click", ".js-note-preview-button", @previewNote
|
||||
|
||||
# reset main target form after submit
|
||||
$(document).on "ajax:complete", ".js-main-target-form", @resetMainTargetForm
|
||||
|
||||
# attachment button
|
||||
$(document).on "click", ".js-choose-note-attachment-button", @chooseNoteAttachment
|
||||
|
||||
# reply to diff/discussion notes
|
||||
$(document).on "click", ".js-discussion-reply-button", @replyToDiscussionNote
|
||||
|
||||
# add diff note
|
||||
$(document).on "click", ".js-add-diff-note-button", @addDiffNote
|
||||
|
||||
cleanBinding: ->
|
||||
$(document).off "ajax:success", ".js-main-target-form"
|
||||
$(document).off "ajax:success", ".js-discussion-note-form"
|
||||
$(document).off "ajax:success", "form.edit_note"
|
||||
$(document).off "click", ".js-note-edit"
|
||||
$(document).off "click", ".note-edit-cancel"
|
||||
$(document).off "click", ".js-note-delete"
|
||||
$(document).off "click", ".js-note-attachment-delete"
|
||||
$(document).off "click", ".js-note-preview-button"
|
||||
$(document).off "ajax:complete", ".js-main-target-form"
|
||||
$(document).off "click", ".js-choose-note-attachment-button"
|
||||
$(document).off "click", ".js-discussion-reply-button"
|
||||
$(document).off "click", ".js-add-diff-note-button"
|
||||
|
||||
|
||||
initRefresh: ->
|
||||
setInterval =>
|
||||
@refresh()
|
||||
, 15000
|
||||
|
||||
refresh: ->
|
||||
@getContent()
|
||||
|
||||
getContent: ->
|
||||
$.ajax
|
||||
url: @notes_url
|
||||
dataType: "json"
|
||||
success: (data) =>
|
||||
notes = data.notes
|
||||
$.each notes, (i, note) =>
|
||||
# render note if it not present in loaded list
|
||||
# or skip if rendered
|
||||
if $.inArray(note.id, @note_ids) == -1
|
||||
@note_ids.push(note.id)
|
||||
@renderNote(note)
|
||||
|
||||
|
||||
###
|
||||
Render note in main comments area.
|
||||
|
||||
Note: for rendering inline notes use renderDiscussionNote
|
||||
###
|
||||
renderNote: (note) ->
|
||||
$('ul.main-notes-list').append(note.html)
|
||||
|
||||
###
|
||||
Render note in discussion area.
|
||||
|
||||
Note: for rendering inline notes use renderDiscussionNote
|
||||
###
|
||||
renderDiscussionNote: (note) ->
|
||||
form = $("form[rel='" + note.discussion_id + "']")
|
||||
row = form.closest("tr")
|
||||
|
||||
# is this the first note of discussion?
|
||||
if row.is(".js-temp-notes-holder")
|
||||
# insert the note and the reply button after the temp row
|
||||
row.after note.discussion_html
|
||||
|
||||
# remove the note (will be added again below)
|
||||
row.next().find(".note").remove()
|
||||
|
||||
# append new note to all matching discussions
|
||||
$(".notes[rel='" + note.discussion_id + "']").append note.html
|
||||
|
||||
# cleanup after successfully creating a diff/discussion note
|
||||
@removeDiscussionNoteForm(form)
|
||||
|
||||
###
|
||||
Shows the note preview.
|
||||
|
||||
Lets the server render GFM into Html and displays it.
|
||||
|
||||
Note: uses the Toggler behavior to toggle preview/edit views/buttons
|
||||
###
|
||||
previewNote: (e) ->
|
||||
e.preventDefault()
|
||||
form = $(this).closest("form")
|
||||
preview = form.find(".js-note-preview")
|
||||
noteText = form.find(".js-note-text").val()
|
||||
if noteText.trim().length is 0
|
||||
preview.text "Nothing to preview."
|
||||
else
|
||||
preview.text "Loading..."
|
||||
$.post($(this).data("url"),
|
||||
note: noteText
|
||||
).success (previewData) ->
|
||||
preview.html previewData
|
||||
|
||||
###
|
||||
Called in response the main target form has been successfully submitted.
|
||||
|
||||
Removes any errors.
|
||||
Resets text and preview.
|
||||
Resets buttons.
|
||||
###
|
||||
resetMainTargetForm: ->
|
||||
form = $(".js-main-target-form")
|
||||
|
||||
# remove validation errors
|
||||
form.find(".js-errors").remove()
|
||||
|
||||
# reset text and preview
|
||||
previewContainer = form.find(".js-toggler-container.note_text_and_preview")
|
||||
previewContainer.removeClass "on" if previewContainer.is(".on")
|
||||
form.find(".js-note-text").val("").trigger "input"
|
||||
|
||||
###
|
||||
Called when clicking the "Choose File" button.
|
||||
|
||||
Opens the file selection dialog.
|
||||
###
|
||||
chooseNoteAttachment: ->
|
||||
form = $(this).closest("form")
|
||||
form.find(".js-note-attachment-input").click()
|
||||
|
||||
###
|
||||
Shows the main form and does some setup on it.
|
||||
|
||||
Sets some hidden fields in the form.
|
||||
###
|
||||
setupMainTargetNoteForm: ->
|
||||
|
||||
# find the form
|
||||
form = $(".js-new-note-form")
|
||||
|
||||
# insert the form after the button
|
||||
form.clone().replaceAll $(".js-main-target-form")
|
||||
form = form.prev("form")
|
||||
|
||||
# show the form
|
||||
@setupNoteForm(form)
|
||||
|
||||
# fix classes
|
||||
form.removeClass "js-new-note-form"
|
||||
form.addClass "js-main-target-form"
|
||||
|
||||
# remove unnecessary fields and buttons
|
||||
form.find("#note_line_code").remove()
|
||||
form.find(".js-close-discussion-note-form").remove()
|
||||
|
||||
###
|
||||
General note form setup.
|
||||
|
||||
deactivates the submit button when text is empty
|
||||
hides the preview button when text is empty
|
||||
setup GFM auto complete
|
||||
show the form
|
||||
###
|
||||
setupNoteForm: (form) ->
|
||||
disableButtonIfEmptyField form.find(".js-note-text"), form.find(".js-comment-button")
|
||||
form.removeClass "js-new-note-form"
|
||||
|
||||
# setup preview buttons
|
||||
form.find(".js-note-edit-button, .js-note-preview-button").tooltip placement: "left"
|
||||
previewButton = form.find(".js-note-preview-button")
|
||||
form.find(".js-note-text").on "input", ->
|
||||
if $(this).val().trim() isnt ""
|
||||
previewButton.removeClass("turn-off").addClass "turn-on"
|
||||
else
|
||||
previewButton.removeClass("turn-on").addClass "turn-off"
|
||||
|
||||
|
||||
# remove notify commit author checkbox for non-commit notes
|
||||
form.find(".js-notify-commit-author").remove() if form.find("#note_noteable_type").val() isnt "Commit"
|
||||
GitLab.GfmAutoComplete.setup()
|
||||
form.show()
|
||||
|
||||
|
||||
###
|
||||
Called in response to the new note form being submitted
|
||||
|
||||
Adds new note to list.
|
||||
###
|
||||
addNote: (xhr, note, status) =>
|
||||
@note_ids.push(note.id)
|
||||
@renderNote(note)
|
||||
|
||||
###
|
||||
Called in response to the new note form being submitted
|
||||
|
||||
Adds new note to list.
|
||||
###
|
||||
addDiscussionNote: (xhr, note, status) =>
|
||||
@note_ids.push(note.id)
|
||||
@renderDiscussionNote(note)
|
||||
|
||||
###
|
||||
Called in response to the edit note form being submitted
|
||||
|
||||
Updates the current note field.
|
||||
###
|
||||
updateNote: (xhr, note, status) =>
|
||||
note_li = $("#note_" + note.id)
|
||||
note_li.replaceWith(note.html)
|
||||
|
||||
###
|
||||
Called in response to clicking the edit note link
|
||||
|
||||
Replaces the note text with the note edit form
|
||||
Adds a hidden div with the original content of the note to fill the edit note form with
|
||||
if the user cancels
|
||||
###
|
||||
showEditForm: (e) ->
|
||||
e.preventDefault()
|
||||
note = $(this).closest(".note")
|
||||
note.find(".note-text").hide()
|
||||
|
||||
# Show the attachment delete link
|
||||
note.find(".js-note-attachment-delete").show()
|
||||
GitLab.GfmAutoComplete.setup()
|
||||
form = note.find(".note-edit-form")
|
||||
form.show()
|
||||
form.find("textarea").focus()
|
||||
|
||||
###
|
||||
Called in response to clicking the edit note link
|
||||
|
||||
Hides edit form
|
||||
###
|
||||
cancelEdit: (e) ->
|
||||
e.preventDefault()
|
||||
note = $(this).closest(".note")
|
||||
note.find(".note-text").show()
|
||||
note.find(".js-note-attachment-delete").hide()
|
||||
note.find(".note-edit-form").hide()
|
||||
|
||||
###
|
||||
Called in response to deleting a note of any kind.
|
||||
|
||||
Removes the actual note from view.
|
||||
Removes the whole discussion if the last note is being removed.
|
||||
###
|
||||
removeNote: ->
|
||||
note = $(this).closest(".note")
|
||||
notes = note.closest(".notes")
|
||||
|
||||
# check if this is the last note for this line
|
||||
if notes.find(".note").length is 1
|
||||
|
||||
# for discussions
|
||||
notes.closest(".discussion").remove()
|
||||
|
||||
# for diff lines
|
||||
notes.closest("tr").remove()
|
||||
|
||||
note.remove()
|
||||
|
||||
###
|
||||
Called in response to clicking the delete attachment link
|
||||
|
||||
Removes the attachment wrapper view, including image tag if it exists
|
||||
Resets the note editing form
|
||||
###
|
||||
removeAttachment: ->
|
||||
note = $(this).closest(".note")
|
||||
note.find(".note-attachment").remove()
|
||||
note.find(".note-text").show()
|
||||
note.find(".js-note-attachment-delete").hide()
|
||||
note.find(".note-edit-form").hide()
|
||||
|
||||
###
|
||||
Called when clicking on the "reply" button for a diff line.
|
||||
|
||||
Shows the note form below the notes.
|
||||
###
|
||||
replyToDiscussionNote: (e) =>
|
||||
form = $(".js-new-note-form")
|
||||
replyLink = $(e.target)
|
||||
replyLink.hide()
|
||||
|
||||
# insert the form after the button
|
||||
form.clone().insertAfter replyLink
|
||||
|
||||
# show the form
|
||||
@setupDiscussionNoteForm(replyLink, replyLink.next("form"))
|
||||
|
||||
###
|
||||
Shows the diff or discussion form and does some setup on it.
|
||||
|
||||
Sets some hidden fields in the form.
|
||||
|
||||
Note: dataHolder must have the "discussionId", "lineCode", "noteableType"
|
||||
and "noteableId" data attributes set.
|
||||
###
|
||||
setupDiscussionNoteForm: (dataHolder, form) =>
|
||||
# setup note target
|
||||
form.attr "rel", dataHolder.data("discussionId")
|
||||
form.find("#note_commit_id").val dataHolder.data("commitId")
|
||||
form.find("#note_line_code").val dataHolder.data("lineCode")
|
||||
form.find("#note_noteable_type").val dataHolder.data("noteableType")
|
||||
form.find("#note_noteable_id").val dataHolder.data("noteableId")
|
||||
@setupNoteForm form
|
||||
form.find(".js-note-text").focus()
|
||||
form.addClass "js-discussion-note-form"
|
||||
|
||||
###
|
||||
General note form setup.
|
||||
|
||||
deactivates the submit button when text is empty
|
||||
hides the preview button when text is empty
|
||||
setup GFM auto complete
|
||||
show the form
|
||||
###
|
||||
setupNoteForm: (form) =>
|
||||
disableButtonIfEmptyField form.find(".js-note-text"), form.find(".js-comment-button")
|
||||
form.removeClass "js-new-note-form"
|
||||
form.removeClass "js-new-note-form"
|
||||
GitLab.GfmAutoComplete.setup()
|
||||
form.show()
|
||||
|
||||
###
|
||||
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: (e) =>
|
||||
e.preventDefault()
|
||||
link = e.target
|
||||
form = $(".js-new-note-form")
|
||||
row = $(link).closest("tr")
|
||||
nextRow = row.next()
|
||||
|
||||
# does it already have notes?
|
||||
if nextRow.is(".notes_holder")
|
||||
$.proxy(@replyToDiscussionNote, nextRow.find(".js-discussion-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
|
||||
@setupDiscussionNoteForm $(link), row.next().find("form")
|
||||
|
||||
###
|
||||
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.
|
||||
###
|
||||
removeDiscussionNoteForm: (form)->
|
||||
row = form.closest("tr")
|
||||
|
||||
# show the reply button (will only work for replies)
|
||||
form.prev(".js-discussion-reply-button").show()
|
||||
if row.is(".js-temp-notes-holder")
|
||||
# remove temporary row for diff lines
|
||||
row.remove()
|
||||
else
|
||||
# only remove the form
|
||||
form.remove()
|
||||
|
||||
@Notes = Notes
|
Loading…
Reference in a new issue