in app/assets/javascripts/notes.js [1627:1819]
postComment(e) {
e.preventDefault();
// Get Form metadata
const $submitBtn = $(e.target);
$submitBtn.prop('disabled', true);
let $form = $submitBtn.parents('form');
const $closeBtn = $form.find('.js-note-target-close');
const isDiscussionNote =
$submitBtn
.parent()
.find('li.droplab-item-selected')
.attr('id') === 'discussion';
const isMainForm = $form.hasClass('js-main-target-form');
const isDiscussionForm = $form.hasClass('js-discussion-note-form');
const isDiscussionResolve = $submitBtn.hasClass('js-comment-resolve-button');
const { formData, formContent, formAction, formContentOriginal } = this.getFormData($form);
let noteUniqueId;
let systemNoteUniqueId;
let hasQuickActions = false;
let $notesContainer;
let tempFormContent;
// Get reference to notes container based on type of comment
if (isDiscussionForm) {
$notesContainer = $form.parent('.discussion-notes').find('.notes');
} else if (isMainForm) {
$notesContainer = $('ul.main-notes-list');
}
// If comment is to resolve discussion, disable submit buttons while
// comment posting is finished.
if (isDiscussionResolve) {
$form.find('.js-comment-submit-button').disable();
}
tempFormContent = formContent;
if (this.hasQuickActions(formContent)) {
tempFormContent = this.stripQuickActions(formContent);
hasQuickActions = true;
}
// Show placeholder note
if (tempFormContent) {
noteUniqueId = _.uniqueId('tempNote_');
$notesContainer.append(
this.createPlaceholderNote({
formContent: tempFormContent,
uniqueId: noteUniqueId,
isDiscussionNote,
currentUsername: gon.current_username,
currentUserFullname: gon.current_user_fullname,
currentUserAvatar: gon.current_user_avatar_url,
}),
);
}
// Show placeholder system note
if (hasQuickActions) {
systemNoteUniqueId = _.uniqueId('tempSystemNote_');
$notesContainer.append(
this.createPlaceholderSystemNote({
formContent: this.getQuickActionDescription(
formContent,
AjaxCache.get(gl.GfmAutoComplete.dataSources.commands),
),
uniqueId: systemNoteUniqueId,
}),
);
}
// Clear the form textarea
if ($notesContainer.length) {
if (isMainForm) {
this.resetMainTargetForm(e);
} else if (isDiscussionForm) {
this.removeDiscussionNoteForm($form);
}
}
$closeBtn.text($closeBtn.data('originalText'));
// Make request to submit comment on server
return axios
.post(`${formAction}?html=true`, formData)
.then(res => {
const note = res.data;
$submitBtn.prop('disabled', false);
// Submission successful! remove placeholder
$notesContainer.find(`#${noteUniqueId}`).remove();
const $diffFile = $form.closest('.diff-file');
if ($diffFile.length > 0) {
const blurEvent = new CustomEvent('blur.imageDiff', {
detail: e,
});
$diffFile[0].dispatchEvent(blurEvent);
}
// Reset cached commands list when command is applied
if (hasQuickActions) {
$form.find('textarea.js-note-text').trigger('clear-commands-cache.atwho');
}
// Clear previous form errors
this.clearFlashWrapper();
// Check if this was discussion comment
if (isDiscussionForm) {
// Remove flash-container
$notesContainer.find('.flash-container').remove();
// If comment intends to resolve discussion, do the same.
if (isDiscussionResolve) {
$form
.attr('data-discussion-id', $submitBtn.data('discussionId'))
.attr('data-resolve-all', 'true')
.attr('data-project-path', $submitBtn.data('projectPath'));
}
// Show final note element on UI
const isNewDiffComment = $notesContainer.length === 0;
this.addDiscussionNote($form, note, isNewDiffComment);
if (isNewDiffComment) {
// Add image badge, avatar badge and toggle discussion badge for new image diffs
const notePosition = $form.find('#note_position').val();
if ($diffFile.length > 0 && notePosition.length > 0) {
const { x, y, width, height } = JSON.parse(notePosition);
const addBadgeEvent = new CustomEvent('addBadge.imageDiff', {
detail: {
x,
y,
width,
height,
noteId: `note_${note.id}`,
discussionId: note.discussion_id,
},
});
$diffFile[0].dispatchEvent(addBadgeEvent);
}
}
// append flash-container to the Notes list
if ($notesContainer.length) {
$notesContainer.append('<div class="flash-container" style="display: none;"></div>');
}
} else if (isMainForm) {
// Check if this was main thread comment
// Show final note element on UI and perform form and action buttons cleanup
this.addNote($form, note);
this.reenableTargetFormSubmitButton(e);
}
if (note.commands_changes) {
this.handleQuickActions(note);
}
$form.trigger('ajax:success', [note]);
})
.catch(() => {
// Submission failed, remove placeholder note and show Flash error message
$notesContainer.find(`#${noteUniqueId}`).remove();
$submitBtn.prop('disabled', false);
const blurEvent = new CustomEvent('blur.imageDiff', {
detail: e,
});
const closestDiffFile = $form.closest('.diff-file');
if (closestDiffFile.length) {
closestDiffFile[0].dispatchEvent(blurEvent);
}
if (hasQuickActions) {
$notesContainer.find(`#${systemNoteUniqueId}`).remove();
}
// Show form again on UI on failure
if (isDiscussionForm && $notesContainer.length) {
const replyButton = $notesContainer.parent().find('.js-discussion-reply-button');
this.replyToDiscussionNote(replyButton[0]);
$form = $notesContainer.parent().find('form');
}
$form.find('.js-note-text').val(formContentOriginal);
this.reenableTargetFormSubmitButton(e);
this.addNoteError($form);
});
}