diff options
Diffstat (limited to 'app/assets/javascripts/import_entities/import_projects/store')
5 files changed, 86 insertions, 45 deletions
diff --git a/app/assets/javascripts/import_entities/import_projects/store/actions.js b/app/assets/javascripts/import_entities/import_projects/store/actions.js index a30c14f9d28..e0db585eb3e 100644 --- a/app/assets/javascripts/import_entities/import_projects/store/actions.js +++ b/app/assets/javascripts/import_entities/import_projects/store/actions.js @@ -1,20 +1,22 @@ import Visibility from 'visibilityjs'; +import _ from 'lodash'; import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; -import httpStatusCodes from '~/lib/utils/http_status'; +import { HTTP_STATUS_TOO_MANY_REQUESTS } from '~/lib/utils/http_status'; import Poll from '~/lib/utils/poll'; import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; import { visitUrl, objectToQuery } from '~/lib/utils/url_utility'; import { s__, sprintf } from '~/locale'; import { isProjectImportable } from '../utils'; +import { PROVIDERS } from '../../constants'; import * as types from './mutation_types'; let eTagPoll; const hasRedirectInError = (e) => e?.response?.data?.error?.redirect; const redirectToUrlInError = (e) => visitUrl(e.response.data.error.redirect); -const tooManyRequests = (e) => e.response.status === httpStatusCodes.TOO_MANY_REQUESTS; +const tooManyRequests = (e) => e.response.status === HTTP_STATUS_TOO_MANY_REQUESTS; const pathWithParams = ({ path, ...params }) => { const filteredParams = Object.fromEntries( Object.entries(params).filter(([, value]) => value !== ''), @@ -22,6 +24,24 @@ const pathWithParams = ({ path, ...params }) => { const queryString = objectToQuery(filteredParams); return queryString ? `${path}?${queryString}` : path; }; +const commitPaginationData = ({ state, commit, data }) => { + const cursorsGitHubResponse = !_.isEmpty(data.pageInfo || {}); + + if (state.provider === PROVIDERS.GITHUB && cursorsGitHubResponse) { + commit(types.SET_PAGE_CURSORS, data.pageInfo); + } else { + const nextPage = state.pageInfo.page + 1; + commit(types.SET_PAGE, nextPage); + } +}; +const paginationParams = ({ state }) => { + if (state.provider === PROVIDERS.GITHUB && state.pageInfo.endCursor) { + return { after: state.pageInfo.endCursor }; + } + + const nextPage = state.pageInfo.page + 1; + return { page: nextPage === 1 ? '' : nextPage.toString() }; +}; const isRequired = () => { // eslint-disable-next-line @gitlab/require-i18n-strings @@ -55,7 +75,6 @@ const importAll = ({ state, dispatch }, config = {}) => { }; const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit }) => { - const nextPage = state.pageInfo.page + 1; commit(types.REQUEST_REPOS); const { provider, filter } = state; @@ -65,12 +84,13 @@ const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit }) pathWithParams({ path: reposPath, filter: filter ?? '', - page: nextPage === 1 ? '' : nextPage.toString(), + ...paginationParams({ state }), }), ) .then(({ data }) => { - commit(types.SET_PAGE, nextPage); - commit(types.RECEIVE_REPOS_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true })); + const camelData = convertObjectPropsToCamelCase(data, { deep: true }); + commitPaginationData({ state, commit, data: camelData }); + commit(types.RECEIVE_REPOS_SUCCESS, camelData); }) .catch((e) => { if (hasRedirectInError(e)) { @@ -139,6 +159,42 @@ const fetchImportFactory = (importPath = isRequired()) => ( }); }; +export const cancelImportFactory = (cancelImportPath) => ({ state, commit }, { repoId }) => { + const existingRepo = state.repositories.find((r) => r.importSource.id === repoId); + + if (!existingRepo?.importedProject) { + throw new Error(`Attempting to cancel project which is not started: ${repoId}`); + } + + const { id } = existingRepo.importedProject; + + return axios + .post(cancelImportPath, { + project_id: id, + }) + .then(() => { + commit(types.CANCEL_IMPORT_SUCCESS, { + repoId, + }); + }) + .catch((e) => { + const serverErrorMessage = e?.response?.data?.errors; + const flashMessage = serverErrorMessage + ? sprintf( + s__('ImportProjects|Cancelling project import failed: %{reason}'), + { + reason: serverErrorMessage, + }, + false, + ) + : s__('ImportProjects|Cancelling project import failed'); + + createAlert({ + message: flashMessage, + }); + }); +}; + export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, dispatch }) => { if (eTagPoll) { stopJobsPolling(); @@ -176,22 +232,6 @@ export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, d }); }; -const fetchNamespacesFactory = (namespacesPath = isRequired()) => ({ commit }) => { - commit(types.REQUEST_NAMESPACES); - axios - .get(namespacesPath) - .then(({ data }) => - commit(types.RECEIVE_NAMESPACES_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true })), - ) - .catch(() => { - createAlert({ - message: s__('ImportProjects|Requesting namespaces failed'), - }); - - commit(types.RECEIVE_NAMESPACES_ERROR); - }); -}; - const setFilter = ({ commit, dispatch }, filter) => { commit(types.SET_FILTER, filter); @@ -207,6 +247,6 @@ export default ({ endpoints = isRequired() }) => ({ importAll, fetchRepos: fetchReposFactory({ reposPath: endpoints.reposPath }), fetchImport: fetchImportFactory(endpoints.importPath), + cancelImport: cancelImportFactory(endpoints.cancelPath), fetchJobs: fetchJobsFactory(endpoints.jobsPath), - fetchNamespaces: fetchNamespacesFactory(endpoints.namespacesPath), }); diff --git a/app/assets/javascripts/import_entities/import_projects/store/getters.js b/app/assets/javascripts/import_entities/import_projects/store/getters.js index ef01a67ec94..31ddffd4eb4 100644 --- a/app/assets/javascripts/import_entities/import_projects/store/getters.js +++ b/app/assets/javascripts/import_entities/import_projects/store/getters.js @@ -1,7 +1,5 @@ import { isProjectImportable, isIncompatible, isImporting } from '../utils'; -export const isLoading = (state) => state.isLoadingRepos || state.isLoadingNamespaces; - export const importingRepoCount = (state) => state.repositories.filter(isImporting).length; export const isImportingAnyRepo = (state) => state.repositories.some(isImporting); diff --git a/app/assets/javascripts/import_entities/import_projects/store/mutation_types.js b/app/assets/javascripts/import_entities/import_projects/store/mutation_types.js index 6adf5e59cff..74832a03ac1 100644 --- a/app/assets/javascripts/import_entities/import_projects/store/mutation_types.js +++ b/app/assets/javascripts/import_entities/import_projects/store/mutation_types.js @@ -2,14 +2,12 @@ export const REQUEST_REPOS = 'REQUEST_REPOS'; export const RECEIVE_REPOS_SUCCESS = 'RECEIVE_REPOS_SUCCESS'; export const RECEIVE_REPOS_ERROR = 'RECEIVE_REPOS_ERROR'; -export const REQUEST_NAMESPACES = 'REQUEST_NAMESPACES'; -export const RECEIVE_NAMESPACES_SUCCESS = 'RECEIVE_NAMESPACES_SUCCESS'; -export const RECEIVE_NAMESPACES_ERROR = 'RECEIVE_NAMESPACES_ERROR'; - export const REQUEST_IMPORT = 'REQUEST_IMPORT'; export const RECEIVE_IMPORT_SUCCESS = 'RECEIVE_IMPORT_SUCCESS'; export const RECEIVE_IMPORT_ERROR = 'RECEIVE_IMPORT_ERROR'; +export const CANCEL_IMPORT_SUCCESS = 'CANCEL_IMPORT_SUCCESS'; + export const RECEIVE_JOBS_SUCCESS = 'RECEIVE_JOBS_SUCCESS'; export const SET_FILTER = 'SET_FILTER'; @@ -18,4 +16,4 @@ export const SET_IMPORT_TARGET = 'SET_IMPORT_TARGET'; export const SET_PAGE = 'SET_PAGE'; -export const SET_PAGE_INFO = 'SET_PAGE_INFO'; +export const SET_PAGE_CURSORS = 'SET_PAGE_CURSORS'; diff --git a/app/assets/javascripts/import_entities/import_projects/store/mutations.js b/app/assets/javascripts/import_entities/import_projects/store/mutations.js index 163a19976de..8b2e0364d7a 100644 --- a/app/assets/javascripts/import_entities/import_projects/store/mutations.js +++ b/app/assets/javascripts/import_entities/import_projects/store/mutations.js @@ -36,7 +36,12 @@ export default { [types.SET_FILTER](state, filter) { state.filter = filter; state.repositories = []; - state.pageInfo.page = 0; + state.pageInfo = { + page: 0, + startCursor: null, + endCursor: null, + hasNextPage: true, + }; }, [types.REQUEST_REPOS](state) { @@ -51,7 +56,9 @@ export default { // https://gitlab.com/gitlab-org/gitlab/-/issues/27370#note_379034091 const newImportedProjects = processLegacyEntries({ - newRepositories: repositories.importedProjects, + newRepositories: repositories.importedProjects.filter( + (p) => p.importStatus !== STATUSES.CANCELED, + ), existingRepositories: state.repositories, factory: makeNewImportedProject, }); @@ -122,17 +129,9 @@ export default { }); }, - [types.REQUEST_NAMESPACES](state) { - state.isLoadingNamespaces = true; - }, - - [types.RECEIVE_NAMESPACES_SUCCESS](state, namespaces) { - state.isLoadingNamespaces = false; - state.namespaces = namespaces; - }, - - [types.RECEIVE_NAMESPACES_ERROR](state) { - state.isLoadingNamespaces = false; + [types.CANCEL_IMPORT_SUCCESS](state, { repoId }) { + const existingRepo = state.repositories.find((r) => r.importSource.id === repoId); + existingRepo.importedProject.importStatus = STATUSES.CANCELED; }, [types.SET_IMPORT_TARGET](state, { repoId, importTarget }) { @@ -151,4 +150,9 @@ export default { [types.SET_PAGE](state, page) { state.pageInfo.page = page; }, + + [types.SET_PAGE_CURSORS](state, pageInfo) { + const { startCursor, endCursor, hasNextPage } = pageInfo; + state.pageInfo = { ...state.pageInfo, startCursor, endCursor, hasNextPage }; + }, }; diff --git a/app/assets/javascripts/import_entities/import_projects/store/state.js b/app/assets/javascripts/import_entities/import_projects/store/state.js index ecd93561d52..c384848f0a0 100644 --- a/app/assets/javascripts/import_entities/import_projects/store/state.js +++ b/app/assets/javascripts/import_entities/import_projects/store/state.js @@ -1,13 +1,14 @@ export default () => ({ provider: '', repositories: [], - namespaces: [], customImportTargets: {}, isLoadingRepos: false, - isLoadingNamespaces: false, ciCdOnly: false, filter: '', pageInfo: { page: 0, + startCursor: null, + endCursor: null, + hasNextPage: true, }, }); |