Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-12-08 00:12:55 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-12-08 00:12:55 +0300
commit2cf4bdd0b060175c7058b395014b101fbe6214a3 (patch)
treef3aaeca09cc434632c8eb2c2998877c3f9a2e0d9 /app/assets/javascripts
parent1bdc6c89c32a7380a81598629b9ad05ba9a2a94f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/environments/components/environment_form.vue87
-rw-r--r--app/assets/javascripts/environments/components/environment_namespace_selector.vue136
-rw-r--r--app/assets/javascripts/environments/constants.js2
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_app.vue116
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js37
-rw-r--r--app/assets/javascripts/environments/graphql/resolvers/base.js13
-rw-r--r--app/assets/javascripts/ide/init_gitlab_web_ide.js25
-rw-r--r--app/assets/javascripts/ide/lib/gitlab_web_ide/get_oauth_config.js12
-rw-r--r--app/assets/javascripts/ide/lib/gitlab_web_ide/index.js2
-rw-r--r--app/assets/javascripts/ide/mount_oauth_callback.js12
-rw-r--r--app/assets/javascripts/pages/ide/index/index.js (renamed from app/assets/javascripts/pages/ide/index.js)0
-rw-r--r--app/assets/javascripts/pages/ide/oauth_redirect/index.js3
-rw-r--r--app/assets/javascripts/sidebar/components/labels/labels_select_vue/dropdown_title.vue1
-rw-r--r--app/assets/javascripts/super_sidebar/components/menu_section.vue4
-rw-r--r--app/assets/javascripts/super_sidebar/components/super_sidebar.vue1
-rw-r--r--app/assets/javascripts/super_sidebar/components/user_menu.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue4
-rw-r--r--app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue1
19 files changed, 341 insertions, 123 deletions
diff --git a/app/assets/javascripts/environments/components/environment_form.vue b/app/assets/javascripts/environments/components/environment_form.vue
index c6cf6b7e24b..a4c2d4fcc51 100644
--- a/app/assets/javascripts/environments/components/environment_form.vue
+++ b/app/assets/javascripts/environments/components/environment_form.vue
@@ -7,7 +7,6 @@ import {
GlCollapsibleListbox,
GlLink,
GlSprintf,
- GlAlert,
} from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { isAbsolute } from '~/lib/utils/url_utility';
@@ -19,9 +18,9 @@ import {
import csrf from '~/lib/utils/csrf';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import getNamespacesQuery from '../graphql/queries/k8s_namespaces.query.graphql';
import getUserAuthorizedAgents from '../graphql/queries/user_authorized_agents.query.graphql';
import EnvironmentFluxResourceSelector from './environment_flux_resource_selector.vue';
+import EnvironmentNamespaceSelector from './environment_namespace_selector.vue';
export default {
components: {
@@ -32,8 +31,8 @@ export default {
GlCollapsibleListbox,
GlLink,
GlSprintf,
- GlAlert,
EnvironmentFluxResourceSelector,
+ EnvironmentNamespaceSelector,
},
mixins: [glFeatureFlagsMixin()],
inject: {
@@ -72,8 +71,6 @@ export default {
urlFeedback: __('The URL should start with http:// or https://'),
agentLabel: s__('Environments|GitLab agent'),
agentHelpText: s__('Environments|Select agent'),
- namespaceLabel: s__('Environments|Kubernetes namespace (optional)'),
- namespaceHelpText: s__('Environments|Select namespace'),
save: __('Save'),
cancel: __('Cancel'),
reset: __('Reset'),
@@ -93,35 +90,9 @@ export default {
selectedAgentId: this.environment.clusterAgentId,
agentSearchTerm: '',
selectedNamespace: this.environment.kubernetesNamespace,
- k8sNamespaces: [],
- namespaceSearchTerm: '',
kubernetesError: '',
};
},
- apollo: {
- k8sNamespaces: {
- query: getNamespacesQuery,
- skip() {
- return !this.showNamespaceSelector;
- },
- variables() {
- return {
- configuration: this.k8sAccessConfiguration,
- };
- },
- update(data) {
- return data?.k8sNamespaces || [];
- },
- error(error) {
- this.kubernetesError = error.message;
- },
- result(result) {
- if (!result?.error && !result.errors?.length) {
- this.kubernetesError = null;
- }
- },
- },
- },
computed: {
loadingNamespacesList() {
return this.$apollo.queries.k8sNamespaces.loading;
@@ -161,26 +132,9 @@ export default {
item.text.toLowerCase().includes(lowerCasedSearchTerm),
);
},
- namespacesList() {
- return this.k8sNamespaces.map((item) => {
- return {
- value: item.metadata.name,
- text: item.metadata.name,
- };
- });
- },
- filteredNamespacesList() {
- const lowerCasedSearchTerm = this.namespaceSearchTerm.toLowerCase();
- return this.namespacesList.filter((item) =>
- item.text.toLowerCase().includes(lowerCasedSearchTerm),
- );
- },
showNamespaceSelector() {
return Boolean(this.selectedAgentId);
},
- namespaceDropdownToggleText() {
- return this.selectedNamespace || this.$options.i18n.namespaceHelpText;
- },
showFluxResourceSelector() {
return Boolean(this.selectedNamespace && this.selectedAgentId);
},
@@ -239,9 +193,6 @@ export default {
fluxResourcePath: null,
});
},
- onNamespaceSearch(search) {
- this.namespaceSearchTerm = search;
- },
},
};
</script>
@@ -334,34 +285,14 @@ export default {
/>
</gl-form-group>
- <gl-form-group
+ <environment-namespace-selector
v-if="showNamespaceSelector"
- :label="$options.i18n.namespaceLabel"
- label-for="environment_namespace"
- >
- <gl-alert v-if="kubernetesError" variant="warning" :dismissible="false" class="gl-mb-5">
- {{ kubernetesError }}
- </gl-alert>
- <gl-collapsible-listbox
- v-else
- id="environment_namespace"
- v-model="selectedNamespace"
- class="gl-w-full"
- data-testid="namespace-selector"
- block
- :items="filteredNamespacesList"
- :loading="loadingNamespacesList"
- :toggle-text="namespaceDropdownToggleText"
- :header-text="$options.i18n.namespaceHelpText"
- :reset-button-label="$options.i18n.reset"
- :searchable="true"
- @search="onNamespaceSearch"
- @select="
- onChange({ ...environment, kubernetesNamespace: $event, fluxResourcePath: null })
- "
- @reset="onChange({ ...environment, kubernetesNamespace: null })"
- />
- </gl-form-group>
+ :namespace="selectedNamespace"
+ :configuration="k8sAccessConfiguration"
+ @change="
+ onChange({ ...environment, kubernetesNamespace: $event, fluxResourcePath: null })
+ "
+ />
<environment-flux-resource-selector
v-if="showFluxResourceSelector"
diff --git a/app/assets/javascripts/environments/components/environment_namespace_selector.vue b/app/assets/javascripts/environments/components/environment_namespace_selector.vue
new file mode 100644
index 00000000000..101d70d36f3
--- /dev/null
+++ b/app/assets/javascripts/environments/components/environment_namespace_selector.vue
@@ -0,0 +1,136 @@
+<script>
+import { GlFormGroup, GlCollapsibleListbox, GlAlert, GlButton, GlSprintf } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
+import getNamespacesQuery from '../graphql/queries/k8s_namespaces.query.graphql';
+
+export default {
+ components: {
+ GlFormGroup,
+ GlCollapsibleListbox,
+ GlAlert,
+ GlButton,
+ GlSprintf,
+ },
+ props: {
+ configuration: {
+ required: true,
+ type: Object,
+ },
+ namespace: {
+ required: false,
+ type: String,
+ default: '',
+ },
+ },
+ i18n: {
+ namespaceLabel: s__('Environments|Kubernetes namespace (optional)'),
+ namespaceHelpText: s__('Environments|Select namespace'),
+ selectButton: s__('Environments|Or select namespace: %{searchTerm}'),
+ reset: __('Reset'),
+ },
+ data() {
+ return {
+ k8sNamespaces: [],
+ searchTerm: '',
+ kubernetesError: '',
+ };
+ },
+ apollo: {
+ k8sNamespaces: {
+ query: getNamespacesQuery,
+
+ variables() {
+ return {
+ configuration: this.configuration,
+ };
+ },
+ update(data) {
+ return (
+ data?.k8sNamespaces?.map((item) => {
+ return {
+ value: item.metadata.name,
+ text: item.metadata.name,
+ };
+ }) || []
+ );
+ },
+ error(error) {
+ this.kubernetesError = error.message;
+ },
+ result(result) {
+ if (!result?.error && !result.errors?.length) {
+ this.kubernetesError = null;
+ }
+ },
+ },
+ },
+ computed: {
+ loadingNamespacesList() {
+ return this.$apollo.queries.k8sNamespaces.loading;
+ },
+ filteredNamespacesList() {
+ const lowerCasedSearchTerm = this.searchTerm.toLowerCase();
+ return this.k8sNamespaces.filter((item) =>
+ item.text.toLowerCase().includes(lowerCasedSearchTerm),
+ );
+ },
+ namespaceDropdownToggleText() {
+ return this.namespace || this.$options.i18n.namespaceHelpText;
+ },
+ shouldRenderSelectButton() {
+ const hasSearchedItem = this.k8sNamespaces.some(
+ (item) => item.text === this.searchTerm.toLowerCase(),
+ );
+ return this.searchTerm && !hasSearchedItem;
+ },
+ },
+ methods: {
+ onChange(namespace) {
+ this.$emit('change', namespace);
+ },
+ onNamespaceSearch(search) {
+ this.searchTerm = search;
+ },
+ onSelect(namespace) {
+ this.onChange(namespace);
+ this.$refs.namespaceSelector.close();
+ },
+ },
+};
+</script>
+<template>
+ <gl-form-group :label="$options.i18n.namespaceLabel" label-for="environment_namespace">
+ <gl-alert v-if="kubernetesError" variant="warning" :dismissible="false" class="gl-mb-5">
+ {{ kubernetesError }}
+ </gl-alert>
+ <gl-collapsible-listbox
+ id="environment_namespace"
+ ref="namespaceSelector"
+ :selected="namespace"
+ class="gl-w-full"
+ block
+ :items="filteredNamespacesList"
+ :loading="loadingNamespacesList"
+ :toggle-text="namespaceDropdownToggleText"
+ :header-text="$options.i18n.namespaceHelpText"
+ :reset-button-label="$options.i18n.reset"
+ :searchable="true"
+ @search="onNamespaceSearch"
+ @select="onChange"
+ @reset="onChange"
+ >
+ <template v-if="shouldRenderSelectButton" #footer>
+ <gl-button
+ category="tertiary"
+ class="gl-justify-content-start! gl-border-t-1! gl-border-t-solid gl-border-t-gray-200 gl-pl-7! gl-rounded-top-left-none! gl-rounded-top-right-none!"
+ :class="{ 'gl-mt-3': !filteredNamespacesList.length }"
+ @click="onSelect(searchTerm)"
+ >
+ <gl-sprintf :message="$options.i18n.selectButton">
+ <template #searchTerm>{{ searchTerm }}</template>
+ </gl-sprintf>
+ </gl-button>
+ </template>
+ </gl-collapsible-listbox>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/environments/constants.js b/app/assets/javascripts/environments/constants.js
index 4f0eabb26a4..2fe9008c042 100644
--- a/app/assets/javascripts/environments/constants.js
+++ b/app/assets/javascripts/environments/constants.js
@@ -162,7 +162,7 @@ const ERROR_OTHER = 'other';
export const CLUSTER_AGENT_ERROR_MESSAGES = {
[ERROR_UNAUTHORIZED]: s__(
- 'Environment|Unauthorized to access the cluster agent from this environment. Check your authentication and try again.',
+ "Environment|You don't have permission to view all the namespaces in the cluster. If a namespace is not shown, you can still enter its name to select it.",
),
[ERROR_FORBIDDEN]: s__(
'Environment|Forbidden to access the cluster agent from this environment.',
diff --git a/app/assets/javascripts/environments/folder/environments_folder_app.vue b/app/assets/javascripts/environments/folder/environments_folder_app.vue
index f2c1b2f5cdf..6804e5cc0c7 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_app.vue
+++ b/app/assets/javascripts/environments/folder/environments_folder_app.vue
@@ -1,13 +1,29 @@
<script>
-import { GlSkeletonLoader } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { GlSkeletonLoader, GlTabs, GlTab, GlBadge } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
import folderQuery from '../graphql/queries/folder.query.graphql';
+import environmentToDeleteQuery from '../graphql/queries/environment_to_delete.query.graphql';
+import environmentToRollbackQuery from '../graphql/queries/environment_to_rollback.query.graphql';
+import environmentToStopQuery from '../graphql/queries/environment_to_stop.query.graphql';
+import environmentToChangeCanaryQuery from '../graphql/queries/environment_to_change_canary.query.graphql';
import EnvironmentItem from '../components/new_environment_item.vue';
+import StopEnvironmentModal from '../components/stop_environment_modal.vue';
+import ConfirmRollbackModal from '../components/confirm_rollback_modal.vue';
+import DeleteEnvironmentModal from '../components/delete_environment_modal.vue';
+import CanaryUpdateModal from '../components/canary_update_modal.vue';
+import { ENVIRONMENTS_SCOPE } from '../constants';
export default {
components: {
+ GlBadge,
+ GlTabs,
+ GlTab,
GlSkeletonLoader,
EnvironmentItem,
+ StopEnvironmentModal,
+ ConfirmRollbackModal,
+ DeleteEnvironmentModal,
+ CanaryUpdateModal,
},
props: {
folderName: {
@@ -18,6 +34,20 @@ export default {
type: String,
required: true,
},
+ scope: {
+ type: String,
+ required: true,
+ default: ENVIRONMENTS_SCOPE.ACTIVE,
+ },
+ },
+ data() {
+ return {
+ environmentToDelete: {},
+ environmentToRollback: {},
+ environmentToStop: {},
+ environmentToChangeCanary: {},
+ weight: 0,
+ };
},
apollo: {
folder: {
@@ -25,11 +55,27 @@ export default {
variables() {
return {
environment: this.environmentQueryData,
- scope: '',
+ scope: this.scope,
search: '',
perPage: 10,
};
},
+ pollInterval: 3000,
+ },
+ environmentToDelete: {
+ query: environmentToDeleteQuery,
+ },
+ environmentToRollback: {
+ query: environmentToRollbackQuery,
+ },
+ environmentToStop: {
+ query: environmentToStopQuery,
+ },
+ environmentToChangeCanary: {
+ query: environmentToChangeCanaryQuery,
+ },
+ weight: {
+ query: environmentToChangeCanaryQuery,
},
},
computed: {
@@ -42,18 +88,65 @@ export default {
isLoading() {
return this.$apollo.queries.folder.loading;
},
+ activeCount() {
+ return this.folder?.activeCount ?? '-';
+ },
+ stoppedCount() {
+ return this.folder?.stoppedCount ?? '-';
+ },
+ activeTab() {
+ return this.scope === ENVIRONMENTS_SCOPE.ACTIVE ? 0 : 1;
+ },
+ },
+ methods: {
+ setScope(scope) {
+ if (scope !== this.scope) {
+ this.$router.push({ query: { scope } });
+ }
+ },
},
i18n: {
pageTitle: s__('Environments|Environments'),
+ active: __('Active'),
+ stopped: __('Stopped'),
},
+ ENVIRONMENTS_SCOPE,
};
</script>
<template>
<div>
+ <delete-environment-modal :environment="environmentToDelete" graphql />
+ <stop-environment-modal :environment="environmentToStop" graphql />
+ <confirm-rollback-modal :environment="environmentToRollback" graphql />
+ <canary-update-modal :environment="environmentToChangeCanary" :weight="weight" />
<h4 class="gl-font-weight-normal" data-testid="folder-name">
{{ $options.i18n.pageTitle }} /
<b>{{ folderName }}</b>
</h4>
+ <gl-tabs :value="activeTab" query-param-name="scope">
+ <gl-tab
+ :query-param-value="$options.ENVIRONMENTS_SCOPE.ACTIVE"
+ @click="setScope($options.ENVIRONMENTS_SCOPE.ACTIVE)"
+ >
+ <template #title>
+ <span>{{ $options.i18n.active }}</span>
+ <gl-badge size="sm" class="gl-tab-counter-badge">
+ {{ activeCount }}
+ </gl-badge>
+ </template>
+ </gl-tab>
+ <gl-tab
+ :query-param-value="$options.ENVIRONMENTS_SCOPE.STOPPED"
+ @click="setScope($options.ENVIRONMENTS_SCOPE.STOPPED)"
+ >
+ <template #title>
+ <span>{{ $options.i18n.stopped }}</span>
+ <gl-badge size="sm" class="gl-tab-counter-badge">
+ {{ stoppedCount }}
+ </gl-badge>
+ </template>
+ </gl-tab>
+ </gl-tabs>
<div v-if="isLoading">
<div
v-for="n in 3"
@@ -63,12 +156,15 @@ export default {
<gl-skeleton-loader :lines="2" />
</div>
</div>
- <environment-item
- v-for="environment in environments"
- :key="environment.name"
- :environment="environment"
- class="gl-border-gray-100 gl-border-t-solid gl-border-1 gl-pt-3"
- in-folder
- />
+ <div v-else>
+ <environment-item
+ v-for="environment in environments"
+ :id="environment.name"
+ :key="environment.name"
+ :environment="environment"
+ class="gl-border-gray-100 gl-border-t-solid gl-border-1 gl-pt-3"
+ in-folder
+ />
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
index 2f06f003bb2..44a5d1e3662 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import VueRouter from 'vue-router';
import createDefaultClient from '~/lib/graphql';
import Translate from '~/vue_shared/translate';
import { apolloProvider } from '../graphql/client';
@@ -17,28 +18,46 @@ export default () => {
const el = document.getElementById('environments-folder-list-view');
const environmentsData = el.dataset;
if (gon.features.environmentsFolderNewLook) {
+ Vue.use(VueRouter);
+
const folderName = environmentsData.environmentsDataFolderName;
const folderPath = environmentsData.environmentsDataEndpoint.replace('.json', '');
const projectPath = environmentsData.environmentsDataProjectPath;
const helpPagePath = environmentsData.environmentsDataHelpPagePath;
+ const router = new VueRouter({
+ mode: 'history',
+ base: window.location.pathname,
+ routes: [
+ {
+ path: '/',
+ name: 'environments_folder',
+ component: EnvironmentsFolderApp,
+ props: (route) => ({
+ scope: route.query.scope,
+ folderName,
+ folderPath,
+ }),
+ },
+ ],
+ scrollBehavior(to, from, savedPosition) {
+ if (savedPosition) {
+ return savedPosition;
+ }
+ return { top: 0 };
+ },
+ });
+
return new Vue({
el,
- components: {
- EnvironmentsFolderApp,
- },
provide: {
projectPath,
helpPagePath,
},
apolloProvider,
+ router,
render(createElement) {
- return createElement('environments-folder-app', {
- props: {
- folderName,
- folderPath,
- },
- });
+ return createElement('router-view');
},
});
}
diff --git a/app/assets/javascripts/environments/graphql/resolvers/base.js b/app/assets/javascripts/environments/graphql/resolvers/base.js
index 404b7024cde..8b0ac039290 100644
--- a/app/assets/javascripts/environments/graphql/resolvers/base.js
+++ b/app/assets/javascripts/environments/graphql/resolvers/base.js
@@ -75,7 +75,7 @@ export const baseQueries = (endpoint) => ({
});
export const baseMutations = {
- stopEnvironmentREST(_, { environment }, { client }) {
+ stopEnvironmentREST(_, { environment }, { client, cache }) {
client.writeQuery({
query: isEnvironmentStoppingQuery,
variables: { environment },
@@ -84,6 +84,9 @@ export const baseMutations = {
return axios
.post(environment.stopPath)
.then(() => buildErrors())
+ .then(() => {
+ cache.evict({ fieldName: 'folder' });
+ })
.catch(() => {
client.writeQuery({
query: isEnvironmentStoppingQuery,
@@ -95,10 +98,11 @@ export const baseMutations = {
]);
});
},
- deleteEnvironment(_, { environment: { deletePath } }) {
+ deleteEnvironment(_, { environment: { deletePath } }, { cache }) {
return axios
.delete(deletePath)
.then(() => buildErrors())
+ .then(() => cache.evict({ fieldName: 'folder' }))
.catch(() =>
buildErrors([
s__(
@@ -107,10 +111,13 @@ export const baseMutations = {
]),
);
},
- rollbackEnvironment(_, { environment, isLastDeployment }) {
+ rollbackEnvironment(_, { environment, isLastDeployment }, { cache }) {
return axios
.post(environment?.retryUrl)
.then(() => buildErrors())
+ .then(() => {
+ cache.evict({ fieldName: 'folder' });
+ })
.catch(() => {
buildErrors([
isLastDeployment
diff --git a/app/assets/javascripts/ide/init_gitlab_web_ide.js b/app/assets/javascripts/ide/init_gitlab_web_ide.js
index 868830c953a..f5fb4c8be2f 100644
--- a/app/assets/javascripts/ide/init_gitlab_web_ide.js
+++ b/app/assets/javascripts/ide/init_gitlab_web_ide.js
@@ -6,10 +6,13 @@ import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_action';
import { createAndSubmitForm } from '~/lib/utils/create_and_submit_form';
import csrf from '~/lib/utils/csrf';
import Tracking from '~/tracking';
-import { getBaseConfig } from './lib/gitlab_web_ide/get_base_config';
-import { setupRootElement } from './lib/gitlab_web_ide/setup_root_element';
+import {
+ getBaseConfig,
+ getOAuthConfig,
+ setupRootElement,
+ handleTracking,
+} from './lib/gitlab_web_ide';
import { GITLAB_WEB_IDE_FEEDBACK_ISSUE } from './constants';
-import { handleTracking } from './lib/gitlab_web_ide/handle_tracking_event';
const buildRemoteIdeURL = (ideRemotePath, remoteHost, remotePathArg) => {
const remotePath = cleanLeadingSeparator(remotePathArg);
@@ -51,15 +54,21 @@ export const initGitlabWebIDE = async (el) => {
: null;
const forkInfo = forkInfoJSON ? JSON.parse(forkInfoJSON) : null;
+ const oauthConfig = getOAuthConfig(el.dataset);
+ const httpHeaders = oauthConfig
+ ? undefined
+ : // Use same headers as defined in axios_utils (not needed in oauth)
+ {
+ [csrf.headerKey]: csrf.token,
+ 'X-Requested-With': 'XMLHttpRequest',
+ };
+
// See ClientOnlyConfig https://gitlab.com/gitlab-org/gitlab-web-ide/-/blob/main/packages/web-ide-types/src/config.ts#L17
start(rootEl, {
...getBaseConfig(),
nonce,
- // Use same headers as defined in axios_utils
- httpHeaders: {
- [csrf.headerKey]: csrf.token,
- 'X-Requested-With': 'XMLHttpRequest',
- },
+ httpHeaders,
+ auth: oauthConfig,
projectPath,
ref,
filePath,
diff --git a/app/assets/javascripts/ide/lib/gitlab_web_ide/get_oauth_config.js b/app/assets/javascripts/ide/lib/gitlab_web_ide/get_oauth_config.js
new file mode 100644
index 00000000000..5493a9ba7c7
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/gitlab_web_ide/get_oauth_config.js
@@ -0,0 +1,12 @@
+export const getOAuthConfig = ({ clientId, callbackUrl }) => {
+ if (!clientId) {
+ return undefined;
+ }
+
+ return {
+ type: 'oauth',
+ clientId,
+ callbackUrl,
+ protectRefreshToken: true,
+ };
+};
diff --git a/app/assets/javascripts/ide/lib/gitlab_web_ide/index.js b/app/assets/javascripts/ide/lib/gitlab_web_ide/index.js
index 8311e11672e..87e0002c8c8 100644
--- a/app/assets/javascripts/ide/lib/gitlab_web_ide/index.js
+++ b/app/assets/javascripts/ide/lib/gitlab_web_ide/index.js
@@ -1,2 +1,4 @@
export * from './get_base_config';
+export * from './get_oauth_config';
+export * from './handle_tracking_event';
export * from './setup_root_element';
diff --git a/app/assets/javascripts/ide/mount_oauth_callback.js b/app/assets/javascripts/ide/mount_oauth_callback.js
new file mode 100644
index 00000000000..79fffb24f8e
--- /dev/null
+++ b/app/assets/javascripts/ide/mount_oauth_callback.js
@@ -0,0 +1,12 @@
+import { oauthCallback } from '@gitlab/web-ide';
+import { getBaseConfig, getOAuthConfig } from './lib/gitlab_web_ide';
+
+export const mountOAuthCallback = () => {
+ const el = document.getElementById('ide');
+
+ return oauthCallback({
+ ...getBaseConfig(),
+ username: gon.current_username,
+ auth: getOAuthConfig(el.dataset),
+ });
+};
diff --git a/app/assets/javascripts/pages/ide/index.js b/app/assets/javascripts/pages/ide/index/index.js
index 15933256e75..15933256e75 100644
--- a/app/assets/javascripts/pages/ide/index.js
+++ b/app/assets/javascripts/pages/ide/index/index.js
diff --git a/app/assets/javascripts/pages/ide/oauth_redirect/index.js b/app/assets/javascripts/pages/ide/oauth_redirect/index.js
new file mode 100644
index 00000000000..ee9233fab38
--- /dev/null
+++ b/app/assets/javascripts/pages/ide/oauth_redirect/index.js
@@ -0,0 +1,3 @@
+import { mountOAuthCallback } from '~/ide/mount_oauth_callback';
+
+mountOAuthCallback();
diff --git a/app/assets/javascripts/sidebar/components/labels/labels_select_vue/dropdown_title.vue b/app/assets/javascripts/sidebar/components/labels/labels_select_vue/dropdown_title.vue
index 50fcd3c9350..478d261d06c 100644
--- a/app/assets/javascripts/sidebar/components/labels/labels_select_vue/dropdown_title.vue
+++ b/app/assets/javascripts/sidebar/components/labels/labels_select_vue/dropdown_title.vue
@@ -37,7 +37,6 @@ export default {
category="tertiary"
size="small"
class="float-right js-sidebar-dropdown-toggle gl-mr-n2"
- data-qa-selector="labels_edit_button"
@click="toggleDropdownContents"
>
{{ __('Edit') }}
diff --git a/app/assets/javascripts/super_sidebar/components/menu_section.vue b/app/assets/javascripts/super_sidebar/components/menu_section.vue
index a672e254004..f93a0256bd4 100644
--- a/app/assets/javascripts/super_sidebar/components/menu_section.vue
+++ b/app/assets/javascripts/super_sidebar/components/menu_section.vue
@@ -111,7 +111,7 @@ export default {
:id="`menu-section-button-${itemId}`"
class="gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-min-h-7 gl-gap-3 gl-mb-2 gl-py-2 gl-px-3 gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-appearance-none gl-border-0 gl-bg-transparent gl-text-left gl-w-full gl-focus--focus"
:class="computedLinkClasses"
- data-qa-selector="menu_section_button"
+ data-testid="menu-section-button"
:data-qa-section-name="item.title"
v-bind="buttonProps"
@click="isExpanded = !isExpanded"
@@ -153,7 +153,7 @@ export default {
:id="itemId"
v-model="isExpanded"
class="gl-list-style-none gl-p-0 gl-m-0 gl-transition-duration-medium gl-transition-timing-function-ease"
- data-qa-selector="menu_section"
+ data-testid="menu-section"
:data-qa-section-name="item.title"
>
<slot>
diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
index 52015484cb5..3beec4ccc14 100644
--- a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
+++ b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue
@@ -188,7 +188,6 @@ export default {
class="super-sidebar"
:class="peekClasses"
data-testid="super-sidebar"
- data-qa-selector="navbar"
:inert="sidebarState.isCollapsed"
@mouseenter="isMouseover = true"
@mouseleave="isMouseover = false"
diff --git a/app/assets/javascripts/super_sidebar/components/user_menu.vue b/app/assets/javascripts/super_sidebar/components/user_menu.vue
index 5dab74374df..1e8f0a81088 100644
--- a/app/assets/javascripts/super_sidebar/components/user_menu.vue
+++ b/app/assets/javascripts/super_sidebar/components/user_menu.vue
@@ -150,7 +150,7 @@ export default {
href: this.data.sign_out_link,
extraAttrs: {
'data-method': 'post',
- 'data-testid': 'sign_out_link',
+ 'data-testid': 'sign-out-link',
class: 'sign-out-link',
},
},
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
index 2bdc8a174d0..e12e06a2454 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
@@ -36,11 +36,6 @@ export default {
required: false,
default: 'confirm-danger-button',
},
- buttonQaSelector: {
- type: String,
- required: false,
- default: null,
- },
buttonVariant: {
type: String,
required: false,
@@ -58,7 +53,6 @@ export default {
:variant="buttonVariant"
:disabled="disabled"
:data-testid="buttonTestid"
- :data-qa-selector="buttonQaSelector"
>{{ buttonText }}</gl-button
>
<confirm-danger-modal
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
index 67ad7769c7c..f3b483c5f53 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
@@ -100,7 +100,7 @@ export default {
type="search"
class="mb-3"
autofocus
- data-qa-selector="project_search_field"
+ data-testid="project-search-field"
@input="onInput"
/>
<div class="d-flex flex-column">
@@ -120,7 +120,7 @@ export default {
:project="project"
:matcher="searchQuery"
class="js-project-list-item"
- data-qa-selector="project_list_item"
+ data-testid="project-list-item"
@click="projectClicked(project)"
/>
</div>
diff --git a/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue b/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
index c1ec39e1545..b81d288d932 100644
--- a/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
+++ b/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
@@ -110,7 +110,6 @@ export default {
:loading="isLoading"
:variant="variant"
:category="category"
- :data-qa-selector="`${feature.type}_mr_button`"
@click="mutate"
>{{ $options.i18n.buttonLabel }}</gl-button
>