diff options
-rw-r--r-- | app/assets/javascripts/diffs/store/actions.js | 49 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/getters.js | 10 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/index.js | 17 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/mutation_types.js | 6 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/mutations.js | 112 | ||||
-rw-r--r-- | app/assets/javascripts/diffs/store/utils.js | 83 |
6 files changed, 277 insertions, 0 deletions
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js new file mode 100644 index 00000000000..321967a5479 --- /dev/null +++ b/app/assets/javascripts/diffs/store/actions.js @@ -0,0 +1,49 @@ +import Vue from 'vue'; +import VueResource from 'vue-resource'; +import Cookies from 'js-cookie'; +import { handleLocationHash } from '~/lib/utils/common_utils'; +import * as types from './mutation_types'; +import { + PARALLEL_DIFF_VIEW_TYPE, + INLINE_DIFF_VIEW_TYPE, + DIFF_VIEW_COOKIE_NAME, +} from '../constants'; + +Vue.use(VueResource); + +export const setEndpoint = ({ commit }, endpoint) => { + commit(types.SET_ENDPOINT, endpoint); +}; + +export const setLoadingState = ({ commit }, state) => { + commit(types.SET_LOADING, state); +}; + +export const fetchDiffFiles = ({ state, commit }) => { + commit(types.SET_LOADING, true); + + return Vue.http + .get(state.endpoint) + .then(res => res.json()) + .then(res => { + commit(types.SET_LOADING, false); + commit(types.SET_DIFF_FILES, res.diff_files); + return Vue.nextTick(); + }) + .then(handleLocationHash); +}; + +export const setDiffViewType = ({ commit }, isParallel) => { + const type = isParallel ? PARALLEL_DIFF_VIEW_TYPE : INLINE_DIFF_VIEW_TYPE; + + commit(types.SET_DIFF_VIEW_TYPE, type); + Cookies.set(DIFF_VIEW_COOKIE_NAME, type); +}; + +export const showCommentForm = ({ commit }, params) => { + commit(types.ADD_COMMENT_FORM_LINE, params); +}; + +export const cancelCommentForm = ({ commit }, params) => { + commit(types.REMOVE_COMMENT_FORM_LINE, params); +}; diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js new file mode 100644 index 00000000000..ec4ea070209 --- /dev/null +++ b/app/assets/javascripts/diffs/store/getters.js @@ -0,0 +1,10 @@ +import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '../constants'; + +export default { + isParallelView(state) { + return state.diffViewType === PARALLEL_DIFF_VIEW_TYPE; + }, + isInlineView(state) { + return state.diffViewType === INLINE_DIFF_VIEW_TYPE; + }, +}; diff --git a/app/assets/javascripts/diffs/store/index.js b/app/assets/javascripts/diffs/store/index.js new file mode 100644 index 00000000000..a25851e2f79 --- /dev/null +++ b/app/assets/javascripts/diffs/store/index.js @@ -0,0 +1,17 @@ +import Cookies from 'js-cookie'; +import * as actions from './actions'; +import getters from './getters'; +import mutations from './mutations'; +import { INLINE_DIFF_VIEW_TYPE, DIFF_VIEW_COOKIE_NAME } from '../constants'; + +export default { + state: { + isLoading: true, + endpoint: '', + diffFiles: [], + diffViewType: Cookies.get(DIFF_VIEW_COOKIE_NAME) || INLINE_DIFF_VIEW_TYPE, + }, + getters, + actions, + mutations, +}; diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js new file mode 100644 index 00000000000..cec771fc04e --- /dev/null +++ b/app/assets/javascripts/diffs/store/mutation_types.js @@ -0,0 +1,6 @@ +export const SET_ENDPOINT = 'SET_ENDPOINT'; +export const SET_LOADING = 'SET_LOADING'; +export const SET_DIFF_FILES = 'SET_DIFF_FILES'; +export const SET_DIFF_VIEW_TYPE = 'SET_DIFF_VIEW_TYPE'; +export const ADD_COMMENT_FORM_LINE = 'ADD_COMMENT_FORM_LINE'; +export const REMOVE_COMMENT_FORM_LINE = 'REMOVE_COMMENT_FORM_LINE'; diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js new file mode 100644 index 00000000000..d83a966fed9 --- /dev/null +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -0,0 +1,112 @@ +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import * as utils from './utils'; +import * as types from './mutation_types'; +import * as constants from '../constants'; + +export default { + [types.SET_ENDPOINT](state, endpoint) { + Object.assign(state, { endpoint }); + }, + + [types.SET_LOADING](state, loadingState) { + Object.assign(state, { isLoading: loadingState }); + }, + + [types.SET_DIFF_FILES](state, diffFiles) { + Object.assign(state, { + diffFiles: convertObjectPropsToCamelCase(diffFiles, { + deep: true, + }), + }); + }, + + [types.SET_DIFF_VIEW_TYPE](state, type) { + Object.assign(state, { diffViewType: type }); + }, + + [types.ADD_COMMENT_FORM_LINE](state, { diffLines, lineCode, linePosition }) { + const index = utils.findDiffLineIndex({ + diffLines, + lineCode, + linePosition, + }); + const commentFormType = constants.COMMENT_FORM_TYPE; + + if (!diffLines[index]) { + return; + } + + const item = linePosition + ? diffLines[index][linePosition] + : diffLines[index]; + + if (!item) { + return; + } + + // We add forms as another diff line so they have to have a unique id + // We later use this id to remove the form from diff lines + const id = `${item.lineCode}_CommentForm_${linePosition || ''}`; + const targetIndex = index + 1; + const targetLine = diffLines[targetIndex]; + const atTargetIndex = linePosition ? targetLine[linePosition] : targetLine; + + // We already have comment form for target line + if (atTargetIndex && atTargetIndex.id === id) { + return; + } + + // Unique comment form object as a diff line + const formObj = { + id, + type: commentFormType, + }; + + if (linePosition) { + // linePosition is only valid for Parallel mode + // Create the final lineObj which will represent the forms as a line + // Restore old form in opposite position so we can rerender it + const reversePosition = utils.getReversePosition(linePosition); + const reverseObj = targetLine[reversePosition]; + const lineObj = { + [linePosition]: formObj, + [reversePosition]: + reverseObj.type === commentFormType ? reverseObj : {}, + }; + + // Check if there is any comment form on the target position + // If we have, we should to remove it because above lineObj should be final version + const { left, right } = targetLine; + const hasAlreadyForm = + left.type === commentFormType || right.type === commentFormType; + const spliceCount = hasAlreadyForm ? 1 : 0; + + diffLines.splice(targetIndex, spliceCount, lineObj); + } else { + diffLines.splice(targetIndex, 0, formObj); + } + }, + + [types.REMOVE_COMMENT_FORM_LINE](state, { diffLines, formId, linePosition }) { + const index = utils.findDiffLineIndex({ diffLines, formId, linePosition }); + + if (index > -1) { + if (linePosition) { + const reversePosition = utils.getReversePosition(linePosition); + const line = diffLines[index]; + const reverse = line[reversePosition]; + const shouldRemove = reverse.type !== constants.COMMENT_FORM_TYPE; + + if (shouldRemove) { + diffLines.splice(index, 1); + } else { + Object.assign(line, { + [linePosition]: {}, + }); + } + } else { + diffLines.splice(index, 1); + } + } + }, +}; diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js new file mode 100644 index 00000000000..9aa44cd4fdb --- /dev/null +++ b/app/assets/javascripts/diffs/store/utils.js @@ -0,0 +1,83 @@ +import _ from 'underscore'; +import { + LINE_POSITION_LEFT, + LINE_POSITION_RIGHT, + TEXT_DIFF_POSITION_TYPE, + DIFF_NOTE_TYPE, + NEW_LINE_TYPE, + OLD_LINE_TYPE, +} from '../constants'; + +export const findDiffLineIndex = options => { + const { diffLines, lineCode, linePosition, formId } = options; + + return _.findIndex(diffLines, l => { + const line = linePosition ? l[linePosition] : l; + + if (!line) { + return null; + } + + if (formId) { + return line.id === formId; + } + + return line.lineCode === lineCode; + }); +}; + +export const getReversePosition = linePosition => { + if (linePosition === LINE_POSITION_RIGHT) { + return LINE_POSITION_LEFT; + } + + return LINE_POSITION_RIGHT; +}; + +export const getNoteFormData = params => { + const { + note, + noteableType, + noteableData, + diffFile, + noteTargetLine, + diffViewType, + linePosition, + } = params; + + // TODO: Discuss with @felipe_arthur to remove this JSON.stringify + const position = JSON.stringify({ + base_sha: diffFile.diffRefs.baseSha, + start_sha: diffFile.diffRefs.startSha, + head_sha: diffFile.diffRefs.headSha, + old_path: diffFile.oldPath, + new_path: diffFile.newPath, + position_type: TEXT_DIFF_POSITION_TYPE, + old_line: noteTargetLine.oldLine, + new_line: noteTargetLine.newLine, + }); + + // TODO: @fatihacet - Double check empty strings + const postData = { + view: diffViewType, + line_type: + linePosition === LINE_POSITION_RIGHT ? NEW_LINE_TYPE : OLD_LINE_TYPE, + merge_request_diff_head_sha: diffFile.diffRefs.headSha, + in_reply_to_discussion_id: '', + note_project_id: '', + target_type: noteableType, + target_id: noteableData.id, + 'note[noteable_type]': noteableType, + 'note[noteable_id]': noteableData.id, + 'note[commit_id]': '', + 'note[type]': DIFF_NOTE_TYPE, + 'note[line_code]': noteTargetLine.lineCode, + 'note[note]': note, + 'note[position]': position, + }; + + return { + endpoint: noteableData.create_note_path, + data: postData, + }; +}; |