diff options
Diffstat (limited to 'app/assets/javascripts/import_entities/import_groups/graphql')
4 files changed, 96 insertions, 74 deletions
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js index 8f2d488d661..8110934efc4 100644 --- a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js +++ b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js @@ -1,15 +1,18 @@ -import axios from '~/lib/utils/axios_utils'; +import createFlash from '~/flash'; import createDefaultClient from '~/lib/graphql'; +import axios from '~/lib/utils/axios_utils'; +import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils'; import { s__ } from '~/locale'; -import createFlash from '~/flash'; import { STATUSES } from '../../constants'; import availableNamespacesQuery from './queries/available_namespaces.query.graphql'; import { SourceGroupsManager } from './services/source_groups_manager'; import { StatusPoller } from './services/status_poller'; export const clientTypenames = { + BulkImportSourceGroupConnection: 'ClientBulkImportSourceGroupConnection', BulkImportSourceGroup: 'ClientBulkImportSourceGroup', AvailableNamespace: 'ClientAvailableNamespace', + BulkImportPageInfo: 'ClientBulkImportPageInfo', }; export function createResolvers({ endpoints }) { @@ -17,22 +20,47 @@ export function createResolvers({ endpoints }) { return { Query: { - async bulkImportSourceGroups(_, __, { client }) { + async bulkImportSourceGroups(_, vars, { client }) { const { data: { availableNamespaces }, } = await client.query({ query: availableNamespacesQuery }); - return axios.get(endpoints.status).then(({ data }) => { - return data.importable_data.map((group) => ({ - __typename: clientTypenames.BulkImportSourceGroup, - ...group, - status: STATUSES.NONE, - import_target: { - new_name: group.full_path, - target_namespace: availableNamespaces[0].full_path, + if (!statusPoller) { + statusPoller = new StatusPoller({ + client, + pollPath: endpoints.jobs, + }); + statusPoller.startPolling(); + } + + return axios + .get(endpoints.status, { + params: { + page: vars.page, + per_page: vars.perPage, + filter: vars.filter, }, - })); - }); + }) + .then(({ headers, data }) => { + const pagination = parseIntPagination(normalizeHeaders(headers)); + + return { + __typename: clientTypenames.BulkImportSourceGroupConnection, + nodes: data.importable_data.map((group) => ({ + __typename: clientTypenames.BulkImportSourceGroup, + ...group, + status: STATUSES.NONE, + import_target: { + new_name: group.full_path, + target_namespace: availableNamespaces[0].full_path, + }, + })), + pageInfo: { + __typename: clientTypenames.BulkImportPageInfo, + ...pagination, + }, + }; + }); }, availableNamespaces: () => @@ -63,7 +91,7 @@ export function createResolvers({ endpoints }) { const group = groupManager.findById(sourceGroupId); groupManager.setImportStatus(group, STATUSES.SCHEDULING); try { - await axios.post(endpoints.createBulkImport, { + const response = await axios.post(endpoints.createBulkImport, { bulk_import: [ { source_type: 'group_entity', @@ -74,10 +102,7 @@ export function createResolvers({ endpoints }) { ], }); groupManager.setImportStatus(group, STATUSES.STARTED); - if (!statusPoller) { - statusPoller = new StatusPoller({ client, interval: 3000 }); - statusPoller.startPolling(); - } + SourceGroupsManager.attachImportId(group, response.data.id); } catch (e) { createFlash({ message: s__('BulkImport|Importing the group failed'), diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql index 8d52d94925c..28dfefdf8a7 100644 --- a/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql +++ b/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql @@ -1,7 +1,15 @@ #import "../fragments/bulk_import_source_group_item.fragment.graphql" -query bulkImportSourceGroups { - bulkImportSourceGroups @client { - ...BulkImportSourceGroupItem +query bulkImportSourceGroups($page: Int = 1, $perPage: Int = 20, $filter: String = "") { + bulkImportSourceGroups(page: $page, filter: $filter, perPage: $perPage) @client { + nodes { + ...BulkImportSourceGroupItem + } + pageInfo { + page + perPage + total + totalPages + } } } diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js index 047b04fe7d6..261e30edbbb 100644 --- a/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js +++ b/app/assets/javascripts/import_entities/import_groups/graphql/services/source_groups_manager.js @@ -14,6 +14,12 @@ function generateGroupId(id) { } export class SourceGroupsManager { + static importMap = new Map(); + + static attachImportId(group, importId) { + SourceGroupsManager.importMap.set(importId, group.id); + } + constructor({ client }) { this.client = client; } @@ -36,6 +42,10 @@ export class SourceGroupsManager { this.update(group, fn); } + findByImportId(importId) { + return this.findById(SourceGroupsManager.importMap.get(importId)); + } + setImportStatus(group, status) { this.update(group, (sourceGroup) => { // eslint-disable-next-line no-param-reassign diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js index 41dd25b9150..63cd6b48fc4 100644 --- a/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js +++ b/app/assets/javascripts/import_entities/import_groups/graphql/services/status_poller.js @@ -1,68 +1,47 @@ -import gql from 'graphql-tag'; +import Visibility from 'visibilityjs'; import createFlash from '~/flash'; +import axios from '~/lib/utils/axios_utils'; +import Poll from '~/lib/utils/poll'; import { s__ } from '~/locale'; -import bulkImportSourceGroupsQuery from '../queries/bulk_import_source_groups.query.graphql'; -import { STATUSES } from '../../../constants'; import { SourceGroupsManager } from './source_groups_manager'; -const groupId = (i) => `group${i}`; - -function generateGroupsQuery(groups) { - return gql`{ - ${groups - .map( - (g, idx) => - `${groupId(idx)}: group(fullPath: "${g.import_target.target_namespace}/${ - g.import_target.new_name - }") { id }`, - ) - .join('\n')} - }`; -} - export class StatusPoller { - constructor({ client, interval }) { + constructor({ client, pollPath }) { this.client = client; - this.interval = interval; - this.timeoutId = null; - this.groupManager = new SourceGroupsManager({ client }); - } - startPolling() { - if (this.timeoutId) { - return; - } + this.eTagPoll = new Poll({ + resource: { + fetchJobs: () => axios.get(pollPath), + }, + method: 'fetchJobs', + successCallback: ({ data }) => this.updateImportsStatuses(data), + errorCallback: () => + createFlash({ + message: s__('BulkImport|Update of import statuses with realtime changes failed'), + }), + }); + + Visibility.change(() => { + if (!Visibility.hidden()) { + this.eTagPoll.restart(); + } else { + this.eTagPoll.stop(); + } + }); - this.checkPendingImports(); + this.groupManager = new SourceGroupsManager({ client }); } - stopPolling() { - clearTimeout(this.timeoutId); - this.timeoutId = null; + startPolling() { + this.eTagPoll.makeRequest(); } - async checkPendingImports() { - try { - const { bulkImportSourceGroups } = this.client.readQuery({ - query: bulkImportSourceGroupsQuery, - }); - const groupsInProgress = bulkImportSourceGroups.filter((g) => g.status === STATUSES.STARTED); - if (groupsInProgress.length) { - const { data: results } = await this.client.query({ - query: generateGroupsQuery(groupsInProgress), - fetchPolicy: 'no-cache', - }); - const completedGroups = groupsInProgress.filter((_, idx) => Boolean(results[groupId(idx)])); - completedGroups.forEach((group) => { - this.groupManager.setImportStatus(group, STATUSES.FINISHED); - }); + async updateImportsStatuses(importStatuses) { + importStatuses.forEach(({ id, status_name: statusName }) => { + const group = this.groupManager.findByImportId(id); + if (group.id) { + this.groupManager.setImportStatus(group, statusName); } - } catch (e) { - createFlash({ - message: s__('BulkImport|Update of import statuses with realtime changes failed'), - }); - } finally { - this.timeoutId = setTimeout(() => this.checkPendingImports(), this.interval); - } + }); } } |