2018-11-08 19:23:39 +05:30
|
|
|
import Vue from 'vue';
|
|
|
|
import axios from '~/lib/utils/axios_utils';
|
|
|
|
import Cookies from 'js-cookie';
|
2018-12-05 23:21:45 +05:30
|
|
|
import createFlash from '~/flash';
|
|
|
|
import { s__ } from '~/locale';
|
2019-02-15 15:39:39 +05:30
|
|
|
import { handleLocationHash, historyPushState, scrollToElement } from '~/lib/utils/common_utils';
|
2018-11-20 20:47:30 +05:30
|
|
|
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
|
2019-03-02 22:35:43 +05:30
|
|
|
import TreeWorker from '../workers/tree_worker';
|
2019-02-15 15:39:39 +05:30
|
|
|
import eventHub from '../../notes/event_hub';
|
2018-12-05 23:21:45 +05:30
|
|
|
import { getDiffPositionByLineCode, getNoteFormData } from './utils';
|
2018-11-08 19:23:39 +05:30
|
|
|
import * as types from './mutation_types';
|
|
|
|
import {
|
|
|
|
PARALLEL_DIFF_VIEW_TYPE,
|
|
|
|
INLINE_DIFF_VIEW_TYPE,
|
|
|
|
DIFF_VIEW_COOKIE_NAME,
|
2018-12-05 23:21:45 +05:30
|
|
|
MR_TREE_SHOW_KEY,
|
2019-03-02 22:35:43 +05:30
|
|
|
TREE_LIST_STORAGE_KEY,
|
|
|
|
WHITESPACE_STORAGE_KEY,
|
2018-11-08 19:23:39 +05:30
|
|
|
} from '../constants';
|
|
|
|
|
|
|
|
export const setBaseConfig = ({ commit }, options) => {
|
|
|
|
const { endpoint, projectPath } = options;
|
|
|
|
commit(types.SET_BASE_CONFIG, { endpoint, projectPath });
|
|
|
|
};
|
|
|
|
|
|
|
|
export const fetchDiffFiles = ({ state, commit }) => {
|
2019-03-02 22:35:43 +05:30
|
|
|
const worker = new TreeWorker();
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
commit(types.SET_LOADING, true);
|
|
|
|
|
2019-03-02 22:35:43 +05:30
|
|
|
worker.addEventListener('message', ({ data }) => {
|
|
|
|
commit(types.SET_TREE_DATA, data);
|
|
|
|
|
|
|
|
worker.terminate();
|
|
|
|
});
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
return axios
|
2019-03-02 22:35:43 +05:30
|
|
|
.get(state.endpoint, { params: { w: state.showWhitespace ? null : '1' } })
|
2018-11-08 19:23:39 +05:30
|
|
|
.then(res => {
|
|
|
|
commit(types.SET_LOADING, false);
|
|
|
|
commit(types.SET_MERGE_REQUEST_DIFFS, res.data.merge_request_diffs || []);
|
|
|
|
commit(types.SET_DIFF_DATA, res.data);
|
2019-03-02 22:35:43 +05:30
|
|
|
|
|
|
|
worker.postMessage(state.diffFiles);
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
return Vue.nextTick();
|
|
|
|
})
|
2019-03-02 22:35:43 +05:30
|
|
|
.then(handleLocationHash)
|
|
|
|
.catch(() => worker.terminate());
|
2018-11-08 19:23:39 +05:30
|
|
|
};
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
export const setHighlightedRow = ({ commit }, lineCode) => {
|
|
|
|
commit(types.SET_HIGHLIGHTED_ROW, lineCode);
|
|
|
|
};
|
|
|
|
|
2018-11-20 20:47:30 +05:30
|
|
|
// This is adding line discussions to the actual lines in the diff tree
|
|
|
|
// once for parallel and once for inline mode
|
2018-12-13 13:39:08 +05:30
|
|
|
export const assignDiscussionsToDiff = (
|
|
|
|
{ commit, state, rootState },
|
|
|
|
discussions = rootState.notes.discussions,
|
|
|
|
) => {
|
2018-11-20 20:47:30 +05:30
|
|
|
const diffPositionByLineCode = getDiffPositionByLineCode(state.diffFiles);
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
discussions
|
|
|
|
.filter(discussion => discussion.diff_discussion)
|
|
|
|
.forEach(discussion => {
|
|
|
|
commit(types.SET_LINE_DISCUSSIONS_FOR_FILE, {
|
|
|
|
discussion,
|
|
|
|
diffPositionByLineCode,
|
|
|
|
});
|
2018-12-13 13:39:08 +05:30
|
|
|
});
|
2019-02-15 15:39:39 +05:30
|
|
|
|
|
|
|
Vue.nextTick(() => {
|
|
|
|
eventHub.$emit('scrollToDiscussion');
|
2018-11-20 20:47:30 +05:30
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
export const removeDiscussionsFromDiff = ({ commit }, removeDiscussion) => {
|
2019-02-15 15:39:39 +05:30
|
|
|
const { file_hash, line_code, id } = removeDiscussion;
|
|
|
|
commit(types.REMOVE_LINE_DISCUSSIONS_FOR_FILE, { fileHash: file_hash, lineCode: line_code, id });
|
|
|
|
};
|
|
|
|
|
|
|
|
export const renderFileForDiscussionId = ({ commit, rootState, state }, discussionId) => {
|
|
|
|
const discussion = rootState.notes.discussions.find(d => d.id === discussionId);
|
|
|
|
|
|
|
|
if (discussion) {
|
|
|
|
const file = state.diffFiles.find(f => f.file_hash === discussion.diff_file.file_hash);
|
|
|
|
|
|
|
|
if (file) {
|
|
|
|
if (!file.renderIt) {
|
|
|
|
commit(types.RENDER_FILE, file);
|
|
|
|
}
|
|
|
|
|
2019-05-30 16:15:17 +05:30
|
|
|
if (file.collapsed) {
|
2019-02-15 15:39:39 +05:30
|
|
|
eventHub.$emit(`loadCollapsedDiff/${file.file_hash}`);
|
|
|
|
scrollToElement(document.getElementById(file.file_hash));
|
|
|
|
} else {
|
|
|
|
eventHub.$emit('scrollToDiscussion');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-20 20:47:30 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
export const startRenderDiffsQueue = ({ state, commit }) => {
|
|
|
|
const checkItem = () =>
|
|
|
|
new Promise(resolve => {
|
|
|
|
const nextFile = state.diffFiles.find(
|
2019-05-30 16:15:17 +05:30
|
|
|
file => !file.renderIt && (!file.collapsed || !file.text),
|
2018-11-20 20:47:30 +05:30
|
|
|
);
|
|
|
|
|
|
|
|
if (nextFile) {
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
commit(types.RENDER_FILE, nextFile);
|
|
|
|
});
|
|
|
|
requestIdleCallback(
|
|
|
|
() => {
|
|
|
|
checkItem()
|
|
|
|
.then(resolve)
|
|
|
|
.catch(() => {});
|
|
|
|
},
|
|
|
|
{ timeout: 1000 },
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return checkItem();
|
|
|
|
};
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
export const setInlineDiffViewType = ({ commit }) => {
|
|
|
|
commit(types.SET_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE);
|
|
|
|
|
|
|
|
Cookies.set(DIFF_VIEW_COOKIE_NAME, INLINE_DIFF_VIEW_TYPE);
|
|
|
|
const url = mergeUrlParams({ view: INLINE_DIFF_VIEW_TYPE }, window.location.href);
|
|
|
|
historyPushState(url);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const setParallelDiffViewType = ({ commit }) => {
|
|
|
|
commit(types.SET_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE);
|
|
|
|
|
|
|
|
Cookies.set(DIFF_VIEW_COOKIE_NAME, PARALLEL_DIFF_VIEW_TYPE);
|
|
|
|
const url = mergeUrlParams({ view: PARALLEL_DIFF_VIEW_TYPE }, window.location.href);
|
|
|
|
historyPushState(url);
|
|
|
|
};
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
export const showCommentForm = ({ commit }, { lineCode, fileHash }) => {
|
|
|
|
commit(types.TOGGLE_LINE_HAS_FORM, { lineCode, fileHash, hasForm: true });
|
2018-11-08 19:23:39 +05:30
|
|
|
};
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
export const cancelCommentForm = ({ commit }, { lineCode, fileHash }) => {
|
|
|
|
commit(types.TOGGLE_LINE_HAS_FORM, { lineCode, fileHash, hasForm: false });
|
2018-11-08 19:23:39 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
export const loadMoreLines = ({ commit }, options) => {
|
|
|
|
const { endpoint, params, lineNumbers, fileHash } = options;
|
|
|
|
|
|
|
|
params.from_merge_request = true;
|
|
|
|
|
|
|
|
return axios.get(endpoint, { params }).then(res => {
|
|
|
|
const contextLines = res.data || [];
|
|
|
|
|
|
|
|
commit(types.ADD_CONTEXT_LINES, {
|
|
|
|
lineNumbers,
|
|
|
|
contextLines,
|
|
|
|
params,
|
|
|
|
fileHash,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-11-20 20:47:30 +05:30
|
|
|
export const scrollToLineIfNeededInline = (_, line) => {
|
|
|
|
const hash = getLocationHash();
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
if (hash && line.line_code === hash) {
|
2018-11-20 20:47:30 +05:30
|
|
|
handleLocationHash();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export const scrollToLineIfNeededParallel = (_, line) => {
|
|
|
|
const hash = getLocationHash();
|
|
|
|
|
|
|
|
if (
|
|
|
|
hash &&
|
2019-02-15 15:39:39 +05:30
|
|
|
((line.left && line.left.line_code === hash) || (line.right && line.right.line_code === hash))
|
2018-11-20 20:47:30 +05:30
|
|
|
) {
|
|
|
|
handleLocationHash();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
export const loadCollapsedDiff = ({ commit, getters }, file) =>
|
|
|
|
axios
|
|
|
|
.get(file.load_collapsed_diff_url, {
|
|
|
|
params: {
|
|
|
|
commit_id: getters.commitId,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then(res => {
|
|
|
|
commit(types.ADD_COLLAPSED_DIFFS, {
|
|
|
|
file,
|
|
|
|
data: res.data,
|
|
|
|
});
|
2018-11-08 19:23:39 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
export const expandAllFiles = ({ commit }) => {
|
|
|
|
commit(types.EXPAND_ALL_FILES);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggles the file discussions after user clicked on the toggle discussions button.
|
|
|
|
*
|
|
|
|
* Gets the discussions for the provided diff.
|
|
|
|
*
|
|
|
|
* If all discussions are expanded, it will collapse all of them
|
|
|
|
* If all discussions are collapsed, it will expand all of them
|
|
|
|
* If some discussions are open and others closed, it will expand the closed ones.
|
|
|
|
*
|
|
|
|
* @param {Object} diff
|
|
|
|
*/
|
|
|
|
export const toggleFileDiscussions = ({ getters, dispatch }, diff) => {
|
|
|
|
const discussions = getters.getDiffFileDiscussions(diff);
|
|
|
|
const shouldCloseAll = getters.diffHasAllExpandedDiscussions(diff);
|
2019-02-15 15:39:39 +05:30
|
|
|
const shouldExpandAll = getters.diffHasAllCollapsedDiscussions(diff);
|
2018-11-08 19:23:39 +05:30
|
|
|
|
|
|
|
discussions.forEach(discussion => {
|
|
|
|
const data = { discussionId: discussion.id };
|
|
|
|
|
|
|
|
if (shouldCloseAll) {
|
|
|
|
dispatch('collapseDiscussion', data, { root: true });
|
|
|
|
} else if (shouldExpandAll || (!shouldCloseAll && !shouldExpandAll && !discussion.expanded)) {
|
|
|
|
dispatch('expandDiscussion', data, { root: true });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
export const saveDiffDiscussion = ({ state, dispatch }, { note, formData }) => {
|
2018-12-05 23:21:45 +05:30
|
|
|
const postData = getNoteFormData({
|
2019-02-15 15:39:39 +05:30
|
|
|
commit: state.commit,
|
2018-12-05 23:21:45 +05:30
|
|
|
note,
|
|
|
|
...formData,
|
|
|
|
});
|
|
|
|
|
|
|
|
return dispatch('saveNote', postData, { root: true })
|
|
|
|
.then(result => dispatch('updateDiscussion', result.discussion, { root: true }))
|
2018-12-13 13:39:08 +05:30
|
|
|
.then(discussion => dispatch('assignDiscussionsToDiff', [discussion]))
|
2019-02-15 15:39:39 +05:30
|
|
|
.then(() => dispatch('updateResolvableDiscussonsCounts', null, { root: true }))
|
|
|
|
.then(() => dispatch('closeDiffFileCommentForm', formData.diffFile.file_hash))
|
2018-12-05 23:21:45 +05:30
|
|
|
.catch(() => createFlash(s__('MergeRequests|Saving the comment failed')));
|
|
|
|
};
|
|
|
|
|
|
|
|
export const toggleTreeOpen = ({ commit }, path) => {
|
|
|
|
commit(types.TOGGLE_FOLDER_OPEN, path);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const scrollToFile = ({ state, commit }, path) => {
|
|
|
|
const { fileHash } = state.treeEntries[path];
|
|
|
|
document.location.hash = fileHash;
|
|
|
|
|
|
|
|
commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
|
2019-05-30 16:15:17 +05:30
|
|
|
|
|
|
|
setTimeout(() => commit(types.UPDATE_CURRENT_DIFF_FILE_ID, ''), 1000);
|
2018-12-05 23:21:45 +05:30
|
|
|
};
|
|
|
|
|
2019-05-30 16:15:17 +05:30
|
|
|
export const toggleShowTreeList = ({ commit, state }) => {
|
2018-12-05 23:21:45 +05:30
|
|
|
commit(types.TOGGLE_SHOW_TREE_LIST);
|
2019-05-30 16:15:17 +05:30
|
|
|
localStorage.setItem(MR_TREE_SHOW_KEY, state.showTreeList);
|
2018-12-05 23:21:45 +05:30
|
|
|
};
|
|
|
|
|
2018-12-13 13:39:08 +05:30
|
|
|
export const openDiffFileCommentForm = ({ commit, getters }, formData) => {
|
|
|
|
const form = getters.getCommentFormForDiffFile(formData.fileHash);
|
|
|
|
|
|
|
|
if (form) {
|
|
|
|
commit(types.UPDATE_DIFF_FILE_COMMENT_FORM, formData);
|
|
|
|
} else {
|
|
|
|
commit(types.OPEN_DIFF_FILE_COMMENT_FORM, formData);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export const closeDiffFileCommentForm = ({ commit }, fileHash) => {
|
|
|
|
commit(types.CLOSE_DIFF_FILE_COMMENT_FORM, fileHash);
|
|
|
|
};
|
|
|
|
|
2019-03-02 22:35:43 +05:30
|
|
|
export const setRenderTreeList = ({ commit }, renderTreeList) => {
|
|
|
|
commit(types.SET_RENDER_TREE_LIST, renderTreeList);
|
|
|
|
|
|
|
|
localStorage.setItem(TREE_LIST_STORAGE_KEY, renderTreeList);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const setShowWhitespace = ({ commit }, { showWhitespace, pushState = false }) => {
|
|
|
|
commit(types.SET_SHOW_WHITESPACE, showWhitespace);
|
|
|
|
|
|
|
|
localStorage.setItem(WHITESPACE_STORAGE_KEY, showWhitespace);
|
|
|
|
|
|
|
|
if (pushState) {
|
|
|
|
historyPushState(showWhitespace ? '?w=0' : '?w=1');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export const toggleFileFinder = ({ commit }, visible) => {
|
|
|
|
commit(types.TOGGLE_FILE_FINDER_VISIBLE, visible);
|
|
|
|
};
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
// prevent babel-plugin-rewire from generating an invalid default during karma tests
|
|
|
|
export default () => {};
|