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-11-22 03:10:40 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-11-22 03:10:40 +0300
commite3736bd03e55076fb8d9f5b4cc4602b32d13b2ec (patch)
treedd15325d34dd9bdb5fe37570f1ae691e6e329b7c /app/assets
parenta3e6d34643e760d1a8b8bd1e7e32d8d74c1ea678 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/access_tokens/components/access_token_table_app.vue2
-rw-r--r--app/assets/javascripts/access_tokens/components/expires_at_field.vue2
-rw-r--r--app/assets/javascripts/access_tokens/components/new_access_token_app.vue4
-rw-r--r--app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue12
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue4
-rw-r--r--app/assets/javascripts/badges/components/badge_list.vue6
-rw-r--r--app/assets/javascripts/badges/components/badge_settings.vue4
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_trigger.vue8
-rw-r--r--app/assets/javascripts/invite_members/constants.js1
-rw-r--r--app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue4
-rw-r--r--app/assets/javascripts/ml/model_registry/components/model_version_list.vue143
-rw-r--r--app/assets/javascripts/ml/model_registry/components/model_version_row.vue49
-rw-r--r--app/assets/javascripts/ml/model_registry/constants.js2
-rw-r--r--app/assets/javascripts/ml/model_registry/graphql/queries/get_model_versions.query.graphql22
-rw-r--r--app/assets/javascripts/ml/model_registry/translations.js3
-rw-r--r--app/assets/javascripts/pages/profiles/two_factor_auths/index.js2
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue4
-rw-r--r--app/assets/javascripts/super_sidebar/components/user_menu.vue4
-rw-r--r--app/assets/javascripts/terms/components/app.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/merge_checks.vue30
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue24
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/merge_checks.subscription.graphql14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js11
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue5
-rw-r--r--app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_new.vue10
28 files changed, 336 insertions, 56 deletions
diff --git a/app/assets/javascripts/access_tokens/components/access_token_table_app.vue b/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
index 9a7296b6b1f..3b71e39d69b 100644
--- a/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
+++ b/app/assets/javascripts/access_tokens/components/access_token_table_app.vue
@@ -158,7 +158,7 @@ export default {
:aria-label="$options.i18n.revokeButton"
:data-confirm="modalMessage(name)"
data-confirm-btn-variant="danger"
- data-qa-selector="revoke_button"
+ data-testid="revoke-button"
data-method="put"
:href="revokePath"
icon="remove"
diff --git a/app/assets/javascripts/access_tokens/components/expires_at_field.vue b/app/assets/javascripts/access_tokens/components/expires_at_field.vue
index 38501d63d3a..65206670a3c 100644
--- a/app/assets/javascripts/access_tokens/components/expires_at_field.vue
+++ b/app/assets/javascripts/access_tokens/components/expires_at_field.vue
@@ -68,7 +68,7 @@ export default {
:input-name="inputAttrs.name"
:input-id="inputAttrs.id"
:placeholder="inputAttrs.placeholder"
- data-qa-selector="expiry_date_field"
+ data-testid="expiry-date-field"
/>
<template #description>
<template v-if="description">
diff --git a/app/assets/javascripts/access_tokens/components/new_access_token_app.vue b/app/assets/javascripts/access_tokens/components/new_access_token_app.vue
index 4b51b4333aa..f476503c091 100644
--- a/app/assets/javascripts/access_tokens/components/new_access_token_app.vue
+++ b/app/assets/javascripts/access_tokens/components/new_access_token_app.vue
@@ -45,7 +45,7 @@ export default {
formInputGroupProps() {
return {
id: this.$options.tokenInputId,
- 'data-qa-selector': 'created_access_token_field',
+ 'data-testid': 'created-access-token-field',
name: this.$options.tokenInputId,
};
},
@@ -110,7 +110,7 @@ export default {
@[$options.EVENT_ERROR]="onError"
@[$options.EVENT_SUCCESS]="onSuccess"
>
- <div ref="container" data-testid="access-token-section" data-qa-selector="access_token_section">
+ <div ref="container" data-testid="access-token-section">
<gl-alert
v-if="newToken"
variant="success"
diff --git a/app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue b/app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue
index d3b914ea8aa..240bf005532 100644
--- a/app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue
+++ b/app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue
@@ -115,14 +115,10 @@ export default {
</gl-sprintf>
</p>
- <gl-card
- class="codes-to-print gl-my-5"
- data-testid="recovery-codes"
- data-qa-selector="codes_content"
- >
+ <gl-card class="codes-to-print gl-my-5" data-testid="recovery-codes">
<ul class="gl-m-0 gl-pl-5">
<li v-for="(code, index) in codes" :key="index">
- <span class="gl-font-monospace" data-qa-selector="code_content">{{ code }}</span>
+ <span class="gl-font-monospace" data-testid="code-content">{{ code }}</span>
</li>
</ul>
</gl-card>
@@ -131,7 +127,7 @@ export default {
<clipboard-button
:title="$options.i18n.copyButton"
:text="codesAsString"
- data-qa-selector="copy_button"
+ data-testid="copy-button"
@click="handleButtonClick($options.copyButtonAction)"
>
{{ $options.i18n.copyButton }}
@@ -163,7 +159,7 @@ export default {
:disabled="proceedButtonDisabled"
:title="$options.i18n.proceedButton"
variant="confirm"
- data-qa-selector="proceed_button"
+ data-testid="proceed-button"
data-track-action="click_button"
:data-track-label="`${$options.trackingLabelPrefix}proceed_button`"
>{{ $options.i18n.proceedButton }}</gl-button
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index 19da1253a17..0645ffa35dc 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -183,9 +183,7 @@ export default {
})
.catch((error) => {
createAlert({
- message: s__(
- 'Badges|Adding the badge failed, please check the entered URLs and try again.',
- ),
+ message: s__('Badges|Failed to add new badge. Check the URLs, then try again.'),
});
throw error;
});
diff --git a/app/assets/javascripts/badges/components/badge_list.vue b/app/assets/javascripts/badges/components/badge_list.vue
index 12c9662b30d..a4f88067fa9 100644
--- a/app/assets/javascripts/badges/components/badge_list.vue
+++ b/app/assets/javascripts/badges/components/badge_list.vue
@@ -29,10 +29,8 @@ export default {
GlModal: GlModalDirective,
},
i18n: {
- emptyGroupMessage: s__('Badges|This group has no badges, start by creating a new one above.'),
- emptyProjectMessage: s__(
- 'Badges|This project has no badges, start by creating a new one above.',
- ),
+ emptyGroupMessage: s__('Badges|This group has no badges. Add an existing badge or create one.'),
+ emptyProjectMessage: s__('Badges|This project has no badges. Start by adding a new badge.'),
},
data() {
return {
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
index f0d354c6378..32c24564d21 100644
--- a/app/assets/javascripts/badges/components/badge_settings.vue
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -25,7 +25,7 @@ export default {
addButton: s__('Badges|Add badge'),
addFormTitle: s__('Badges|Add new badge'),
deleteModalText: s__(
- 'Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored.',
+ 'Badges|If you delete this badge, you %{strongStart}cannot%{strongEnd} restore it.',
),
},
data() {
@@ -74,7 +74,7 @@ export default {
})
.catch((error) => {
createAlert({
- message: s__('Badges|Deleting the badge failed, please try again.'),
+ message: s__('Badges|Failed to delete the badge. Try again.'),
});
throw error;
});
diff --git a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
index b37333d923c..7f76b7ca1ac 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -4,7 +4,6 @@ import { s__ } from '~/locale';
import eventHub from '../event_hub';
import {
TRIGGER_ELEMENT_BUTTON,
- TRIGGER_DEFAULT_TESTID,
TRIGGER_ELEMENT_WITH_EMOJI,
TRIGGER_ELEMENT_DROPDOWN_WITH_EMOJI,
TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN,
@@ -42,17 +41,12 @@ export default {
required: false,
default: 'button',
},
- testId: {
- type: String,
- required: false,
- default: TRIGGER_DEFAULT_TESTID,
- },
},
computed: {
componentAttributes() {
return {
class: this.classes,
- 'data-testid': this.testId,
+ 'data-testid': 'invite-members-button',
};
},
item() {
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index f44313ff41f..3b2840ecf11 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -20,7 +20,6 @@ export const TRIGGER_ELEMENT_WITH_EMOJI = 'text-emoji';
export const TRIGGER_ELEMENT_DROPDOWN_WITH_EMOJI = 'dropdown-text-emoji';
export const TRIGGER_ELEMENT_DISCLOSURE_DROPDOWN = 'dropdown-text';
export const INVITE_MEMBER_MODAL_TRACKING_CATEGORY = 'invite_members_modal';
-export const TRIGGER_DEFAULT_TESTID = 'invite-members-button';
export const IMPORT_PROJECT_MEMBERS_MODAL_TRACKING_CATEGORY = 'invite_project_members_modal';
export const IMPORT_PROJECT_MEMBERS_MODAL_TRACKING_LABEL = 'project-members-page';
export const MEMBERS_MODAL_DEFAULT_TITLE = s__('InviteMembersModal|Invite members');
diff --git a/app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue b/app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue
index e8ec8f157ef..2c60e05dc57 100644
--- a/app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue
+++ b/app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue
@@ -2,11 +2,13 @@
import { GlTab, GlTabs, GlBadge } from '@gitlab/ui';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import ModelVersionList from '~/ml/model_registry/components/model_version_list.vue';
import * as i18n from '../translations';
export default {
name: 'ShowMlModelApp',
components: {
+ ModelVersionList,
TitleArea,
GlTabs,
GlTab,
@@ -59,6 +61,8 @@ export default {
{{ $options.i18n.MODEL_OTHER_VERSIONS_TAB_LABEL }}
<gl-badge size="sm" class="gl-tab-counter-badge">{{ versionCount }}</gl-badge>
</template>
+
+ <model-version-list :model-id="model.id" />
</gl-tab>
<gl-tab>
<template #title>
diff --git a/app/assets/javascripts/ml/model_registry/components/model_version_list.vue b/app/assets/javascripts/ml/model_registry/components/model_version_list.vue
new file mode 100644
index 00000000000..bf036b1085e
--- /dev/null
+++ b/app/assets/javascripts/ml/model_registry/components/model_version_list.vue
@@ -0,0 +1,143 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { n__ } from '~/locale';
+import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
+import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
+import * as Sentry from '~/sentry/sentry_browser_wrapper';
+import {
+ FAILED_TO_LOAD_MODEL_VERSIONS_MESSAGE,
+ NO_VERSIONS_LABEL,
+} from '~/ml/model_registry/translations';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import getModelVersionsQuery from '../graphql/queries/get_model_versions.query.graphql';
+import { GRAPHQL_PAGE_SIZE } from '../constants';
+import ModelVersionRow from './model_version_row.vue';
+
+export default {
+ components: {
+ GlAlert,
+ ModelVersionRow,
+ PackagesListLoader,
+ RegistryList,
+ },
+ props: {
+ modelId: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ modelVersions: {},
+ fetchModelVersionsError: false,
+ };
+ },
+ apollo: {
+ modelVersions: {
+ query: getModelVersionsQuery,
+ variables() {
+ return this.queryVariables;
+ },
+ update(data) {
+ return data.mlModel?.versions ?? {};
+ },
+ error(error) {
+ this.fetchModelVersionsError = true;
+ Sentry.captureException(error);
+ },
+ },
+ },
+ computed: {
+ gid() {
+ return convertToGraphQLId('Ml::Model', this.modelId);
+ },
+ isListEmpty() {
+ return this.count === 0;
+ },
+ isLoading() {
+ return this.$apollo.queries.modelVersions.loading;
+ },
+ pageInfo() {
+ return this.modelVersions?.pageInfo ?? {};
+ },
+ listTitle() {
+ return n__('%d version', '%d versions', this.versions.length);
+ },
+ queryVariables() {
+ return {
+ id: this.gid,
+ first: GRAPHQL_PAGE_SIZE,
+ };
+ },
+ versions() {
+ return this.modelVersions?.nodes ?? [];
+ },
+ count() {
+ return this.modelVersions?.count ?? 0;
+ },
+ },
+ methods: {
+ fetchPreviousVersionsPage() {
+ const variables = {
+ ...this.queryVariables,
+ first: null,
+ last: GRAPHQL_PAGE_SIZE,
+ before: this.pageInfo?.startCursor,
+ };
+ this.$apollo.queries.modelVersions.fetchMore({
+ variables,
+ updateQuery: (previousResult, { fetchMoreResult }) => {
+ return fetchMoreResult;
+ },
+ });
+ },
+ fetchNextVersionsPage() {
+ const variables = {
+ ...this.queryVariables,
+ first: GRAPHQL_PAGE_SIZE,
+ last: null,
+ after: this.pageInfo?.endCursor,
+ };
+
+ this.$apollo.queries.modelVersions.fetchMore({
+ variables,
+ updateQuery: (previousResult, { fetchMoreResult }) => {
+ return fetchMoreResult;
+ },
+ });
+ },
+ },
+ i18n: {
+ FAILED_TO_LOAD_MODEL_VERSIONS_MESSAGE,
+ NO_VERSIONS_LABEL,
+ },
+};
+</script>
+<template>
+ <div>
+ <div v-if="isLoading">
+ <packages-list-loader />
+ </div>
+ <gl-alert v-else-if="fetchModelVersionsError" variant="danger" :dismissible="false">{{
+ $options.i18n.FAILED_TO_LOAD_MODEL_VERSIONS_MESSAGE
+ }}</gl-alert>
+ <div v-else-if="isListEmpty" class="gl-text-secondary">
+ {{ $options.i18n.NO_VERSIONS_LABEL }}
+ </div>
+ <div v-else>
+ <registry-list
+ :hidden-delete="true"
+ :is-loading="isLoading"
+ :items="versions"
+ :pagination="pageInfo"
+ :title="listTitle"
+ @prev-page="fetchPreviousVersionsPage"
+ @next-page="fetchNextVersionsPage"
+ >
+ <template #default="{ item }">
+ <model-version-row :model-version="item" />
+ </template>
+ </registry-list>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/ml/model_registry/components/model_version_row.vue b/app/assets/javascripts/ml/model_registry/components/model_version_row.vue
new file mode 100644
index 00000000000..7e024ff546d
--- /dev/null
+++ b/app/assets/javascripts/ml/model_registry/components/model_version_row.vue
@@ -0,0 +1,49 @@
+<script>
+import { GlLink, GlSprintf, GlTruncate } from '@gitlab/ui';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+export default {
+ name: 'MlModelVersionRow',
+ components: {
+ ListItem,
+ GlLink,
+ GlTruncate,
+ GlSprintf,
+ TimeAgoTooltip,
+ },
+ props: {
+ modelVersion: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ pathToDetails() {
+ return this.modelVersion._links?.showPath;
+ },
+ },
+};
+</script>
+
+<template>
+ <list-item v-bind="$attrs">
+ <template #left-primary>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-link class="gl-text-body" :href="pathToDetails">
+ <gl-truncate :text="modelVersion.version" />
+ </gl-link>
+ </div>
+ </template>
+
+ <template #left-secondary>
+ <span>
+ <gl-sprintf :message="__('Created %{timestamp}')">
+ <template #timestamp>
+ <time-ago-tooltip :time="modelVersion.createdAt" />
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+ </list-item>
+</template>
diff --git a/app/assets/javascripts/ml/model_registry/constants.js b/app/assets/javascripts/ml/model_registry/constants.js
index 10c21ec4f12..7b94264dfd5 100644
--- a/app/assets/javascripts/ml/model_registry/constants.js
+++ b/app/assets/javascripts/ml/model_registry/constants.js
@@ -11,3 +11,5 @@ export const BASE_SORT_FIELDS = Object.freeze([
label: s__('MlExperimentTracking|Created at'),
},
]);
+
+export const GRAPHQL_PAGE_SIZE = 30;
diff --git a/app/assets/javascripts/ml/model_registry/graphql/queries/get_model_versions.query.graphql b/app/assets/javascripts/ml/model_registry/graphql/queries/get_model_versions.query.graphql
new file mode 100644
index 00000000000..1b48a67a0bd
--- /dev/null
+++ b/app/assets/javascripts/ml/model_registry/graphql/queries/get_model_versions.query.graphql
@@ -0,0 +1,22 @@
+query getModelVersions($id: MlModelID!, $first: Int, $last: Int, $after: String, $before: String) {
+ mlModel(id: $id) {
+ id
+ versions(after: $after, before: $before, first: $first, last: $last) {
+ count
+ nodes {
+ id
+ version
+ createdAt
+ _links {
+ showPath
+ }
+ }
+ pageInfo {
+ hasNextPage
+ hasPreviousPage
+ endCursor
+ startCursor
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/ml/model_registry/translations.js b/app/assets/javascripts/ml/model_registry/translations.js
index 689eeb45b00..bbafde0b943 100644
--- a/app/assets/javascripts/ml/model_registry/translations.js
+++ b/app/assets/javascripts/ml/model_registry/translations.js
@@ -32,3 +32,6 @@ export const CI_SECTION_LABEL = s__('MlModelRegistry|CI Info');
export const JOB_LABEL = __('Job');
export const CI_USER_LABEL = s__('MlModelRegistry|Triggered by');
export const CI_MR_LABEL = __('Merge request');
+export const FAILED_TO_LOAD_MODEL_VERSIONS_MESSAGE = s__(
+ 'MlModelRegistry|Failed to load model versions',
+);
diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
index 8fe822e4639..41952a33c05 100644
--- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
+++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
@@ -8,7 +8,7 @@ const skippable = twoFactorNode ? parseBoolean(twoFactorNode.dataset.twoFactorSk
if (skippable) {
const button = `<div class="gl-alert-actions">
- <a class="btn gl-button btn-md btn-confirm gl-alert-action" data-qa-selector="configure_it_later_button" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>
+ <a class="btn gl-button btn-md btn-confirm gl-alert-action" data-testid="configure-it-later-button" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>
</div>`;
const flashAlert = document.querySelector('.flash-alert');
if (flashAlert) {
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 915f6578ac3..e9a67a401b8 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -42,7 +42,7 @@ export default {
text: __('Delete account'),
attributes: {
variant: 'danger',
- 'data-qa-selector': 'confirm_delete_account_button',
+ 'data-testid': 'confirm-delete-account-button',
category: 'primary',
disabled: !this.canSubmit,
},
@@ -128,7 +128,7 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
name="password"
class="form-control"
type="password"
- data-qa-selector="password_confirmation_field"
+ data-testid="password-confirmation-field"
aria-labelledby="input-label"
/>
<input
diff --git a/app/assets/javascripts/super_sidebar/components/user_menu.vue b/app/assets/javascripts/super_sidebar/components/user_menu.vue
index 2823aeaee7b..db769df873f 100644
--- a/app/assets/javascripts/super_sidebar/components/user_menu.vue
+++ b/app/assets/javascripts/super_sidebar/components/user_menu.vue
@@ -97,7 +97,7 @@ export default {
text: this.$options.i18n.editProfile,
href: this.data.settings.profile_path,
extraAttrs: {
- 'data-testid': 'edit_profile_link',
+ 'data-testid': 'edit-profile-link',
...USER_MENU_TRACKING_DEFAULTS,
'data-track-label': 'user_edit_profile',
},
@@ -242,7 +242,7 @@ export default {
:entity-name="data.name"
:src="data.avatar_url"
aria-hidden="true"
- data-testid="user_avatar_content"
+ data-testid="user-avatar-content"
/>
<span
v-if="showNotificationDot"
diff --git a/app/assets/javascripts/terms/components/app.vue b/app/assets/javascripts/terms/components/app.vue
index 29099bcc366..75ee0e16d4e 100644
--- a/app/assets/javascripts/terms/components/app.vue
+++ b/app/assets/javascripts/terms/components/app.vue
@@ -66,7 +66,7 @@ export default {
<template>
<div>
- <div class="gl-relative gl-pb-0 gl-px-0" data-qa-selector="terms_content">
+ <div class="gl-relative gl-pb-0 gl-px-0" data-testid="terms-content">
<div
class="terms-fade gl-absolute gl-left-5 gl-right-5 gl-bottom-0 gl-h-11 gl-pointer-events-none"
></div>
@@ -97,7 +97,7 @@ export default {
type="submit"
variant="confirm"
:disabled="acceptDisabled"
- data-qa-selector="accept_terms_button"
+ data-testid="accept-terms-button"
>{{ $options.i18n.accept }}</gl-button
>
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/merge_checks.vue b/app/assets/javascripts/vue_merge_request_widget/components/merge_checks.vue
index ac403c2c6f2..750f53a29b6 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/merge_checks.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/merge_checks.vue
@@ -1,9 +1,12 @@
<script>
import { GlSkeletonLoader } from '@gitlab/ui';
import { __, n__, sprintf } from '~/locale';
+import { TYPENAME_MERGE_REQUEST } from '~/graphql_shared/constants';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
import { COMPONENTS } from '~/vue_merge_request_widget/components/checks/constants';
import mergeRequestQueryVariablesMixin from '../mixins/merge_request_query_variables';
import mergeChecksQuery from '../queries/merge_checks.query.graphql';
+import mergeChecksSubscription from '../queries/merge_checks.subscription.graphql';
import StateContainer from './state_container.vue';
import BoldText from './bold_text.vue';
@@ -18,6 +21,31 @@ export default {
return this.mergeRequestQueryVariables;
},
update: (data) => data?.project?.mergeRequest,
+ subscribeToMore: {
+ document() {
+ return mergeChecksSubscription;
+ },
+ skip() {
+ return !this.mr?.id;
+ },
+ variables() {
+ return {
+ issuableId: convertToGraphQLId(TYPENAME_MERGE_REQUEST, this.mr?.id),
+ };
+ },
+ updateQuery(
+ _,
+ {
+ subscriptionData: {
+ data: { mergeRequestMergeStatusUpdated },
+ },
+ },
+ ) {
+ if (mergeRequestMergeStatusUpdated) {
+ this.state = mergeRequestMergeStatusUpdated;
+ }
+ },
+ },
},
},
components: {
@@ -86,7 +114,7 @@ export default {
</script>
<template>
- <div>
+ <div class="gl-rounded-0!">
<state-container
:is-loading="isLoading"
:status="statusIcon"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
index 122abc7d034..8fb2b6acc4d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
@@ -50,7 +50,6 @@ export default {
{
text: s__('mrWidget|Refresh now'),
onClick: () => this.refresh(),
- testId: 'merge-request-failed-refresh-button',
},
];
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index cc116b42f1e..e2f301b1911 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -54,6 +54,7 @@ import getStateQuery from './queries/get_state.query.graphql';
import getStateSubscription from './queries/get_state.subscription.graphql';
import ReportWidgetContainer from './components/report_widget_container.vue';
import MrWidgetReadyToMerge from './components/states/new_ready_to_merge.vue';
+import MergeChecks from './components/merge_checks.vue';
export default {
// False positive i18n lint: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25
@@ -94,6 +95,7 @@ export default {
MergeChecksFailed: () => import('./components/states/merge_checks_failed.vue'),
ReadyToMerge: ReadyToMergeState,
ReportWidgetContainer,
+ MergeChecks,
},
apollo: {
state: {
@@ -248,6 +250,25 @@ export default {
hasExtensions() {
return registeredExtensions.extensions.length;
},
+ mergeBlockedComponentEnabled() {
+ return (
+ window.gon?.features?.mergeBlockedComponent &&
+ !(
+ [
+ 'checking',
+ 'preparing',
+ 'nothingToMerge',
+ 'archived',
+ 'missingBranch',
+ 'merged',
+ 'closed',
+ 'merging',
+ 'autoMergeEnabled',
+ 'shaMismatch',
+ ].includes(this.mr.state) || ['MERGING', 'AUTO_MERGE'].includes(this.mr.machineValue)
+ )
+ );
+ },
},
watch: {
'mr.machineValue': {
@@ -556,7 +577,8 @@ export default {
</div>
<div class="mr-widget-section" data-testid="mr-widget-content">
- <component :is="componentName" :mr="mr" :service="service" />
+ <merge-checks v-if="mergeBlockedComponentEnabled" :mr="mr" :service="service" />
+ <component :is="componentName" v-else :mr="mr" :service="service" />
<ready-to-merge
v-if="mr.commitsCount"
v-show="shouldShowMergeDetails"
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/merge_checks.subscription.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/merge_checks.subscription.graphql
new file mode 100644
index 00000000000..9cf2b9be405
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/merge_checks.subscription.graphql
@@ -0,0 +1,14 @@
+subscription mergeChecksSubscrption($issuableId: IssuableID!) {
+ mergeRequestMergeStatusUpdated(issuableId: $issuableId) {
+ ... on MergeRequest {
+ id
+ userPermissions {
+ canMerge
+ }
+ mergeabilityChecks {
+ identifier
+ status
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
index d6bab074f3f..5765d7a56fa 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
@@ -15,25 +15,25 @@ export default function deviseState() {
return stateKey.missingBranch;
}
if (this.detailedMergeStatus === DETAILED_MERGE_STATUS.CHECKING) {
- return stateKey.checking;
+ return window.gon?.features?.mergeBlockedComponent ? null : stateKey.checking;
}
if (this.hasConflicts) {
- return stateKey.conflicts;
+ return window.gon?.features?.mergeBlockedComponent ? null : stateKey.conflicts;
}
if (this.shouldBeRebased) {
- return stateKey.rebase;
+ return window.gon?.features?.mergeBlockedComponent ? null : stateKey.rebase;
}
if (this.hasMergeChecksFailed && !this.autoMergeEnabled) {
- return stateKey.mergeChecksFailed;
+ return window.gon?.features?.mergeBlockedComponent ? null : stateKey.mergeChecksFailed;
}
if (this.detailedMergeStatus === DETAILED_MERGE_STATUS.CI_MUST_PASS) {
- return stateKey.pipelineFailed;
+ return window.gon?.features?.mergeBlockedComponent ? null : stateKey.pipelineFailed;
}
if (this.detailedMergeStatus === DETAILED_MERGE_STATUS.DRAFT_STATUS) {
- return stateKey.draft;
+ return window.gon?.features?.mergeBlockedComponent ? null : stateKey.draft;
}
if (this.detailedMergeStatus === DETAILED_MERGE_STATUS.DISCUSSIONS_NOT_RESOLVED) {
- return stateKey.unresolvedDiscussions;
+ return window.gon?.features?.mergeBlockedComponent ? null : stateKey.unresolvedDiscussions;
}
if (this.canMerge && this.isSHAMismatch) {
return stateKey.shaMismatch;
@@ -47,5 +47,5 @@ export default function deviseState() {
) {
return stateKey.readyToMerge;
}
- return stateKey.checking;
+ return window.gon?.features?.mergeBlockedComponent ? null : stateKey.checking;
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index a1b86c86979..473e8a936fd 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -30,7 +30,8 @@ export default class MergeRequestStore {
this.stateMachine = machine(STATE_MACHINE.definition);
this.machineValue = this.stateMachine.value;
- this.mergeDetailsCollapsed = window.innerWidth < 768;
+ this.mergeDetailsCollapsed =
+ !window.gon?.features?.mergeBlockedComponent && window.innerWidth < 768;
this.mergeError = data.mergeError;
this.multipleApprovalRulesAvailable = data.multiple_approval_rules_available || false;
this.id = data.id;
@@ -196,7 +197,9 @@ export default class MergeRequestStore {
}
this.commitsCount = mergeRequest.commitCount;
- this.branchMissing = !mergeRequest.sourceBranchExists || !mergeRequest.targetBranchExists;
+ this.branchMissing =
+ mergeRequest.detailedMergeStatus !== 'NOT_OPEN' &&
+ (!mergeRequest.sourceBranchExists || !mergeRequest.targetBranchExists);
this.hasConflicts = mergeRequest.conflicts;
this.hasMergeableDiscussionsState = mergeRequest.mergeableDiscussionsState === false;
this.mergeError = mergeRequest.mergeError;
@@ -418,6 +421,10 @@ export default class MergeRequestStore {
}
toggleMergeDetails(val = !this.mergeDetailsCollapsed) {
+ if (window.gon?.features?.mergeBlockedComponent) {
+ return;
+ }
+
this.mergeDetailsCollapsed = val;
}
}
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
index a1ef1f30ebb..5019ab901fd 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
@@ -72,7 +72,7 @@ export default {
attributes: {
variant: 'danger',
disabled: !this.isValid,
- 'data-qa-selector': 'confirm_danger_modal_button',
+ 'data-testid': 'confirm-danger-modal-button',
},
};
},
@@ -133,8 +133,7 @@ export default {
id="confirm_name_input"
v-model="confirmationPhrase"
class="form-control"
- data-qa-selector="confirm_danger_field"
- data-testid="confirm-danger-input"
+ data-testid="confirm-danger-field"
type="text"
/>
</gl-form-group>
diff --git a/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue b/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue
index 0455685627d..b03da19a896 100644
--- a/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue
+++ b/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue
@@ -179,7 +179,6 @@ export default {
:aria-label="toggleVisibilityLabel"
:icon="toggleVisibilityIcon"
data-testid="toggle-visibility-button"
- data-qa-selector="toggle_visibility_button"
@click.stop="handleToggleVisibilityButtonClick"
/>
<clipboard-button
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_new.vue b/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_new.vue
index 3b6dcace8fe..89b64f03e1f 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_new.vue
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_new.vue
@@ -66,6 +66,10 @@ export default {
const page = getPageParamValue(this.number);
return getPageSearchString(this.blamePath, page);
},
+ codeStyling() {
+ const defaultGutterWidth = 96;
+ return { marginLeft: `${this.$refs.lineNumbers?.offsetWidth || defaultGutterWidth}px` };
+ },
},
methods: {
handleChunkAppear() {
@@ -80,7 +84,7 @@ export default {
</script>
<template>
<div class="gl-display-flex">
- <div v-if="shouldHighlight" class="gl-display-flex gl-flex-direction-column">
+ <div v-if="shouldHighlight" class="gl-display-flex gl-flex-direction-column gl-absolute">
<div
v-for="(n, index) in totalLines"
:key="index"
@@ -102,14 +106,14 @@ export default {
</div>
</div>
- <div v-else class="line-numbers gl-p-0! gl-mr-3 gl-text-transparent">
+ <div v-else ref="lineNumbers" class="line-numbers gl-p-0! gl-mr-3 gl-text-transparent">
<!-- Placeholder for line numbers while content is not highlighted -->
</div>
<gl-intersection-observer class="gl-w-full" @appear="handleChunkAppear">
<pre
class="gl-m-0 gl-p-0! gl-w-full gl-overflow-visible! gl-border-none! code highlight gl-line-height-0"
- ><code v-if="shouldHighlight" v-safe-html="highlightedContent" data-testid="content"></code><code v-else v-once class="line gl-white-space-pre-wrap! gl-ml-1" data-testid="content" v-text="rawContent"></code></pre>
+ ><code v-if="shouldHighlight" v-safe-html="highlightedContent" :style="codeStyling" data-testid="content"></code><code v-else v-once class="line gl-white-space-pre-wrap! gl-ml-1" data-testid="content" v-text="rawContent"></code></pre>
</gl-intersection-observer>
</div>
</template>