diff options
Diffstat (limited to 'app/assets/javascripts/diffs/store')
-rw-r--r-- | app/assets/javascripts/diffs/store/actions.js | 65 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/getters.js | 68 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/getters_versions_dropdowns.js | 28 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/modules/diff_state.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/mutation_types.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/mutations.js | 57 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/utils.js | 97 |
7 files changed, 197 insertions, 122 deletions
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js index 5b410051705..e95e9ac3ee4 100644 --- a/app/assets/javascripts/diffs/store/actions.js +++ b/app/assets/javascripts/diffs/store/actions.js @@ -50,6 +50,8 @@ import { } from '../constants'; import { diffViewerModes } from '~/ide/constants'; import { isCollapsed } from '../utils/diff_file'; +import { getDerivedMergeRequestInformation } from '../utils/merge_request'; +import { markFileReview, setReviewsForMergeRequest } from '../utils/file_reviews'; export const setBaseConfig = ({ commit }, options) => { const { @@ -60,7 +62,9 @@ export const setBaseConfig = ({ commit }, options) => { projectPath, dismissEndpoint, showSuggestPopover, + defaultSuggestionCommitMessage, viewDiffsFileByFile, + mrReviews, } = options; commit(types.SET_BASE_CONFIG, { endpoint, @@ -70,7 +74,9 @@ export const setBaseConfig = ({ commit }, options) => { projectPath, dismissEndpoint, showSuggestPopover, + defaultSuggestionCommitMessage, viewDiffsFileByFile, + mrReviews, }); }; @@ -123,7 +129,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { // We need to check that the currentDiffFileId points to a file that exists if ( state.currentDiffFileId && - !state.diffFiles.some(f => f.file_hash === state.currentDiffFileId) && + !state.diffFiles.some((f) => f.file_hash === state.currentDiffFileId) && !isNoteLink ) { commit(types.VIEW_DIFF_FILE, state.diffFiles[0].file_hash); @@ -131,11 +137,11 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { if (state.diffFiles?.length) { // eslint-disable-next-line promise/catch-or-return,promise/no-nesting - import('~/code_navigation').then(m => + import('~/code_navigation').then((m) => m.default({ blobs: state.diffFiles - .filter(f => f.code_navigation_path) - .map(f => ({ + .filter((f) => f.code_navigation_path) + .map((f) => ({ path: f.new_path, codeNavigationPath: f.code_navigation_path, })), @@ -157,7 +163,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => { return pagination.next_page; }) - .then(nextPage => nextPage && getBatch(nextPage)) + .then((nextPage) => nextPage && getBatch(nextPage)) .catch(() => commit(types.SET_RETRIEVING_BATCHES, false)); return getBatch() @@ -207,7 +213,7 @@ export const fetchDiffFilesMeta = ({ commit, state }) => { export const fetchCoverageFiles = ({ commit, state }) => { const coveragePoll = new Poll({ resource: { - getCoverageReports: endpoint => axios.get(endpoint), + getCoverageReports: (endpoint) => axios.get(endpoint), }, data: state.endpointCoverage, method: 'getCoverageReports', @@ -242,8 +248,8 @@ export const assignDiscussionsToDiff = ( const hash = getLocationHash(); discussions - .filter(discussion => discussion.diff_discussion) - .forEach(discussion => { + .filter((discussion) => discussion.diff_discussion) + .forEach((discussion) => { commit(types.SET_LINE_DISCUSSIONS_FOR_FILE, { discussion, diffPositionByLineCode, @@ -270,10 +276,10 @@ export const toggleLineDiscussions = ({ commit }, options) => { }; export const renderFileForDiscussionId = ({ commit, rootState, state }, discussionId) => { - const discussion = rootState.notes.discussions.find(d => d.id === discussionId); + const discussion = rootState.notes.discussions.find((d) => d.id === discussionId); if (discussion && discussion.diff_file) { - const file = state.diffFiles.find(f => f.file_hash === discussion.diff_file.file_hash); + const file = state.diffFiles.find((f) => f.file_hash === discussion.diff_file.file_hash); if (file) { if (!file.renderIt) { @@ -299,11 +305,12 @@ export const renderFileForDiscussionId = ({ commit, rootState, state }, discussi export const startRenderDiffsQueue = ({ state, commit }) => { const checkItem = () => - new Promise(resolve => { + new Promise((resolve) => { const nextFile = state.diffFiles.find( - file => + (file) => !file.renderIt && - (file.viewer && (!isCollapsed(file) || file.viewer.name !== diffViewerModes.text)), + file.viewer && + (!isCollapsed(file) || file.viewer.name !== diffViewerModes.text), ); if (nextFile) { @@ -357,7 +364,7 @@ export const loadMoreLines = ({ commit }, options) => { params.from_merge_request = true; - return axios.get(endpoint, { params }).then(res => { + return axios.get(endpoint, { params }).then((res) => { const contextLines = res.data || []; commit(types.ADD_CONTEXT_LINES, { @@ -398,7 +405,7 @@ export const loadCollapsedDiff = ({ commit, getters, state }, file) => w: state.showWhitespace ? '0' : '1', }, }) - .then(res => { + .then((res) => { commit(types.ADD_COLLAPSED_DIFFS, { file, data: res.data, @@ -421,7 +428,7 @@ export const toggleFileDiscussions = ({ getters, dispatch }, diff) => { const shouldCloseAll = getters.diffHasAllExpandedDiscussions(diff); const shouldExpandAll = getters.diffHasAllCollapsedDiscussions(diff); - discussions.forEach(discussion => { + discussions.forEach((discussion) => { const data = { discussionId: discussion.id }; if (shouldCloseAll) { @@ -435,13 +442,13 @@ export const toggleFileDiscussions = ({ getters, dispatch }, diff) => { export const toggleFileDiscussionWrappers = ({ commit }, diff) => { const discussionWrappersExpanded = allDiscussionWrappersExpanded(diff); const lineCodesWithDiscussions = new Set(); - const lineHasDiscussion = line => Boolean(line?.discussions.length); - const registerDiscussionLine = line => lineCodesWithDiscussions.add(line.line_code); + const lineHasDiscussion = (line) => Boolean(line?.discussions.length); + const registerDiscussionLine = (line) => lineCodesWithDiscussions.add(line.line_code); diff[INLINE_DIFF_LINES_KEY].filter(lineHasDiscussion).forEach(registerDiscussionLine); if (lineCodesWithDiscussions.size) { - Array.from(lineCodesWithDiscussions).forEach(lineCode => { + Array.from(lineCodesWithDiscussions).forEach((lineCode) => { commit(types.TOGGLE_LINE_DISCUSSIONS, { fileHash: diff.file_hash, expanded: !discussionWrappersExpanded, @@ -459,8 +466,8 @@ export const saveDiffDiscussion = ({ state, dispatch }, { note, formData }) => { }); return dispatch('saveNote', postData, { root: true }) - .then(result => dispatch('updateDiscussion', result.discussion, { root: true })) - .then(discussion => dispatch('assignDiscussionsToDiff', [discussion])) + .then((result) => dispatch('updateDiscussion', result.discussion, { root: true })) + .then((discussion) => dispatch('assignDiscussionsToDiff', [discussion])) .then(() => dispatch('updateResolvableDiscussionsCounts', null, { root: true })) .then(() => dispatch('closeDiffFileCommentForm', formData.diffFile.file_hash)) .catch(() => createFlash(s__('MergeRequests|Saving the comment failed'))); @@ -560,7 +567,7 @@ export const setExpandedDiffLines = ({ commit }, { file, data }) => { }); commit(types.TOGGLE_DIFF_FILE_RENDERING_MORE, file.file_path); - const idleCb = t => { + const idleCb = (t) => { const startIndex = index; while ( @@ -608,7 +615,7 @@ export const fetchFullDiff = ({ commit, dispatch }, file) => .catch(() => dispatch('receiveFullDiffError', file.file_path)); export const toggleFullDiff = ({ dispatch, commit, getters, state }, filePath) => { - const file = state.diffFiles.find(f => f.file_path === filePath); + const file = state.diffFiles.find((f) => f.file_path === filePath); commit(types.REQUEST_FULL_DIFF, filePath); @@ -719,7 +726,7 @@ export const setCurrentDiffFileIdFromNote = ({ commit, state, rootGetters }, not const fileHash = rootGetters.getDiscussion(note.discussion_id).diff_file?.file_hash; - if (fileHash && state.diffFiles.some(f => f.file_hash === fileHash)) { + if (fileHash && state.diffFiles.some((f) => f.file_hash === fileHash)) { commit(types.VIEW_DIFF_FILE, fileHash); } }; @@ -741,3 +748,13 @@ export const setFileByFile = ({ commit }, { fileByFile }) => { mergeUrlParams({ [DIFF_FILE_BY_FILE_COOKIE_NAME]: fileViewMode }, window.location.href), ); }; + +export function reviewFile({ commit, state, getters }, { file, reviewed = true }) { + const { mrPath } = getDerivedMergeRequestInformation({ endpoint: file.load_collapsed_diff_url }); + const reviews = setReviewsForMergeRequest( + mrPath, + markFileReview(getters.fileReviews(state), file, reviewed), + ); + + commit(types.SET_MR_FILE_REVIEWS, reviews); +} diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js index baf54188932..a167b6d4694 100644 --- a/app/assets/javascripts/diffs/store/getters.js +++ b/app/assets/javascripts/diffs/store/getters.js @@ -1,5 +1,6 @@ import { __, n__ } from '~/locale'; import { parallelizeDiffLines } from './utils'; +import { isFileReviewed } from '../utils/file_reviews'; import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE, @@ -8,13 +9,13 @@ import { export * from './getters_versions_dropdowns'; -export const isParallelView = state => state.diffViewType === PARALLEL_DIFF_VIEW_TYPE; +export const isParallelView = (state) => state.diffViewType === PARALLEL_DIFF_VIEW_TYPE; -export const isInlineView = state => state.diffViewType === INLINE_DIFF_VIEW_TYPE; +export const isInlineView = (state) => state.diffViewType === INLINE_DIFF_VIEW_TYPE; -export const whichCollapsedTypes = state => { - const automatic = state.diffFiles.some(file => file.viewer?.automaticallyCollapsed); - const manual = state.diffFiles.some(file => file.viewer?.manuallyCollapsed); +export const whichCollapsedTypes = (state) => { + const automatic = state.diffFiles.some((file) => file.viewer?.automaticallyCollapsed); + const manual = state.diffFiles.some((file) => file.viewer?.manuallyCollapsed); return { any: automatic || manual, @@ -23,18 +24,18 @@ export const whichCollapsedTypes = state => { }; }; -export const commitId = state => (state.commit && state.commit.id ? state.commit.id : null); +export const commitId = (state) => (state.commit && state.commit.id ? state.commit.id : null); /** * Checks if the diff has all discussions expanded * @param {Object} diff * @returns {Boolean} */ -export const diffHasAllExpandedDiscussions = (state, getters) => diff => { +export const diffHasAllExpandedDiscussions = (state, getters) => (diff) => { const discussions = getters.getDiffFileDiscussions(diff); return ( - (discussions && discussions.length && discussions.every(discussion => discussion.expanded)) || + (discussions && discussions.length && discussions.every((discussion) => discussion.expanded)) || false ); }; @@ -44,11 +45,13 @@ export const diffHasAllExpandedDiscussions = (state, getters) => diff => { * @param {Object} diff * @returns {Boolean} */ -export const diffHasAllCollapsedDiscussions = (state, getters) => diff => { +export const diffHasAllCollapsedDiscussions = (state, getters) => (diff) => { const discussions = getters.getDiffFileDiscussions(diff); return ( - (discussions && discussions.length && discussions.every(discussion => !discussion.expanded)) || + (discussions && + discussions.length && + discussions.every((discussion) => !discussion.expanded)) || false ); }; @@ -58,9 +61,9 @@ export const diffHasAllCollapsedDiscussions = (state, getters) => diff => { * @param {Object} diff * @returns {Boolean} */ -export const diffHasExpandedDiscussions = () => diff => { - return diff[INLINE_DIFF_LINES_KEY].filter(l => l.discussions.length >= 1).some( - l => l.discussionsExpanded, +export const diffHasExpandedDiscussions = () => (diff) => { + return diff[INLINE_DIFF_LINES_KEY].filter((l) => l.discussions.length >= 1).some( + (l) => l.discussionsExpanded, ); }; @@ -69,8 +72,8 @@ export const diffHasExpandedDiscussions = () => diff => { * @param {Boolean} diff * @returns {Boolean} */ -export const diffHasDiscussions = () => diff => { - return diff[INLINE_DIFF_LINES_KEY].some(l => l.discussions.length >= 1); +export const diffHasDiscussions = () => (diff) => { + return diff[INLINE_DIFF_LINES_KEY].some((l) => l.discussions.length >= 1); }; /** @@ -78,22 +81,22 @@ export const diffHasDiscussions = () => diff => { * @param {Object} diff * @returns {Array} */ -export const getDiffFileDiscussions = (state, getters, rootState, rootGetters) => diff => +export const getDiffFileDiscussions = (state, getters, rootState, rootGetters) => (diff) => rootGetters.discussions.filter( - discussion => discussion.diff_discussion && discussion.diff_file.file_hash === diff.file_hash, + (discussion) => discussion.diff_discussion && discussion.diff_file.file_hash === diff.file_hash, ) || []; -export const getDiffFileByHash = state => fileHash => - state.diffFiles.find(file => file.file_hash === fileHash); +export const getDiffFileByHash = (state) => (fileHash) => + state.diffFiles.find((file) => file.file_hash === fileHash); -export const flatBlobsList = state => - Object.values(state.treeEntries).filter(f => f.type === 'blob'); +export const flatBlobsList = (state) => + Object.values(state.treeEntries).filter((f) => f.type === 'blob'); export const allBlobs = (state, getters) => getters.flatBlobsList.reduce((acc, file) => { const { parentPath } = file; - if (parentPath && !acc.some(f => f.path === parentPath)) { + if (parentPath && !acc.some((f) => f.path === parentPath)) { acc.push({ path: parentPath, isHeader: true, @@ -101,13 +104,13 @@ export const allBlobs = (state, getters) => }); } - acc.find(f => f.path === parentPath).tree.push(file); + acc.find((f) => f.path === parentPath).tree.push(file); return acc; }, []); -export const getCommentFormForDiffFile = state => fileHash => - state.commentForms.find(form => form.fileHash === fileHash); +export const getCommentFormForDiffFile = (state) => (fileHash) => + state.commentForms.find((form) => form.fileHash === fileHash); /** * Returns the test coverage hits for a specific line of a given file @@ -115,7 +118,7 @@ export const getCommentFormForDiffFile = state => fileHash => * @param {number} line * @returns {number} */ -export const fileLineCoverage = state => (file, line) => { +export const fileLineCoverage = (state) => (file, line) => { if (!state.coverageFiles.files) return {}; const fileCoverage = state.coverageFiles.files[file]; if (!fileCoverage) return {}; @@ -136,10 +139,13 @@ export const fileLineCoverage = state => (file, line) => { * Returns index of a currently selected diff in diffFiles * @returns {number} */ -export const currentDiffIndex = state => - Math.max(0, state.diffFiles.findIndex(diff => diff.file_hash === state.currentDiffFileId)); +export const currentDiffIndex = (state) => + Math.max( + 0, + state.diffFiles.findIndex((diff) => diff.file_hash === state.currentDiffFileId), + ); -export const diffLines = state => (file, unifiedDiffComponents) => { +export const diffLines = (state) => (file, unifiedDiffComponents) => { if (!unifiedDiffComponents && state.diffViewType === INLINE_DIFF_VIEW_TYPE) { return null; } @@ -149,3 +155,7 @@ export const diffLines = state => (file, unifiedDiffComponents) => { state.diffViewType === INLINE_DIFF_VIEW_TYPE, ); }; + +export function fileReviews(state) { + return state.diffFiles.map((file) => isFileReviewed(state.mrReviews, file)); +} diff --git a/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js b/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js index 135b1c61ef5..3f33b0c900e 100644 --- a/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js +++ b/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js @@ -2,10 +2,10 @@ import { __, n__, sprintf } from '~/locale'; import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils'; import { DIFF_COMPARE_BASE_VERSION_INDEX, DIFF_COMPARE_HEAD_VERSION_INDEX } from '../constants'; -export const selectedTargetIndex = state => +export const selectedTargetIndex = (state) => state.startVersion?.version_index || DIFF_COMPARE_BASE_VERSION_INDEX; -export const selectedSourceIndex = state => state.mergeRequestDiff.version_index; +export const selectedSourceIndex = (state) => state.mergeRequestDiff.version_index; export const diffCompareDropdownTargetVersions = (state, getters) => { // startVersion only exists if the user has selected a version other @@ -40,7 +40,7 @@ export const diffCompareDropdownTargetVersions = (state, getters) => { selected: isHeadSelected, }; // Appended properties here are to make the compare_dropdown_layout easier to reason about - const formatVersion = v => { + const formatVersion = (v) => { return { href: v.compare_path, versionName: sprintf(__(`version %{versionIndex}`), { versionIndex: v.version_index }), @@ -53,19 +53,23 @@ export const diffCompareDropdownTargetVersions = (state, getters) => { ...state.mergeRequestDiffs.slice(1).map(formatVersion), baseVersion, state.mergeRequestDiff.head_version_path && headVersion, - ].filter(a => a); + ].filter((a) => a); }; export const diffCompareDropdownSourceVersions = (state, getters) => { // Appended properties here are to make the compare_dropdown_layout easier to reason about - return state.mergeRequestDiffs.map((v, i) => ({ - ...v, - href: v.version_path, - commitsText: n__(`%d commit,`, `%d commits,`, v.commits_count), - versionName: - i === 0 + return state.mergeRequestDiffs.map((v, i) => { + const isLatestVersion = i === 0; + + return { + ...v, + href: v.version_path, + commitsText: n__(`%d commit,`, `%d commits,`, v.commits_count), + isLatestVersion, + versionName: isLatestVersion ? __('latest version') : sprintf(__(`version %{versionIndex}`), { versionIndex: v.version_index }), - selected: v.version_index === getters.selectedSourceIndex, - })); + selected: v.version_index === getters.selectedSourceIndex, + }; + }); }; diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js index c331e52c887..aa89c74cef0 100644 --- a/app/assets/javascripts/diffs/store/modules/diff_state.js +++ b/app/assets/javascripts/diffs/store/modules/diff_state.js @@ -45,4 +45,6 @@ export default () => ({ fileFinderVisible: false, dismissEndpoint: '', showSuggestPopover: true, + defaultSuggestionCommitMessage: '', + mrReviews: {}, }); diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js index 30097239aaa..4641731c4b6 100644 --- a/app/assets/javascripts/diffs/store/mutation_types.js +++ b/app/assets/javascripts/diffs/store/mutation_types.js @@ -7,6 +7,8 @@ export const SET_DIFF_METADATA = 'SET_DIFF_METADATA'; export const SET_DIFF_DATA_BATCH = 'SET_DIFF_DATA_BATCH'; export const SET_DIFF_FILES = 'SET_DIFF_FILES'; +export const SET_MR_FILE_REVIEWS = 'SET_MR_FILE_REVIEWS'; + export const SET_DIFF_VIEW_TYPE = 'SET_DIFF_VIEW_TYPE'; export const SET_COVERAGE_DATA = 'SET_COVERAGE_DATA'; export const SET_MERGE_REQUEST_DIFFS = 'SET_MERGE_REQUEST_DIFFS'; diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js index 19122c3096f..06f0f2c3dfb 100644 --- a/app/assets/javascripts/diffs/store/mutations.js +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -36,7 +36,9 @@ export default { projectPath, dismissEndpoint, showSuggestPopover, + defaultSuggestionCommitMessage, viewDiffsFileByFile, + mrReviews, } = options; Object.assign(state, { endpoint, @@ -46,7 +48,9 @@ export default { projectPath, dismissEndpoint, showSuggestPopover, + defaultSuggestionCommitMessage, viewDiffsFileByFile, + mrReviews, }); }, @@ -103,11 +107,11 @@ export default { }, [types.TOGGLE_LINE_HAS_FORM](state, { lineCode, fileHash, hasForm }) { - const diffFile = state.diffFiles.find(f => f.file_hash === fileHash); + const diffFile = state.diffFiles.find((f) => f.file_hash === fileHash); if (!diffFile) return; - diffFile[INLINE_DIFF_LINES_KEY].find(l => l.line_code === lineCode).hasForm = hasForm; + diffFile[INLINE_DIFF_LINES_KEY].find((l) => l.line_code === lineCode).hasForm = hasForm; }, [types.ADD_CONTEXT_LINES](state, options) { @@ -123,7 +127,7 @@ export default { bottom, isExpandDown, nextLineNumbers, - ).map(line => { + ).map((line) => { const lineCode = line.type === 'match' ? `${fileHash}_${line.meta_data.old_pos}_${line.meta_data.new_pos}_match` @@ -147,8 +151,8 @@ export default { [types.ADD_COLLAPSED_DIFFS](state, { file, data }) { const files = prepareDiffData({ diff: data }); - const [newFileData] = files.filter(f => f.file_hash === file.file_hash); - const selectedFile = state.diffFiles.find(f => f.file_hash === file.file_hash); + const [newFileData] = files.filter((f) => f.file_hash === file.file_hash); + const selectedFile = state.diffFiles.find((f) => f.file_hash === file.file_hash); Object.assign(selectedFile, { ...newFileData }); }, @@ -157,9 +161,9 @@ export default { const discussionLineCodes = [discussion.line_code, ...(discussion.line_codes || [])]; const fileHash = discussion.diff_file.file_hash; - const lineCheck = line => + const lineCheck = (line) => discussionLineCodes.some( - discussionLineCode => + (discussionLineCode) => line.line_code === discussionLineCode && isDiscussionApplicableToLine({ discussion, @@ -177,26 +181,26 @@ export default { : [], }); - const setDiscussionsExpanded = line => { + const setDiscussionsExpanded = (line) => { const isLineNoteTargeted = line.discussions && line.discussions.some( - disc => disc.notes && disc.notes.find(note => hash === `note_${note.id}`), + (disc) => disc.notes && disc.notes.find((note) => hash === `note_${note.id}`), ); return { ...line, discussionsExpanded: line.discussions && line.discussions.length - ? line.discussions.some(disc => !disc.resolved) || isLineNoteTargeted + ? line.discussions.some((disc) => !disc.resolved) || isLineNoteTargeted : false, }; }; - state.diffFiles.forEach(file => { + state.diffFiles.forEach((file) => { if (file.file_hash === fileHash) { if (file[INLINE_DIFF_LINES_KEY].length) { - file[INLINE_DIFF_LINES_KEY].forEach(line => { + file[INLINE_DIFF_LINES_KEY].forEach((line) => { Object.assign( line, setDiscussionsExpanded(lineCheck(line) ? mapDiscussions(line) : line), @@ -206,7 +210,7 @@ export default { if (!file[INLINE_DIFF_LINES_KEY].length) { const newDiscussions = (file.discussions || []) - .filter(d => d.id !== discussion.id) + .filter((d) => d.id !== discussion.id) .concat(discussion); Object.assign(file, { @@ -218,26 +222,26 @@ export default { }, [types.REMOVE_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash, lineCode }) { - const selectedFile = state.diffFiles.find(f => f.file_hash === fileHash); + const selectedFile = state.diffFiles.find((f) => f.file_hash === fileHash); if (selectedFile) { - updateLineInFile(selectedFile, lineCode, line => + updateLineInFile(selectedFile, lineCode, (line) => Object.assign(line, { - discussions: line.discussions.filter(discussion => discussion.notes.length), + discussions: line.discussions.filter((discussion) => discussion.notes.length), }), ); if (selectedFile.discussions && selectedFile.discussions.length) { selectedFile.discussions = selectedFile.discussions.filter( - discussion => discussion.notes.length, + (discussion) => discussion.notes.length, ); } } }, [types.TOGGLE_LINE_DISCUSSIONS](state, { fileHash, lineCode, expanded }) { - const selectedFile = state.diffFiles.find(f => f.file_hash === fileHash); + const selectedFile = state.diffFiles.find((f) => f.file_hash === fileHash); - updateLineInFile(selectedFile, lineCode, line => { + updateLineInFile(selectedFile, lineCode, (line) => { Object.assign(line, { discussionsExpanded: expanded }); }); }, @@ -260,7 +264,7 @@ export default { [types.UPDATE_DIFF_FILE_COMMENT_FORM](state, formData) { const { fileHash } = formData; - state.commentForms = state.commentForms.map(form => { + state.commentForms = state.commentForms.map((form) => { if (form.fileHash === fileHash) { return { ...formData, @@ -271,7 +275,7 @@ export default { }); }, [types.CLOSE_DIFF_FILE_COMMENT_FORM](state, fileHash) { - state.commentForms = state.commentForms.filter(form => form.fileHash !== fileHash); + state.commentForms = state.commentForms.filter((form) => form.fileHash !== fileHash); }, [types.SET_HIGHLIGHTED_ROW](state, lineCode) { state.highlightedRow = lineCode; @@ -311,7 +315,7 @@ export default { state, { filePath, collapsed, trigger = DIFF_FILE_AUTOMATIC_COLLAPSE }, ) { - const file = state.diffFiles.find(f => f.file_path === filePath); + const file = state.diffFiles.find((f) => f.file_path === filePath); if (file && file.viewer) { if (trigger === DIFF_FILE_MANUAL_COLLAPSE) { @@ -328,17 +332,17 @@ export default { } }, [types.SET_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, lines }) { - const file = state.diffFiles.find(f => f.file_path === filePath); + const file = state.diffFiles.find((f) => f.file_path === filePath); file[INLINE_DIFF_LINES_KEY] = lines; }, [types.ADD_CURRENT_VIEW_DIFF_FILE_LINES](state, { filePath, line }) { - const file = state.diffFiles.find(f => f.file_path === filePath); + const file = state.diffFiles.find((f) => f.file_path === filePath); file[INLINE_DIFF_LINES_KEY].push(line); }, [types.TOGGLE_DIFF_FILE_RENDERING_MORE](state, filePath) { - const file = state.diffFiles.find(f => f.file_path === filePath); + const file = state.diffFiles.find((f) => f.file_path === filePath); file.renderingLines = !file.renderingLines; }, @@ -353,4 +357,7 @@ export default { [types.SET_FILE_BY_FILE](state, fileByFile) { state.viewDiffsFileByFile = fileByFile; }, + [types.SET_MR_FILE_REVIEWS](state, newReviews) { + state.mrReviews = newReviews; + }, }; diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index 1839df12c96..c52da558be2 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -15,13 +15,23 @@ import { INLINE_DIFF_LINES_KEY, SHOW_WHITESPACE, NO_SHOW_WHITESPACE, + CONFLICT_OUR, + CONFLICT_THEIR, + CONFLICT_MARKER, + CONFLICT_MARKER_OUR, + CONFLICT_MARKER_THEIR, } from '../constants'; import { prepareRawDiffFile } from '../utils/diff_file'; -export const isAdded = line => ['new', 'new-nonewline'].includes(line.type); -export const isRemoved = line => ['old', 'old-nonewline'].includes(line.type); -export const isUnchanged = line => !line.type; -export const isMeta = line => ['match', 'new-nonewline', 'old-nonewline'].includes(line.type); +export const isAdded = (line) => ['new', 'new-nonewline'].includes(line.type); +export const isRemoved = (line) => ['old', 'old-nonewline'].includes(line.type); +export const isUnchanged = (line) => !line.type; +export const isMeta = (line) => ['match', 'new-nonewline', 'old-nonewline'].includes(line.type); +export const isConflictMarker = (line) => + [CONFLICT_MARKER_OUR, CONFLICT_MARKER_THEIR].includes(line.type); +export const isConflictSeperator = (line) => line.type === CONFLICT_MARKER; +export const isConflictOur = (line) => line.type === CONFLICT_OUR; +export const isConflictTheir = (line) => line.type === CONFLICT_THEIR; /** * Pass in the inline diff lines array which gets converted @@ -42,12 +52,22 @@ export const isMeta = line => ['match', 'new-nonewline', 'old-nonewline'].includ export const parallelizeDiffLines = (diffLines, inline) => { let freeRightIndex = null; + let conflictStartIndex = -1; const lines = []; + // `chunk` is used for dragging to select diff lines + // we are restricting commenting to only lines that appear between + // "expansion rows". Here equal chunks are lines grouped together + // inbetween expansion rows. + let chunk = 0; + for (let i = 0, diffLinesLength = diffLines.length, index = 0; i < diffLinesLength; i += 1) { const line = diffLines[i]; + line.chunk = chunk; + + if (isMeta(line)) chunk += 1; - if (isRemoved(line) || inline) { + if (isRemoved(line) || isConflictOur(line) || inline) { lines.push({ [LINE_POSITION_LEFT]: line, [LINE_POSITION_RIGHT]: null, @@ -58,7 +78,7 @@ export const parallelizeDiffLines = (diffLines, inline) => { freeRightIndex = index; } index += 1; - } else if (isAdded(line)) { + } else if (isAdded(line) || isConflictTheir(line)) { if (freeRightIndex !== null) { // If an old line came before this without a line on the right, this // line can be put to the right of it. @@ -77,15 +97,28 @@ export const parallelizeDiffLines = (diffLines, inline) => { freeRightIndex = null; index += 1; } - } else if (isMeta(line) || isUnchanged(line)) { - // line in the right panel is the same as in the left one - lines.push({ - [LINE_POSITION_LEFT]: line, - [LINE_POSITION_RIGHT]: line, - }); + } else if ( + isMeta(line) || + isUnchanged(line) || + isConflictMarker(line) || + (isConflictSeperator(line) && inline) + ) { + if (conflictStartIndex <= 0) { + // line in the right panel is the same as in the left one + lines.push({ + [LINE_POSITION_LEFT]: line, + [LINE_POSITION_RIGHT]: !inline && line, + }); - freeRightIndex = null; - index += 1; + if (!inline && isConflictMarker(line)) { + conflictStartIndex = index; + } + freeRightIndex = null; + index += 1; + } else { + lines[conflictStartIndex][LINE_POSITION_RIGHT] = line; + conflictStartIndex = -1; + } } } @@ -93,10 +126,10 @@ export const parallelizeDiffLines = (diffLines, inline) => { }; export function findDiffFile(files, match, matchKey = 'file_hash') { - return files.find(file => file[matchKey] === match); + return files.find((file) => file[matchKey] === match); } -export const getReversePosition = linePosition => { +export const getReversePosition = (linePosition) => { if (linePosition === LINE_POSITION_RIGHT) { return LINE_POSITION_LEFT; } @@ -173,7 +206,7 @@ export const findIndexInInlineLines = (lines, lineNumbers) => { const { oldLineNumber, newLineNumber } = lineNumbers; return lines.findIndex( - line => line.old_line === oldLineNumber && line.new_line === newLineNumber, + (line) => line.old_line === oldLineNumber && line.new_line === newLineNumber, ); }; @@ -346,7 +379,7 @@ export function prepareLineForRenamedFile({ line, diffFile, index = 0 }) { function prepareDiffFileLines(file) { const inlineLines = file[INLINE_DIFF_LINES_KEY]; - inlineLines.forEach(line => prepareLine(line, file)); // WARNING: In-Place Mutations! + inlineLines.forEach((line) => prepareLine(line, file)); // WARNING: In-Place Mutations! Object.assign(file, { inlineLinesCount: inlineLines.length, @@ -400,7 +433,7 @@ export function getDiffPositionByLineCode(diffFiles) { let lines = []; lines = diffFiles.reduce((acc, diffFile) => { - diffFile[INLINE_DIFF_LINES_KEY].forEach(line => { + diffFile[INLINE_DIFF_LINES_KEY].forEach((line) => { acc.push({ file: diffFile, line }); }); @@ -447,21 +480,21 @@ export function isDiscussionApplicableToLine({ discussion, diffPosition, latestD ...(discussion.positions || []), ]; - const removeLineRange = position => { + const removeLineRange = (position) => { const { line_range: pNotUsed, ...positionNoLineRange } = position; return positionNoLineRange; }; return discussionPositions .map(removeLineRange) - .some(position => isEqual(position, diffPositionCopy)); + .some((position) => isEqual(position, diffPositionCopy)); } // eslint-disable-next-line return latestDiff && discussion.active && line_code === discussion.line_code; } -export const getLowestSingleFolder = folder => { +export const getLowestSingleFolder = (folder) => { const getFolder = (blob, start = []) => blob.tree.reduce( (acc, file) => { @@ -493,8 +526,8 @@ export const getLowestSingleFolder = folder => { }; }; -export const flattenTree = tree => { - const flatten = blobTree => +export const flattenTree = (tree) => { + const flatten = (blobTree) => blobTree.reduce((acc, file) => { const blob = file; let treeToFlatten = blob.tree; @@ -516,7 +549,7 @@ export const flattenTree = tree => { return flatten(tree); }; -export const generateTreeList = files => { +export const generateTreeList = (files) => { const { treeEntries, tree } = files.reduce( (acc, file) => { const split = file.new_path.split('/'); @@ -566,8 +599,8 @@ export const generateTreeList = files => { return { treeEntries, tree: flattenTree(tree) }; }; -export const getDiffMode = diffFile => { - const diffModeKey = Object.keys(diffModes).find(key => diffFile[`${key}_file`]); +export const getDiffMode = (diffFile) => { + const diffModeKey = Object.keys(diffModes).find((key) => diffFile[`${key}_file`]); return ( diffModes[diffModeKey] || (diffFile.viewer && @@ -615,11 +648,11 @@ export const convertExpandLines = ({ return lines; }; -export const idleCallback = cb => requestIdleCallback(cb); +export const idleCallback = (cb) => requestIdleCallback(cb); function getLinesFromFileByLineCode(file, lineCode) { const inlineLines = file[INLINE_DIFF_LINES_KEY]; - const matchesCode = line => line.line_code === lineCode; + const matchesCode = (line) => line.line_code === lineCode; return inlineLines.filter(matchesCode); } @@ -628,15 +661,15 @@ export const updateLineInFile = (selectedFile, lineCode, updateFn) => { getLinesFromFileByLineCode(selectedFile, lineCode).forEach(updateFn); }; -export const allDiscussionWrappersExpanded = diff => { +export const allDiscussionWrappersExpanded = (diff) => { let discussionsExpanded = true; - const changeExpandedResult = line => { + const changeExpandedResult = (line) => { if (line && line.discussions.length) { discussionsExpanded = discussionsExpanded && line.discussionsExpanded; } }; - diff[INLINE_DIFF_LINES_KEY].forEach(line => { + diff[INLINE_DIFF_LINES_KEY].forEach((line) => { changeExpandedResult(line); }); |