comment_post.js 4.13 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
import { BLACK, COMMENT_BOX, MUTED } from '../shared';
import { clearSavedComment } from './comment_storage';
import { clearNote, postError } from './note';
import { selectCommentBox, selectCommentButton, selectNote, selectNoteContainer } from './utils';

const resetCommentButton = () => {
  const commentButton = selectCommentButton();

  /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
  commentButton.innerText = 'Send feedback';
  commentButton.classList.replace('gitlab-button-secondary', 'gitlab-button-success');
  commentButton.style.opacity = 1;
};

const resetCommentBox = () => {
  const commentBox = selectCommentBox();
  commentBox.style.pointerEvents = 'auto';
  commentBox.style.color = BLACK;
};

const resetCommentText = () => {
  const commentBox = selectCommentBox();
  commentBox.value = '';
  clearSavedComment();
};

const resetComment = () => {
  resetCommentButton();
  resetCommentBox();
  resetCommentText();
};

const confirmAndClear = feedbackInfo => {
  const commentButton = selectCommentButton();
  const currentNote = selectNote();
  const noteContainer = selectNoteContainer();

  /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
  commentButton.innerText = 'Feedback sent';
  noteContainer.style.visibility = 'visible';
  currentNote.insertAdjacentHTML('beforeend', feedbackInfo);

  setTimeout(resetComment, 1000);
  setTimeout(clearNote, 6000);
};

const setInProgressState = () => {
  const commentButton = selectCommentButton();
  const commentBox = selectCommentBox();

  /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
  commentButton.innerText = 'Sending feedback';
  commentButton.classList.replace('gitlab-button-success', 'gitlab-button-secondary');
  commentButton.style.opacity = 0.5;
  commentBox.style.color = MUTED;
  commentBox.style.pointerEvents = 'none';
};

const commentErrors = error => {
  switch (error.status) {
    case 401:
      /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
      return 'Unauthorized. You may have entered an incorrect authentication token.';
    case 404:
      /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
      return 'Not found. You may have entered an incorrect merge request ID.';
    default:
      /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
      return `Your comment could not be sent. Please try again. Error: ${error.message}`;
  }
};

const postComment = ({
  platform,
  browser,
  userAgent,
  innerWidth,
  innerHeight,
  projectId,
  projectPath,
  mergeRequestId,
  mrUrl,
  token,
}) => {
  // Clear any old errors
  clearNote(COMMENT_BOX);

  setInProgressState();

  const commentText = selectCommentBox().value.trim();
  // Get the href at the last moment to support SPAs
  const { href } = window.location;

  if (!commentText) {
    /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
    postError('Your comment appears to be empty.', COMMENT_BOX);
    resetCommentBox();
    resetCommentButton();
    return;
  }

  const detailText = `
 \n
<details>
  <summary>Metadata</summary>
  Posted from ${href} | ${platform} | ${browser} | ${innerWidth} x ${innerHeight}.
  <br /><br />
  <em>User agent: ${userAgent}</em>
</details>
  `;

  const url = `
    ${mrUrl}/api/v4/projects/${projectId}/merge_requests/${mergeRequestId}/discussions`;

  const body = `${commentText} ${detailText}`;

  fetch(url, {
    method: 'POST',
    headers: {
      'PRIVATE-TOKEN': token,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ body }),
  })
    .then(response => {
      if (response.ok) {
        return response.json();
      }

      throw response;
    })
    .then(data => {
      const commentId = data.notes[0].id;
      const feedbackLink = `${mrUrl}/${projectPath}/merge_requests/${mergeRequestId}#note_${commentId}`;
      const feedbackInfo = `Feedback sent. View at <a class="gitlab-link" href="${feedbackLink}">${projectPath} !${mergeRequestId} (comment ${commentId})</a>`;
      confirmAndClear(feedbackInfo);
    })
    .catch(err => {
      postError(commentErrors(err), COMMENT_BOX);
      resetCommentBox();
      resetCommentButton();
    });
};

export default postComment;