Skip to content

Commit

Permalink
Write new Notes coffee class to handle comments
Browse files Browse the repository at this point in the history
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
  • Loading branch information
dzaporozhets committed Dec 25, 2013
1 parent f7e7dc7 commit 923bd2e
Showing 1 changed file with 397 additions and 0 deletions.
397 changes: 397 additions & 0 deletions app/assets/javascripts/notes.js.coffee
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 923bd2e

Please sign in to comment.