gitlab-org--gitlab-foss/app/assets/javascripts/ide/stores/actions/merge_request.js

240 lines
7.6 KiB
JavaScript

import createFlash from '~/flash';
import { __ } from '~/locale';
import { leftSidebarViews, PERMISSION_READ_MR, MAX_MR_FILES_AUTO_OPEN } from '../../constants';
import service from '../../services';
import * as types from '../mutation_types';
export const getMergeRequestsForBranch = (
{ commit, state, getters },
{ projectId, branchId } = {},
) => {
if (!getters.findProjectPermissions(projectId)[PERMISSION_READ_MR]) {
return Promise.resolve();
}
return service
.getProjectMergeRequests(`${projectId}`, {
source_branch: branchId,
source_project_id: state.projects[projectId].id,
state: 'opened',
order_by: 'created_at',
per_page: 1,
})
.then(({ data }) => {
if (data.length > 0) {
const currentMR = data[0];
commit(types.SET_MERGE_REQUEST, {
projectPath: projectId,
mergeRequestId: currentMR.iid,
mergeRequest: currentMR,
});
commit(types.SET_CURRENT_MERGE_REQUEST, `${currentMR.iid}`);
}
})
.catch((e) => {
createFlash({
message: __(`Error fetching merge requests for ${branchId}`),
fadeTransition: false,
addBodyClass: true,
});
throw e;
});
};
export const getMergeRequestData = (
{ commit, dispatch, state },
{ projectId, mergeRequestId, targetProjectId = null, force = false } = {},
) =>
new Promise((resolve, reject) => {
if (!state.projects[projectId].mergeRequests[mergeRequestId] || force) {
service
.getProjectMergeRequestData(targetProjectId || projectId, mergeRequestId)
.then(({ data }) => {
commit(types.SET_MERGE_REQUEST, {
projectPath: projectId,
mergeRequestId,
mergeRequest: data,
});
commit(types.SET_CURRENT_MERGE_REQUEST, mergeRequestId);
resolve(data);
})
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request.'),
action: (payload) =>
dispatch('getMergeRequestData', payload).then(() =>
dispatch('setErrorMessage', null),
),
actionText: __('Please try again'),
actionPayload: { projectId, mergeRequestId, force },
});
reject(new Error(`Merge request not loaded ${projectId}`));
});
} else {
resolve(state.projects[projectId].mergeRequests[mergeRequestId]);
}
});
export const getMergeRequestChanges = (
{ commit, dispatch, state },
{ projectId, mergeRequestId, targetProjectId = null, force = false } = {},
) =>
new Promise((resolve, reject) => {
if (!state.projects[projectId].mergeRequests[mergeRequestId].changes.length || force) {
service
.getProjectMergeRequestChanges(targetProjectId || projectId, mergeRequestId)
.then(({ data }) => {
commit(types.SET_MERGE_REQUEST_CHANGES, {
projectPath: projectId,
mergeRequestId,
changes: data,
});
resolve(data);
})
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request changes.'),
action: (payload) =>
dispatch('getMergeRequestChanges', payload).then(() =>
dispatch('setErrorMessage', null),
),
actionText: __('Please try again'),
actionPayload: { projectId, mergeRequestId, force },
});
reject(new Error(`Merge request changes not loaded ${projectId}`));
});
} else {
resolve(state.projects[projectId].mergeRequests[mergeRequestId].changes);
}
});
export const getMergeRequestVersions = (
{ commit, dispatch, state },
{ projectId, mergeRequestId, targetProjectId = null, force = false } = {},
) =>
new Promise((resolve, reject) => {
if (!state.projects[projectId].mergeRequests[mergeRequestId].versions.length || force) {
service
.getProjectMergeRequestVersions(targetProjectId || projectId, mergeRequestId)
.then((res) => res.data)
.then((data) => {
commit(types.SET_MERGE_REQUEST_VERSIONS, {
projectPath: projectId,
mergeRequestId,
versions: data,
});
resolve(data);
})
.catch(() => {
dispatch('setErrorMessage', {
text: __('An error occurred while loading the merge request version data.'),
action: (payload) =>
dispatch('getMergeRequestVersions', payload).then(() =>
dispatch('setErrorMessage', null),
),
actionText: __('Please try again'),
actionPayload: { projectId, mergeRequestId, force },
});
reject(new Error(`Merge request versions not loaded ${projectId}`));
});
} else {
resolve(state.projects[projectId].mergeRequests[mergeRequestId].versions);
}
});
export const openMergeRequestChanges = async ({ dispatch, getters, state, commit }, changes) => {
const entryChanges = changes
.map((change) => ({ entry: state.entries[change.new_path], change }))
.filter((x) => x.entry);
const pathsToOpen = entryChanges
.slice(0, MAX_MR_FILES_AUTO_OPEN)
.map(({ change }) => change.new_path);
// If there are no changes with entries, do nothing.
if (!entryChanges.length) {
return;
}
dispatch('updateActivityBarView', leftSidebarViews.review.name);
entryChanges.forEach(({ change, entry }) => {
commit(types.SET_FILE_MERGE_REQUEST_CHANGE, { file: entry, mrChange: change });
});
// Open paths in order as they appear in MR changes
pathsToOpen.forEach((path) => {
commit(types.TOGGLE_FILE_OPEN, path);
});
// Activate first path.
// We don't `getFileData` here since the editor component kicks that off. Otherwise, we'd fetch twice.
const [firstPath, ...remainingPaths] = pathsToOpen;
await dispatch('router/push', getters.getUrlForPath(firstPath));
await dispatch('setFileActive', firstPath);
// Lastly, eagerly fetch the remaining paths for improved user experience.
await Promise.all(
remainingPaths.map(async (path) => {
try {
await dispatch('getFileData', {
path,
makeFileActive: false,
});
await dispatch('getRawFileData', { path });
} catch (e) {
// If one of the file fetches fails, we dont want to blow up the rest of them.
// eslint-disable-next-line no-console
console.error('[gitlab] An unexpected error occurred fetching MR file data', e);
}
}),
);
};
export const openMergeRequest = async (
{ dispatch, getters },
{ projectId, targetProjectId, mergeRequestId } = {},
) => {
try {
const mr = await dispatch('getMergeRequestData', {
projectId,
targetProjectId,
mergeRequestId,
});
dispatch('setCurrentBranchId', mr.source_branch);
await dispatch('getBranchData', {
projectId,
branchId: mr.source_branch,
});
const branch = getters.findBranch(projectId, mr.source_branch);
await dispatch('getFiles', {
projectId,
branchId: mr.source_branch,
ref: branch.commit.id,
});
await dispatch('getMergeRequestVersions', {
projectId,
targetProjectId,
mergeRequestId,
});
const { changes } = await dispatch('getMergeRequestChanges', {
projectId,
targetProjectId,
mergeRequestId,
});
await dispatch('openMergeRequestChanges', changes);
} catch (e) {
createFlash({ message: __('Error while loading the merge request. Please try again.') });
throw e;
}
};