summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshampton <shampton@gitlab.com>2019-08-23 10:37:25 -0700
committershampton <shampton@gitlab.com>2019-08-23 10:37:25 -0700
commit63a8fa2ffe59656ce123a3f74e163b0a78ae8775 (patch)
tree2957eac3535db74c6c183e7358b1741d0e9f9231
parent8f797950e8e5f92da800d67444a1f67bb6078f21 (diff)
downloadgitlab-ce-66402-use-visual-review-tools-npm-package.tar.gz
Move visual review toolbar to NPM66402-use-visual-review-tools-npm-package
Remove the visual review toolbar code in favor of using the NPM package.
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/comment.js39
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/comment_mr_note.js31
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/comment_post.js145
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/comment_storage.js20
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/form_elements.js17
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/index.js23
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/login.js47
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/mr_id.js63
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/note.js35
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/utils.js51
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/wrapper.js79
-rw-r--r--app/assets/javascripts/visual_review_toolbar/components/wrapper_icons.js15
-rw-r--r--app/assets/javascripts/visual_review_toolbar/index.js51
-rw-r--r--app/assets/javascripts/visual_review_toolbar/shared/constants.js56
-rw-r--r--app/assets/javascripts/visual_review_toolbar/shared/index.js55
-rw-r--r--app/assets/javascripts/visual_review_toolbar/shared/storage_utils.js42
-rw-r--r--app/assets/javascripts/visual_review_toolbar/store/events.js73
-rw-r--r--app/assets/javascripts/visual_review_toolbar/store/index.js11
-rw-r--r--app/assets/javascripts/visual_review_toolbar/store/state.js95
-rw-r--r--app/assets/javascripts/visual_review_toolbar/store/utils.js15
-rw-r--r--app/assets/javascripts/visual_review_toolbar/styles/toolbar.css188
-rw-r--r--changelogs/unreleased/66402-use-visual-review-tools-npm-package.yml5
-rw-r--r--config/webpack.config.js7
-rw-r--r--config/webpack.config.review_toolbar.js58
-rw-r--r--lib/tasks/gitlab/assets.rake6
-rw-r--r--package.json418
-rw-r--r--yarn.lock5
27 files changed, 226 insertions, 1424 deletions
diff --git a/app/assets/javascripts/visual_review_toolbar/components/comment.js b/app/assets/javascripts/visual_review_toolbar/components/comment.js
deleted file mode 100644
index a03dc14b319..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/comment.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { nextView } from '../store';
-import { localStorage, COMMENT_BOX, LOGOUT, STORAGE_MR_ID, STORAGE_TOKEN } from '../shared';
-import { clearNote } from './note';
-import { buttonClearStyles } from './utils';
-import { addForm } from './wrapper';
-import { changeSelectedMr, selectedMrNote } from './comment_mr_note';
-import postComment from './comment_post';
-import { saveComment, getSavedComment } from './comment_storage';
-
-const comment = state => {
- const savedComment = getSavedComment();
-
- return `
- <div>
- <textarea id="${COMMENT_BOX}" name="${COMMENT_BOX}" rows="3" placeholder="Enter your feedback or idea" class="gitlab-input" aria-required="true">${savedComment}</textarea>
- ${selectedMrNote(state)}
- <p class="gitlab-metadata-note">Additional metadata will be included: browser, OS, current page, user agent, and viewport dimensions.</p>
- </div>
- <div class="gitlab-button-wrapper">
- <button class="gitlab-button gitlab-button-success" style="${buttonClearStyles}" type="button" id="gitlab-comment-button"> Send feedback </button>
- <button class="gitlab-button gitlab-button-secondary" style="${buttonClearStyles}" type="button" id="${LOGOUT}"> Log out </button>
- </div>
- `;
-};
-
-// This function is here becaause it is called only from the comment view
-// If we reach a design where we can logout from multiple views, promote this
-// to it's own package
-const logoutUser = state => {
- localStorage.removeItem(STORAGE_TOKEN);
- localStorage.removeItem(STORAGE_MR_ID);
- state.token = '';
- state.mergeRequestId = '';
-
- clearNote();
- addForm(nextView(state, COMMENT_BOX));
-};
-
-export { changeSelectedMr, comment, logoutUser, postComment, saveComment };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/comment_mr_note.js b/app/assets/javascripts/visual_review_toolbar/components/comment_mr_note.js
deleted file mode 100644
index da67763261c..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/comment_mr_note.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { nextView } from '../store';
-import { localStorage, CHANGE_MR_ID_BUTTON, COMMENT_BOX, STORAGE_MR_ID } from '../shared';
-import { clearNote } from './note';
-import { buttonClearStyles } from './utils';
-import { addForm } from './wrapper';
-
-const selectedMrNote = state => {
- const { mrUrl, projectPath, mergeRequestId } = state;
-
- const mrLink = `${mrUrl}/${projectPath}/merge_requests/${mergeRequestId}`;
-
- return `
- <p class="gitlab-metadata-note">
- This posts to merge request <a class="gitlab-link" href="${mrLink}">!${mergeRequestId}</a>.
- <button style="${buttonClearStyles}" type="button" id="${CHANGE_MR_ID_BUTTON}" class="gitlab-link gitlab-link-button">Change</button>
- </p>
- `;
-};
-
-const clearMrId = state => {
- localStorage.removeItem(STORAGE_MR_ID);
- state.mergeRequestId = '';
-};
-
-const changeSelectedMr = state => {
- clearMrId(state);
- clearNote();
- addForm(nextView(state, COMMENT_BOX));
-};
-
-export { changeSelectedMr, selectedMrNote };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/comment_post.js b/app/assets/javascripts/visual_review_toolbar/components/comment_post.js
deleted file mode 100644
index ee5f2b62425..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/comment_post.js
+++ /dev/null
@@ -1,145 +0,0 @@
-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;
diff --git a/app/assets/javascripts/visual_review_toolbar/components/comment_storage.js b/app/assets/javascripts/visual_review_toolbar/components/comment_storage.js
deleted file mode 100644
index 49c9400437e..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/comment_storage.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { selectCommentBox } from './utils';
-import { sessionStorage, STORAGE_COMMENT } from '../shared';
-
-const getSavedComment = () => sessionStorage.getItem(STORAGE_COMMENT) || '';
-
-const saveComment = () => {
- const currentComment = selectCommentBox();
-
- // This may be added to any view via top-level beforeunload listener
- // so let's skip if it does not apply
- if (currentComment && currentComment.value) {
- sessionStorage.setItem(STORAGE_COMMENT, currentComment.value);
- }
-};
-
-const clearSavedComment = () => {
- sessionStorage.removeItem(STORAGE_COMMENT);
-};
-
-export { getSavedComment, saveComment, clearSavedComment };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/form_elements.js b/app/assets/javascripts/visual_review_toolbar/components/form_elements.js
deleted file mode 100644
index 608488a6fea..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/form_elements.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { REMEMBER_ITEM } from '../shared';
-import { buttonClearStyles } from './utils';
-
-/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
-const rememberBox = (rememberText = 'Remember me') => `
- <div class="gitlab-checkbox-wrapper">
- <input type="checkbox" id="${REMEMBER_ITEM}" name="${REMEMBER_ITEM}" value="remember">
- <label for="${REMEMBER_ITEM}" class="gitlab-checkbox-label">${rememberText}</label>
- </div>
-`;
-
-const submitButton = buttonId => `
- <div class="gitlab-button-wrapper">
- <button class="gitlab-button-wide gitlab-button gitlab-button-success" style="${buttonClearStyles}" type="button" id="${buttonId}"> Submit </button>
- </div>
-`;
-export { rememberBox, submitButton };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/index.js b/app/assets/javascripts/visual_review_toolbar/components/index.js
deleted file mode 100644
index e88b3637ad8..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import { changeSelectedMr, comment, logoutUser, postComment, saveComment } from './comment';
-import { authorizeUser, login } from './login';
-import { addMr, mrForm } from './mr_id';
-import { note } from './note';
-import { selectContainer, selectForm } from './utils';
-import { buttonAndForm, toggleForm } from './wrapper';
-
-export {
- addMr,
- authorizeUser,
- buttonAndForm,
- changeSelectedMr,
- comment,
- login,
- logoutUser,
- mrForm,
- note,
- postComment,
- saveComment,
- selectContainer,
- selectForm,
- toggleForm,
-};
diff --git a/app/assets/javascripts/visual_review_toolbar/components/login.js b/app/assets/javascripts/visual_review_toolbar/components/login.js
deleted file mode 100644
index 20ab01bc690..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/login.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import { nextView } from '../store';
-import { localStorage, LOGIN, TOKEN_BOX, STORAGE_TOKEN } from '../shared';
-import { clearNote, postError } from './note';
-import { rememberBox, submitButton } from './form_elements';
-import { selectRemember, selectToken } from './utils';
-import { addForm } from './wrapper';
-
-const labelText = `
- Enter your <a class="gitlab-link" href="https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html">personal access token</a>
-`;
-
-const login = `
- <div>
- <label for="${TOKEN_BOX}" class="gitlab-label">${labelText}</label>
- <input class="gitlab-input" type="password" id="${TOKEN_BOX}" name="${TOKEN_BOX}" autocomplete="current-password" aria-required="true">
- </div>
- ${rememberBox()}
- ${submitButton(LOGIN)}
-`;
-
-const storeToken = (token, state) => {
- const rememberMe = selectRemember().checked;
-
- if (rememberMe) {
- localStorage.setItem(STORAGE_TOKEN, token);
- }
-
- state.token = token;
-};
-
-const authorizeUser = state => {
- // Clear any old errors
- clearNote(TOKEN_BOX);
-
- const token = selectToken().value;
-
- if (!token) {
- /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
- postError('Please enter your token.', TOKEN_BOX);
- return;
- }
-
- storeToken(token, state);
- addForm(nextView(state, LOGIN));
-};
-
-export { authorizeUser, login, storeToken };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/mr_id.js b/app/assets/javascripts/visual_review_toolbar/components/mr_id.js
deleted file mode 100644
index 695b3af8aa0..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/mr_id.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import { nextView } from '../store';
-import { MR_ID, MR_ID_BUTTON, STORAGE_MR_ID, localStorage } from '../shared';
-import { clearNote, postError } from './note';
-import { rememberBox, submitButton } from './form_elements';
-import { selectForm, selectMrBox, selectRemember } from './utils';
-import { addForm } from './wrapper';
-
-/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
-const mrLabel = `Enter your merge request ID`;
-/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
-const mrRememberText = `Remember this number`;
-
-const mrForm = `
- <div>
- <label for="${MR_ID}" class="gitlab-label">${mrLabel}</label>
- <input class="gitlab-input" type="text" pattern="[1-9][0-9]*" id="${MR_ID}" name="${MR_ID}" placeholder="e.g., 321" aria-required="true">
- </div>
- ${rememberBox(mrRememberText)}
- ${submitButton(MR_ID_BUTTON)}
-`;
-
-const storeMR = (id, state) => {
- const rememberMe = selectRemember().checked;
-
- if (rememberMe) {
- localStorage.setItem(STORAGE_MR_ID, id);
- }
-
- state.mergeRequestId = id;
-};
-
-const getFormError = (mrNumber, form) => {
- if (!mrNumber) {
- /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
- return 'Please enter your merge request ID number.';
- }
-
- if (!form.checkValidity()) {
- /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
- return 'Please remove any non-number values from the field.';
- }
-
- return null;
-};
-
-const addMr = state => {
- // Clear any old errors
- clearNote(MR_ID);
-
- const mrNumber = selectMrBox().value;
- const form = selectForm();
- const formError = getFormError(mrNumber, form);
-
- if (formError) {
- postError(formError, MR_ID);
- return;
- }
-
- storeMR(mrNumber, state);
- addForm(nextView(state, MR_ID));
-};
-
-export { addMr, mrForm, storeMR };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/note.js b/app/assets/javascripts/visual_review_toolbar/components/note.js
deleted file mode 100644
index 9cddcb710f2..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/note.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { NOTE, NOTE_CONTAINER, RED } from '../shared';
-import { selectById, selectNote, selectNoteContainer } from './utils';
-
-const note = `
- <div id="${NOTE_CONTAINER}" style="visibility: hidden;">
- <p id="${NOTE}" class="gitlab-message"></p>
- </div>
-`;
-
-const clearNote = inputId => {
- const currentNote = selectNote();
- const noteContainer = selectNoteContainer();
-
- currentNote.innerText = '';
- currentNote.style.color = '';
- noteContainer.style.visibility = 'hidden';
-
- if (inputId) {
- const field = document.getElementById(inputId);
- field.style.borderColor = '';
- }
-};
-
-const postError = (message, inputId) => {
- const currentNote = selectNote();
- const noteContainer = selectNoteContainer();
- const field = selectById(inputId);
- field.style.borderColor = RED;
- currentNote.style.color = RED;
- currentNote.innerText = message;
- noteContainer.style.visibility = 'visible';
- setTimeout(clearNote.bind(null, inputId), 5000);
-};
-
-export { clearNote, note, postError };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/utils.js b/app/assets/javascripts/visual_review_toolbar/components/utils.js
deleted file mode 100644
index 4ec9bd4a32a..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/utils.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/* global document */
-
-import {
- COLLAPSE_BUTTON,
- COMMENT_BOX,
- COMMENT_BUTTON,
- FORM,
- FORM_CONTAINER,
- MR_ID,
- NOTE,
- NOTE_CONTAINER,
- REMEMBER_ITEM,
- REVIEW_CONTAINER,
- TOKEN_BOX,
-} from '../shared';
-
-// this style must be applied inline in a handful of components
-/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
-const buttonClearStyles = `
- -webkit-appearance: none;
-`;
-
-// selector functions to abstract out a little
-const selectById = id => document.getElementById(id);
-const selectCollapseButton = () => document.getElementById(COLLAPSE_BUTTON);
-const selectCommentBox = () => document.getElementById(COMMENT_BOX);
-const selectCommentButton = () => document.getElementById(COMMENT_BUTTON);
-const selectContainer = () => document.getElementById(REVIEW_CONTAINER);
-const selectForm = () => document.getElementById(FORM);
-const selectFormContainer = () => document.getElementById(FORM_CONTAINER);
-const selectMrBox = () => document.getElementById(MR_ID);
-const selectNote = () => document.getElementById(NOTE);
-const selectNoteContainer = () => document.getElementById(NOTE_CONTAINER);
-const selectRemember = () => document.getElementById(REMEMBER_ITEM);
-const selectToken = () => document.getElementById(TOKEN_BOX);
-
-export {
- buttonClearStyles,
- selectById,
- selectCollapseButton,
- selectContainer,
- selectCommentBox,
- selectCommentButton,
- selectForm,
- selectFormContainer,
- selectMrBox,
- selectNote,
- selectNoteContainer,
- selectRemember,
- selectToken,
-};
diff --git a/app/assets/javascripts/visual_review_toolbar/components/wrapper.js b/app/assets/javascripts/visual_review_toolbar/components/wrapper.js
deleted file mode 100644
index fdf8ad7c41f..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/wrapper.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import { CLEAR, FORM, FORM_CONTAINER, WHITE } from '../shared';
-import {
- selectCollapseButton,
- selectForm,
- selectFormContainer,
- selectNoteContainer,
-} from './utils';
-import { collapseButton, commentIcon, compressIcon } from './wrapper_icons';
-
-const form = content => `
- <form id="${FORM}" novalidate>
- ${content}
- </form>
-`;
-
-const buttonAndForm = content => `
- <div id="${FORM_CONTAINER}" class="gitlab-form-open">
- ${collapseButton}
- ${form(content)}
- </div>
-`;
-
-const addForm = nextForm => {
- const formWrapper = selectForm();
- formWrapper.innerHTML = nextForm;
-};
-
-function toggleForm() {
- const toggleButton = selectCollapseButton();
- const currentForm = selectForm();
- const formContainer = selectFormContainer();
- const noteContainer = selectNoteContainer();
- const OPEN = 'open';
- const CLOSED = 'closed';
-
- /*
- You may wonder why we spread the arrays before we reverse them.
- In the immortal words of MDN,
- Careful: reverse is destructive. It also changes the original array
- */
-
- const openButtonClasses = ['gitlab-collapse-closed', 'gitlab-collapse-open'];
- const closedButtonClasses = [...openButtonClasses].reverse();
- const openContainerClasses = ['gitlab-wrapper-closed', 'gitlab-wrapper-open'];
- const closedContainerClasses = [...openContainerClasses].reverse();
-
- const stateVals = {
- [OPEN]: {
- buttonClasses: openButtonClasses,
- containerClasses: openContainerClasses,
- icon: compressIcon,
- display: 'flex',
- backgroundColor: WHITE,
- },
- [CLOSED]: {
- buttonClasses: closedButtonClasses,
- containerClasses: closedContainerClasses,
- icon: commentIcon,
- display: 'none',
- backgroundColor: CLEAR,
- },
- };
-
- const nextState = toggleButton.classList.contains('gitlab-collapse-open') ? CLOSED : OPEN;
- const currentVals = stateVals[nextState];
-
- formContainer.classList.replace(...currentVals.containerClasses);
- formContainer.style.backgroundColor = currentVals.backgroundColor;
- formContainer.classList.toggle('gitlab-form-open');
- currentForm.style.display = currentVals.display;
- toggleButton.classList.replace(...currentVals.buttonClasses);
- toggleButton.innerHTML = currentVals.icon;
-
- if (noteContainer && noteContainer.innerText.length > 0) {
- noteContainer.style.display = currentVals.display;
- }
-}
-
-export { addForm, buttonAndForm, toggleForm };
diff --git a/app/assets/javascripts/visual_review_toolbar/components/wrapper_icons.js b/app/assets/javascripts/visual_review_toolbar/components/wrapper_icons.js
deleted file mode 100644
index b686fd4f5c2..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/components/wrapper_icons.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { buttonClearStyles } from './utils';
-
-const commentIcon = `
- <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/comment</title><path d="M4 11.132l1.446-.964A1 1 0 0 1 6 10h5a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v6.132zM6.303 12l-2.748 1.832A1 1 0 0 1 2 13V5a3 3 0 0 1 3-3h6a3 3 0 0 1 3 3v4a3 3 0 0 1-3 3H6.303z" id="gitlab-comment-icon"/></svg>
-`;
-
-const compressIcon = `
- <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>icn/compress</title><path d="M5.27 12.182l-1.562 1.561a1 1 0 0 1-1.414 0h-.001a1 1 0 0 1 0-1.415l1.56-1.56L2.44 9.353a.5.5 0 0 1 .353-.854H7.09a.5.5 0 0 1 .5.5v4.294a.5.5 0 0 1-.853.353l-1.467-1.465zm6.911-6.914l1.464 1.464a.5.5 0 0 1-.353.854H8.999a.5.5 0 0 1-.5-.5V2.793a.5.5 0 0 1 .854-.354l1.414 1.415 1.56-1.561a1 1 0 1 1 1.415 1.414l-1.561 1.56z" id="gitlab-compress-icon"/></svg>
-`;
-
-const collapseButton = `
- <button id='gitlab-collapse' style='${buttonClearStyles}' class='gitlab-button gitlab-button-secondary gitlab-collapse gitlab-collapse-open'>${compressIcon}</button>
-`;
-
-export { commentIcon, compressIcon, collapseButton };
diff --git a/app/assets/javascripts/visual_review_toolbar/index.js b/app/assets/javascripts/visual_review_toolbar/index.js
deleted file mode 100644
index 67b3fadd772..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/index.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import './styles/toolbar.css';
-
-import { buttonAndForm, note, selectForm, selectContainer } from './components';
-import { REVIEW_CONTAINER } from './shared';
-import { eventLookup, getInitialView, initializeGlobalListeners, initializeState } from './store';
-
-/*
-
- Welcome to the visual review toolbar files. A few useful notes:
-
- - These files build a static script that is served from our webpack
- assets folder. (https://gitlab.com/assets/webpack/visual_review_toolbar.js)
-
- - To compile this file, run `yarn webpack-vrt`.
-
- - Vue is not used in these files because we do not want to ask users to
- install another library at this time. It's all pure vanilla javascript.
-
-*/
-
-window.addEventListener('load', () => {
- initializeState(window, document);
-
- const mainContent = buttonAndForm(getInitialView());
- const container = document.createElement('div');
- container.setAttribute('id', REVIEW_CONTAINER);
- container.insertAdjacentHTML('beforeend', note);
- container.insertAdjacentHTML('beforeend', mainContent);
-
- document.body.insertBefore(container, document.body.firstChild);
-
- selectContainer().addEventListener('click', event => {
- eventLookup(event.target.id)();
- });
-
- selectForm().addEventListener('submit', event => {
- // this is important to prevent the form from adding data
- // as URL params and inadvertently revealing secrets
- event.preventDefault();
-
- const id =
- event.target.querySelector('.gitlab-button-wrapper') &&
- event.target.querySelector('.gitlab-button-wrapper').getElementsByTagName('button')[0] &&
- event.target.querySelector('.gitlab-button-wrapper').getElementsByTagName('button')[0].id;
-
- // even if this is called with false, it's ok; it will get the default no-op
- eventLookup(id)();
- });
-
- initializeGlobalListeners();
-});
diff --git a/app/assets/javascripts/visual_review_toolbar/shared/constants.js b/app/assets/javascripts/visual_review_toolbar/shared/constants.js
deleted file mode 100644
index 0d5b666ab0a..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/shared/constants.js
+++ /dev/null
@@ -1,56 +0,0 @@
-// component selectors
-const CHANGE_MR_ID_BUTTON = 'gitlab-change-mr';
-const COLLAPSE_BUTTON = 'gitlab-collapse';
-const COMMENT_BOX = 'gitlab-comment';
-const COMMENT_BUTTON = 'gitlab-comment-button';
-const FORM = 'gitlab-form';
-const FORM_CONTAINER = 'gitlab-form-wrapper';
-const LOGIN = 'gitlab-login-button';
-const LOGOUT = 'gitlab-logout-button';
-const MR_ID = 'gitlab-submit-mr';
-const MR_ID_BUTTON = 'gitlab-submit-mr-button';
-const NOTE = 'gitlab-validation-note';
-const NOTE_CONTAINER = 'gitlab-note-wrapper';
-const REMEMBER_ITEM = 'gitlab-remember-item';
-const REVIEW_CONTAINER = 'gitlab-review-container';
-const TOKEN_BOX = 'gitlab-token';
-
-// Storage keys
-const STORAGE_PREFIX = '--gitlab'; // Using `--` to make the prefix more unique
-const STORAGE_MR_ID = `${STORAGE_PREFIX}-merge-request-id`;
-const STORAGE_TOKEN = `${STORAGE_PREFIX}-token`;
-const STORAGE_COMMENT = `${STORAGE_PREFIX}-comment`;
-
-// colors — these are applied programmatically
-// rest of styles belong in ./styles
-const BLACK = 'rgba(46, 46, 46, 1)';
-const CLEAR = 'rgba(255, 255, 255, 0)';
-const MUTED = 'rgba(223, 223, 223, 0.5)';
-const RED = 'rgba(219, 59, 33, 1)';
-const WHITE = 'rgba(250, 250, 250, 1)';
-
-export {
- CHANGE_MR_ID_BUTTON,
- COLLAPSE_BUTTON,
- COMMENT_BOX,
- COMMENT_BUTTON,
- FORM,
- FORM_CONTAINER,
- LOGIN,
- LOGOUT,
- MR_ID,
- MR_ID_BUTTON,
- NOTE,
- NOTE_CONTAINER,
- REMEMBER_ITEM,
- REVIEW_CONTAINER,
- TOKEN_BOX,
- STORAGE_MR_ID,
- STORAGE_TOKEN,
- STORAGE_COMMENT,
- BLACK,
- CLEAR,
- MUTED,
- RED,
- WHITE,
-};
diff --git a/app/assets/javascripts/visual_review_toolbar/shared/index.js b/app/assets/javascripts/visual_review_toolbar/shared/index.js
deleted file mode 100644
index d8ccb170592..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/shared/index.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import {
- CHANGE_MR_ID_BUTTON,
- COLLAPSE_BUTTON,
- COMMENT_BOX,
- COMMENT_BUTTON,
- FORM,
- FORM_CONTAINER,
- LOGIN,
- LOGOUT,
- MR_ID,
- MR_ID_BUTTON,
- NOTE,
- NOTE_CONTAINER,
- REMEMBER_ITEM,
- REVIEW_CONTAINER,
- TOKEN_BOX,
- STORAGE_MR_ID,
- STORAGE_TOKEN,
- STORAGE_COMMENT,
- BLACK,
- CLEAR,
- MUTED,
- RED,
- WHITE,
-} from './constants';
-
-import { localStorage, sessionStorage } from './storage_utils';
-
-export {
- localStorage,
- sessionStorage,
- CHANGE_MR_ID_BUTTON,
- COLLAPSE_BUTTON,
- COMMENT_BOX,
- COMMENT_BUTTON,
- FORM,
- FORM_CONTAINER,
- LOGIN,
- LOGOUT,
- MR_ID,
- MR_ID_BUTTON,
- NOTE,
- NOTE_CONTAINER,
- REMEMBER_ITEM,
- REVIEW_CONTAINER,
- TOKEN_BOX,
- STORAGE_MR_ID,
- STORAGE_TOKEN,
- STORAGE_COMMENT,
- BLACK,
- CLEAR,
- MUTED,
- RED,
- WHITE,
-};
diff --git a/app/assets/javascripts/visual_review_toolbar/shared/storage_utils.js b/app/assets/javascripts/visual_review_toolbar/shared/storage_utils.js
deleted file mode 100644
index 00456d3536e..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/shared/storage_utils.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { setUsingGracefulStorageFlag } from '../store/state';
-
-const TEST_KEY = 'gitlab-storage-test';
-
-const createStorageStub = () => {
- const items = {};
-
- return {
- getItem(key) {
- return items[key];
- },
- setItem(key, value) {
- items[key] = value;
- },
- removeItem(key) {
- delete items[key];
- },
- };
-};
-
-const hasStorageSupport = storage => {
- // Support test taken from https://stackoverflow.com/a/11214467/1708147
- try {
- storage.setItem(TEST_KEY, TEST_KEY);
- storage.removeItem(TEST_KEY);
- setUsingGracefulStorageFlag(true);
-
- return true;
- } catch (err) {
- setUsingGracefulStorageFlag(false);
- return false;
- }
-};
-
-const useGracefulStorage = storage =>
- // If a browser does not support local storage, let's return a graceful implementation.
- hasStorageSupport(storage) ? storage : createStorageStub();
-
-const localStorage = useGracefulStorage(window.localStorage);
-const sessionStorage = useGracefulStorage(window.sessionStorage);
-
-export { localStorage, sessionStorage };
diff --git a/app/assets/javascripts/visual_review_toolbar/store/events.js b/app/assets/javascripts/visual_review_toolbar/store/events.js
deleted file mode 100644
index c9095c77ef1..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/store/events.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import {
- addMr,
- authorizeUser,
- changeSelectedMr,
- logoutUser,
- postComment,
- saveComment,
- toggleForm,
-} from '../components';
-
-import {
- CHANGE_MR_ID_BUTTON,
- COLLAPSE_BUTTON,
- COMMENT_BUTTON,
- LOGIN,
- LOGOUT,
- MR_ID_BUTTON,
-} from '../shared';
-
-import { state } from './state';
-import debounce from './utils';
-
-const noop = () => {};
-
-// State needs to be bound here to be acted on
-// because these are called by click events and
-// as such are called with only the `event` object
-const eventLookup = id => {
- switch (id) {
- case CHANGE_MR_ID_BUTTON:
- return () => {
- saveComment();
- changeSelectedMr(state);
- };
- case COLLAPSE_BUTTON:
- return toggleForm;
- case COMMENT_BUTTON:
- return postComment.bind(null, state);
- case LOGIN:
- return authorizeUser.bind(null, state);
- case LOGOUT:
- return () => {
- saveComment();
- logoutUser(state);
- };
- case MR_ID_BUTTON:
- return addMr.bind(null, state);
- default:
- return noop;
- }
-};
-
-const updateWindowSize = wind => {
- state.innerWidth = wind.innerWidth;
- state.innerHeight = wind.innerHeight;
-};
-
-const initializeGlobalListeners = () => {
- window.addEventListener('resize', debounce(updateWindowSize.bind(null, window), 200));
- window.addEventListener('beforeunload', event => {
- if (state.usingGracefulStorage) {
- // if there is no browser storage support, reloading will lose the comment; this way, the user will be warned
- // we assign the return value because it is required by Chrome see: https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload#Example,
- event.preventDefault();
- /* eslint-disable-next-line no-param-reassign */
- event.returnValue = '';
- }
-
- saveComment();
- });
-};
-
-export { eventLookup, initializeGlobalListeners };
diff --git a/app/assets/javascripts/visual_review_toolbar/store/index.js b/app/assets/javascripts/visual_review_toolbar/store/index.js
deleted file mode 100644
index 07c8dd6f1d2..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/store/index.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { eventLookup, initializeGlobalListeners } from './events';
-import { nextView, getInitialView, initializeState, setUsingGracefulStorageFlag } from './state';
-
-export {
- eventLookup,
- getInitialView,
- initializeGlobalListeners,
- initializeState,
- nextView,
- setUsingGracefulStorageFlag,
-};
diff --git a/app/assets/javascripts/visual_review_toolbar/store/state.js b/app/assets/javascripts/visual_review_toolbar/store/state.js
deleted file mode 100644
index b7853bb0723..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/store/state.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import { comment, login, mrForm } from '../components';
-import { localStorage, COMMENT_BOX, LOGIN, MR_ID, STORAGE_MR_ID, STORAGE_TOKEN } from '../shared';
-
-const state = {
- browser: '',
- usingGracefulStorage: '',
- innerWidth: '',
- innerHeight: '',
- mergeRequestId: '',
- mrUrl: '',
- platform: '',
- projectId: '',
- userAgent: '',
- token: '',
-};
-
-// adapted from https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator#Example_2_Browser_detect_and_return_an_index
-const getBrowserId = sUsrAg => {
- /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
- const aKeys = ['MSIE', 'Edge', 'Firefox', 'Safari', 'Chrome', 'Opera'];
- let nIdx = aKeys.length - 1;
-
- for (nIdx; nIdx > -1 && sUsrAg.indexOf(aKeys[nIdx]) === -1; nIdx -= 1);
- return aKeys[nIdx];
-};
-
-const nextView = (appState, form = 'none') => {
- const formsList = {
- [COMMENT_BOX]: currentState => (currentState.token ? mrForm : login),
- [LOGIN]: currentState => (currentState.mergeRequestId ? comment(currentState) : mrForm),
- [MR_ID]: currentState => (currentState.token ? comment(currentState) : login),
- none: currentState => {
- if (!currentState.token) {
- return login;
- }
-
- if (currentState.token && !currentState.mergeRequestId) {
- return mrForm;
- }
-
- return comment(currentState);
- },
- };
-
- return formsList[form](appState);
-};
-
-const initializeState = (wind, doc) => {
- const {
- innerWidth,
- innerHeight,
- navigator: { platform, userAgent },
- } = wind;
-
- const browser = getBrowserId(userAgent);
-
- const scriptEl = doc.getElementById('review-app-toolbar-script');
- const { projectId, mergeRequestId, mrUrl, projectPath } = scriptEl.dataset;
-
- // This mutates our default state object above. It's weird but it makes the linter happy.
- Object.assign(state, {
- browser,
- innerWidth,
- innerHeight,
- mergeRequestId,
- mrUrl,
- platform,
- projectId,
- projectPath,
- userAgent,
- });
-
- return state;
-};
-
-const getInitialView = () => {
- const token = localStorage.getItem(STORAGE_TOKEN);
- const mrId = localStorage.getItem(STORAGE_MR_ID);
-
- if (token) {
- state.token = token;
- }
-
- if (mrId) {
- state.mergeRequestId = mrId;
- }
-
- return nextView(state);
-};
-
-const setUsingGracefulStorageFlag = flag => {
- state.usingGracefulStorage = !flag;
-};
-
-export { initializeState, getInitialView, nextView, setUsingGracefulStorageFlag, state };
diff --git a/app/assets/javascripts/visual_review_toolbar/store/utils.js b/app/assets/javascripts/visual_review_toolbar/store/utils.js
deleted file mode 100644
index 5cf145351b3..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/store/utils.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const debounce = (fn, time) => {
- let current;
-
- const debounced = () => {
- if (current) {
- clearTimeout(current);
- }
-
- current = setTimeout(fn, time);
- };
-
- return debounced;
-};
-
-export default debounce;
diff --git a/app/assets/javascripts/visual_review_toolbar/styles/toolbar.css b/app/assets/javascripts/visual_review_toolbar/styles/toolbar.css
deleted file mode 100644
index d1a8d66ef40..00000000000
--- a/app/assets/javascripts/visual_review_toolbar/styles/toolbar.css
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- As a standalone script, the toolbar has its own css
- */
-
-#gitlab-collapse > * {
- pointer-events: none;
-}
-
-#gitlab-comment {
- background-color: #fafafa;
-}
-
-#gitlab-form {
- display: flex;
- flex-direction: column;
- width: 100%;
- margin-bottom: 0;
-}
-
-#gitlab-note-wrapper {
- display: flex;
- flex-direction: column;
- background-color: #fafafa;
- border-radius: 4px;
- margin-bottom: .5rem;
- padding: 1rem;
-}
-
-#gitlab-form-wrapper {
- overflow: auto;
- display: flex;
- flex-direction: row-reverse;
- border-radius: 4px;
-}
-
-#gitlab-review-container {
- max-width: 22rem;
- max-height: 22rem;
- overflow: auto;
- display: flex;
- flex-direction: column;
- position: fixed;
- bottom: 1rem;
- right: 1rem;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Noto Sans', Ubuntu, Cantarell,
- 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
- 'Noto Color Emoji';
- font-size: .8rem;
- font-weight: 400;
- color: #2e2e2e;
- z-index: 9999; /* toolbar should always be on top */
-}
-
-.gitlab-wrapper-open {
- max-width: 22rem;
- max-height: 22rem;
-}
-
-.gitlab-wrapper-closed {
- max-width: 3.4rem;
- max-height: 3.4rem;
-}
-
-.gitlab-button {
- cursor: pointer;
- transition: background-color 100ms linear, border-color 100ms linear, color 100ms linear, box-shadow 100ms linear;
-}
-
-.gitlab-button-secondary {
- background: none #fafafa;
- margin: 0 .5rem;
- border: 1px solid #e3e3e3;
-}
-
-.gitlab-button-secondary:hover {
- background-color: #f0f0f0;
- border-color: #e3e3e3;
- color: #2e2e2e;
-}
-
-.gitlab-button-secondary:active {
- color: #2e2e2e;
- background-color: #e1e1e1;
- border-color: #dadada;
-}
-
-.gitlab-button-success:hover {
- color: #fff;
- background-color: #137e3f;
- border-color: #127339;
-}
-
-.gitlab-button-success:active {
- background-color: #168f48;
- border-color: #12753a;
- color: #fff;
-}
-
-.gitlab-button-success {
- background-color: #1aaa55;
- border: 1px solid #168f48;
- color: #fff;
-}
-
-.gitlab-button-wide {
- width: 100%;
-}
-
-.gitlab-button-wrapper {
- margin-top: 0.5rem;
- display: flex;
- align-items: baseline;
- /*
- this makes sure the hit enter to submit picks the correct button
- on the comment view
- */
- flex-direction: row-reverse;
-}
-
-.gitlab-collapse {
- width: 2.4rem;
- height: 2.2rem;
- margin-left: 1rem;
- padding: .5rem;
-}
-
-.gitlab-collapse-closed {
- align-self: center;
-}
-
-.gitlab-checkbox-label {
- padding: 0 .2rem;
-}
-
-.gitlab-checkbox-wrapper {
- display: flex;
- align-items: baseline;
-}
-
-.gitlab-form-open {
- padding: 1rem;
- background-color: #fafafa;
-}
-
-.gitlab-label {
- font-weight: 600;
- display: inline-block;
- width: 100%;
-}
-
-.gitlab-link {
- color: #1b69b6;
- text-decoration: none;
- background-color: transparent;
- background-image: none;
-}
-
-.gitlab-link:hover {
- text-decoration: underline;
-}
-
-.gitlab-link-button {
- border: none;
- cursor: pointer;
- padding: 0 .15rem;
-}
-
-.gitlab-message {
- padding: .25rem 0;
- margin: 0;
- line-height: 1.2rem;
-}
-
-.gitlab-metadata-note {
- font-size: .7rem;
- line-height: 1rem;
- color: #666;
- margin-bottom: .5rem;
-}
-
-.gitlab-input {
- width: 100%;
- border: 1px solid #dfdfdf;
- border-radius: 4px;
- padding: .1rem .2rem;
- min-height: 2rem;
- max-width: 17rem;
-}
diff --git a/changelogs/unreleased/66402-use-visual-review-tools-npm-package.yml b/changelogs/unreleased/66402-use-visual-review-tools-npm-package.yml
new file mode 100644
index 00000000000..46773e12002
--- /dev/null
+++ b/changelogs/unreleased/66402-use-visual-review-tools-npm-package.yml
@@ -0,0 +1,5 @@
+---
+title: Move visual review toolbar code to NPM
+merge_request: 32159
+author:
+type: fixed
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 442b4b4c21e..969a84e85dd 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -298,6 +298,13 @@ module.exports = {
from: path.join(ROOT_PATH, 'node_modules/pdfjs-dist/cmaps/'),
to: path.join(ROOT_PATH, 'public/assets/webpack/cmaps/'),
},
+ {
+ from: path.join(
+ ROOT_PATH,
+ 'node_modules/@gitlab/visual-review-tools/dist/visual_review_toolbar.js',
+ ),
+ to: path.join(ROOT_PATH, 'public/assets/webpack'),
+ },
]),
// compression can require a lot of compute time and is disabled in CI
diff --git a/config/webpack.config.review_toolbar.js b/config/webpack.config.review_toolbar.js
deleted file mode 100644
index baaba7ed387..00000000000
--- a/config/webpack.config.review_toolbar.js
+++ /dev/null
@@ -1,58 +0,0 @@
-const path = require('path');
-const CompressionPlugin = require('compression-webpack-plugin');
-
-const ROOT_PATH = path.resolve(__dirname, '..');
-const CACHE_PATH = process.env.WEBPACK_CACHE_PATH || path.join(ROOT_PATH, 'tmp/cache');
-const NO_SOURCEMAPS = process.env.NO_SOURCEMAPS;
-const IS_PRODUCTION = process.env.NODE_ENV === 'production';
-
-const devtool = IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map';
-
-const alias = {
- vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
- spec: path.join(ROOT_PATH, 'spec/javascripts'),
-};
-
-module.exports = {
- mode: IS_PRODUCTION ? 'production' : 'development',
-
- context: path.join(ROOT_PATH, 'app/assets/javascripts'),
-
- name: 'visual_review_toolbar',
-
- entry: './visual_review_toolbar',
-
- output: {
- path: path.join(ROOT_PATH, 'public/assets/webpack'),
- filename: 'visual_review_toolbar.js',
- library: 'VisualReviewToolbar',
- libraryTarget: 'var',
- },
-
- resolve: {
- alias,
- },
-
- module: {
- rules: [
- {
- test: /\.js$/,
- loader: 'babel-loader',
- options: {
- cacheDirectory: path.join(CACHE_PATH, 'babel-loader'),
- },
- },
- {
- test: /\.css$/,
- use: ['style-loader', 'css-loader'],
- },
- ],
- },
-
- plugins: [
- // compression can require a lot of compute time and is disabled in CI
- new CompressionPlugin(),
- ].filter(Boolean),
-
- devtool: NO_SOURCEMAPS ? false : devtool,
-};
diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake
index a07ae3a418a..7a42e4e92a0 100644
--- a/lib/tasks/gitlab/assets.rake
+++ b/lib/tasks/gitlab/assets.rake
@@ -10,15 +10,9 @@ namespace :gitlab do
rake:assets:precompile
webpack:compile
gitlab:assets:fix_urls
- gitlab:assets:compile_vrt
].each(&Gitlab::TaskHelpers.method(:invoke_and_time_task))
end
- desc 'GitLab | Assets | Compile visual review toolbar'
- task :compile_vrt do
- system 'yarn', 'webpack-vrt'
- end
-
desc 'GitLab | Assets | Clean up old compiled frontend assets'
task clean: ['rake:assets:clean']
diff --git a/package.json b/package.json
index df5f758fa20..a86f96b7d93 100644
--- a/package.json
+++ b/package.json
@@ -1,210 +1,210 @@
{
- "private": true,
- "scripts": {
- "check-dependencies": "yarn check --integrity",
- "clean": "rm -rf public/assets tmp/cache/*-loader",
- "dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" nodemon -w 'config/webpack.config.js' --exec 'webpack-dev-server --config config/webpack.config.js'",
- "eslint": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue .",
- "eslint-fix": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue --fix .",
- "eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html --no-inline-config .",
- "file-coverage": "scripts/frontend/file_test_coverage.js",
- "prejest": "yarn check-dependencies",
- "jest": "jest",
- "jest-debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
- "jsdoc": "jsdoc -c config/jsdocs.config.js",
- "prekarma": "yarn check-dependencies",
- "karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js",
- "karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
- "karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
- "postinstall": "node ./scripts/frontend/postinstall.js",
- "prettier-staged": "node ./scripts/frontend/prettier.js check",
- "prettier-staged-save": "node ./scripts/frontend/prettier.js save",
- "prettier-all": "node ./scripts/frontend/prettier.js check-all",
- "prettier-all-save": "node ./scripts/frontend/prettier.js save-all",
- "stylelint": "node node_modules/stylelint/bin/stylelint.js app/assets/stylesheets/**/*.* ee/app/assets/stylesheets/**/*.* !**/vendors/**",
- "stylelint-file": "node node_modules/stylelint/bin/stylelint.js",
- "stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
- "test": "node scripts/frontend/test",
- "webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js",
- "webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js",
- "webpack-vrt": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.review_toolbar.js"
- },
- "dependencies": {
- "@babel/core": "^7.5.5",
- "@babel/plugin-proposal-class-properties": "^7.5.5",
- "@babel/plugin-proposal-json-strings": "^7.2.0",
- "@babel/plugin-proposal-private-methods": "^7.4.4",
- "@babel/plugin-syntax-dynamic-import": "^7.2.0",
- "@babel/plugin-syntax-import-meta": "^7.2.0",
- "@babel/preset-env": "^7.5.5",
- "@gitlab/csslab": "^1.9.0",
- "@gitlab/svgs": "^1.68.0",
- "@gitlab/ui": "5.18.0",
- "apollo-cache-inmemory": "^1.5.1",
- "apollo-client": "^2.5.1",
- "apollo-link": "^1.2.11",
- "apollo-link-batch-http": "^1.2.11",
- "apollo-upload-client": "^10.0.0",
- "at.js": "^1.5.4",
- "autosize": "^4.0.0",
- "axios": "^0.19.0",
- "babel-loader": "^8.0.5",
- "bootstrap": "4.3.1",
- "brace-expansion": "^1.1.8",
- "cache-loader": "^2.0.1",
- "chart.js": "2.7.2",
- "classlist-polyfill": "^1.2.0",
- "clipboard": "^1.7.1",
- "codesandbox-api": "^0.0.20",
- "compression-webpack-plugin": "^2.0.0",
- "copy-webpack-plugin": "^5.0.4",
- "core-js": "^3.1.3",
- "cropper": "^2.3.0",
- "css-loader": "^1.0.0",
- "d3": "^4.13.0",
- "d3-array": "^1.2.1",
- "d3-axis": "^1.0.8",
- "d3-brush": "^1.0.4",
- "d3-ease": "^1.0.3",
- "d3-scale": "^1.0.7",
- "d3-selection": "^1.2.0",
- "d3-shape": "^1.2.0",
- "d3-time": "^1.0.8",
- "d3-time-format": "^2.1.1",
- "d3-transition": "^1.1.1",
- "dateformat": "^3.0.3",
- "deckar01-task_list": "^2.2.0",
- "diff": "^3.4.0",
- "document-register-element": "1.13.1",
- "dropzone": "^4.2.0",
- "emoji-regex": "^7.0.3",
- "emoji-unicode-version": "^0.2.1",
- "exports-loader": "^0.7.0",
- "file-loader": "^3.0.1",
- "formdata-polyfill": "^3.0.11",
- "fuzzaldrin-plus": "^0.5.0",
- "glob": "^7.1.2",
- "graphql": "^14.0.2",
- "imports-loader": "^0.8.0",
- "jed": "^1.1.1",
- "jest-transform-graphql": "^2.1.0",
- "jquery": "^3.4.1",
- "jquery-ujs": "1.2.2",
- "jquery.caret": "^0.3.1",
- "jquery.waitforimages": "^2.2.0",
- "js-cookie": "^2.1.3",
- "jszip": "^3.1.3",
- "jszip-utils": "^0.0.2",
- "katex": "^0.10.0",
- "marked": "^0.3.12",
- "mermaid": "^8.2.3",
- "monaco-editor": "^0.15.6",
- "monaco-editor-webpack-plugin": "^1.7.0",
- "mousetrap": "^1.4.6",
- "pdfjs-dist": "^2.0.943",
- "pikaday": "^1.8.0",
- "popper.js": "^1.14.7",
- "prismjs": "^1.6.0",
- "prosemirror-markdown": "^1.3.0",
- "prosemirror-model": "^1.6.4",
- "raphael": "^2.2.7",
- "raven-js": "^3.22.1",
- "raw-loader": "^1.0.0",
- "sanitize-html": "^1.16.1",
- "select2": "3.5.2-browserify",
- "sha1": "^1.1.1",
- "smooshpack": "^0.0.54",
- "sortablejs": "^1.7.0",
- "sql.js": "^0.4.0",
- "stickyfilljs": "^2.0.5",
- "style-loader": "^0.23.1",
- "svg4everybody": "2.1.9",
- "three": "^0.84.0",
- "three-orbit-controls": "^82.1.0",
- "three-stl-loader": "^1.0.4",
- "timeago.js": "^3.0.2",
- "tiptap": "^1.8.0",
- "tiptap-commands": "^1.4.0",
- "tiptap-extensions": "^1.8.0",
- "underscore": "^1.9.0",
- "url-loader": "^1.1.2",
- "visibilityjs": "^1.2.4",
- "vue": "^2.6.10",
- "vue-apollo": "^3.0.0-beta.28",
- "vue-loader": "^15.7.0",
- "vue-resource": "^1.5.1",
- "vue-router": "^3.0.2",
- "vue-template-compiler": "^2.6.10",
- "vue-virtual-scroll-list": "^1.3.1",
- "vuex": "^3.1.0",
- "webpack": "^4.29.0",
- "webpack-bundle-analyzer": "^3.3.2",
- "webpack-cli": "^3.2.1",
- "webpack-stats-plugin": "^0.2.1",
- "worker-loader": "^2.0.0",
- "xterm": "^3.5.0"
- },
- "devDependencies": {
- "@babel/plugin-transform-modules-commonjs": "^7.5.0",
- "@gitlab/eslint-config": "^1.6.0",
- "@gitlab/eslint-plugin-i18n": "^1.1.0",
- "@gitlab/eslint-plugin-vue-i18n": "^1.2.0",
- "@vue/test-utils": "^1.0.0-beta.25",
- "axios-mock-adapter": "^1.15.0",
- "babel-jest": "^24.1.0",
- "babel-plugin-dynamic-import-node": "^2.2.0",
- "babel-plugin-istanbul": "^5.1.0",
- "babel-plugin-rewire": "^1.2.0",
- "chalk": "^2.4.1",
- "commander": "^2.18.0",
- "custom-jquery-matchers": "^2.1.0",
- "docdash": "^1.0.2",
- "eslint": "~5.9.0",
- "eslint-import-resolver-jest": "^2.1.1",
- "eslint-import-resolver-webpack": "^0.10.1",
- "eslint-plugin-html": "5.0.0",
- "eslint-plugin-import": "^2.14.0",
- "eslint-plugin-jasmine": "^2.10.1",
- "eslint-plugin-jest": "^22.3.0",
- "gettext-extractor": "^3.4.3",
- "gettext-extractor-vue": "^4.0.2",
- "graphql-tag": "^2.10.0",
- "jasmine-core": "^2.9.0",
- "jasmine-diff": "^0.1.3",
- "jasmine-jquery": "^2.1.1",
- "jest": "^24.1.0",
- "jest-environment-jsdom": "^24.0.0",
- "jest-junit": "^6.3.0",
- "jest-util": "^24.0.0",
- "jsdoc": "^3.5.5",
- "jsdoc-vue": "^1.0.0",
- "karma": "^4.2.0",
- "karma-chrome-launcher": "^3.0.0",
- "karma-coverage-istanbul-reporter": "^2.1.0",
- "karma-jasmine": "^1.1.2",
- "karma-junit-reporter": "^1.2.0",
- "karma-mocha-reporter": "^2.2.5",
- "karma-sourcemap-loader": "^0.3.7",
- "karma-webpack": "^4.0.2",
- "md5": "^2.2.1",
- "node-sass": "^4.12.0",
- "nodemon": "^1.18.9",
- "pixelmatch": "^4.0.2",
- "postcss": "^7.0.14",
- "prettier": "1.18.2",
- "readdir-enhanced": "^2.2.4",
- "stylelint": "^10.1.0",
- "stylelint-config-recommended": "^2.2.0",
- "stylelint-scss": "^3.9.2",
- "vue-jest": "^4.0.0-beta.2",
- "webpack-dev-server": "^3.1.14",
- "yarn-deduplicate": "^1.1.1"
- },
- "resolutions": {
- "vue-jest/ts-jest": "24.0.0"
- },
- "engines": {
- "node": ">=8.10.0",
- "yarn": "^1.10.0"
- }
-}
+ "private": true,
+ "scripts": {
+ "check-dependencies": "yarn check --integrity",
+ "clean": "rm -rf public/assets tmp/cache/*-loader",
+ "dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" nodemon -w 'config/webpack.config.js' --exec 'webpack-dev-server --config config/webpack.config.js'",
+ "eslint": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue .",
+ "eslint-fix": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue --fix .",
+ "eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html --no-inline-config .",
+ "file-coverage": "scripts/frontend/file_test_coverage.js",
+ "prejest": "yarn check-dependencies",
+ "jest": "jest",
+ "jest-debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
+ "jsdoc": "jsdoc -c config/jsdocs.config.js",
+ "prekarma": "yarn check-dependencies",
+ "karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js",
+ "karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
+ "karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
+ "postinstall": "node ./scripts/frontend/postinstall.js",
+ "prettier-staged": "node ./scripts/frontend/prettier.js check",
+ "prettier-staged-save": "node ./scripts/frontend/prettier.js save",
+ "prettier-all": "node ./scripts/frontend/prettier.js check-all",
+ "prettier-all-save": "node ./scripts/frontend/prettier.js save-all",
+ "stylelint": "node node_modules/stylelint/bin/stylelint.js app/assets/stylesheets/**/*.* ee/app/assets/stylesheets/**/*.* !**/vendors/**",
+ "stylelint-file": "node node_modules/stylelint/bin/stylelint.js",
+ "stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
+ "test": "node scripts/frontend/test",
+ "webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js",
+ "webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js"
+ },
+ "dependencies": {
+ "@babel/core": "^7.5.5",
+ "@babel/plugin-proposal-class-properties": "^7.5.5",
+ "@babel/plugin-proposal-json-strings": "^7.2.0",
+ "@babel/plugin-proposal-private-methods": "^7.4.4",
+ "@babel/plugin-syntax-dynamic-import": "^7.2.0",
+ "@babel/plugin-syntax-import-meta": "^7.2.0",
+ "@babel/preset-env": "^7.5.5",
+ "@gitlab/csslab": "^1.9.0",
+ "@gitlab/svgs": "^1.68.0",
+ "@gitlab/ui": "5.18.0",
+ "@gitlab/visual-review-tools": "^1.0.0",
+ "apollo-cache-inmemory": "^1.5.1",
+ "apollo-client": "^2.5.1",
+ "apollo-link": "^1.2.11",
+ "apollo-link-batch-http": "^1.2.11",
+ "apollo-upload-client": "^10.0.0",
+ "at.js": "^1.5.4",
+ "autosize": "^4.0.0",
+ "axios": "^0.19.0",
+ "babel-loader": "^8.0.5",
+ "bootstrap": "4.3.1",
+ "brace-expansion": "^1.1.8",
+ "cache-loader": "^2.0.1",
+ "chart.js": "2.7.2",
+ "classlist-polyfill": "^1.2.0",
+ "clipboard": "^1.7.1",
+ "codesandbox-api": "^0.0.20",
+ "compression-webpack-plugin": "^2.0.0",
+ "copy-webpack-plugin": "^5.0.4",
+ "core-js": "^3.1.3",
+ "cropper": "^2.3.0",
+ "css-loader": "^1.0.0",
+ "d3": "^4.13.0",
+ "d3-array": "^1.2.1",
+ "d3-axis": "^1.0.8",
+ "d3-brush": "^1.0.4",
+ "d3-ease": "^1.0.3",
+ "d3-scale": "^1.0.7",
+ "d3-selection": "^1.2.0",
+ "d3-shape": "^1.2.0",
+ "d3-time": "^1.0.8",
+ "d3-time-format": "^2.1.1",
+ "d3-transition": "^1.1.1",
+ "dateformat": "^3.0.3",
+ "deckar01-task_list": "^2.2.0",
+ "diff": "^3.4.0",
+ "document-register-element": "1.13.1",
+ "dropzone": "^4.2.0",
+ "emoji-regex": "^7.0.3",
+ "emoji-unicode-version": "^0.2.1",
+ "exports-loader": "^0.7.0",
+ "file-loader": "^3.0.1",
+ "formdata-polyfill": "^3.0.11",
+ "fuzzaldrin-plus": "^0.5.0",
+ "glob": "^7.1.2",
+ "graphql": "^14.0.2",
+ "imports-loader": "^0.8.0",
+ "jed": "^1.1.1",
+ "jest-transform-graphql": "^2.1.0",
+ "jquery": "^3.4.1",
+ "jquery-ujs": "1.2.2",
+ "jquery.caret": "^0.3.1",
+ "jquery.waitforimages": "^2.2.0",
+ "js-cookie": "^2.1.3",
+ "jszip": "^3.1.3",
+ "jszip-utils": "^0.0.2",
+ "katex": "^0.10.0",
+ "marked": "^0.3.12",
+ "mermaid": "^8.2.3",
+ "monaco-editor": "^0.15.6",
+ "monaco-editor-webpack-plugin": "^1.7.0",
+ "mousetrap": "^1.4.6",
+ "pdfjs-dist": "^2.0.943",
+ "pikaday": "^1.8.0",
+ "popper.js": "^1.14.7",
+ "prismjs": "^1.6.0",
+ "prosemirror-markdown": "^1.3.0",
+ "prosemirror-model": "^1.6.4",
+ "raphael": "^2.2.7",
+ "raven-js": "^3.22.1",
+ "raw-loader": "^1.0.0",
+ "sanitize-html": "^1.16.1",
+ "select2": "3.5.2-browserify",
+ "sha1": "^1.1.1",
+ "smooshpack": "^0.0.54",
+ "sortablejs": "^1.7.0",
+ "sql.js": "^0.4.0",
+ "stickyfilljs": "^2.0.5",
+ "style-loader": "^0.23.1",
+ "svg4everybody": "2.1.9",
+ "three": "^0.84.0",
+ "three-orbit-controls": "^82.1.0",
+ "three-stl-loader": "^1.0.4",
+ "timeago.js": "^3.0.2",
+ "tiptap": "^1.8.0",
+ "tiptap-commands": "^1.4.0",
+ "tiptap-extensions": "^1.8.0",
+ "underscore": "^1.9.0",
+ "url-loader": "^1.1.2",
+ "visibilityjs": "^1.2.4",
+ "vue": "^2.6.10",
+ "vue-apollo": "^3.0.0-beta.28",
+ "vue-loader": "^15.7.0",
+ "vue-resource": "^1.5.1",
+ "vue-router": "^3.0.2",
+ "vue-template-compiler": "^2.6.10",
+ "vue-virtual-scroll-list": "^1.3.1",
+ "vuex": "^3.1.0",
+ "webpack": "^4.29.0",
+ "webpack-bundle-analyzer": "^3.3.2",
+ "webpack-cli": "^3.2.1",
+ "webpack-stats-plugin": "^0.2.1",
+ "worker-loader": "^2.0.0",
+ "xterm": "^3.5.0"
+ },
+ "devDependencies": {
+ "@babel/plugin-transform-modules-commonjs": "^7.5.0",
+ "@gitlab/eslint-config": "^1.6.0",
+ "@gitlab/eslint-plugin-i18n": "^1.1.0",
+ "@gitlab/eslint-plugin-vue-i18n": "^1.2.0",
+ "@vue/test-utils": "^1.0.0-beta.25",
+ "axios-mock-adapter": "^1.15.0",
+ "babel-jest": "^24.1.0",
+ "babel-plugin-dynamic-import-node": "^2.2.0",
+ "babel-plugin-istanbul": "^5.1.0",
+ "babel-plugin-rewire": "^1.2.0",
+ "chalk": "^2.4.1",
+ "commander": "^2.18.0",
+ "custom-jquery-matchers": "^2.1.0",
+ "docdash": "^1.0.2",
+ "eslint": "~5.9.0",
+ "eslint-import-resolver-jest": "^2.1.1",
+ "eslint-import-resolver-webpack": "^0.10.1",
+ "eslint-plugin-html": "5.0.0",
+ "eslint-plugin-import": "^2.14.0",
+ "eslint-plugin-jasmine": "^2.10.1",
+ "eslint-plugin-jest": "^22.3.0",
+ "gettext-extractor": "^3.4.3",
+ "gettext-extractor-vue": "^4.0.2",
+ "graphql-tag": "^2.10.0",
+ "jasmine-core": "^2.9.0",
+ "jasmine-diff": "^0.1.3",
+ "jasmine-jquery": "^2.1.1",
+ "jest": "^24.1.0",
+ "jest-environment-jsdom": "^24.0.0",
+ "jest-junit": "^6.3.0",
+ "jest-util": "^24.0.0",
+ "jsdoc": "^3.5.5",
+ "jsdoc-vue": "^1.0.0",
+ "karma": "^4.2.0",
+ "karma-chrome-launcher": "^3.0.0",
+ "karma-coverage-istanbul-reporter": "^2.1.0",
+ "karma-jasmine": "^1.1.2",
+ "karma-junit-reporter": "^1.2.0",
+ "karma-mocha-reporter": "^2.2.5",
+ "karma-sourcemap-loader": "^0.3.7",
+ "karma-webpack": "^4.0.2",
+ "md5": "^2.2.1",
+ "node-sass": "^4.12.0",
+ "nodemon": "^1.18.9",
+ "pixelmatch": "^4.0.2",
+ "postcss": "^7.0.14",
+ "prettier": "1.18.2",
+ "readdir-enhanced": "^2.2.4",
+ "stylelint": "^10.1.0",
+ "stylelint-config-recommended": "^2.2.0",
+ "stylelint-scss": "^3.9.2",
+ "vue-jest": "^4.0.0-beta.2",
+ "webpack-dev-server": "^3.1.14",
+ "yarn-deduplicate": "^1.1.1"
+ },
+ "resolutions": {
+ "vue-jest/ts-jest": "24.0.0"
+ },
+ "engines": {
+ "node": ">=8.10.0",
+ "yarn": "^1.10.0"
+ }
+} \ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 4489b10815a..dd85729333a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1021,6 +1021,11 @@
vue "^2.6.10"
vue-loader "^15.4.2"
+"@gitlab/visual-review-tools@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.0.0.tgz#6012e0a19797c1f5dad34ccf4dacdaf38e400a73"
+ integrity sha512-xMvz9IwrXisQ1MH+Tj6lfbQcQSiQy88nTPuQV6OTLBGuV+vIQeVwXeIkQeTKuSpd0GqZvigPdRqxyQCa3blpIg==
+
"@gitlab/vue-toasted@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@gitlab/vue-toasted/-/vue-toasted-1.2.1.tgz#f407b5aa710863e5b7f021f4a1f66160331ab263"