diff --git a/.rubocop_todo/style/open_struct_use.yml b/.rubocop_todo/style/open_struct_use.yml index 54ae23d232a..18b1015a6ba 100644 --- a/.rubocop_todo/style/open_struct_use.yml +++ b/.rubocop_todo/style/open_struct_use.yml @@ -12,11 +12,9 @@ Style/OpenStructUse: - lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb - lib/gitlab/testing/request_inspector_middleware.rb - lib/mattermost/session.rb - - spec/controllers/groups/clusters_controller_spec.rb - spec/controllers/projects/clusters_controller_spec.rb - spec/factories/go_module_versions.rb - spec/factories/wiki_pages.rb - - spec/features/projects/clusters_spec.rb - spec/graphql/mutations/branches/create_spec.rb - spec/graphql/mutations/clusters/agent_tokens/create_spec.rb - spec/graphql/mutations/clusters/agents/create_spec.rb diff --git a/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql b/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql index 09278e1776a..cdc8a952ead 100644 --- a/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql +++ b/app/assets/javascripts/access_tokens/graphql/queries/get_projects.query.graphql @@ -22,6 +22,7 @@ query accessTokensGetProjects( avatarUrl } pageInfo { + __typename ...PageInfo } } diff --git a/app/assets/javascripts/actioncable_link.js b/app/assets/javascripts/actioncable_link.js index 895a34ba157..cf53d9e21b4 100644 --- a/app/assets/javascripts/actioncable_link.js +++ b/app/assets/javascripts/actioncable_link.js @@ -1,4 +1,4 @@ -import { ApolloLink, Observable } from 'apollo-link'; +import { ApolloLink, Observable } from '@apollo/client/core'; import { print } from 'graphql'; import cable from '~/actioncable_consumer'; import { uuids } from '~/lib/utils/uuids'; diff --git a/app/assets/javascripts/alert_management/list.js b/app/assets/javascripts/alert_management/list.js index b23f8a8eba4..42cbeef56bf 100644 --- a/app/assets/javascripts/alert_management/list.js +++ b/app/assets/javascripts/alert_management/list.js @@ -1,4 +1,4 @@ -import { defaultDataIdFromObject } from 'apollo-cache-inmemory'; +import { defaultDataIdFromObject } from '@apollo/client/core'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js index b64e2e3eefa..36a98145457 100644 --- a/app/assets/javascripts/alerts_settings/graphql.js +++ b/app/assets/javascripts/alerts_settings/graphql.js @@ -1,15 +1,9 @@ -import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import produce from 'immer'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; -import introspectionQueryResultData from './graphql/fragmentTypes.json'; import getCurrentIntegrationQuery from './graphql/queries/get_current_integration.query.graphql'; -const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData, -}); - Vue.use(VueApollo); const resolvers = { @@ -55,9 +49,5 @@ const resolvers = { }; export default new VueApollo({ - defaultClient: createDefaultClient(resolvers, { - cacheConfig: { - fragmentMatcher, - }, - }), + defaultClient: createDefaultClient(resolvers), }); diff --git a/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json b/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json deleted file mode 100644 index 07dfc43aa6c..00000000000 --- a/app/assets/javascripts/alerts_settings/graphql/fragmentTypes.json +++ /dev/null @@ -1 +0,0 @@ -{"__schema":{"types":[{"kind":"UNION","name":"AlertManagementIntegration","possibleTypes":[{"name":"AlertManagementHttpIntegration"},{"name":"AlertManagementPrometheusIntegration"}]}]}} diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql index 3cd3f2d92f8..ac9304391f9 100644 --- a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql +++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql @@ -5,6 +5,7 @@ query getIntegrations($projectPath: ID!) { id alertManagementIntegrations { nodes { + __typename ...IntegrationItem } } diff --git a/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql b/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql index 2bde5973600..b353bcdfd0e 100644 --- a/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql +++ b/app/assets/javascripts/analytics/usage_trends/graphql/fragments/count.fragment.graphql @@ -1,4 +1,5 @@ fragment Count on UsageTrendsMeasurement { + __typename count recordedAt } diff --git a/app/assets/javascripts/boards/graphql.js b/app/assets/javascripts/boards/graphql.js index 64938cb42ed..95863d4d5ac 100644 --- a/app/assets/javascripts/boards/graphql.js +++ b/app/assets/javascripts/boards/graphql.js @@ -1,10 +1,5 @@ -import { IntrospectionFragmentMatcher, defaultDataIdFromObject } from 'apollo-cache-inmemory'; +import { defaultDataIdFromObject } from '@apollo/client/core'; import createDefaultClient from '~/lib/graphql'; -import introspectionQueryResultData from '~/sidebar/fragmentTypes.json'; - -const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData, -}); export const gqlClient = createDefaultClient( {}, @@ -14,8 +9,6 @@ export const gqlClient = createDefaultClient( // eslint-disable-next-line no-underscore-dangle return object.__typename === 'BoardList' ? object.iid : defaultDataIdFromObject(object); }, - - fragmentMatcher, }, }, ); diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js index ed32579a9c3..26dd8b99f98 100644 --- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js +++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js @@ -1,27 +1,14 @@ -import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import BoardsSelector from 'ee_else_ce/boards/components/boards_selector.vue'; import store from '~/boards/stores'; import createDefaultClient from '~/lib/graphql'; import { parseBoolean } from '~/lib/utils/common_utils'; -import introspectionQueryResultData from '~/sidebar/fragmentTypes.json'; Vue.use(VueApollo); -const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData, -}); - const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - cacheConfig: { - fragmentMatcher, - }, - }, - ), + defaultClient: createDefaultClient(), }); export default (params = {}) => { diff --git a/app/assets/javascripts/captcha/apollo_captcha_link.js b/app/assets/javascripts/captcha/apollo_captcha_link.js index e49abc10b29..d63ffaf5f1a 100644 --- a/app/assets/javascripts/captcha/apollo_captcha_link.js +++ b/app/assets/javascripts/captcha/apollo_captcha_link.js @@ -1,4 +1,4 @@ -import { ApolloLink, Observable } from 'apollo-link'; +import { ApolloLink, Observable } from '@apollo/client/core'; export const apolloCaptchaLink = new ApolloLink((operation, forward) => forward(operation).flatMap((result) => { diff --git a/app/assets/javascripts/clusters/agents/graphql/provider.js b/app/assets/javascripts/clusters/agents/graphql/provider.js index 8b068fa1eee..9153c5252b3 100644 --- a/app/assets/javascripts/clusters/agents/graphql/provider.js +++ b/app/assets/javascripts/clusters/agents/graphql/provider.js @@ -1,25 +1,10 @@ -import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; -import { vulnerabilityLocationTypes } from '~/graphql_shared/fragment_types/vulnerability_location_types'; Vue.use(VueApollo); -// We create a fragment matcher so that we can create a fragment from an interface -// Without this, Apollo throws a heuristic fragment matcher warning -const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData: vulnerabilityLocationTypes, -}); - -const defaultClient = createDefaultClient( - {}, - { - cacheConfig: { - fragmentMatcher, - }, - }, -); +const defaultClient = createDefaultClient(); export default new VueApollo({ defaultClient, diff --git a/app/assets/javascripts/design_management/graphql.js b/app/assets/javascripts/design_management/graphql.js index 5cf32cb7fe3..8c44c5a5d0a 100644 --- a/app/assets/javascripts/design_management/graphql.js +++ b/app/assets/javascripts/design_management/graphql.js @@ -1,11 +1,10 @@ -import { defaultDataIdFromObject, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; +import { defaultDataIdFromObject } from '@apollo/client/core'; import produce from 'immer'; import { uniqueId } from 'lodash'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; import axios from '~/lib/utils/axios_utils'; -import introspectionQueryResultData from './graphql/fragmentTypes.json'; import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql'; import getDesignQuery from './graphql/queries/get_design.query.graphql'; import typeDefs from './graphql/typedefs.graphql'; @@ -13,10 +12,6 @@ import { addPendingTodoToStore } from './utils/cache_update'; import { extractTodoIdFromDeletePath, createPendingTodo } from './utils/design_management_utils'; import { CREATE_DESIGN_TODO_EXISTS_ERROR } from './utils/error_messages'; -const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData, -}); - Vue.use(VueApollo); const resolvers = { @@ -85,7 +80,6 @@ const defaultClient = createDefaultClient( } return defaultDataIdFromObject(object); }, - fragmentMatcher, }, typeDefs, }, diff --git a/app/assets/javascripts/design_management/graphql/fragmentTypes.json b/app/assets/javascripts/design_management/graphql/fragmentTypes.json deleted file mode 100644 index 0953231ea4c..00000000000 --- a/app/assets/javascripts/design_management/graphql/fragmentTypes.json +++ /dev/null @@ -1 +0,0 @@ -{"__schema":{"types":[{"kind":"INTERFACE","name":"User","possibleTypes":[{"name":"UserCore"}]},{"kind":"UNION","name":"NoteableType","possibleTypes":[{"name":"Design"},{"name":"Issue"},{"name":"MergeRequest"}]}]}} diff --git a/app/assets/javascripts/graphql_shared/fragment_types/vulnerability_location_types.js b/app/assets/javascripts/graphql_shared/fragment_types/vulnerability_location_types.js deleted file mode 100644 index 30888e20a46..00000000000 --- a/app/assets/javascripts/graphql_shared/fragment_types/vulnerability_location_types.js +++ /dev/null @@ -1,17 +0,0 @@ -export const vulnerabilityLocationTypes = { - __schema: { - types: [ - { - kind: 'UNION', - name: 'VulnerabilityLocation', - possibleTypes: [ - { name: 'VulnerabilityLocationContainerScanning' }, - { name: 'VulnerabilityLocationDast' }, - { name: 'VulnerabilityLocationDependencyScanning' }, - { name: 'VulnerabilityLocationSast' }, - { name: 'VulnerabilityLocationSecretDetection' }, - ], - }, - ], - }, -}; diff --git a/app/assets/javascripts/graphql_shared/possibleTypes.json b/app/assets/javascripts/graphql_shared/possibleTypes.json new file mode 100644 index 00000000000..9a24d2a3afc --- /dev/null +++ b/app/assets/javascripts/graphql_shared/possibleTypes.json @@ -0,0 +1 @@ +{"AlertManagementIntegration":["AlertManagementHttpIntegration","AlertManagementPrometheusIntegration"],"CurrentUserTodos":["BoardEpic","Design","Epic","EpicIssue","Issue","MergeRequest"],"DependencyLinkMetadata":["NugetDependencyLinkMetadata"],"DesignFields":["Design","DesignAtVersion"],"Entry":["Blob","Submodule","TreeEntry"],"Eventable":["BoardEpic","Epic"],"Issuable":["Epic","Issue","MergeRequest"],"JobNeedUnion":["CiBuildNeed","CiJob"],"MemberInterface":["GroupMember","ProjectMember"],"NoteableInterface":["AlertManagementAlert","BoardEpic","Design","Epic","EpicIssue","Issue","MergeRequest","Snippet","Vulnerability"],"NoteableType":["Design","Issue","MergeRequest"],"OrchestrationPolicy":["ScanExecutionPolicy","ScanResultPolicy"],"PackageFileMetadata":["ConanFileMetadata","HelmFileMetadata"],"PackageMetadata":["ComposerMetadata","ConanMetadata","MavenMetadata","NugetMetadata","PypiMetadata"],"ResolvableInterface":["Discussion","Note"],"Service":["BaseService","JiraService"],"TimeboxReportInterface":["Iteration","Milestone"],"User":["MergeRequestAssignee","MergeRequestReviewer","UserCore"],"VulnerabilityDetail":["VulnerabilityDetailBase","VulnerabilityDetailBoolean","VulnerabilityDetailCode","VulnerabilityDetailCommit","VulnerabilityDetailDiff","VulnerabilityDetailFileLocation","VulnerabilityDetailInt","VulnerabilityDetailList","VulnerabilityDetailMarkdown","VulnerabilityDetailModuleLocation","VulnerabilityDetailTable","VulnerabilityDetailText","VulnerabilityDetailUrl"],"VulnerabilityLocation":["VulnerabilityLocationClusterImageScanning","VulnerabilityLocationContainerScanning","VulnerabilityLocationCoverageFuzzing","VulnerabilityLocationDast","VulnerabilityLocationDependencyScanning","VulnerabilityLocationGeneric","VulnerabilityLocationSast","VulnerabilityLocationSecretDetection"]} diff --git a/app/assets/javascripts/issues/list/components/issues_list_app.vue b/app/assets/javascripts/issues/list/components/issues_list_app.vue index a2bb6c3cd77..3866a7b3305 100644 --- a/app/assets/javascripts/issues/list/components/issues_list_app.vue +++ b/app/assets/javascripts/issues/list/components/issues_list_app.vue @@ -181,6 +181,9 @@ export default { return data[this.namespace]?.issues.nodes ?? []; }, result({ data }) { + if (!data) { + return; + } this.pageInfo = data[this.namespace]?.issues.pageInfo ?? {}; this.exportCsvPathWithQuery = this.getExportCsvPathWithQuery(); }, diff --git a/app/assets/javascripts/issues/list/queries/issue.fragment.graphql b/app/assets/javascripts/issues/list/queries/issue.fragment.graphql index 07dae3fd756..430d494deab 100644 --- a/app/assets/javascripts/issues/list/queries/issue.fragment.graphql +++ b/app/assets/javascripts/issues/list/queries/issue.fragment.graphql @@ -1,4 +1,5 @@ fragment IssueFragment on Issue { + __typename id iid closedAt @@ -18,6 +19,7 @@ fragment IssueFragment on Issue { webUrl assignees { nodes { + __typename id avatarUrl name @@ -26,6 +28,7 @@ fragment IssueFragment on Issue { } } author { + __typename id avatarUrl name diff --git a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue index c786d35ac68..81f42c1e293 100644 --- a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue +++ b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue @@ -51,7 +51,9 @@ export default { }, data() { return { - jobs: {}, + jobs: { + list: [], + }, hasError: false, isAlertDismissed: false, scope: null, diff --git a/app/assets/javascripts/lib/apollo/instrumentation_link.js b/app/assets/javascripts/lib/apollo/instrumentation_link.js index 2ab364557b8..bbe16d260e7 100644 --- a/app/assets/javascripts/lib/apollo/instrumentation_link.js +++ b/app/assets/javascripts/lib/apollo/instrumentation_link.js @@ -1,4 +1,4 @@ -import { ApolloLink } from 'apollo-link'; +import { ApolloLink } from '@apollo/client/core'; import { memoize } from 'lodash'; export const FEATURE_CATEGORY_HEADER = 'x-gitlab-feature-category'; diff --git a/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js b/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js index 9b7901685b6..b2a86ac257b 100644 --- a/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js +++ b/app/assets/javascripts/lib/apollo/suppress_network_errors_during_navigation_link.js @@ -1,5 +1,5 @@ -import { Observable } from 'apollo-link'; -import { onError } from 'apollo-link-error'; +import { Observable } from '@apollo/client/core'; +import { onError } from '@apollo/client/link/error'; import { isNavigatingAway } from '~/lib/utils/is_navigating_away'; /** diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js index df2e85afe24..0fb7bf52562 100644 --- a/app/assets/javascripts/lib/graphql.js +++ b/app/assets/javascripts/lib/graphql.js @@ -1,11 +1,9 @@ -import { InMemoryCache } from 'apollo-cache-inmemory'; -import { ApolloClient } from 'apollo-client'; -import { ApolloLink } from 'apollo-link'; -import { BatchHttpLink } from 'apollo-link-batch-http'; -import { HttpLink } from 'apollo-link-http'; +import { ApolloClient, InMemoryCache, ApolloLink, HttpLink } from '@apollo/client/core'; +import { BatchHttpLink } from '@apollo/client/link/batch-http'; import { createUploadLink } from 'apollo-upload-client'; import ActionCableLink from '~/actioncable_link'; import { apolloCaptchaLink } from '~/captcha/apollo_captcha_link'; +import possibleTypes from '~/graphql_shared/possibleTypes.json'; import { StartupJSLink } from '~/lib/utils/apollo_startup_js_link'; import csrf from '~/lib/utils/csrf'; import { objectToQuery, queryToObject } from '~/lib/utils/url_utility'; @@ -21,6 +19,33 @@ export const fetchPolicies = { CACHE_ONLY: 'cache-only', }; +export const typePolicies = { + Repository: { + merge: true, + }, + UserPermissions: { + merge: true, + }, + MergeRequestPermissions: { + merge: true, + }, + ContainerRepositoryConnection: { + merge: true, + }, + TimelogConnection: { + merge: true, + }, + BranchList: { + merge: true, + }, + InstanceSecurityDashboard: { + merge: true, + }, + PipelinePermissions: { + merge: true, + }, +}; + export const stripWhitespaceFromQuery = (url, path) => { /* eslint-disable-next-line no-unused-vars */ const [_, params] = url.split(path); @@ -46,6 +71,30 @@ export const stripWhitespaceFromQuery = (url, path) => { return `${path}?${reassembled}`; }; +const acs = []; + +let pendingApolloMutations = 0; + +// ### Why track pendingApolloMutations, but calculate pendingApolloRequests? +// +// In Apollo 2, we had a single link for counting operations. +// +// With Apollo 3, the `forward().map(...)` of deduped queries is never called. +// So, we resorted to calculating the sum of `inFlightLinkObservables?.size`. +// However! Mutations don't use `inFLightLinkObservables`, but since they are likely +// not deduped we can count them... +// +// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55062#note_838943715 +// https://www.apollographql.com/docs/react/v2/networking/network-layer/#query-deduplication +Object.defineProperty(window, 'pendingApolloRequests', { + get() { + return acs.reduce( + (sum, ac) => sum + (ac?.queryManager?.inFlightLinkObservables?.size || 0), + pendingApolloMutations, + ); + }, +}); + export default (resolvers = {}, config = {}) => { const { baseUrl, @@ -56,6 +105,7 @@ export default (resolvers = {}, config = {}) => { path = '/api/graphql', useGet = false, } = config; + let ac = null; let uri = `${gon.relative_url_root || ''}${path}`; if (baseUrl) { @@ -75,16 +125,6 @@ export default (resolvers = {}, config = {}) => { batchMax, }; - const requestCounterLink = new ApolloLink((operation, forward) => { - window.pendingApolloRequests = window.pendingApolloRequests || 0; - window.pendingApolloRequests += 1; - - return forward(operation).map((response) => { - window.pendingApolloRequests -= 1; - return response; - }); - }); - /* This custom fetcher intervention is to deal with an issue where we are using GET to access eTag polling, but Apollo Client adds excessive whitespace, which causes the @@ -138,6 +178,22 @@ export default (resolvers = {}, config = {}) => { ); }; + const hasMutation = (operation) => + (operation?.query?.definitions || []).some((x) => x.operation === 'mutation'); + + const requestCounterLink = new ApolloLink((operation, forward) => { + if (hasMutation(operation)) { + pendingApolloMutations += 1; + } + + return forward(operation).map((response) => { + if (hasMutation(operation)) { + pendingApolloMutations -= 1; + } + return response; + }); + }); + const appLink = ApolloLink.split( hasSubscriptionOperation, new ActionCableLink(), @@ -155,19 +211,23 @@ export default (resolvers = {}, config = {}) => { ), ); - return new ApolloClient({ + ac = new ApolloClient({ typeDefs, link: appLink, cache: new InMemoryCache({ + typePolicies, + possibleTypes, ...cacheConfig, - freezeResults: true, }), resolvers, - assumeImmutableResults: true, defaultOptions: { query: { fetchPolicy, }, }, }); + + acs.push(ac); + + return ac; }; diff --git a/app/assets/javascripts/lib/utils/apollo_startup_js_link.js b/app/assets/javascripts/lib/utils/apollo_startup_js_link.js index 014823f3831..f240226e991 100644 --- a/app/assets/javascripts/lib/utils/apollo_startup_js_link.js +++ b/app/assets/javascripts/lib/utils/apollo_startup_js_link.js @@ -1,4 +1,4 @@ -import { ApolloLink, Observable } from 'apollo-link'; +import { ApolloLink, Observable } from '@apollo/client/core'; import { parse } from 'graphql'; import { isEqual, pickBy } from 'lodash'; diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue index ad3a3596991..e2acebf39d6 100644 --- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue +++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue @@ -96,6 +96,9 @@ export default { return data[this.graphqlResource]?.containerRepositories.nodes; }, result({ data }) { + if (!data) { + return; + } this.pageInfo = data[this.graphqlResource]?.containerRepositories?.pageInfo; this.containerRepositoriesCount = data[this.graphqlResource]?.containerRepositoriesCount; }, diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragmentTypes.json b/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragmentTypes.json deleted file mode 100644 index c61a653d10b..00000000000 --- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragmentTypes.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "__schema": { - "types": [ - { - "kind": "UNION", - "name": "PackageMetadata", - "possibleTypes": [ - { "name": "ComposerMetadata" }, - { "name": "ConanMetadata" }, - { "name": "MavenMetadata" }, - { "name": "NugetMetadata" }, - { "name": "PypiMetadata" } - ] - } - ] - } -} diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js b/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js index 21d6fbc9e1f..56f95fa2c1f 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js +++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js @@ -1,22 +1,9 @@ -import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; -import introspectionQueryResultData from './fragmentTypes.json'; - -const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData, -}); Vue.use(VueApollo); export const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - cacheConfig: { - fragmentMatcher, - }, - }, - ), + defaultClient: createDefaultClient(), }); diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue index 42c40cda601..d50945e0be2 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue +++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue @@ -2,7 +2,8 @@ import { GlProgressBar, GlSprintf, GlAlert } from '@gitlab/ui'; import eventHub from '~/invite_members/event_hub'; import { s__ } from '~/locale'; -import { ACTION_LABELS, ACTION_SECTIONS } from '../constants'; +import { getCookie, removeCookie, parseBoolean } from '~/lib/utils/common_utils'; +import { ACTION_LABELS, ACTION_SECTIONS, INVITE_MODAL_OPEN_COOKIE } from '../constants'; import LearnGitlabSectionCard from './learn_gitlab_section_card.vue'; export default { @@ -26,7 +27,7 @@ export default { required: true, type: Object, }, - inviteMembersOpen: { + inviteMembers: { type: Boolean, required: false, default: false, @@ -53,7 +54,7 @@ export default { }, }, mounted() { - if (this.inviteMembersOpen) { + if (this.inviteMembers && this.getCookieForInviteMembers()) { this.openInviteMembersModal('celebrate'); } @@ -63,6 +64,13 @@ export default { eventHub.$off('showSuccessfulInvitationsAlert', this.handleShowSuccessfulInvitationsAlert); }, methods: { + getCookieForInviteMembers() { + const value = parseBoolean(getCookie(INVITE_MODAL_OPEN_COOKIE)); + + removeCookie(INVITE_MODAL_OPEN_COOKIE); + + return value; + }, openInviteMembersModal(mode) { eventHub.$emit('openModal', { mode, inviteeType: 'members', source: 'learn-gitlab' }); }, diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js index 8a88ad299b4..880cf699e5e 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js +++ b/app/assets/javascripts/pages/projects/learn_gitlab/constants/index.js @@ -95,3 +95,5 @@ export const ACTION_SECTIONS = { ), }, }; + +export const INVITE_MODAL_OPEN_COOKIE = 'confetti_post_signup'; diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js index 1f91cc46946..c62cab1a425 100644 --- a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js +++ b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js @@ -1,6 +1,6 @@ import Vue from 'vue'; import initInviteMembersModal from '~/invite_members/init_invite_members_modal'; -import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils'; import LearnGitlab from '../components/learn_gitlab.vue'; function initLearnGitlab() { @@ -13,13 +13,13 @@ function initLearnGitlab() { const actions = convertObjectPropsToCamelCase(JSON.parse(el.dataset.actions)); const sections = convertObjectPropsToCamelCase(JSON.parse(el.dataset.sections)); const project = convertObjectPropsToCamelCase(JSON.parse(el.dataset.project)); - const { inviteMembersOpen } = el.dataset; + const { inviteMembers } = el.dataset; return new Vue({ el, render(createElement) { return createElement(LearnGitlab, { - props: { actions, sections, project, inviteMembersOpen }, + props: { actions, sections, project, inviteMembers: parseBoolean(inviteMembers) }, }); }, }); diff --git a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue index 72b492a5877..4b9c98135ec 100644 --- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue +++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue @@ -49,7 +49,7 @@ export default { pipelineEtag: { query: getPipelineEtag, update(data) { - return data.etags.pipeline; + return data.etags?.pipeline; }, }, pipeline: { diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue index 604f87a0cda..1da50c55a68 100644 --- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue +++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue @@ -196,7 +196,7 @@ export default { currentBranch: { query: getCurrentBranch, update(data) { - return data.workBranches.current.name; + return data.workBranches?.current?.name; }, }, starterTemplate: { @@ -214,7 +214,7 @@ export default { return data.project?.ciTemplate?.content || ''; }, result({ data }) { - this.updateCiConfig(data.project?.ciTemplate?.content || ''); + this.updateCiConfig(data?.project?.ciTemplate?.content || ''); }, error() { this.reportFailure(LOAD_FAILURE_UNKNOWN); diff --git a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue index 6f35cdac641..99fb5c146ba 100644 --- a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue +++ b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue @@ -36,6 +36,9 @@ export default { return data.project?.pipeline?.jobs?.nodes || []; }, result({ data }) { + if (!data) { + return; + } this.jobsPageInfo = data.project?.pipeline?.jobs?.pageInfo || {}; }, error() { diff --git a/app/assets/javascripts/pipelines/graphql/fragmentTypes.json b/app/assets/javascripts/pipelines/graphql/fragmentTypes.json deleted file mode 100644 index 4601b74b5c1..00000000000 --- a/app/assets/javascripts/pipelines/graphql/fragmentTypes.json +++ /dev/null @@ -1 +0,0 @@ -{"__schema":{"types":[{"kind":"UNION","name":"JobNeedUnion","possibleTypes":[{"name":"CiBuildNeed"},{"name":"CiJob"}]}]}} \ No newline at end of file diff --git a/app/assets/javascripts/pipelines/pipeline_shared_client.js b/app/assets/javascripts/pipelines/pipeline_shared_client.js index 84276588d6a..c3be487caae 100644 --- a/app/assets/javascripts/pipelines/pipeline_shared_client.js +++ b/app/assets/javascripts/pipelines/pipeline_shared_client.js @@ -1,19 +1,10 @@ import VueApollo from 'vue-apollo'; -import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import createDefaultClient from '~/lib/graphql'; -import introspectionQueryResultData from './graphql/fragmentTypes.json'; - -export const fragmentMatcher = new IntrospectionFragmentMatcher({ - introspectionQueryResultData, -}); export const apolloProvider = new VueApollo({ defaultClient: createDefaultClient( {}, { - cacheConfig: { - fragmentMatcher, - }, useGet: true, }, ), diff --git a/app/assets/javascripts/related_issues/components/add_issuable_form.vue b/app/assets/javascripts/related_issues/components/add_issuable_form.vue index f936c03c5d3..9ee2e7a4ffd 100644 --- a/app/assets/javascripts/related_issues/components/add_issuable_form.vue +++ b/app/assets/javascripts/related_issues/components/add_issuable_form.vue @@ -9,6 +9,8 @@ import { linkedIssueTypesMap, addRelatedIssueErrorMap, addRelatedItemErrorMap, + issuablesFormCategoryHeaderTextMap, + issuablesFormInputTextMap, } from '../constants'; import RelatedIssuableInput from './related_issuable_input.vue'; @@ -134,6 +136,12 @@ export default { epics: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.epics), }; }, + issuableCategoryHeaderText() { + return issuablesFormCategoryHeaderTextMap[this.issuableType]; + }, + issuableInputText() { + return issuablesFormInputTextMap[this.issuableType]; + }, }, methods: { onPendingIssuableRemoveRequest(params) { @@ -162,7 +170,7 @@ export default {