summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-08 21:08:52 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-08 21:08:52 +0000
commiteef3d92529e978c3cabafc321965569776c289b7 (patch)
tree7983f7ed7bafb52a7941c1cae5dc1b5d56d36ea1
parent33ed90457e6c14d8344882efa01355c080e14149 (diff)
downloadgitlab-ce-eef3d92529e978c3cabafc321965569776c289b7.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--Gemfile.lock2
-rw-r--r--app/assets/javascripts/authentication/two_factor_auth/components/recovery_codes.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_form.vue2
-rw-r--r--app/assets/javascripts/environments/components/environments_detail_header.vue2
-rw-r--r--app/assets/javascripts/feature_flags/components/feature_flags.vue5
-rw-r--r--app/assets/javascripts/feature_flags/components/new_feature_flag.vue2
-rw-r--r--app/assets/javascripts/groups/components/group_name_and_path.vue232
-rw-r--r--app/assets/javascripts/groups/create_edit_form.js29
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue2
-rw-r--r--app/assets/javascripts/issues/show/components/title.vue2
-rw-r--r--app/assets/javascripts/jira_connect/branches/pages/index.vue2
-rw-r--r--app/assets/javascripts/jira_import/components/jira_import_form.vue2
-rw-r--r--app/assets/javascripts/lib/utils/forms.js4
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue2
-rw-r--r--app/assets/javascripts/pages/admin/groups/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/groups/new/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js5
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue2
-rw-r--r--app/assets/stylesheets/framework/page_title.scss2
-rw-r--r--app/assets/stylesheets/framework/typography.scss2
-rw-r--r--app/assets/stylesheets/pages/detail_page.scss1
-rw-r--r--app/helpers/groups_helper.rb9
-rw-r--r--app/views/abuse_reports/new.html.haml2
-rw-r--r--app/views/admin/abuse_reports/index.html.haml2
-rw-r--r--app/views/admin/applications/edit.html.haml2
-rw-r--r--app/views/admin/applications/index.html.haml2
-rw-r--r--app/views/admin/applications/new.html.haml2
-rw-r--r--app/views/admin/applications/show.html.haml2
-rw-r--r--app/views/admin/background_jobs/show.html.haml2
-rw-r--r--app/views/admin/broadcast_messages/index.html.haml2
-rw-r--r--app/views/admin/deploy_keys/edit.html.haml2
-rw-r--r--app/views/admin/deploy_keys/new.html.haml2
-rw-r--r--app/views/admin/gitaly_servers/index.html.haml2
-rw-r--r--app/views/admin/groups/edit.html.haml2
-rw-r--r--app/views/admin/groups/new.html.haml2
-rw-r--r--app/views/admin/groups/show.html.haml2
-rw-r--r--app/views/admin/health_check/show.html.haml2
-rw-r--r--app/views/admin/hook_logs/show.html.haml2
-rw-r--r--app/views/admin/identities/edit.html.haml2
-rw-r--r--app/views/admin/identities/new.html.haml2
-rw-r--r--app/views/admin/labels/edit.html.haml2
-rw-r--r--app/views/admin/labels/index.html.haml2
-rw-r--r--app/views/admin/labels/new.html.haml2
-rw-r--r--app/views/admin/projects/show.html.haml2
-rw-r--r--app/views/admin/spam_logs/index.html.haml2
-rw-r--r--app/views/admin/topics/edit.html.haml2
-rw-r--r--app/views/admin/topics/new.html.haml2
-rw-r--r--app/views/admin/users/_head.html.haml2
-rw-r--r--app/views/admin/users/edit.html.haml2
-rw-r--r--app/views/admin/users/new.html.haml2
-rw-r--r--app/views/dashboard/_activity_head.html.haml2
-rw-r--r--app/views/dashboard/_groups_head.html.haml2
-rw-r--r--app/views/dashboard/_projects_head.html.haml2
-rw-r--r--app/views/dashboard/_snippets_head.html.haml2
-rw-r--r--app/views/dashboard/issues.html.haml2
-rw-r--r--app/views/dashboard/merge_requests.html.haml2
-rw-r--r--app/views/dashboard/milestones/index.html.haml2
-rw-r--r--app/views/dashboard/todos/index.html.haml2
-rw-r--r--app/views/doorkeeper/applications/edit.html.haml2
-rw-r--r--app/views/doorkeeper/applications/new.html.haml2
-rw-r--r--app/views/doorkeeper/applications/show.html.haml2
-rw-r--r--app/views/doorkeeper/authorizations/error.html.haml2
-rw-r--r--app/views/doorkeeper/authorizations/redirect.html.haml2
-rw-r--r--app/views/doorkeeper/authorizations/show.html.haml2
-rw-r--r--app/views/explore/topics/_head.html.haml2
-rw-r--r--app/views/groups/labels/edit.html.haml2
-rw-r--r--app/views/groups/labels/new.html.haml2
-rw-r--r--app/views/groups/milestones/edit.html.haml2
-rw-r--r--app/views/groups/milestones/new.html.haml2
-rw-r--r--app/views/groups/runners/edit.html.haml2
-rw-r--r--app/views/groups/settings/applications/edit.html.haml2
-rw-r--r--app/views/groups/settings/applications/show.html.haml2
-rw-r--r--app/views/import/bitbucket/status.html.haml2
-rw-r--r--app/views/import/bitbucket_server/new.html.haml2
-rw-r--r--app/views/import/bitbucket_server/status.html.haml2
-rw-r--r--app/views/import/fogbugz/new.html.haml2
-rw-r--r--app/views/import/fogbugz/new_user_map.html.haml2
-rw-r--r--app/views/import/fogbugz/status.html.haml2
-rw-r--r--app/views/import/gitea/new.html.haml2
-rw-r--r--app/views/import/gitea/status.html.haml2
-rw-r--r--app/views/import/github/new.html.haml2
-rw-r--r--app/views/import/github/status.html.haml2
-rw-r--r--app/views/import/gitlab/status.html.haml2
-rw-r--r--app/views/import/gitlab_projects/new.html.haml2
-rw-r--r--app/views/import/manifest/new.html.haml2
-rw-r--r--app/views/import/manifest/status.html.haml2
-rw-r--r--app/views/import/phabricator/new.html.haml2
-rw-r--r--app/views/invites/show.html.haml2
-rw-r--r--app/views/profiles/chat_names/new.html.haml2
-rw-r--r--app/views/profiles/passwords/new.html.haml2
-rw-r--r--app/views/projects/_visibility_modal.html.haml2
-rw-r--r--app/views/projects/blob/_new_dir.html.haml2
-rw-r--r--app/views/projects/blob/_remove.html.haml2
-rw-r--r--app/views/projects/blob/_upload.html.haml2
-rw-r--r--app/views/projects/blob/edit.html.haml2
-rw-r--r--app/views/projects/blob/new.html.haml2
-rw-r--r--app/views/projects/branches/new.html.haml2
-rw-r--r--app/views/projects/compare/index.html.haml2
-rw-r--r--app/views/projects/deploy_keys/edit.html.haml2
-rw-r--r--app/views/projects/environments/terminal.html.haml2
-rw-r--r--app/views/projects/hook_logs/show.html.haml2
-rw-r--r--app/views/projects/imports/new.html.haml2
-rw-r--r--app/views/projects/issues/edit.html.haml2
-rw-r--r--app/views/projects/issues/new.html.haml2
-rw-r--r--app/views/projects/labels/edit.html.haml2
-rw-r--r--app/views/projects/labels/new.html.haml2
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml2
-rw-r--r--app/views/projects/merge_requests/creations/_new_compare.html.haml2
-rw-r--r--app/views/projects/merge_requests/creations/_new_submit.html.haml2
-rw-r--r--app/views/projects/merge_requests/edit.html.haml2
-rw-r--r--app/views/projects/milestones/edit.html.haml2
-rw-r--r--app/views/projects/milestones/new.html.haml2
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/pages/show.html.haml2
-rw-r--r--app/views/projects/pages_domains/new.html.haml2
-rw-r--r--app/views/projects/pages_domains/show.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/edit.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/new.html.haml2
-rw-r--r--app/views/projects/pipelines/new.html.haml2
-rw-r--r--app/views/projects/runners/edit.html.haml2
-rw-r--r--app/views/projects/snippets/edit.html.haml2
-rw-r--r--app/views/projects/snippets/new.html.haml2
-rw-r--r--app/views/projects/tags/new.html.haml2
-rw-r--r--app/views/projects/tracings/show.html.haml2
-rw-r--r--app/views/projects/usage_quotas/index.html.haml2
-rw-r--r--app/views/search/show.html.haml2
-rw-r--r--app/views/sent_notifications/unsubscribe.html.haml2
-rw-r--r--app/views/shared/_captcha_check.html.haml2
-rw-r--r--app/views/shared/_group_form.html.haml78
-rw-r--r--app/views/shared/groups/_group_name_and_path_fields.html.haml4
-rw-r--r--app/views/shared/integrations/overrides.html.haml2
-rw-r--r--app/views/shared/runners/_runner_details.html.haml2
-rw-r--r--app/views/shared/wikis/diff.html.haml2
-rw-r--r--app/views/shared/wikis/edit.html.haml2
-rw-r--r--app/views/shared/wikis/history.html.haml2
-rw-r--r--app/views/shared/wikis/pages.html.haml2
-rw-r--r--app/views/snippets/edit.html.haml2
-rw-r--r--app/views/snippets/new.html.haml2
-rw-r--r--app/views/users/unsubscribes/show.html.haml2
-rw-r--r--config/feature_flags/development/group_name_path_vue.yml8
-rw-r--r--config/feature_flags/development/use_received_header_for_incoming_emails.yml8
-rw-r--r--doc/administration/incoming_email.md3
-rw-r--r--doc/administration/reference_architectures/10k_users.md10
-rw-r--r--doc/administration/reference_architectures/25k_users.md10
-rw-r--r--doc/administration/reference_architectures/3k_users.md10
-rw-r--r--doc/administration/reference_architectures/50k_users.md10
-rw-r--r--doc/administration/reference_architectures/5k_users.md10
-rw-r--r--doc/ci/yaml/index.md6
-rw-r--r--doc/user/application_security/dependency_scanning/index.md1
-rw-r--r--lib/gitlab/email/receiver.rb2
-rw-r--r--qa/Gemfile.lock2
-rw-r--r--qa/qa/page/component/access_tokens.rb10
-rw-r--r--qa/qa/page/component/snippet.rb9
-rw-r--r--qa/qa/page/group/show.rb6
-rw-r--r--qa/qa/page/profile/emails.rb9
-rw-r--r--qa/qa/page/project/branches/show.rb7
-rw-r--r--qa/qa/page/project/settings/access_tokens.rb1
-rw-r--r--qa/qa/page/project/settings/advanced.rb12
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb14
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb6
-rw-r--r--qa/qa/support/page_error_checker.rb40
-rwxr-xr-xscripts/license-check.sh32
-rwxr-xr-xscripts/static-analysis2
-rw-r--r--scripts/utils.sh2
-rw-r--r--spec/features/admin/admin_groups_spec.rb12
-rw-r--r--spec/features/projects/new_project_spec.rb27
-rw-r--r--spec/frontend/groups/components/group_name_and_path_spec.js261
-rw-r--r--spec/frontend/lib/utils/forms_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js6
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js2
-rw-r--r--spec/helpers/groups_helper_spec.rb27
-rw-r--r--spec/lib/gitlab/email/receiver_spec.rb12
174 files changed, 945 insertions, 277 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index c8550b6c697..53e8c321d22 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1736,4 +1736,4 @@ DEPENDENCIES
yajl-ruby (~> 1.4.1)
BUNDLED WITH
- 2.3.6
+ 2.3.15
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 6a2e5f5c2c5..9cf41750efe 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
@@ -101,7 +101,7 @@ export default {
<template>
<div>
- <h1 class="page-title">
+ <h1 class="page-title gl-font-size-h-display">
{{ $options.i18n.pageTitle }}
</h1>
<hr />
diff --git a/app/assets/javascripts/environments/components/environment_form.vue b/app/assets/javascripts/environments/components/environment_form.vue
index e0b3572082c..1bac0ef1359 100644
--- a/app/assets/javascripts/environments/components/environment_form.vue
+++ b/app/assets/javascripts/environments/components/environment_form.vue
@@ -81,7 +81,7 @@ export default {
</script>
<template>
<div>
- <h1 class="page-title">
+ <h1 class="page-title gl-font-size-h-display">
{{ title }}
</h1>
<div class="row col-12">
diff --git a/app/assets/javascripts/environments/components/environments_detail_header.vue b/app/assets/javascripts/environments/components/environments_detail_header.vue
index 7acb453b58b..13b9cf14f52 100644
--- a/app/assets/javascripts/environments/components/environments_detail_header.vue
+++ b/app/assets/javascripts/environments/components/environments_detail_header.vue
@@ -94,7 +94,7 @@ export default {
<template>
<header class="top-area gl-justify-content-between">
<div class="gl-display-flex gl-flex-grow-1 gl-align-items-center">
- <h1 class="page-title">
+ <h1 class="page-title gl-font-size-h-display">
{{ environment.name }}
</h1>
<p v-if="shouldShowCancelAutoStopButton" class="gl-mb-0 gl-ml-3" data-testid="auto-stops-at">
diff --git a/app/assets/javascripts/feature_flags/components/feature_flags.vue b/app/assets/javascripts/feature_flags/components/feature_flags.vue
index c86a9fce050..645c2456c6e 100644
--- a/app/assets/javascripts/feature_flags/components/feature_flags.vue
+++ b/app/assets/javascripts/feature_flags/components/feature_flags.vue
@@ -184,7 +184,10 @@ export default {
class="gl-display-flex gl-align-items-baseline gl-flex-direction-row gl-justify-content-space-between gl-mt-6"
>
<div class="gl-display-flex gl-align-items-center">
- <h2 data-testid="feature-flags-tab-title" class="gl-font-size-h2 gl-my-0">
+ <h2
+ data-testid="feature-flags-tab-title"
+ class="page-title gl-font-size-h-display gl-my-0"
+ >
{{ s__('FeatureFlags|Feature Flags') }}
</h2>
<gl-badge v-if="count" class="gl-ml-4">{{ count }}</gl-badge>
diff --git a/app/assets/javascripts/feature_flags/components/new_feature_flag.vue b/app/assets/javascripts/feature_flags/components/new_feature_flag.vue
index 041c9e5cd14..bc05e88e643 100644
--- a/app/assets/javascripts/feature_flags/components/new_feature_flag.vue
+++ b/app/assets/javascripts/feature_flags/components/new_feature_flag.vue
@@ -24,7 +24,7 @@ export default {
</script>
<template>
<div>
- <h1 class="page-title">{{ s__('FeatureFlags|New feature flag') }}</h1>
+ <h1 class="page-title gl-font-size-h-display">{{ s__('FeatureFlags|New feature flag') }}</h1>
<gl-alert v-if="error.length" variant="warning" class="gl-mb-5" :dismissible="false">
<p v-for="(message, index) in error" :key="index" class="gl-mb-0">{{ message }}</p>
diff --git a/app/assets/javascripts/groups/components/group_name_and_path.vue b/app/assets/javascripts/groups/components/group_name_and_path.vue
new file mode 100644
index 00000000000..6c5f39345af
--- /dev/null
+++ b/app/assets/javascripts/groups/components/group_name_and_path.vue
@@ -0,0 +1,232 @@
+<script>
+import { GlFormGroup, GlFormInput, GlFormInputGroup, GlInputGroupText } from '@gitlab/ui';
+import { debounce } from 'lodash';
+
+import { s__, __ } from '~/locale';
+import { getGroupPathAvailability } from '~/rest_api';
+import { createAlert } from '~/flash';
+import { slugify } from '~/lib/utils/text_utility';
+import axios from '~/lib/utils/axios_utils';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+const DEBOUNCE_DURATION = 1000;
+
+export default {
+ i18n: {
+ inputs: {
+ name: {
+ label: s__('Groups|Group name'),
+ placeholder: __('My awesome group'),
+ description: s__(
+ 'Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.',
+ ),
+ invalidFeedback: s__('Groups|Enter a descriptive name for your group.'),
+ },
+ path: {
+ label: s__('Groups|Group URL'),
+ placeholder: __('my-awesome-group'),
+ invalidFeedbackInvalidPattern: s__(
+ 'GroupSettings|Choose a group path that does not start with a dash or end with a period. It can also contain alphanumeric characters and underscores.',
+ ),
+ invalidFeedbackPathUnavailable: s__(
+ 'Groups|Group path is unavailable. Path has been replaced with a suggested available path.',
+ ),
+ validFeedback: s__('Groups|Group path is available.'),
+ },
+ },
+ apiLoadingMessage: s__('Groups|Checking group URL availability...'),
+ apiErrorMessage: __(
+ 'An error occurred while checking group path. Please refresh and try again.',
+ ),
+ },
+ nameInputSize: { md: 'lg' },
+ changingGroupPathHelpPagePath: helpPagePath('user/group/index', {
+ anchor: 'change-a-groups-path',
+ }),
+ mattermostDataBindName: 'create_chat_team',
+ components: { GlFormGroup, GlFormInput, GlFormInputGroup, GlInputGroupText },
+ inject: ['fields', 'basePath', 'mattermostEnabled'],
+ data() {
+ return {
+ name: this.fields.name.value,
+ path: this.fields.path.value,
+ apiSuggestedPath: '',
+ apiLoading: false,
+ nameFeedbackState: null,
+ pathFeedbackState: null,
+ pathInvalidFeedback: null,
+ activeApiRequestAbortController: null,
+ };
+ },
+ computed: {
+ computedPath() {
+ return this.apiSuggestedPath || this.path;
+ },
+ pathDescription() {
+ return this.apiLoading ? this.$options.i18n.apiLoadingMessage : '';
+ },
+ },
+ watch: {
+ name: [
+ function updatePath(newName) {
+ this.nameFeedbackState = null;
+ this.pathFeedbackState = null;
+ this.apiSuggestedPath = '';
+ this.path = slugify(newName);
+ },
+ debounce(async function updatePathWithSuggestions() {
+ try {
+ const { suggests } = await this.checkPathAvailability();
+
+ const [suggestedPath] = suggests;
+
+ this.apiSuggestedPath = suggestedPath;
+ } catch (error) {
+ // Do nothing, error handled in `checkPathAvailability`
+ }
+ }, DEBOUNCE_DURATION),
+ ],
+ },
+ methods: {
+ async checkPathAvailability() {
+ if (!this.path) return Promise.reject();
+
+ this.apiLoading = true;
+
+ if (this.activeApiRequestAbortController !== null) {
+ this.activeApiRequestAbortController.abort();
+ }
+
+ this.activeApiRequestAbortController = new AbortController();
+
+ try {
+ const {
+ data: { exists, suggests },
+ } = await getGroupPathAvailability(this.path, this.fields.parentId?.value, {
+ signal: this.activeApiRequestAbortController.signal,
+ });
+
+ if (exists) {
+ if (suggests.length) {
+ return Promise.resolve({ exists, suggests });
+ }
+
+ createAlert({
+ message: this.$options.i18n.apiErrorMessage,
+ });
+
+ return Promise.reject();
+ }
+
+ return Promise.resolve({ exists, suggests });
+ } catch (error) {
+ if (!axios.isCancel(error)) {
+ createAlert({
+ message: this.$options.i18n.apiErrorMessage,
+ });
+ }
+
+ return Promise.reject();
+ } finally {
+ this.apiLoading = false;
+ }
+ },
+ handlePathInput(value) {
+ this.pathFeedbackState = null;
+ this.apiSuggestedPath = '';
+ this.path = value;
+ this.debouncedValidatePath();
+ },
+ debouncedValidatePath: debounce(async function validatePath() {
+ try {
+ const {
+ exists,
+ suggests: [suggestedPath],
+ } = await this.checkPathAvailability();
+
+ if (exists) {
+ this.apiSuggestedPath = suggestedPath;
+ this.pathInvalidFeedback = this.$options.i18n.inputs.path.invalidFeedbackPathUnavailable;
+ this.pathFeedbackState = false;
+ } else {
+ this.pathFeedbackState = true;
+ }
+ } catch (error) {
+ // Do nothing, error handled in `checkPathAvailability`
+ }
+ }, DEBOUNCE_DURATION),
+ handleInvalidName(event) {
+ event.preventDefault();
+
+ this.nameFeedbackState = false;
+ },
+ handleInvalidPath(event) {
+ event.preventDefault();
+
+ this.pathInvalidFeedback = this.$options.i18n.inputs.path.invalidFeedbackInvalidPattern;
+ this.pathFeedbackState = false;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <input
+ :id="fields.parentId.id"
+ type="hidden"
+ :name="fields.parentId.name"
+ :value="fields.parentId.value"
+ />
+ <gl-form-group
+ :label="$options.i18n.inputs.name.label"
+ :description="$options.i18n.inputs.name.description"
+ :label-for="fields.name.id"
+ :invalid-feedback="$options.i18n.inputs.name.invalidFeedback"
+ :state="nameFeedbackState"
+ >
+ <gl-form-input
+ :id="fields.name.id"
+ v-model="name"
+ class="gl-field-error-ignore"
+ required
+ :name="fields.name.name"
+ :placeholder="$options.i18n.inputs.name.placeholder"
+ data-qa-selector="group_name_field"
+ :size="$options.nameInputSize"
+ :state="nameFeedbackState"
+ @invalid="handleInvalidName"
+ />
+ </gl-form-group>
+ <gl-form-group
+ :label="$options.i18n.inputs.path.label"
+ :label-for="fields.path.id"
+ :description="pathDescription"
+ :state="pathFeedbackState"
+ :valid-feedback="$options.i18n.inputs.path.validFeedback"
+ :invalid-feedback="pathInvalidFeedback"
+ >
+ <gl-form-input-group>
+ <template #prepend>
+ <gl-input-group-text class="group-root-path">{{ basePath }}</gl-input-group-text>
+ </template>
+ <gl-form-input
+ :id="fields.path.id"
+ class="gl-field-error-ignore"
+ :name="fields.path.name"
+ :value="computedPath"
+ :placeholder="$options.i18n.inputs.path.placeholder"
+ :maxlength="fields.path.maxLength"
+ :pattern="fields.path.pattern"
+ :state="pathFeedbackState"
+ :size="$options.nameInputSize"
+ required
+ data-qa-selector="group_path_field"
+ :data-bind-in="mattermostEnabled ? $options.mattermostDataBindName : null"
+ @input="handlePathInput"
+ @invalid="handleInvalidPath"
+ />
+ </gl-form-input-group>
+ </gl-form-group>
+ </div>
+</template>
diff --git a/app/assets/javascripts/groups/create_edit_form.js b/app/assets/javascripts/groups/create_edit_form.js
new file mode 100644
index 00000000000..8ca0e6077e9
--- /dev/null
+++ b/app/assets/javascripts/groups/create_edit_form.js
@@ -0,0 +1,29 @@
+import Vue from 'vue';
+import { parseRailsFormFields } from '~/lib/utils/forms';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import GroupNameAndPath from './components/group_name_and_path.vue';
+
+export const initGroupNameAndPath = () => {
+ const elements = document.querySelectorAll('.js-group-name-and-path');
+
+ if (!elements.length) {
+ return;
+ }
+
+ elements.forEach((element) => {
+ const fields = parseRailsFormFields(element);
+ const { basePath, mattermostEnabled } = element.dataset;
+
+ return new Vue({
+ el: element,
+ provide: {
+ fields,
+ basePath,
+ mattermostEnabled: parseBoolean(mattermostEnabled),
+ },
+ render(h) {
+ return h(GroupNameAndPath);
+ },
+ });
+ });
+};
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
index cb906374fe1..05a254d3fbf 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -154,7 +154,7 @@ export default {
<gl-button
:disabled="commitButtonDisabled"
category="primary"
- variant="info"
+ variant="confirm"
block
class="qa-begin-commit-button"
data-testid="begin-commit-button"
diff --git a/app/assets/javascripts/issues/show/components/title.vue b/app/assets/javascripts/issues/show/components/title.vue
index 1982147e454..7f67b31b122 100644
--- a/app/assets/javascripts/issues/show/components/title.vue
+++ b/app/assets/javascripts/issues/show/components/title.vue
@@ -74,7 +74,7 @@ export default {
'issue-realtime-pre-pulse': preAnimation,
'issue-realtime-trigger-pulse': pulseAnimation,
}"
- class="title qa-title"
+ class="title qa-title gl-font-size-h-display"
dir="auto"
></h1>
<gl-button
diff --git a/app/assets/javascripts/jira_connect/branches/pages/index.vue b/app/assets/javascripts/jira_connect/branches/pages/index.vue
index d72dec6cdee..953e823ec96 100644
--- a/app/assets/javascripts/jira_connect/branches/pages/index.vue
+++ b/app/assets/javascripts/jira_connect/branches/pages/index.vue
@@ -46,7 +46,7 @@ export default {
<template>
<div>
<div class="gl-border-1 gl-border-b-solid gl-border-gray-100 gl-mb-5 gl-mt-7">
- <h1 data-testid="page-title" class="page-title">{{ pageTitle }}</h1>
+ <h1 data-testid="page-title" class="page-title gl-font-size-h-display">{{ pageTitle }}</h1>
</div>
<new-branch-form v-if="showForm" @success="onNewBranchFormSuccess" />
diff --git a/app/assets/javascripts/jira_import/components/jira_import_form.vue b/app/assets/javascripts/jira_import/components/jira_import_form.vue
index 6f49aad1b77..f8ca62da1a5 100644
--- a/app/assets/javascripts/jira_import/components/jira_import_form.vue
+++ b/app/assets/javascripts/jira_import/components/jira_import_form.vue
@@ -254,7 +254,7 @@ export default {
</gl-sprintf>
</gl-alert>
- <h1 class="page-title">{{ __('New Jira import') }}</h1>
+ <h1 class="page-title gl-font-size-h-display">{{ __('New Jira import') }}</h1>
<hr />
diff --git a/app/assets/javascripts/lib/utils/forms.js b/app/assets/javascripts/lib/utils/forms.js
index b58aef15dda..1d8c6ee23fc 100644
--- a/app/assets/javascripts/lib/utils/forms.js
+++ b/app/assets/javascripts/lib/utils/forms.js
@@ -119,12 +119,14 @@ export const parseRailsFormFields = (mountEl) => {
}
const fieldNameCamelCase = convertToCamelCase(fieldName);
- const { id, placeholder, name, value, type, checked } = input;
+ const { id, placeholder, name, value, type, checked, maxLength, pattern } = input;
const attributes = {
name,
id,
value,
...(placeholder && { placeholder }),
+ ...(input.hasAttribute('maxlength') && { maxLength }),
+ ...(pattern && { pattern }),
};
// Store radio buttons and checkboxes as an array so they can be
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
index 378fb102bdd..9e700a5236f 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
@@ -102,7 +102,7 @@ export default {
<template #cell(name)="{ item, toggleDetails, detailsShowing }">
<gl-button
v-if="hasDetails(item)"
- :icon="detailsShowing ? 'angle-up' : 'angle-down'"
+ :icon="detailsShowing ? 'chevron-up' : 'chevron-down'"
:aria-label="detailsShowing ? __('Collapse') : __('Expand')"
category="tertiary"
size="small"
diff --git a/app/assets/javascripts/pages/admin/groups/edit/index.js b/app/assets/javascripts/pages/admin/groups/edit/index.js
index 01e03ed437d..a4df1cf8274 100644
--- a/app/assets/javascripts/pages/admin/groups/edit/index.js
+++ b/app/assets/javascripts/pages/admin/groups/edit/index.js
@@ -1,3 +1,5 @@
import initFilePickers from '~/file_pickers';
+import { initGroupNameAndPath } from '~/groups/create_edit_form';
initFilePickers();
+initGroupNameAndPath();
diff --git a/app/assets/javascripts/pages/admin/groups/new/index.js b/app/assets/javascripts/pages/admin/groups/new/index.js
index 710d2d72f4c..a341ef9656d 100644
--- a/app/assets/javascripts/pages/admin/groups/new/index.js
+++ b/app/assets/javascripts/pages/admin/groups/new/index.js
@@ -1,6 +1,7 @@
import initFilePickers from '~/file_pickers';
import BindInOut from '~/behaviors/bind_in_out';
import Group from '~/group';
+import { initGroupNameAndPath } from '~/groups/create_edit_form';
(() => {
BindInOut.initAll();
@@ -8,3 +9,5 @@ import Group from '~/group';
return new Group();
})();
+
+initGroupNameAndPath();
diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js
index 702b152d25a..7c409010510 100644
--- a/app/assets/javascripts/pages/groups/new/index.js
+++ b/app/assets/javascripts/pages/groups/new/index.js
@@ -2,18 +2,19 @@ import Vue from 'vue';
import BindInOut from '~/behaviors/bind_in_out';
import initFilePickers from '~/file_pickers';
import Group from '~/group';
+import { initGroupNameAndPath } from '~/groups/create_edit_form';
import { parseBoolean } from '~/lib/utils/common_utils';
import NewGroupCreationApp from './components/app.vue';
import GroupPathValidator from './group_path_validator';
import initToggleInviteMembers from './toggle_invite_members';
new GroupPathValidator(); // eslint-disable-line no-new
+new Group(); // eslint-disable-line no-new
+initGroupNameAndPath();
BindInOut.initAll();
initFilePickers();
-new Group(); // eslint-disable-line no-new
-
function initNewGroupCreation(el) {
const { hasErrors, verificationRequired, verificationFormUrl, subscriptionsUrl } = el.dataset;
diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue
index 22d28a32b7a..3d7c71ce974 100644
--- a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue
@@ -64,7 +64,7 @@ export default {
<div class="title-container">
<h1
v-safe-html="issuable.titleHtml || issuable.title"
- class="title qa-title"
+ class="title qa-title gl-font-size-h-display"
dir="auto"
data-testid="title"
></h1>
diff --git a/app/assets/stylesheets/framework/page_title.scss b/app/assets/stylesheets/framework/page_title.scss
index c77e2be8e5a..5ed5b1e1445 100644
--- a/app/assets/stylesheets/framework/page_title.scss
+++ b/app/assets/stylesheets/framework/page_title.scss
@@ -3,8 +3,6 @@
.page-title {
margin: $gl-padding 0;
- font-size: 1.75em;
- font-weight: $gl-font-weight-bold;
color: $gl-text-color;
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 25fa4379064..b5e0dcd875a 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -611,8 +611,6 @@ body {
.page-title {
margin: #{2 * $grid-size} 0;
line-height: 1.3;
- font-size: 1.25em;
- font-weight: $gl-font-weight-bold;
&.with-button {
line-height: 34px;
diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss
index 092c676c397..909de9d57f2 100644
--- a/app/assets/stylesheets/pages/detail_page.scss
+++ b/app/assets/stylesheets/pages/detail_page.scss
@@ -58,7 +58,6 @@
.detail-page-description {
.title {
margin: 0 0 16px;
- font-size: 2em;
color: $gl-text-color;
padding: 0 0 0.3em;
border-bottom: 1px solid $white-dark;
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index c58a365b884..d491e222665 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -144,6 +144,15 @@ module GroupsHelper
false
end
+ def group_name_and_path_app_data(group)
+ parent = group.parent
+
+ {
+ base_path: URI.join(root_url, parent&.full_path || "").to_s,
+ mattermost_enabled: Gitlab.config.mattermost.enabled.to_s
+ }
+ end
+
private
def group_title_link(group, hidable: false, show_avatar: false, for_dropdown: false)
diff --git a/app/views/abuse_reports/new.html.haml b/app/views/abuse_reports/new.html.haml
index 3d85c203603..cb8f1bd1e9c 100644
--- a/app/views/abuse_reports/new.html.haml
+++ b/app/views/abuse_reports/new.html.haml
@@ -1,5 +1,5 @@
- page_title _("Report abuse to admin")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Report abuse to admin")
%p
= _("Please use this form to report to the admin users who create spam issues, comments or behave inappropriately.")
diff --git a/app/views/admin/abuse_reports/index.html.haml b/app/views/admin/abuse_reports/index.html.haml
index 731683e55ef..20499a2e3bf 100644
--- a/app/views/admin/abuse_reports/index.html.haml
+++ b/app/views/admin/abuse_reports/index.html.haml
@@ -1,6 +1,6 @@
- page_title _('Abuse Reports')
-%h1.page-title= _('Abuse Reports')
+%h1.page-title.gl-font-size-h-display= _('Abuse Reports')
.row-content-block.second-block
= form_tag admin_abuse_reports_path, method: :get, class: 'filter-form' do
diff --git a/app/views/admin/applications/edit.html.haml b/app/views/admin/applications/edit.html.haml
index 189bbc5894e..10a27fb906f 100644
--- a/app/views/admin/applications/edit.html.haml
+++ b/app/views/admin/applications/edit.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title @application.name
- page_title _("Edit"), @application.name, _("Applications")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Edit application')
- @url = admin_application_path(@application)
= render 'form', application: @application
diff --git a/app/views/admin/applications/index.html.haml b/app/views/admin/applications/index.html.haml
index 7c6d1d75e96..180871e48dd 100644
--- a/app/views/admin/applications/index.html.haml
+++ b/app/views/admin/applications/index.html.haml
@@ -1,6 +1,6 @@
- page_title s_('AdminArea|Instance OAuth applications')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= s_('AdminArea|Instance OAuth applications')
%p.light
- docs_link_path = help_page_path('integration/oauth_provider')
diff --git a/app/views/admin/applications/new.html.haml b/app/views/admin/applications/new.html.haml
index 6dba2406330..b7e28923057 100644
--- a/app/views/admin/applications/new.html.haml
+++ b/app/views/admin/applications/new.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Add new application")
- page_title _("Add new application")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Add new application")
- @url = admin_applications_path
= render 'form', application: @application
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
index 7884b9fd89e..212e3eeb951 100644
--- a/app/views/admin/applications/show.html.haml
+++ b/app/views/admin/applications/show.html.haml
@@ -1,6 +1,6 @@
- page_title @application.name, _("Applications")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
Application: #{@application.name}
= render 'shared/doorkeeper/applications/show',
diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml
index 6ad4ab74ba2..6d2cab06010 100644
--- a/app/views/admin/background_jobs/show.html.haml
+++ b/app/views/admin/background_jobs/show.html.haml
@@ -1,6 +1,6 @@
- page_title _("Background Jobs")
-%h1.page-title= _('Background Jobs')
+%h1.page-title.gl-font-size-h-display= _('Background Jobs')
%p.light
- sidekiq_link_url = 'http://sidekiq.org/'
- sidekiq_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: sidekiq_link_url }
diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml
index 6a60d5418f4..9405a7862ba 100644
--- a/app/views/admin/broadcast_messages/index.html.haml
+++ b/app/views/admin/broadcast_messages/index.html.haml
@@ -2,7 +2,7 @@
- page_title _("Broadcast Messages")
- targeted_broadcast_messages_enabled = Feature.enabled?(:role_targeted_broadcast_messages)
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Broadcast Messages')
%p.light
= _('Use banners and notifications to notify your users about scheduled maintenance, recent upgrades, and more.')
diff --git a/app/views/admin/deploy_keys/edit.html.haml b/app/views/admin/deploy_keys/edit.html.haml
index 87de176245e..12a1c0c3de2 100644
--- a/app/views/admin/deploy_keys/edit.html.haml
+++ b/app/views/admin/deploy_keys/edit.html.haml
@@ -1,5 +1,5 @@
- page_title _('Edit Deploy Key')
-%h1.page-title= _('Edit public deploy key')
+%h1.page-title.gl-font-size-h-display= _('Edit public deploy key')
%hr
%div
diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml
index e3053001dd7..74882900756 100644
--- a/app/views/admin/deploy_keys/new.html.haml
+++ b/app/views/admin/deploy_keys/new.html.haml
@@ -1,5 +1,5 @@
- page_title _('New Deploy Key')
-%h1.page-title= _('New public deploy key')
+%h1.page-title.gl-font-size-h-display= _('New public deploy key')
%hr
%div
diff --git a/app/views/admin/gitaly_servers/index.html.haml b/app/views/admin/gitaly_servers/index.html.haml
index b9134c7670e..5bd4e066409 100644
--- a/app/views/admin/gitaly_servers/index.html.haml
+++ b/app/views/admin/gitaly_servers/index.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Gitaly Servers")
- page_title _("Gitaly Servers")
-%h1.page-title= _("Gitaly Servers")
+%h1.page-title.gl-font-size-h-display= _("Gitaly Servers")
%hr
.gitaly_servers
- if @gitaly_servers.any?
diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml
index e18f757bfd9..2a1e6b8f637 100644
--- a/app/views/admin/groups/edit.html.haml
+++ b/app/views/admin/groups/edit.html.haml
@@ -1,4 +1,4 @@
- page_title _("Edit"), @group.name, _("Groups")
-%h1.page-title= _('Edit group: %{group_name}') % { group_name: @group.name }
+%h1.page-title.gl-font-size-h-display= _('Edit group: %{group_name}') % { group_name: @group.name }
%hr
= render 'form', visibility_level: @group.visibility_level
diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml
index 781a7c15df4..a98c685281d 100644
--- a/app/views/admin/groups/new.html.haml
+++ b/app/views/admin/groups/new.html.haml
@@ -1,4 +1,4 @@
- page_title _("New Group")
-%h1.page-title= _('New group')
+%h1.page-title.gl-font-size-h-display= _('New group')
%hr
= render 'form', visibility_level: default_group_visibility
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 3419b234710..7dc9d59b498 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -4,7 +4,7 @@
- page_title @group.name, _("Groups")
- current_user_is_group_owner = @group && @group.has_owner?(current_user)
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Group: %{group_name}') % { group_name: @group.full_name }
= link_to admin_group_edit_path(@group), class: "btn btn-default gl-button float-right", data: { qa_selector: 'edit_group_link' } do
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
index 9e864a83033..98427cb6419 100644
--- a/app/views/admin/health_check/show.html.haml
+++ b/app/views/admin/health_check/show.html.haml
@@ -1,7 +1,7 @@
- page_title _('Health Check')
- no_errors = @errors.blank?
-%h1.page-title= page_title
+%h1.page-title.gl-font-size-h-display= page_title
.bs-callout.clearfix
.float-left
%p
diff --git a/app/views/admin/hook_logs/show.html.haml b/app/views/admin/hook_logs/show.html.haml
index 2ace46c0acf..6fcaf2ea152 100644
--- a/app/views/admin/hook_logs/show.html.haml
+++ b/app/views/admin/hook_logs/show.html.haml
@@ -1,5 +1,5 @@
- page_title _('Request details')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Request details")
%hr
diff --git a/app/views/admin/identities/edit.html.haml b/app/views/admin/identities/edit.html.haml
index 28466658aff..54cc9139aca 100644
--- a/app/views/admin/identities/edit.html.haml
+++ b/app/views/admin/identities/edit.html.haml
@@ -2,7 +2,7 @@
- add_to_breadcrumbs @user.name, admin_user_identities_path(@user)
- breadcrumb_title _('Edit Identity')
- page_title _("Edit"), @identity.provider, _("Identities"), @user.name, _("Users")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Edit identity for %{user_name}') % { user_name: @user.name }
%hr
diff --git a/app/views/admin/identities/new.html.haml b/app/views/admin/identities/new.html.haml
index 8ca27581693..d3e7bb8a370 100644
--- a/app/views/admin/identities/new.html.haml
+++ b/app/views/admin/identities/new.html.haml
@@ -2,6 +2,6 @@
- add_to_breadcrumbs @user.name, admin_user_identities_path(@user)
- breadcrumb_title _('New Identity')
- page_title _('New Identity')
-%h1.page-title= _('New identity')
+%h1.page-title.gl-font-size-h-display= _('New identity')
%hr
= render 'form'
diff --git a/app/views/admin/labels/edit.html.haml b/app/views/admin/labels/edit.html.haml
index bd9db7530a6..80112595adf 100644
--- a/app/views/admin/labels/edit.html.haml
+++ b/app/views/admin/labels/edit.html.haml
@@ -1,7 +1,7 @@
- add_to_breadcrumbs _("Labels"), admin_labels_path
- breadcrumb_title _("Edit Label")
- page_title _("Edit"), @label.name, _("Labels")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Edit Label')
%hr
= render 'shared/labels/form', url: admin_label_path(@label), back_path: admin_labels_path
diff --git a/app/views/admin/labels/index.html.haml b/app/views/admin/labels/index.html.haml
index fb278f19185..21b19236683 100644
--- a/app/views/admin/labels/index.html.haml
+++ b/app/views/admin/labels/index.html.haml
@@ -3,7 +3,7 @@
%div
= link_to new_admin_label_path, class: "float-right btn gl-button btn-confirm" do
= _('New label')
- %h1.page-title
+ %h1.page-title.gl-font-size-h-display
= _('Labels')
%hr
- if @labels.present?
diff --git a/app/views/admin/labels/new.html.haml b/app/views/admin/labels/new.html.haml
index 0976416b592..76f9eee717e 100644
--- a/app/views/admin/labels/new.html.haml
+++ b/app/views/admin/labels/new.html.haml
@@ -1,5 +1,5 @@
- page_title _("New Label")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('New Label')
%hr
= render 'shared/labels/form', url: admin_labels_path, back_path: admin_labels_path
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 3fb3f1f5e54..6fa787fb550 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -5,7 +5,7 @@
- @content_class = "admin-projects"
- current_user_is_group_owner = @group && @group.has_owner?(current_user)
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Project: %{name}') % { name: @project.full_name }
= link_to edit_project_path(@project), class: "btn btn-default gl-button float-right" do
= sprite_icon('pencil-square', css_class: 'gl-icon')
diff --git a/app/views/admin/spam_logs/index.html.haml b/app/views/admin/spam_logs/index.html.haml
index d6f5f5a17da..c974f455112 100644
--- a/app/views/admin/spam_logs/index.html.haml
+++ b/app/views/admin/spam_logs/index.html.haml
@@ -1,5 +1,5 @@
- page_title _("Spam Logs")
-%h1.page-title= _('Spam Logs')
+%h1.page-title.gl-font-size-h-display= _('Spam Logs')
%hr
- if @spam_logs.present?
.table-holder
diff --git a/app/views/admin/topics/edit.html.haml b/app/views/admin/topics/edit.html.haml
index a242a3d6eea..73796949e39 100644
--- a/app/views/admin/topics/edit.html.haml
+++ b/app/views/admin/topics/edit.html.haml
@@ -1,4 +1,4 @@
- page_title _("Edit"), @topic.name, _("Topics")
-%h1.page-title= _('Edit topic: %{topic_name}') % { topic_name: @topic.name }
+%h1.page-title.gl-font-size-h-display= _('Edit topic: %{topic_name}') % { topic_name: @topic.name }
%hr
= render 'form', url: admin_topic_path(@topic)
diff --git a/app/views/admin/topics/new.html.haml b/app/views/admin/topics/new.html.haml
index 428e46efed7..aefa1bbcf95 100644
--- a/app/views/admin/topics/new.html.haml
+++ b/app/views/admin/topics/new.html.haml
@@ -1,4 +1,4 @@
- page_title _("New topic")
-%h1.page-title= _('New topic')
+%h1.page-title.gl-font-size-h-display= _('New topic')
%hr
= render 'form', url: admin_topics_path(@topic)
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index 17a97bbdc66..378caf803dd 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -1,6 +1,6 @@
.gl-display-flex.gl-flex-wrap.gl-justify-content-space-between.gl-align-items-center.gl-py-3.gl-mb-5.gl-border-b-solid.gl-border-gray-100.gl-border-b-1
.gl-my-3
- %h1.page-title.gl-m-0
+ %h1.page-title.gl-font-size-h-display.gl-m-0
= @user.name
- if @user.blocked_pending_approval?
%span.gl-text-red-500
diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml
index 598c0aec851..5507d640e04 100644
--- a/app/views/admin/users/edit.html.haml
+++ b/app/views/admin/users/edit.html.haml
@@ -1,4 +1,4 @@
- page_title _("Edit"), @user.name, _("Users")
-%h1.page-title.gl-font-size-h-display.gl-mb-6
+%h1.page-title.gl-font-size-h-display
= _("Edit user: %{user_name}") % { user_name: @user.name }
= render 'form'
diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml
index 650aba858c6..425d0150d10 100644
--- a/app/views/admin/users/new.html.haml
+++ b/app/views/admin/users/new.html.haml
@@ -1,4 +1,4 @@
- page_title _("New User")
-%h1.page-title.gl-font-size-h-display.gl-mb-6
+%h1.page-title.gl-font-size-h-display
= s_('AdminUsers|New user')
= render 'form'
diff --git a/app/views/dashboard/_activity_head.html.haml b/app/views/dashboard/_activity_head.html.haml
index c65b947d1ba..ca9f69ab73a 100644
--- a/app/views/dashboard/_activity_head.html.haml
+++ b/app/views/dashboard/_activity_head.html.haml
@@ -1,5 +1,5 @@
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _('Activity')
+ %h1.page-title.gl-font-size-h-display= _('Activity')
.top-area
= gl_tabs_nav({ class: 'gl-border-b-0', data: { testid: 'dashboard-activity-tabs' } }) do
diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml
index 7b1d25b9b43..f0f1413831a 100644
--- a/app/views/dashboard/_groups_head.html.haml
+++ b/app/views/dashboard/_groups_head.html.haml
@@ -1,5 +1,5 @@
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _('Groups')
+ %h1.page-title.gl-font-size-h-display= _('Groups')
- if current_user.can_create_group?
.page-title-controls
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index b94b14bf6bd..028edefe821 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -5,7 +5,7 @@
= render 'shared/project_limit'
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _('Projects')
+ %h1.page-title.gl-font-size-h-display= _('Projects')
- if current_user.can_create_project?
.page-title-controls
diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml
index 8c468812e33..be2124fdd7e 100644
--- a/app/views/dashboard/_snippets_head.html.haml
+++ b/app/views/dashboard/_snippets_head.html.haml
@@ -1,5 +1,5 @@
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _('Snippets')
+ %h1.page-title.gl-font-size-h-display= _('Snippets')
- if current_user && current_user.snippets.any? || @snippets.any?
.page-title-controls
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index f0216253dad..95e772f324b 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -7,7 +7,7 @@
= render_dashboard_ultimate_trial(current_user)
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _('Issues')
+ %h1.page-title.gl-font-size-h-display= _('Issues')
- if current_user
.page-title-controls
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index 90fb09ed909..8a639d08a27 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -5,7 +5,7 @@
= render_dashboard_ultimate_trial(current_user)
.page-title-holder.d-flex.align-items-start.flex-column.flex-sm-row.align-items-sm-center
- %h1.page-title= _('Merge requests')
+ %h1.page-title.gl-font-size-h-display= _('Merge requests')
- if current_user
.page-title-controls.ml-0.mb-3.ml-sm-auto.mb-sm-0
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index 2bbca851dcc..39fbd9bc097 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -4,7 +4,7 @@
- add_page_specific_style 'page_bundles/milestone'
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _('Milestones')
+ %h1.page-title.gl-font-size-h-display= _('Milestones')
- if current_user
.page-title-controls
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 4f6ddf10984..6bfe18fd3b2 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -7,7 +7,7 @@
- add_page_specific_style 'page_bundles/todos'
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _("To-Do List")
+ %h1.page-title.gl-font-size-h-display= _("To-Do List")
- if current_user.todos.any?
.top-area
diff --git a/app/views/doorkeeper/applications/edit.html.haml b/app/views/doorkeeper/applications/edit.html.haml
index 2d00760a7d1..c48e2cd4db0 100644
--- a/app/views/doorkeeper/applications/edit.html.haml
+++ b/app/views/doorkeeper/applications/edit.html.haml
@@ -1,5 +1,5 @@
- page_title _("Edit"), @application.name, _("Applications")
- @content_class = "limit-container-width" unless fluid_layout
-%h1.page-title= _('Edit application')
+%h1.page-title.gl-font-size-h-display= _('Edit application')
= render 'shared/doorkeeper/applications/form', url: doorkeeper_submit_path(@application)
diff --git a/app/views/doorkeeper/applications/new.html.haml b/app/views/doorkeeper/applications/new.html.haml
index 15f3700e077..884d33b9a10 100644
--- a/app/views/doorkeeper/applications/new.html.haml
+++ b/app/views/doorkeeper/applications/new.html.haml
@@ -1,6 +1,6 @@
- page_title _("New Application")
-%h1.page-title= _("New Application")
+%h1.page-title.gl-font-size-h-display= _("New Application")
%hr
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index 1fb843e95b0..0428b9c340c 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -3,7 +3,7 @@
- page_title @application.name, _("Applications")
- @content_class = "limit-container-width" unless fluid_layout
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Application: %{name}") % { name: @application.name }
= render 'shared/doorkeeper/applications/show',
diff --git a/app/views/doorkeeper/authorizations/error.html.haml b/app/views/doorkeeper/authorizations/error.html.haml
index aa4f8b892ad..ecd011342c4 100644
--- a/app/views/doorkeeper/authorizations/error.html.haml
+++ b/app/views/doorkeeper/authorizations/error.html.haml
@@ -1,3 +1,3 @@
-%h1.page-title= _("An error has occurred")
+%h1.page-title.gl-font-size-h-display= _("An error has occurred")
%main{ :role => "main" }
%pre= @pre_auth.error_response.body[:error_description]
diff --git a/app/views/doorkeeper/authorizations/redirect.html.haml b/app/views/doorkeeper/authorizations/redirect.html.haml
index f32fb3181c6..b45db62dce1 100644
--- a/app/views/doorkeeper/authorizations/redirect.html.haml
+++ b/app/views/doorkeeper/authorizations/redirect.html.haml
@@ -1,4 +1,4 @@
-%h1.page-title= _("Redirecting")
+%h1.page-title.gl-font-size-h-display= _("Redirecting")
%div
%a{ :href => redirect_uri } Click here to redirect to #{redirect_uri}
diff --git a/app/views/doorkeeper/authorizations/show.html.haml b/app/views/doorkeeper/authorizations/show.html.haml
index f4f937fe14d..16d787c2f41 100644
--- a/app/views/doorkeeper/authorizations/show.html.haml
+++ b/app/views/doorkeeper/authorizations/show.html.haml
@@ -1,3 +1,3 @@
-%h1.page-title= _("Authorization code:")
+%h1.page-title.gl-font-size-h-display= _("Authorization code:")
%main{ :role => "main" }
%code#authorization_code= params[:code]
diff --git a/app/views/explore/topics/_head.html.haml b/app/views/explore/topics/_head.html.haml
index f5ee95b16c3..2a96c6c97c6 100644
--- a/app/views/explore/topics/_head.html.haml
+++ b/app/views/explore/topics/_head.html.haml
@@ -1,5 +1,5 @@
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _('Projects')
+ %h1.page-title.gl-font-size-h-display= _('Projects')
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= sprite_icon('chevron-lg-left', size: 12)
diff --git a/app/views/groups/labels/edit.html.haml b/app/views/groups/labels/edit.html.haml
index f6d7d958365..9af842b01df 100644
--- a/app/views/groups/labels/edit.html.haml
+++ b/app/views/groups/labels/edit.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title _("Edit")
- page_title _("Edit"), @label.name, _("Labels")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Edit Label')
= render 'shared/labels/form', url: group_label_path(@group, @label), back_path: @previous_labels_path
diff --git a/app/views/groups/labels/new.html.haml b/app/views/groups/labels/new.html.haml
index 534e2d13acf..fd9aae987d4 100644
--- a/app/views/groups/labels/new.html.haml
+++ b/app/views/groups/labels/new.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title _("New")
- page_title _("New Label")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('New Label')
= render 'shared/labels/form', url: group_labels_path, back_path: @previous_labels_path
diff --git a/app/views/groups/milestones/edit.html.haml b/app/views/groups/milestones/edit.html.haml
index 1e7d38b3dac..931d73715d3 100644
--- a/app/views/groups/milestones/edit.html.haml
+++ b/app/views/groups/milestones/edit.html.haml
@@ -3,7 +3,7 @@
- render "header_title"
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Edit Milestone')
%hr
diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml
index 9df6d656f82..8bceb1ddd5c 100644
--- a/app/views/groups/milestones/new.html.haml
+++ b/app/views/groups/milestones/new.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title _("New")
- page_title _("Milestones"), @milestone.name, _("Milestones")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("New Milestone")
%hr
diff --git a/app/views/groups/runners/edit.html.haml b/app/views/groups/runners/edit.html.haml
index 04b9d88723f..c5999317597 100644
--- a/app/views/groups/runners/edit.html.haml
+++ b/app/views/groups/runners/edit.html.haml
@@ -5,7 +5,7 @@
- add_to_breadcrumbs "#{@runner.short_sha}", group_runner_path(@group, @runner)
-%h2.page-title
+%h1.page-title.gl-font-size-h-display
= s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
= render 'shared/runners/runner_type_badge', runner: @runner
diff --git a/app/views/groups/settings/applications/edit.html.haml b/app/views/groups/settings/applications/edit.html.haml
index 7967586d312..ee71fd5d886 100644
--- a/app/views/groups/settings/applications/edit.html.haml
+++ b/app/views/groups/settings/applications/edit.html.haml
@@ -1,5 +1,5 @@
- page_title _("Edit"), @application.name, _("Group applications")
- @content_class = "limit-container-width" unless fluid_layout
-%h1.page-title= _('Edit group application')
+%h1.page-title.gl-font-size-h-display= _('Edit group application')
= render 'shared/doorkeeper/applications/form', url: group_settings_application_path(@group, @application)
diff --git a/app/views/groups/settings/applications/show.html.haml b/app/views/groups/settings/applications/show.html.haml
index a2f079a7215..4a83d96aae4 100644
--- a/app/views/groups/settings/applications/show.html.haml
+++ b/app/views/groups/settings/applications/show.html.haml
@@ -3,7 +3,7 @@
- page_title @application.name, _("Group applications")
- @content_class = "limit-container-width" unless fluid_layout
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Group application: %{name}") % { name: @application.name }
= render 'shared/doorkeeper/applications/show',
diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml
index 52cb60db749..e69ca4663b4 100644
--- a/app/views/import/bitbucket/status.html.haml
+++ b/app/views/import/bitbucket/status.html.haml
@@ -1,7 +1,7 @@
- page_title _('Bitbucket import')
- header_title _('Projects'), root_path
-%h1.page-title.d-flex
+%h1.page-title.gl-font-size-h-display.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bitbucket', css_class: 'gl-mr-2')
= _('Import projects from Bitbucket')
diff --git a/app/views/import/bitbucket_server/new.html.haml b/app/views/import/bitbucket_server/new.html.haml
index 718832b0a1b..0d87cf66814 100644
--- a/app/views/import/bitbucket_server/new.html.haml
+++ b/app/views/import/bitbucket_server/new.html.haml
@@ -2,7 +2,7 @@
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-%h1.page-title.d-flex
+%h1.page-title.gl-font-size-h-display.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bitbucket', css_class: 'gl-mr-2')
= _('Import repositories from Bitbucket Server')
diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml
index 4cdef031036..05b42767668 100644
--- a/app/views/import/bitbucket_server/status.html.haml
+++ b/app/views/import/bitbucket_server/status.html.haml
@@ -1,6 +1,6 @@
- page_title _('Bitbucket Server import')
-%h1.page-title.d-flex
+%h1.page-title.gl-font-size-h-display.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bitbucket', css_class: 'gl-mr-2')
= _('Import projects from Bitbucket Server')
diff --git a/app/views/import/fogbugz/new.html.haml b/app/views/import/fogbugz/new.html.haml
index ef4bff678a6..b74262f2567 100644
--- a/app/views/import/fogbugz/new.html.haml
+++ b/app/views/import/fogbugz/new.html.haml
@@ -2,7 +2,7 @@
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-%h1.page-title.d-flex
+%h1.page-title.gl-font-size-h-display.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bug', css_class: 'gl-mr-2')
= _('Import projects from FogBugz')
diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml
index 330cd8d3f36..5caee78b9c4 100644
--- a/app/views/import/fogbugz/new_user_map.html.haml
+++ b/app/views/import/fogbugz/new_user_map.html.haml
@@ -2,7 +2,7 @@
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-%h1.page-title.d-flex
+%h1.page-title.gl-font-size-h-display.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bug', css_class: 'gl-mr-2')
= _('Import projects from FogBugz')
diff --git a/app/views/import/fogbugz/status.html.haml b/app/views/import/fogbugz/status.html.haml
index e858b9f1c4b..3e303d3163d 100644
--- a/app/views/import/fogbugz/status.html.haml
+++ b/app/views/import/fogbugz/status.html.haml
@@ -1,5 +1,5 @@
- page_title _("FogBugz import")
-%h1.page-title.d-flex
+%h1.page-title.gl-font-size-h-display.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('bug', css_class: 'gl-mr-2')
= _('Import projects from FogBugz')
diff --git a/app/views/import/gitea/new.html.haml b/app/views/import/gitea/new.html.haml
index 6dfa78cbcd2..a7feedd91ad 100644
--- a/app/views/import/gitea/new.html.haml
+++ b/app/views/import/gitea/new.html.haml
@@ -2,7 +2,7 @@
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= custom_icon('gitea_logo')
= _('Import Projects from Gitea')
diff --git a/app/views/import/gitea/status.html.haml b/app/views/import/gitea/status.html.haml
index c34c3ffaa3b..2e318f77b7c 100644
--- a/app/views/import/gitea/status.html.haml
+++ b/app/views/import/gitea/status.html.haml
@@ -1,5 +1,5 @@
- page_title _("Gitea Import")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= custom_icon('gitea_logo')
= _('Import Projects from Gitea')
diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml
index cfd65e116c5..cc8637b5c4f 100644
--- a/app/views/import/github/new.html.haml
+++ b/app/views/import/github/new.html.haml
@@ -3,7 +3,7 @@
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= title
%p
diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml
index b79c5c3092f..1b556cd0f7f 100644
--- a/app/views/import/github/status.html.haml
+++ b/app/views/import/github/status.html.haml
@@ -1,6 +1,6 @@
- title = has_ci_cd_only_params? ? _('Connect repositories from GitHub') : _('GitHub import')
- page_title title
-%h1.page-title.mb-0.gl-display-flex
+%h1.page-title.gl-font-size-h-display.mb-0.gl-display-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('github', css_class: 'gl-mr-2')
= _('Import repositories from GitHub')
diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml
index 6ec8eb0eff8..13aaa41de9b 100644
--- a/app/views/import/gitlab/status.html.haml
+++ b/app/views/import/gitlab/status.html.haml
@@ -1,5 +1,5 @@
- page_title _("GitLab.com import")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= sprite_icon('heart', css_class: 'gl-vertical-align-middle')
= _('Import projects from GitLab.com')
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index 4c4ca33926d..42a9d2c3136 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -2,7 +2,7 @@
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-%h1.page-title.d-flex
+%h1.page-title.gl-font-size-h-display.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('tanuki', css_class: 'gl-mr-2')
= _('Import an exported GitLab project')
diff --git a/app/views/import/manifest/new.html.haml b/app/views/import/manifest/new.html.haml
index 5415dbcbea6..3d33e229f8f 100644
--- a/app/views/import/manifest/new.html.haml
+++ b/app/views/import/manifest/new.html.haml
@@ -3,7 +3,7 @@
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Manifest file import')
= render 'import/shared/errors'
diff --git a/app/views/import/manifest/status.html.haml b/app/views/import/manifest/status.html.haml
index 9856e0976f9..ced507de271 100644
--- a/app/views/import/manifest/status.html.haml
+++ b/app/views/import/manifest/status.html.haml
@@ -1,6 +1,6 @@
- page_title _("Manifest import")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Manifest file import')
= render 'import/githubish_status', provider: 'manifest'
diff --git a/app/views/import/phabricator/new.html.haml b/app/views/import/phabricator/new.html.haml
index d9cdc3903ed..d4fdd107043 100644
--- a/app/views/import/phabricator/new.html.haml
+++ b/app/views/import/phabricator/new.html.haml
@@ -2,7 +2,7 @@
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-%h1.page-title.d-flex
+%h1.page-title.gl-font-size-h-display.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
= sprite_icon('issues', css_class: 'gl-mr-2')
= _('Import tasks from Phabricator into issues')
diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml
index 2789bea70b1..c1ee12bb6c8 100644
--- a/app/views/invites/show.html.haml
+++ b/app/views/invites/show.html.haml
@@ -1,5 +1,5 @@
- page_title _("Invitation")
-%h1.page-title= _("Invitation")
+%h1.page-title.gl-font-size-h-display= _("Invitation")
- if current_user_matches_invite?
- if member?
diff --git a/app/views/profiles/chat_names/new.html.haml b/app/views/profiles/chat_names/new.html.haml
index 0f03516b697..303b8b10027 100644
--- a/app/views/profiles/chat_names/new.html.haml
+++ b/app/views/profiles/chat_names/new.html.haml
@@ -1,4 +1,4 @@
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Authorization required")
%main{ :role => "main" }
%p.h4
diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml
index 8d743e72bc3..a2180dc68a6 100644
--- a/app/views/profiles/passwords/new.html.haml
+++ b/app/views/profiles/passwords/new.html.haml
@@ -1,7 +1,7 @@
- page_title _('New Password')
- breadcrumb_title _('New Password')
-%h1.page-title= _('Set up new password')
+%h1.page-title.gl-font-size-h-display= _('Set up new password')
%hr
= form_for @user, url: profile_password_path, method: :post do |f|
%p.slead
diff --git a/app/views/projects/_visibility_modal.html.haml b/app/views/projects/_visibility_modal.html.haml
index 25fd0b78ac8..66066ceb5b2 100644
--- a/app/views/projects/_visibility_modal.html.haml
+++ b/app/views/projects/_visibility_modal.html.haml
@@ -5,7 +5,7 @@
.modal-dialog
.modal-content
.modal-header
- %h1.page-title= _('Reduce this project’s visibility?')
+ %h1.page-title.gl-font-size-h-display= _('Reduce this project’s visibility?')
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": "true" }= sprite_icon("close")
.modal-body
diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml
index 3d87e2daeeb..3ae7741d24d 100644
--- a/app/views/projects/blob/_new_dir.html.haml
+++ b/app/views/projects/blob/_new_dir.html.haml
@@ -2,7 +2,7 @@
.modal-dialog.modal-lg
.modal-content
.modal-header
- %h1.page-title= _('Create New Directory')
+ %h1.page-title.gl-font-size-h-display= _('Create New Directory')
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": "true" } &times;
.modal-body
diff --git a/app/views/projects/blob/_remove.html.haml b/app/views/projects/blob/_remove.html.haml
index 24603ee54c8..7511de76223 100644
--- a/app/views/projects/blob/_remove.html.haml
+++ b/app/views/projects/blob/_remove.html.haml
@@ -2,7 +2,7 @@
.modal-dialog
.modal-content
.modal-header
- %h1.page-title Delete #{@blob.name}
+ %h1.page-title.gl-font-size-h-display Delete #{@blob.name}
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": "true" } &times;
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
index 59e9c2d73a8..7251349c0e3 100644
--- a/app/views/projects/blob/_upload.html.haml
+++ b/app/views/projects/blob/_upload.html.haml
@@ -2,7 +2,7 @@
.modal-dialog.modal-lg
.modal-content
.modal-header
- %h1.page-title= title
+ %h1.page-title.gl-font-size-h-display= title
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": "true" } &times;
.modal-body
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index 2771fba79c5..9b628e7ec43 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -15,7 +15,7 @@
= _('Someone edited the file the same time you did. Please check out %{link_start}the file %{icon}%{link_end} and make sure your changes will not unintentionally remove theirs.').html_safe % { link_start: blob_link_start, link_end: '</a>'.html_safe , icon: external_link_icon }
-%h1.page-title.blob-edit-page-title
+%h1.page-title.gl-font-size-h-display.blob-edit-page-title
Edit file
.file-editor
= gl_tabs_nav({ class: 'js-edit-mode nav-links gl-border-0'}) do
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index b2922e22713..27f64104cf4 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Repository")
- page_title _("New File"), @path.presence, @ref
-%h1.page-title.blob-new-page-title
+%h1.page-title.blob-new-page-title.gl-font-size-h-display
= _('New file')
.file-editor
= form_tag(project_create_blob_path(@project, @id), method: :post, class: 'js-edit-blob-form js-new-blob-form js-quick-submit js-requires-input', data: blob_editor_paths(@project)) do
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 1e12e17a874..5b6834d3d82 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -5,7 +5,7 @@
= render Pajamas::AlertComponent.new(variant: :danger) do |c|
= c.body do
= @error
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('New Branch')
%hr
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index 33ff8a5add7..70a94c58a3b 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Compare Revisions")
- page_title _("Compare")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Compare Git revisions")
.sub-header-block
- example_branch = capture do
diff --git a/app/views/projects/deploy_keys/edit.html.haml b/app/views/projects/deploy_keys/edit.html.haml
index 98dc15c17f6..04e364d6b15 100644
--- a/app/views/projects/deploy_keys/edit.html.haml
+++ b/app/views/projects/deploy_keys/edit.html.haml
@@ -1,5 +1,5 @@
- page_title _('Edit Deploy Key')
-%h1.page-title= _('Edit Deploy Key')
+%h1.page-title.gl-font-size-h-display= _('Edit Deploy Key')
%hr
%div
diff --git a/app/views/projects/environments/terminal.html.haml b/app/views/projects/environments/terminal.html.haml
index 571578dd921..7c837d4ded0 100644
--- a/app/views/projects/environments/terminal.html.haml
+++ b/app/views/projects/environments/terminal.html.haml
@@ -6,7 +6,7 @@
.top-area
.row
.col-sm-6
- %h1.page-title
+ %h1.page-title.gl-font-size-h-display
= _("Terminal for environment")
= @environment.name
diff --git a/app/views/projects/hook_logs/show.html.haml b/app/views/projects/hook_logs/show.html.haml
index 2e2e7ba848e..d610ef21400 100644
--- a/app/views/projects/hook_logs/show.html.haml
+++ b/app/views/projects/hook_logs/show.html.haml
@@ -2,7 +2,7 @@
- add_to_breadcrumbs _('Webhook Settings'), namespace_project_hooks_path
- page_title _('Webhook Logs')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Request details")
%hr
diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml
index 4abe58faf80..bcfa32566fb 100644
--- a/app/views/projects/imports/new.html.haml
+++ b/app/views/projects/imports/new.html.haml
@@ -1,5 +1,5 @@
- page_title _("Import repository")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Import repository')
%hr
diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml
index 00199b42c43..c2b620280d8 100644
--- a/app/views/projects/issues/edit.html.haml
+++ b/app/views/projects/issues/edit.html.haml
@@ -1,6 +1,6 @@
- page_title _("Edit"), "#{@issue.title} (#{@issue.to_reference})", _("Issues")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
Edit Issue ##{@issue.iid}
%hr
diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml
index edefdfbed97..617579cdd6f 100644
--- a/app/views/projects/issues/new.html.haml
+++ b/app/views/projects/issues/new.html.haml
@@ -3,6 +3,6 @@
- page_title _("New Issue")
.top-area.gl-lg-flex-direction-row.gl-border-bottom-0
- %h1.page-title= _("New Issue")
+ %h1.page-title.gl-font-size-h-display= _("New Issue")
= render "form"
diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml
index f15f2ec2f49..4f4609e6016 100644
--- a/app/views/projects/labels/edit.html.haml
+++ b/app/views/projects/labels/edit.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title _("Edit")
- page_title _("Edit"), @label.name, _("Labels")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Edit Label')
= render 'shared/labels/form', url: project_label_path(@project, @label), back_path: project_labels_path(@project)
diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml
index 37f5664990c..7002da0b76a 100644
--- a/app/views/projects/labels/new.html.haml
+++ b/app/views/projects/labels/new.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title _("New")
- page_title _("New Label")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('New Label')
= render 'shared/labels/form', url: project_labels_path(@project), back_path: project_labels_path(@project)
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 3cbe5baea96..615e9e42869 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -17,7 +17,7 @@
.detail-page-header-body
.issuable-meta.gl-display-flex
#js-issuable-header-warnings
- %h2.title.gl-my-0.gl-display-inline-block{ data: { qa_selector: 'title_content' } }
+ %h1.gl-font-size-h-display.gl-my-0.gl-display-inline-block{ data: { qa_selector: 'title_content' } }
= markdown_field(@merge_request, :title)
- unless hide_gutter_toggle
diff --git a/app/views/projects/merge_requests/creations/_new_compare.html.haml b/app/views/projects/merge_requests/creations/_new_compare.html.haml
index 12faba68315..9513b904804 100644
--- a/app/views/projects/merge_requests/creations/_new_compare.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_compare.html.haml
@@ -1,4 +1,4 @@
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('New merge request')
= form_for [@project, @merge_request], url: project_new_merge_request_path(@project), method: :get, html: { class: "merge-request-form js-requires-input" } do |f|
diff --git a/app/views/projects/merge_requests/creations/_new_submit.html.haml b/app/views/projects/merge_requests/creations/_new_submit.html.haml
index 6e400ae560a..3c39c04d3a3 100644
--- a/app/views/projects/merge_requests/creations/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_submit.html.haml
@@ -1,4 +1,4 @@
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('New merge request')
= gitlab_ui_form_for [@project, @merge_request], html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' } do |f|
= render 'shared/issuable/form', f: f, issuable: @merge_request, commits: @commits, presenter: @mr_presenter
diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml
index 497eddff9ac..77cc69f32ab 100644
--- a/app/views/projects/merge_requests/edit.html.haml
+++ b/app/views/projects/merge_requests/edit.html.haml
@@ -2,6 +2,6 @@
- breadcrumb_title @merge_request.to_reference
- page_title _("Edit"), "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge requests")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
Edit merge request #{@merge_request.to_reference}
= render 'form'
diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml
index 5017f116232..8d4ea2c3c21 100644
--- a/app/views/projects/milestones/edit.html.haml
+++ b/app/views/projects/milestones/edit.html.haml
@@ -2,7 +2,7 @@
- add_to_breadcrumbs _('Milestones'), project_milestones_path(@project)
- page_title _('Edit'), @milestone.title, _('Milestones')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Edit Milestone')
%hr
diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml
index d982e09e2c2..70ec1b0008a 100644
--- a/app/views/projects/milestones/new.html.haml
+++ b/app/views/projects/milestones/new.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title _('New')
- page_title _('New Milestone')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('New Milestone')
%hr
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index ea586c6b366..511adf37b39 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -30,7 +30,7 @@
#import-project-pane.tab-pane.js-toggle-container
- if import_sources_enabled?
- = render 'import_project_pane'
+ = render 'import_project_pane', destination_namespace_id: @namespace&.id
- else
.nothing-here-block
%h4= s_('ProjectsNew|No import options available')
diff --git a/app/views/projects/pages/show.html.haml b/app/views/projects/pages/show.html.haml
index e302c6cb68a..3fea9f9ff1b 100644
--- a/app/views/projects/pages/show.html.haml
+++ b/app/views/projects/pages/show.html.haml
@@ -1,7 +1,7 @@
- page_title _('Pages')
- if @project.pages_enabled?
- %h1.page-title.with-button
+ %h1.page-title.gl-font-size-h-display.with-button
= s_('GitLabPages|Pages')
- if can?(current_user, :update_pages, @project) && (Gitlab.config.pages.external_http || Gitlab.config.pages.external_https)
diff --git a/app/views/projects/pages_domains/new.html.haml b/app/views/projects/pages_domains/new.html.haml
index 5ac9ae732e3..6de8117df6b 100644
--- a/app/views/projects/pages_domains/new.html.haml
+++ b/app/views/projects/pages_domains/new.html.haml
@@ -1,6 +1,6 @@
- add_to_breadcrumbs _("Pages"), project_pages_path(@project)
- page_title _('New Pages Domain')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("New Pages Domain")
= render 'projects/pages_domains/helper_text'
%div
diff --git a/app/views/projects/pages_domains/show.html.haml b/app/views/projects/pages_domains/show.html.haml
index 50328a94eab..0edf75c9abc 100644
--- a/app/views/projects/pages_domains/show.html.haml
+++ b/app/views/projects/pages_domains/show.html.haml
@@ -11,7 +11,7 @@
.container-fluid.container-limited
= _("This domain is not verified. You will need to verify ownership before access is enabled.")
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Pages Domain')
= render 'projects/pages_domains/helper_text'
%div
diff --git a/app/views/projects/pipeline_schedules/edit.html.haml b/app/views/projects/pipeline_schedules/edit.html.haml
index eb2c87b8db5..642b458eea6 100644
--- a/app/views/projects/pipeline_schedules/edit.html.haml
+++ b/app/views/projects/pipeline_schedules/edit.html.haml
@@ -3,7 +3,7 @@
- page_title _("Edit"), @schedule.description, _("Pipeline Schedule")
- add_page_specific_style 'page_bundles/pipeline_schedules'
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Edit Pipeline Schedule")
%hr
diff --git a/app/views/projects/pipeline_schedules/new.html.haml b/app/views/projects/pipeline_schedules/new.html.haml
index 06208d95305..3b4acf5b8c5 100644
--- a/app/views/projects/pipeline_schedules/new.html.haml
+++ b/app/views/projects/pipeline_schedules/new.html.haml
@@ -5,7 +5,7 @@
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Schedule a new pipeline")
= render "form"
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index 06949c7e113..a4144f8ab0d 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _('Pipelines')
- page_title s_('Pipeline|Run pipeline')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= s_('Pipeline|Run pipeline')
%hr
diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
index e87c52ff1a8..ce56b160187 100644
--- a/app/views/projects/runners/edit.html.haml
+++ b/app/views/projects/runners/edit.html.haml
@@ -3,7 +3,7 @@
- add_to_breadcrumbs _('CI/CD Settings'), project_settings_ci_cd_path(@project)
- add_to_breadcrumbs "#{@runner.short_sha}", project_runner_path(@project, @runner)
-%h2.page-title
+%h1.page-title.gl-font-size-h-display
= s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
= render 'shared/runners/runner_type_badge', runner: @runner
diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml
index 8a25a58a8fe..d9bf064ad24 100644
--- a/app/views/projects/snippets/edit.html.haml
+++ b/app/views/projects/snippets/edit.html.haml
@@ -3,7 +3,7 @@
- page_title _("Edit"), "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
- @content_class = "limit-container-width" unless fluid_layout
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Edit Snippet")
%hr
= render "shared/snippets/form", url: project_snippet_path(@project, @snippet)
diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml
index df64f817064..5086b5eaa3d 100644
--- a/app/views/projects/snippets/new.html.haml
+++ b/app/views/projects/snippets/new.html.haml
@@ -3,7 +3,7 @@
- page_title _("New Snippet")
- @content_class = "limit-container-width" unless fluid_layout
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("New Snippet")
%hr
= render "shared/snippets/form", url: project_snippets_path(@project, @snippet)
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index d88397bbc7c..549e5e91488 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -6,7 +6,7 @@
= c.body do
= @error
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= s_('TagsPage|New Tag')
%hr
diff --git a/app/views/projects/tracings/show.html.haml b/app/views/projects/tracings/show.html.haml
index f306853b0c7..61f2cd8ac7f 100644
--- a/app/views/projects/tracings/show.html.haml
+++ b/app/views/projects/tracings/show.html.haml
@@ -17,7 +17,7 @@
= html_escape(s_('Deprecations|The logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
- if @project.tracing_external_url.present?
- %h1.page-title= _('Tracing')
+ %h1.page-title.gl-font-size-h-display= _('Tracing')
.gl-alert.gl-alert-info.gl-mb-5
.gl-alert-container
= sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
diff --git a/app/views/projects/usage_quotas/index.html.haml b/app/views/projects/usage_quotas/index.html.haml
index ca7e1cda2e2..40b952d4ae9 100644
--- a/app/views/projects/usage_quotas/index.html.haml
+++ b/app/views/projects/usage_quotas/index.html.haml
@@ -6,7 +6,7 @@
= c.body do
= _('To view usage, refresh this page in a few minutes.')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= s_('UsageQuota|Usage Quotas')
.row
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index ab5ca0cd90f..7d0859ac0ec 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -16,7 +16,7 @@
- page_card_attributes("Namespace" => @group&.full_path, "Project" => @project&.full_path)
.page-title-holder.d-flex.flex-wrap.justify-content-between
- %h1.page-title.mr-3= _('Search')
+ %h1.page-title.gl-font-size-h-display.mr-3= _('Search')
= render_if_exists 'search/form_elasticsearch', attrs: { class: 'mb-2 mb-sm-0 align-self-center' }
.gl-mt-3
diff --git a/app/views/sent_notifications/unsubscribe.html.haml b/app/views/sent_notifications/unsubscribe.html.haml
index 86c5ad9d0a6..03b030eb257 100644
--- a/app/views/sent_notifications/unsubscribe.html.haml
+++ b/app/views/sent_notifications/unsubscribe.html.haml
@@ -6,7 +6,7 @@
- noteable_url = show_project_path ? url_for([@sent_notification.project, noteable]) : breadcrumb_title_link
- page_title _('Unsubscribe'), noteable_text, noteable_type.pluralize, project_path
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Unsubscribe from %{type}") % { type: noteable_type }
%p
diff --git a/app/views/shared/_captcha_check.html.haml b/app/views/shared/_captcha_check.html.haml
index b7b19a6e8f1..a10ae655ea6 100644
--- a/app/views/shared/_captcha_check.html.haml
+++ b/app/views/shared/_captcha_check.html.haml
@@ -3,7 +3,7 @@
- script = local_assigns.fetch(:script, true)
- method = params[:action] == 'create' ? :post : :put
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _('Anti-spam verification')
%hr
diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml
index ee8cfe3abb6..5ae99474c70 100644
--- a/app/views/shared/_group_form.html.haml
+++ b/app/views/shared/_group_form.html.haml
@@ -2,38 +2,42 @@
- group_path = root_url
- group_path << parent.full_path + '/' if parent
-.row
- .form-group.group-name-holder.col-sm-12
- = f.label :name, class: 'label-bold' do
- = s_('Groups|Group name')
- = f.text_field :name, placeholder: _('My awesome group'), class: 'js-autofill-group-name form-control input-lg', data: { qa_selector: 'group_name_field' },
- required: true,
- title: s_('Groups|Enter a descriptive name for your group.'),
- autofocus: true
- .text-muted
- = s_('Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.')
-.row
- .form-group.col-xs-12.col-sm-8
- = f.label :path, class: 'label-bold' do
- = s_('Groups|Group URL')
- .input-group.gl-field-error-anchor
- .group-root-path.input-group-prepend.has-tooltip{ title: group_path, :'data-placement' => 'bottom' }
- .input-group-text
- %span>= root_url
- - if parent
- %strong= parent.full_path + '/'
- = f.hidden_field :parent_id
- = f.text_field :path, placeholder: _('my-awesome-group'), class: 'form-control js-validate-group-path js-autofill-group-path', data: { qa_selector: 'group_path_field' },
- autofocus: local_assigns[:autofocus] || false, required: true,
- pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
- title: group_url_error_message,
- maxlength: ::Namespace::URL_MAX_LENGTH,
- "data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
- %p.validation-error.gl-field-error.field-validation.hide
- = s_('Groups|Group path is unavailable. Path has been replaced with a suggested available path.')
- %p.validation-success.gl-field-success.field-validation.hide= s_('Groups|Group path is available.')
- %p.validation-pending.gl-field-error-ignore.field-validation.hide= s_('Groups|Checking group URL availability...')
+- if Feature::enabled?(:group_name_path_vue, current_user)
+ = render 'shared/groups/group_name_and_path_fields', f: f
+- else
+ .row
+ .form-group.group-name-holder.col-sm-12
+ = f.label :name, class: 'label-bold' do
+ = s_('Groups|Group name')
+ = f.text_field :name, placeholder: _('My awesome group'), class: 'js-autofill-group-name form-control input-lg', data: { qa_selector: 'group_name_field' },
+ required: true,
+ title: s_('Groups|Enter a descriptive name for your group.'),
+ autofocus: true
+ .text-muted
+ = s_('Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.')
+
+ .row
+ .form-group.col-xs-12.col-sm-8
+ = f.label :path, class: 'label-bold' do
+ = s_('Groups|Group URL')
+ .input-group.gl-field-error-anchor
+ .group-root-path.input-group-prepend.has-tooltip{ title: group_path, :'data-placement' => 'bottom' }
+ .input-group-text
+ %span>= root_url
+ - if parent
+ %strong= parent.full_path + '/'
+ = f.hidden_field :parent_id
+ = f.text_field :path, placeholder: _('my-awesome-group'), class: 'form-control js-validate-group-path js-autofill-group-path', data: { qa_selector: 'group_path_field' },
+ autofocus: local_assigns[:autofocus] || false, required: true,
+ pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
+ title: group_url_error_message,
+ maxlength: ::Namespace::URL_MAX_LENGTH,
+ "data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
+ %p.validation-error.gl-field-error.field-validation.hide
+ = s_('Groups|Group path is unavailable. Path has been replaced with a suggested available path.')
+ %p.validation-success.gl-field-success.field-validation.hide= s_('Groups|Group path is available.')
+ %p.validation-pending.gl-field-error-ignore.field-validation.hide= s_('Groups|Checking group URL availability...')
- if @group.persisted?
.gl-alert.gl-alert-warning.gl-mt-3.gl-mb-3
@@ -43,9 +47,9 @@
= succeed '.' do
= link_to s_('Groups|Learn more'), help_page_path('user/group/index', anchor: 'change-a-groups-path'), target: '_blank', class: 'gl-link'
-- if @group.persisted?
- .row
- .form-group.group-name-holder.col-sm-8
- = f.label :id, class: 'label-bold' do
- = s_('Groups|Group ID')
- = f.text_field :id, class: 'form-control', readonly: true
+ - if @group.persisted?
+ .row
+ .form-group.group-name-holder.col-sm-8
+ = f.label :id, class: 'label-bold' do
+ = s_('Groups|Group ID')
+ = f.text_field :id, class: 'form-control', readonly: true
diff --git a/app/views/shared/groups/_group_name_and_path_fields.html.haml b/app/views/shared/groups/_group_name_and_path_fields.html.haml
new file mode 100644
index 00000000000..21f5c966e3e
--- /dev/null
+++ b/app/views/shared/groups/_group_name_and_path_fields.html.haml
@@ -0,0 +1,4 @@
+.js-group-name-and-path{ data: group_name_and_path_app_data(@group) }
+ = f.hidden_field :name, data: { js_name: 'name' }
+ = f.hidden_field :path, maxlength: ::Namespace::URL_MAX_LENGTH, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, data: { js_name: 'path' }
+ = f.hidden_field :parent_id, data: { js_name: 'parentId' }
diff --git a/app/views/shared/integrations/overrides.html.haml b/app/views/shared/integrations/overrides.html.haml
index 15889351af3..a63053bde0a 100644
--- a/app/views/shared/integrations/overrides.html.haml
+++ b/app/views/shared/integrations/overrides.html.haml
@@ -3,7 +3,7 @@
- page_title @integration.title, _('Integrations')
- @content_class = 'limit-container-width' unless fluid_layout
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= @integration.title
.js-vue-integration-overrides{ data: integration_overrides_data(@integration, project: @project, group: @group) }
diff --git a/app/views/shared/runners/_runner_details.html.haml b/app/views/shared/runners/_runner_details.html.haml
index 7a35b1cec0a..f6396168cb3 100644
--- a/app/views/shared/runners/_runner_details.html.haml
+++ b/app/views/shared/runners/_runner_details.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title runner.short_sha
- page_title "##{runner.id} (#{runner.short_sha})"
-%h2.page-title
+%h1.page-title.gl-font-size-h-display
= s_('Runners|Runner #%{runner_id}' % { runner_id: runner.id })
= render 'shared/runners/runner_type_badge', runner: runner
diff --git a/app/views/shared/wikis/diff.html.haml b/app/views/shared/wikis/diff.html.haml
index 8ef13ff8a28..c39739ac422 100644
--- a/app/views/shared/wikis/diff.html.haml
+++ b/app/views/shared/wikis/diff.html.haml
@@ -5,7 +5,7 @@
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
- %h1.page-title.gl-flex-grow-1
+ %h1.page-title.gl-font-size-h-display.gl-flex-grow-1
= link_to_wiki_page @page
%span.light
&middot;
diff --git a/app/views/shared/wikis/edit.html.haml b/app/views/shared/wikis/edit.html.haml
index b5786fcb8b5..6bbce6b80d8 100644
--- a/app/views/shared/wikis/edit.html.haml
+++ b/app/views/shared/wikis/edit.html.haml
@@ -7,7 +7,7 @@
.js-wiki-edit-page.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
- %h1.page-title.gl-flex-grow-1
+ %h1.page-title.gl-font-size-h-display.gl-flex-grow-1
- if @page.persisted?
= link_to_wiki_page @page
%span.light
diff --git a/app/views/shared/wikis/history.html.haml b/app/views/shared/wikis/history.html.haml
index be55fef2621..052bbb3b410 100644
--- a/app/views/shared/wikis/history.html.haml
+++ b/app/views/shared/wikis/history.html.haml
@@ -4,7 +4,7 @@
.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
- %h1.page-title
+ %h1.page-title.gl-font-size-h-display
= link_to_wiki_page @page
%span.light
&middot;
diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml
index 1a12993afe1..21d63a6db3d 100644
--- a/app/views/shared/wikis/pages.html.haml
+++ b/app/views/shared/wikis/pages.html.haml
@@ -5,7 +5,7 @@
- wiki_sort_options = [{ text: s_("Wiki|Title"), value: 'title', href: wiki_path(@wiki, action: :pages, sort: Wiki::TITLE_ORDER)}, { text: s_("Wiki|Created date"), value: 'created_at', href: wiki_path(@wiki, action: :pages, sort: Wiki::CREATED_AT_ORDER) }]
.wiki-page-header.top-area.flex-column.flex-lg-row
- %h1.page-title.gl-flex-grow-1
+ %h1.page-title.gl-font-size-h-display.gl-flex-grow-1
= s_("Wiki|Wiki Pages")
.nav-controls.pb-md-3.pb-lg-0
diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml
index 09d92a70c10..5fa4a6775f9 100644
--- a/app/views/snippets/edit.html.haml
+++ b/app/views/snippets/edit.html.haml
@@ -3,7 +3,7 @@
- content_for :prefetch_asset_tags do
- webpack_preload_asset_tag('monaco')
-%h1.page-title
+%h1.page-title.gl-font-size-h-display
= _("Edit Snippet")
%hr
= render 'shared/snippets/form', url: gitlab_snippet_path(@snippet)
diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml
index 2669754cc3a..418f96a1024 100644
--- a/app/views/snippets/new.html.haml
+++ b/app/views/snippets/new.html.haml
@@ -4,7 +4,7 @@
- @content_class = "limit-container-width" unless fluid_layout
.page-title-holder.d-flex.align-items-center
- %h1.page-title= _('New Snippet')
+ %h1.page-title.gl-font-size-h-display= _('New Snippet')
.gl-mt-3
= render "shared/snippets/form", url: snippets_path(@snippet)
diff --git a/app/views/users/unsubscribes/show.html.haml b/app/views/users/unsubscribes/show.html.haml
index b22b8097333..df8989ad979 100644
--- a/app/views/users/unsubscribes/show.html.haml
+++ b/app/views/users/unsubscribes/show.html.haml
@@ -1,5 +1,5 @@
- page_title _("Unsubscribe"), _("Admin Notifications")
-%h1.page-title Unsubscribe from Admin notifications
+%h1.page-title.gl-font-size-h-display Unsubscribe from Admin notifications
%hr
= form_tag unsubscribe_path(Base64.urlsafe_encode64(@email)) do
diff --git a/config/feature_flags/development/group_name_path_vue.yml b/config/feature_flags/development/group_name_path_vue.yml
new file mode 100644
index 00000000000..6ecb0eaf20e
--- /dev/null
+++ b/config/feature_flags/development/group_name_path_vue.yml
@@ -0,0 +1,8 @@
+---
+name: group_name_path_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88085
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363623
+milestone: '15.1'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/config/feature_flags/development/use_received_header_for_incoming_emails.yml b/config/feature_flags/development/use_received_header_for_incoming_emails.yml
deleted file mode 100644
index e466a266367..00000000000
--- a/config/feature_flags/development/use_received_header_for_incoming_emails.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: use_received_header_for_incoming_emails
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81489
-rollout_issue_url:
-milestone: '14.9'
-type: development
-group: group::certify
-default_enabled: true
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 6f44307e65c..95301ec026a 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -68,7 +68,8 @@ this method only supports replies, and not the other features of [incoming email
## Accepted headers
-> Accepting `Received` headers [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81489) in GitLab 14.9 [with a flag](feature_flags.md) named `use_received_header_for_incoming_emails`. Enabled by default.
+> - Accepting `Received` headers [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81489) in GitLab 14.9 [with a flag](feature_flags.md) named `use_received_header_for_incoming_emails`. Enabled by default.
+> - Accepting `Received` headers: [feature flag](feature_flags.md) named `use_received_header_for_incoming_emails` [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/362596) in GitLab 14.1.
Email is processed correctly when a configured email address is present in one of the following headers
(sorted in the order they are checked):
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index 73947da84d5..61b23527f8f 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -2196,10 +2196,6 @@ There are two ways of specifying object storage configuration in GitLab:
Starting with GitLab 13.2, consolidated object storage configuration is available. It simplifies your GitLab configuration since the connection details are shared across object types. Refer to [Consolidated object storage configuration](../object_storage.md#consolidated-object-storage-configuration) guide for instructions on how to set it up.
-GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared via NFS on any GitLab Rails and Sidekiq nodes.
-
-In GitLab 13.6 and later, it's also recommended to switch to [Incremental logging](../job_logs.md#incremental-logging-architecture), which uses Redis instead of disk space for temporary caching of job logs. This is required when no NFS node has been deployed.
-
For configuring object storage in GitLab 13.1 and earlier, or for storage types not
supported by consolidated configuration form, refer to the following guides based
on what features you intend to use:
@@ -2229,6 +2225,12 @@ in the future.
</a>
</div>
+## Enable incremental logging
+
+GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared through NFS on any GitLab Rails and Sidekiq nodes.
+
+While sharing the job logs through NFS is supported, it's recommended to avoid the need to use NFS by enabling [incremental logging](../job_logs.md#incremental-logging-architecture) (required when no NFS node has been deployed). Incremental logging uses Redis instead of disk space for temporary caching of job logs.
+
## Configure Advanced Search
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 2bbb43732fd..d5e13940f01 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -2200,10 +2200,6 @@ There are two ways of specifying object storage configuration in GitLab:
Starting with GitLab 13.2, consolidated object storage configuration is available. It simplifies your GitLab configuration since the connection details are shared across object types. Refer to [Consolidated object storage configuration](../object_storage.md#consolidated-object-storage-configuration) guide for instructions on how to set it up.
-GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared via NFS on any GitLab Rails and Sidekiq nodes.
-
-In GitLab 13.6 and later, it's also recommended to switch to [Incremental logging](../job_logs.md#incremental-logging-architecture), which uses Redis instead of disk space for temporary caching of job logs. This is required when no NFS node has been deployed.
-
For configuring object storage in GitLab 13.1 and earlier, or for storage types not
supported by consolidated configuration form, refer to the following guides based
on what features you intend to use:
@@ -2233,6 +2229,12 @@ in the future.
</a>
</div>
+## Enable incremental logging
+
+GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared through NFS on any GitLab Rails and Sidekiq nodes.
+
+While sharing the job logs through NFS is supported, it's recommended to avoid the need to use NFS by enabling [incremental logging](../job_logs.md#incremental-logging-architecture) (required when no NFS node has been deployed). Incremental logging uses Redis instead of disk space for temporary caching of job logs.
+
## Configure Advanced Search
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index fe038ab5860..de5f7c7455c 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -2135,10 +2135,6 @@ There are two ways of specifying object storage configuration in GitLab:
Starting with GitLab 13.2, consolidated object storage configuration is available. It simplifies your GitLab configuration since the connection details are shared across object types. Refer to [Consolidated object storage configuration](../object_storage.md#consolidated-object-storage-configuration) guide for instructions on how to set it up.
-GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared via NFS on any GitLab Rails and Sidekiq nodes.
-
-In GitLab 13.6 and later, it's also recommended to switch to [Incremental logging](../job_logs.md#incremental-logging-architecture), which uses Redis instead of disk space for temporary caching of job logs. This is required when no NFS node has been deployed.
-
For configuring object storage in GitLab 13.1 and earlier, or for storage types not
supported by consolidated configuration form, refer to the following guides based
on what features you intend to use:
@@ -2168,6 +2164,12 @@ in the future.
</a>
</div>
+## Enable incremental logging
+
+GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared through NFS on any GitLab Rails and Sidekiq nodes.
+
+While sharing the job logs through NFS is supported, it's recommended to avoid the need to use NFS by enabling [incremental logging](../job_logs.md#incremental-logging-architecture) (required when no NFS node has been deployed). Incremental logging uses Redis instead of disk space for temporary caching of job logs.
+
## Configure Advanced Search
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index 5ef317e3a55..53e39a576c8 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -2216,10 +2216,6 @@ There are two ways of specifying object storage configuration in GitLab:
Starting with GitLab 13.2, consolidated object storage configuration is available. It simplifies your GitLab configuration since the connection details are shared across object types. Refer to [Consolidated object storage configuration](../object_storage.md#consolidated-object-storage-configuration) guide for instructions on how to set it up.
-GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared via NFS on any GitLab Rails and Sidekiq nodes.
-
-In GitLab 13.6 and later, it's also recommended to switch to [Incremental logging](../job_logs.md#incremental-logging-architecture), which uses Redis instead of disk space for temporary caching of job logs. This is required when no NFS node has been deployed.
-
For configuring object storage in GitLab 13.1 and earlier, or for storage types not
supported by consolidated configuration form, refer to the following guides based
on what features you intend to use:
@@ -2249,6 +2245,12 @@ in the future.
</a>
</div>
+## Enable incremental logging
+
+GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared through NFS on any GitLab Rails and Sidekiq nodes.
+
+While sharing the job logs through NFS is supported, it's recommended to avoid the need to use NFS by enabling [incremental logging](../job_logs.md#incremental-logging-architecture) (required when no NFS node has been deployed). Incremental logging uses Redis instead of disk space for temporary caching of job logs.
+
## Configure Advanced Search
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 86a92d12b15..170496d84e9 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -2135,10 +2135,6 @@ There are two ways of specifying object storage configuration in GitLab:
Starting with GitLab 13.2, consolidated object storage configuration is available. It simplifies your GitLab configuration since the connection details are shared across object types. Refer to [Consolidated object storage configuration](../object_storage.md#consolidated-object-storage-configuration) guide for instructions on how to set it up.
-GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared via NFS on any GitLab Rails and Sidekiq nodes.
-
-In GitLab 13.6 and later, it's also recommended to switch to [Incremental logging](../job_logs.md#incremental-logging-architecture), which uses Redis instead of disk space for temporary caching of job logs. This is required when no NFS node has been deployed.
-
For configuring object storage in GitLab 13.1 and earlier, or for storage types not
supported by consolidated configuration form, refer to the following guides based
on what features you intend to use:
@@ -2168,6 +2164,12 @@ in the future.
</a>
</div>
+## Enable incremental logging
+
+GitLab Runner returns job logs in chunks which Omnibus GitLab caches temporarily on disk in `/var/opt/gitlab/gitlab-ci/builds` by default, even when using consolidated object storage. With default configuration, this directory needs to be shared through NFS on any GitLab Rails and Sidekiq nodes.
+
+While sharing the job logs through NFS is supported, it's recommended to avoid the need to use NFS by enabling [incremental logging](../job_logs.md#incremental-logging-architecture) (required when no NFS node has been deployed). Incremental logging uses Redis instead of disk space for temporary caching of job logs.
+
## Configure Advanced Search
You can leverage Elasticsearch and [enable Advanced Search](../../integration/elasticsearch.md)
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index a3d17cea5b8..2f275e205af 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -2013,9 +2013,9 @@ job2:
Use `interruptible` if a job should be canceled when a newer pipeline starts before the job completes.
-This keyword is used with the [automatic cancellation of redundant pipelines](../pipelines/settings.md#auto-cancel-redundant-pipelines)
-feature. When enabled, a running job with `interruptible: true` can be cancelled when
-a new pipeline starts on the same branch.
+This keyword has no effect if [automatic cancellation of redundant pipelines](../pipelines/settings.md#auto-cancel-redundant-pipelines)
+is disabled. When enabled, a running job with `interruptible: true` is cancelled when
+starting a pipeline for a new change on the same branch.
You can't cancel subsequent jobs after a job with `interruptible: false` starts.
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 310f4af0df8..9c605ca5b75 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -608,6 +608,7 @@ The following variables are used for configuring specific analyzers (used for a
| `PIP_REQUIREMENTS_FILE` | `gemnasium-python` | | Pip requirements file to be scanned. |
| `DS_PIP_VERSION` | `gemnasium-python` | | Force the install of a specific pip version (example: `"19.3"`), otherwise the pip installed in the Docker image is used. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12811) in GitLab 12.7) |
| `DS_PIP_DEPENDENCY_PATH` | `gemnasium-python` | | Path to load Python pip dependencies from. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12412) in GitLab 12.2) |
+| `DS_INCLUDE_DEV_DEPENDENCIES` | `gemnasium` | `"true"` | When set to `"false"`, development dependencies and their vulnerabilities are not reported. Only NPM projects are supported. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227861) in GitLab 15.1. |
#### Other variables
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index 8b0f3d7cf24..ba84be6e8ca 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -158,8 +158,6 @@ module Gitlab
end
def find_first_key_from_received_headers
- return unless ::Feature.enabled?(:use_received_header_for_incoming_emails)
-
recipients_from_received_headers.find do |email|
key = email_class.key_from_address(email)
break key if key
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 3b89c3ece56..c8402287d70 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -358,4 +358,4 @@ DEPENDENCIES
zeitwerk (~> 2.4)
BUNDLED WITH
- 2.3.6
+ 2.3.15
diff --git a/qa/qa/page/component/access_tokens.rb b/qa/qa/page/component/access_tokens.rb
index ec8bbe8ff97..7caba55e41d 100644
--- a/qa/qa/page/component/access_tokens.rb
+++ b/qa/qa/page/component/access_tokens.rb
@@ -9,6 +9,10 @@ module QA
def self.included(base)
super
+ base.class_eval do
+ include QA::Page::Component::ConfirmModal
+ end
+
base.view 'app/assets/javascripts/access_tokens/components/expires_at_field.vue' do
element :expiry_date_field
end
@@ -76,10 +80,10 @@ module QA
def revoke_first_token_with_name(token_name)
within first_token_row_for_name(token_name) do
- accept_confirm do
- click_element(:revoke_button)
- end
+ click_element(:revoke_button)
end
+
+ click_confirmation_ok_button
end
end
end
diff --git a/qa/qa/page/component/snippet.rb b/qa/qa/page/component/snippet.rb
index 47d32ae8225..47ed1a9616b 100644
--- a/qa/qa/page/component/snippet.rb
+++ b/qa/qa/page/component/snippet.rb
@@ -9,6 +9,10 @@ module QA
def self.included(base)
super
+ base.class_eval do
+ include QA::Page::Component::ConfirmModal
+ end
+
base.view 'app/assets/javascripts/snippets/components/snippet_title.vue' do
element :snippet_title_content
end
@@ -224,9 +228,8 @@ module QA
def delete_comment(comment)
click_element(:more_actions_dropdown)
- accept_alert do
- click_element(:delete_comment_button)
- end
+ click_element(:delete_comment_button)
+ click_confirmation_ok_button
unless has_no_element?(:note_content, text: comment)
raise ElementNotFound, "Comment was not removed as expected"
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index 2cd78f9f17a..b057a27fa3e 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -5,6 +5,7 @@ module QA
module Group
class Show < Page::Base
include Page::Component::GroupsFilter
+ include QA::Page::Component::ConfirmModal
view 'app/views/groups/_home_panel.html.haml' do
element :new_project_button
@@ -46,9 +47,8 @@ module QA
end
def leave_group
- accept_alert do
- click_element :leave_group_link
- end
+ click_element :leave_group_link
+ click_confirmation_ok_button
end
end
end
diff --git a/qa/qa/page/profile/emails.rb b/qa/qa/page/profile/emails.rb
index c20bc6a5c57..f8aeea50513 100644
--- a/qa/qa/page/profile/emails.rb
+++ b/qa/qa/page/profile/emails.rb
@@ -4,6 +4,8 @@ module QA
module Page
module Profile
class Emails < Page::Base
+ include QA::Page::Component::ConfirmModal
+
view 'app/views/profiles/emails/index.html.haml' do
element :email_address_field
element :add_email_address_button
@@ -17,11 +19,10 @@ module QA
end
def delete_email_address(email_address)
- page.accept_alert do
- within_element(:email_row_content, text: email_address) do
- click_element(:delete_email_link)
- end
+ within_element(:email_row_content, text: email_address) do
+ click_element(:delete_email_link)
end
+ click_confirmation_ok_button
end
end
end
diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb
index a19fcf8ec6e..4bf8abb555b 100644
--- a/qa/qa/page/project/branches/show.rb
+++ b/qa/qa/page/project/branches/show.rb
@@ -5,6 +5,8 @@ module QA
module Project
module Branches
class Show < Page::Base
+ include Page::Component::ConfirmModal
+
view 'app/assets/javascripts/branches/components/delete_branch_button.vue' do
element :delete_branch_button
end
@@ -54,9 +56,8 @@ module QA
end
def delete_merged_branches
- accept_alert do
- click_element(:delete_merged_branches)
- end
+ click_element(:delete_merged_branches)
+ click_confirmation_ok_button
end
end
end
diff --git a/qa/qa/page/project/settings/access_tokens.rb b/qa/qa/page/project/settings/access_tokens.rb
index d559ca4daaa..47afa26191c 100644
--- a/qa/qa/page/project/settings/access_tokens.rb
+++ b/qa/qa/page/project/settings/access_tokens.rb
@@ -8,6 +8,7 @@ module QA
module Settings
class AccessTokens < Page::Base
include Page::Component::AccessTokens
+ include Page::Component::ConfirmModal
end
end
end
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index 525210a08f6..fd9cc8a13e7 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -5,7 +5,7 @@ module QA
module Project
module Settings
class Advanced < Page::Base
- include Component::ConfirmModal
+ include QA::Page::Component::ConfirmModal
include Component::NamespaceSelect
view 'app/views/projects/edit.html.haml' do
@@ -65,15 +65,13 @@ module QA
end
def archive_project
- page.accept_alert("Are you sure that you want to archive this project?") do
- click_element :archive_project_link
- end
+ click_element :archive_project_link
+ click_confirmation_ok_button
end
def unarchive_project
- page.accept_alert("Are you sure that you want to unarchive this project?") do
- click_element :unarchive_project_link
- end
+ click_element :unarchive_project_link
+ click_confirmation_ok_button
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb
index 381a25a14d0..19aa3d12568 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb
@@ -2,10 +2,20 @@
module QA
RSpec.describe 'Manage' do
- describe 'Project access tokens', :reliable do
+ describe 'Project access tokens', :reliable, feature_flag: {
+ name: 'bootstrap_confirmation_modals',
+ scope: :global
+ } do
let(:project_access_token) { QA::Resource::ProjectAccessToken.fabricate_via_browser_ui! }
- it 'can be created and revoked via the UI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347688' do
+ before do
+ Runtime::Feature.enable(:bootstrap_confirmation_modals)
+ end
+
+ it(
+ 'can be created and revoked via the UI',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347688'
+ ) do
expect(project_access_token.token).not_to be_nil
project_access_token.revoke_via_ui!
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
index 0bd470fcb77..2300e384ab5 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create' do
+ RSpec.describe 'Create', feature_flag: {
+ name: 'bootstrap_confirmation_modals',
+ scope: :global
+ } do
describe 'Create, list, and delete branches via web', :requires_admin do
master_branch = nil
second_branch = 'second-branch'
@@ -16,6 +19,8 @@ module QA
commit_message_of_third_branch = "Add #{file_third_branch}"
before do
+ Runtime::Feature.enable(:bootstrap_confirmation_modals)
+
Flow::Login.sign_in
project = Resource::Project.fabricate_via_api! do |proj|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
index 1a7c64a363f..171567b7ed9 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create' do
+ RSpec.describe 'Create', feature_flag: {
+ name: 'bootstrap_confirmation_modals',
+ scope: :global
+ } do
describe 'Adding comments on snippets' do
let(:comment_author) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
let(:comment_content) { 'Comment 123' }
@@ -20,6 +23,7 @@ module QA
end
before do
+ Runtime::Feature.enable(:bootstrap_confirmation_modals)
Flow::Login.sign_in
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
index a50b995e483..ed421ac7279 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :reliable do
+ RSpec.describe 'Create', :reliable, feature_flag: {
+ name: 'bootstrap_confirmation_modals',
+ scope: :global
+ } do
describe 'Multiple file snippet' do
let(:first_file_content) { 'First file content' }
let(:second_file_content) { 'Second file content' }
@@ -51,6 +54,7 @@ module QA
end
before do
+ Runtime::Feature.enable(:bootstrap_confirmation_modals)
Flow::Login.sign_in
end
diff --git a/qa/qa/support/page_error_checker.rb b/qa/qa/support/page_error_checker.rb
index b89f745d551..a40ace24030 100644
--- a/qa/qa/support/page_error_checker.rb
+++ b/qa/qa/support/page_error_checker.rb
@@ -8,9 +8,7 @@ module QA
request_id_string = ''
if error_code == 500
request_id = parse_five_c_page_request_id(page)
- if request_id
- request_id_string = "\n\n" + Loglinking.failure_metadata(request_id)
- end
+ request_id_string = "\n\n#{Loglinking.failure_metadata(request_id)}" if request_id
end
report = if QA::Runtime::Env.browser == :chrome
@@ -26,7 +24,7 @@ module QA
end
def parse_five_c_page_request_id(page)
- Nokogiri::HTML.parse(page.html).xpath("/html/body/div/p[1]/code").children.first
+ page_html(page).xpath("/html/body/div/p[1]/code").children.first
end
def return_chrome_errors(page, error_code)
@@ -43,26 +41,26 @@ module QA
"Status code #{error_code} found"
end
+ # rubocop:disable Rails/Pluck
def check_page_for_error_code(page)
- error_code = 0
# Test for 404 img alt
- error_code = 404 if Nokogiri::HTML.parse(page.html).xpath("//img").map { |t| t[:alt] }.first.eql?('404')
+ return report!(page, 404) if page_html(page).xpath("//img").map { |t| t[:alt] }.first.eql?('404')
# 500 error page in header surrounded by newlines, try to match
- five_hundred_test = Nokogiri::HTML.parse(page.html).xpath("//h1/text()").map.first
- five_hundred_title = Nokogiri::HTML.parse(page.html).xpath("//head/title/text()").map.first
- unless five_hundred_test.nil?
- error_code = 500 if
- five_hundred_test.text.include?('500') &&
- five_hundred_title.text.eql?('Something went wrong (500)')
+ five_hundred_test = page_html(page).xpath("//h1/text()").map.first
+ five_hundred_title = page_html(page).xpath("//head/title/text()").map.first
+ if five_hundred_test&.text&.include?('500') && five_hundred_title&.text.eql?('Something went wrong (500)')
+ return report!(page, 500)
end
- # GDK shows backtrace rather than error page
- error_code = 500 if Nokogiri::HTML.parse(page.html).xpath("//body//section").map { |t| t[:class] }.first.eql?('backtrace')
- unless error_code == 0
- report!(page, error_code)
- end
+ # GDK shows backtrace rather than error page
+ report!(page, 500) if page_html(page).xpath("//body//section").map { |t| t[:class] }.first.eql?('backtrace')
+ rescue StandardError => e
+ # There are instances where page check can raise errors like: WebDriver::Error::UnexpectedAlertOpenError
+ # Log error but do not fail the test itself
+ Runtime::Logger.error("Page error check raised error: #{e}")
end
+ # rubocop:enable Rails/Pluck
# Log request errors triggered from async api calls from the browser
#
@@ -87,9 +85,7 @@ module QA
"#{error_metadata} -- #{request_id_string}"
end
- unless errors.nil? || errors.empty?
- QA::Runtime::Logger.error "Interceptor Api Errors\n#{errors.join("\n")}"
- end
+ QA::Runtime::Logger.error "Interceptor Api Errors\n#{errors.join("\n")}" unless errors.nil? || errors.empty?
# clear the cache after logging the errors
page.execute_script <<~JS
@@ -109,6 +105,10 @@ module QA
private
+ def page_html(page)
+ Nokogiri::HTML.parse(page.html)
+ end
+
def group_errors(errors)
errors.each_with_object({}) do |error, memo|
url = error['url']&.split('?')&.first || 'Unknown url'
diff --git a/scripts/license-check.sh b/scripts/license-check.sh
new file mode 100755
index 00000000000..c2d5cfd8cde
--- /dev/null
+++ b/scripts/license-check.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# This script runs the LicenseFinder gem to verify that all licenses are
+# compliant. However, bundler v2.2+ and LicenseFinder do not play well
+# together when:
+#
+# 1. There are native gems installed (e.g. nokogiri, grpc, and google-protobuf).
+# 2. `Gemfile.lock` doesn't list the platform-specific gems that were installed.
+#
+# A full explanation is here:
+# https://github.com/pivotal/LicenseFinder/issues/828#issuecomment-953359134
+#
+# To work around the issue, we configure bundler to install gems for the
+# current Ruby platform, which causes Gemfile and Gemfile.lock to be
+# updated with the platform-specific gems. This allows LicenseFinder to
+# run properly. After it finishes, we clean up the mess.
+
+PROJECT_PATH=${1:-`pwd`}
+
+echo "Using project path ${PROJECT_PATH}"
+
+GEMFILE_DIFF=`git diff Gemfile Gemfile.lock`
+
+if [ ! -z "$GEMFILE_DIFF" ]; then
+ echo "LicenseFinder needs to lock the Gemfile to the current platform, but Gemfile or Gemfile.lock has changes."
+ exit 1
+fi
+
+BUNDLE_DEPLOYMENT=false BUNDLE_FROZEN=false bundle lock --add-platform `ruby -e "puts RUBY_PLATFORM"`
+bundle exec license_finder --decisions-file config/dependency_decisions.yml --project-path ${PROJECT_PATH}
+
+git checkout -q Gemfile Gemfile.lock
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 317652eb075..14d6a3deccb 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -46,7 +46,7 @@ class StaticAnalysis
(Gitlab.ee? ? Task.new(%w[bin/rake gettext:updated_check], 360) : nil),
Task.new(%w[yarn run lint:prettier], 160),
Task.new(%w[bin/rake gettext:lint], 85),
- Task.new(%W[bundle exec license_finder --decisions-file config/dependency_decisions.yml --project-path #{project_path}], 20),
+ Task.new(%W[scripts/license-check.sh #{project_path}], 20),
Task.new(%w[bin/rake lint:static_verification], 35),
Task.new(%w[scripts/rubocop-max-files-in-cache-check], 20),
Task.new(%w[bin/rake config_lint], 10),
diff --git a/scripts/utils.sh b/scripts/utils.sh
index 41a8234466e..4f339bbc850 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -38,7 +38,7 @@ function bundle_install_script() {
exit 1;
fi;
- gem install bundler --no-document --conservative --version 2.3.6
+ gem install bundler --no-document --conservative --version 2.3.15
bundle --version
bundle config set path "$(pwd)/vendor"
bundle config set clean 'true'
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 3dc11b806a0..1b97bdb6294 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'Admin Groups' do
end
end
- describe 'create a group' do
+ describe 'create a group', :js do
describe 'with expected fields' do
it 'renders from as expected', :aggregate_failures do
visit new_admin_group_path
@@ -42,6 +42,8 @@ RSpec.describe 'Admin Groups' do
end
it 'creates new group' do
+ stub_feature_flags(group_name_path_vue: false)
+
visit admin_groups_path
page.within '#content-body' do
@@ -75,7 +77,7 @@ RSpec.describe 'Admin Groups' do
expect_selected_visibility(internal)
end
- it 'when entered in group name, it auto filled the group path', :js do
+ it 'when entered in group name, it auto filled the group path' do
visit admin_groups_path
click_link "New group"
group_name = 'gitlab'
@@ -84,7 +86,7 @@ RSpec.describe 'Admin Groups' do
expect(path_field.value).to eq group_name
end
- it 'auto populates the group path with the group name', :js do
+ it 'auto populates the group path with the group name' do
visit admin_groups_path
click_link "New group"
group_name = 'my gitlab project'
@@ -93,7 +95,9 @@ RSpec.describe 'Admin Groups' do
expect(path_field.value).to eq 'my-gitlab-project'
end
- it 'when entering in group path, group name does not change anymore', :js do
+ it 'when entering in group path, group name does not change anymore' do
+ stub_feature_flags(group_name_path_vue: false)
+
visit admin_groups_path
click_link "New group"
group_path = 'my-gitlab-project'
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index aa65169860c..c323e60bb71 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -61,6 +61,33 @@ RSpec.describe 'New project', :js do
expect(page).to have_link('GitLab export')
end
+ describe 'github import option' do
+ context 'with user namespace' do
+ before do
+ visit new_project_path
+ click_link 'Import project'
+ end
+
+ it 'renders link to github importer' do
+ expect(page).to have_link(href: new_import_github_path)
+ end
+ end
+
+ context 'with group namespace' do
+ let(:group) { create(:group, :private) }
+
+ before do
+ group.add_owner(user)
+ visit new_project_path(namespace_id: group.id)
+ click_link 'Import project'
+ end
+
+ it 'renders link to github importer including namespace id' do
+ expect(page).to have_link(href: new_import_github_path(namespace_id: group.id))
+ end
+ end
+ end
+
describe 'manifest import option' do
before do
visit new_project_path
diff --git a/spec/frontend/groups/components/group_name_and_path_spec.js b/spec/frontend/groups/components/group_name_and_path_spec.js
new file mode 100644
index 00000000000..e656cb11d2f
--- /dev/null
+++ b/spec/frontend/groups/components/group_name_and_path_spec.js
@@ -0,0 +1,261 @@
+import { merge } from 'lodash';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import GroupNameAndPath from '~/groups/components/group_name_and_path.vue';
+import { getGroupPathAvailability } from '~/rest_api';
+import { createAlert } from '~/flash';
+
+jest.mock('~/flash');
+jest.mock('~/rest_api', () => ({
+ getGroupPathAvailability: jest.fn(),
+}));
+
+describe('GroupNameAndPath', () => {
+ let wrapper;
+
+ const mockGroupName = 'My awesome group';
+ const mockGroupUrl = 'my-awesome-group';
+ const mockGroupUrlSuggested = 'my-awesome-group1';
+
+ const defaultProvide = {
+ basePath: 'http://gitlab.com/',
+ fields: {
+ name: { name: 'group[name]', id: 'group_name', value: '' },
+ path: {
+ name: 'group[path]',
+ id: 'group_path',
+ value: '',
+ maxLength: 255,
+ pattern: '[a-zA-Z0-9_\\.][a-zA-Z0-9_\\-\\.]*[a-zA-Z0-9_\\-]|[a-zA-Z0-9_]',
+ },
+ parentId: { name: 'group[parent_id]', id: 'group_parent_id', value: '1' },
+ groupId: { name: 'group[id]', id: 'group_id', value: '' },
+ },
+ mattermostEnabled: false,
+ };
+
+ const createComponent = ({ provide = {} } = {}) => {
+ wrapper = mountExtended(GroupNameAndPath, { provide: merge({}, defaultProvide, provide) });
+ };
+
+ const findGroupNameField = () => wrapper.findByLabelText(GroupNameAndPath.i18n.inputs.name.label);
+ const findGroupUrlField = () => wrapper.findByLabelText(GroupNameAndPath.i18n.inputs.path.label);
+
+ const apiMockAvailablePath = () => {
+ getGroupPathAvailability.mockResolvedValue({
+ data: { exists: false, suggests: [] },
+ });
+ };
+ const apiMockUnavailablePath = (suggests = [mockGroupUrlSuggested]) => {
+ getGroupPathAvailability.mockResolvedValue({
+ data: { exists: true, suggests },
+ });
+ };
+ const apiMockLoading = () => {
+ getGroupPathAvailability.mockImplementation(() => new Promise(() => {}));
+ };
+
+ const expectLoadingMessageExists = () => {
+ expect(wrapper.findByText(GroupNameAndPath.i18n.apiLoadingMessage).exists()).toBe(true);
+ };
+
+ describe('when user types in the `Group name` field', () => {
+ it('updates `Group URL` field as user types', async () => {
+ createComponent();
+
+ await findGroupNameField().setValue(mockGroupName);
+
+ expect(findGroupUrlField().element.value).toBe(mockGroupUrl);
+ });
+
+ it('shows loading message', async () => {
+ apiMockLoading();
+
+ createComponent();
+
+ await findGroupNameField().setValue(mockGroupName);
+
+ expectLoadingMessageExists();
+ });
+
+ describe('when path is available', () => {
+ it('does not update `Group URL` field', async () => {
+ apiMockAvailablePath();
+
+ createComponent();
+
+ await findGroupNameField().setValue(mockGroupName);
+
+ expect(getGroupPathAvailability).toHaveBeenCalledWith(
+ mockGroupUrl,
+ defaultProvide.fields.parentId.value,
+ { signal: expect.any(AbortSignal) },
+ );
+
+ await waitForPromises();
+
+ expect(findGroupUrlField().element.value).toBe(mockGroupUrl);
+ });
+ });
+
+ describe('when path is not available', () => {
+ it('updates `Group URL` field', async () => {
+ apiMockUnavailablePath();
+
+ createComponent();
+
+ await findGroupNameField().setValue(mockGroupName);
+ await waitForPromises();
+
+ expect(findGroupUrlField().element.value).toBe(mockGroupUrlSuggested);
+ });
+ });
+
+ describe('when API returns no suggestions', () => {
+ it('calls `createAlert`', async () => {
+ apiMockUnavailablePath([]);
+
+ createComponent();
+
+ await findGroupNameField().setValue(mockGroupName);
+ await waitForPromises();
+
+ expect(createAlert).toHaveBeenCalledWith({
+ message: GroupNameAndPath.i18n.apiErrorMessage,
+ });
+ });
+ });
+
+ describe('when API call fails', () => {
+ it('calls `createAlert`', async () => {
+ getGroupPathAvailability.mockRejectedValue({});
+
+ createComponent();
+
+ await findGroupNameField().setValue(mockGroupName);
+ await waitForPromises();
+
+ expect(createAlert).toHaveBeenCalledWith({
+ message: GroupNameAndPath.i18n.apiErrorMessage,
+ });
+ });
+ });
+
+ describe('when multiple API calls are in-flight', () => {
+ it('aborts the first API call and resolves second API call', async () => {
+ apiMockLoading();
+ apiMockUnavailablePath();
+ const abortSpy = jest.spyOn(AbortController.prototype, 'abort');
+
+ createComponent();
+
+ await findGroupNameField().setValue('Foo');
+ await findGroupNameField().setValue(mockGroupName);
+ await waitForPromises();
+
+ expect(createAlert).not.toHaveBeenCalled();
+ expect(findGroupUrlField().element.value).toBe(mockGroupUrlSuggested);
+ expect(abortSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('when `Group URL` is empty', () => {
+ it('does not call API', async () => {
+ createComponent({
+ provide: { fields: { name: { value: mockGroupName }, path: mockGroupUrl } },
+ });
+
+ await findGroupNameField().setValue('');
+
+ expect(getGroupPathAvailability).not.toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('when `Group name` field is invalid', () => {
+ it('shows error message', async () => {
+ createComponent();
+
+ await findGroupNameField().trigger('invalid');
+
+ expect(wrapper.findByText(GroupNameAndPath.i18n.inputs.name.invalidFeedback).exists()).toBe(
+ true,
+ );
+ });
+ });
+
+ describe('when user types in `Group URL` field', () => {
+ it('shows loading message', async () => {
+ apiMockLoading();
+
+ createComponent();
+
+ await findGroupUrlField().setValue(mockGroupUrl);
+
+ expectLoadingMessageExists();
+ });
+
+ describe('when path is available', () => {
+ it('displays success message', async () => {
+ apiMockAvailablePath();
+
+ createComponent();
+
+ await findGroupUrlField().setValue(mockGroupUrl);
+ await waitForPromises();
+
+ expect(wrapper.findByText(GroupNameAndPath.i18n.inputs.path.validFeedback).exists()).toBe(
+ true,
+ );
+ });
+ });
+
+ describe('when path is not available', () => {
+ it('displays error message and updates `Group URL` field', async () => {
+ apiMockUnavailablePath();
+
+ createComponent();
+
+ await findGroupUrlField().setValue(mockGroupUrl);
+ await waitForPromises();
+
+ expect(
+ wrapper
+ .findByText(GroupNameAndPath.i18n.inputs.path.invalidFeedbackPathUnavailable)
+ .exists(),
+ ).toBe(true);
+ expect(findGroupUrlField().element.value).toBe(mockGroupUrlSuggested);
+ });
+ });
+ });
+
+ describe('when `Group URL` field is invalid', () => {
+ it('shows error message', async () => {
+ createComponent();
+
+ await findGroupUrlField().trigger('invalid');
+
+ expect(
+ wrapper
+ .findByText(GroupNameAndPath.i18n.inputs.path.invalidFeedbackInvalidPattern)
+ .exists(),
+ ).toBe(true);
+ });
+ });
+
+ describe('mattermost', () => {
+ it('adds `data-bind-in` attribute when enabled', () => {
+ createComponent({ provide: { mattermostEnabled: true } });
+
+ expect(findGroupUrlField().attributes('data-bind-in')).toBe(
+ GroupNameAndPath.mattermostDataBindName,
+ );
+ });
+
+ it('does not add `data-bind-in` attribute when disabled', () => {
+ createComponent();
+
+ expect(findGroupUrlField().attributes('data-bind-in')).toBeUndefined();
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/forms_spec.js b/spec/frontend/lib/utils/forms_spec.js
index 123d36ac5d5..2f71b26b29a 100644
--- a/spec/frontend/lib/utils/forms_spec.js
+++ b/spec/frontend/lib/utils/forms_spec.js
@@ -157,7 +157,7 @@ describe('lib/utils/forms', () => {
mountEl.innerHTML = `
<input type="text" placeholder="Name" value="Administrator" name="user[name]" id="user_name" data-js-name="name">
<input type="text" placeholder="Email" value="foo@bar.com" name="user[contact_info][email]" id="user_contact_info_email" data-js-name="contactInfoEmail">
- <input type="text" placeholder="Phone" value="(123) 456-7890" name="user[contact_info][phone]" id="user_contact_info_phone" data-js-name="contact_info_phone">
+ <input type="text" placeholder="Phone" value="(123) 456-7890" name="user[contact_info][phone]" id="user_contact_info_phone" maxlength="12" pattern="mockPattern" data-js-name="contact_info_phone">
<input type="hidden" placeholder="Job title" value="" name="user[job_title]" id="user_job_title" data-js-name="jobTitle">
<textarea name="user[bio]" id="user_bio" data-js-name="bio">Foo bar</textarea>
<select name="user[timezone]" id="user_timezone" data-js-name="timezone">
@@ -192,6 +192,8 @@ describe('lib/utils/forms', () => {
id: 'user_contact_info_phone',
value: '(123) 456-7890',
placeholder: 'Phone',
+ maxLength: 12,
+ pattern: 'mockPattern',
},
jobTitle: {
name: 'user[job_title]',
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
index f5444a185c7..0447ead0830 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
@@ -219,19 +219,19 @@ describe('Package Files', () => {
it('toggles the details row', async () => {
createComponent();
- expect(findFirstToggleDetailsButton().props('icon')).toBe('angle-down');
+ expect(findFirstToggleDetailsButton().props('icon')).toBe('chevron-down');
findFirstToggleDetailsButton().vm.$emit('click');
await nextTick();
expect(findFirstRowShaComponent('sha-256').exists()).toBe(true);
- expect(findFirstToggleDetailsButton().props('icon')).toBe('angle-up');
+ expect(findFirstToggleDetailsButton().props('icon')).toBe('chevron-up');
findFirstToggleDetailsButton().vm.$emit('click');
await nextTick();
expect(findFirstRowShaComponent('sha-256').exists()).toBe(false);
- expect(findFirstToggleDetailsButton().props('icon')).toBe('angle-down');
+ expect(findFirstToggleDetailsButton().props('icon')).toBe('chevron-down');
});
});
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js
index 75e7e6ce8f8..5aa67667033 100644
--- a/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js
@@ -70,7 +70,7 @@ describe('IssuableTitle', () => {
expect(titleEl.exists()).toBe(true);
expect(titleEl.html()).toBe(
- '<h1 dir="auto" data-testid="title" class="title qa-title"><b>Sample</b> title</h1>',
+ '<h1 dir="auto" data-testid="title" class="title qa-title gl-font-size-h-display"><b>Sample</b> title</h1>',
);
wrapperWithTitle.destroy();
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 8859ed27022..0fb17fb8922 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -419,4 +419,31 @@ RSpec.describe GroupsHelper do
expect(localized_jobs_to_be_done_choices.keys).to match_array(NamespaceSetting.jobs_to_be_dones.keys)
end
end
+
+ describe '#group_name_and_path_app_data' do
+ let_it_be(:group) { build(:group, name: 'My awesome group', path: 'my-awesome-group') }
+ let_it_be(:subgroup) { build(:group, parent: group) }
+ let_it_be(:root_url) { 'https://gitlab.com/' }
+
+ before do
+ allow(Gitlab.config.mattermost).to receive(:enabled).and_return(true)
+ allow(helper).to receive(:root_url) { root_url }
+ end
+
+ context 'when group has a parent' do
+ it 'returns expected hash' do
+ expect(group_name_and_path_app_data(subgroup)).to match(
+ { base_path: 'https://gitlab.com/my-awesome-group', mattermost_enabled: 'true' }
+ )
+ end
+ end
+
+ context 'when group does not have a parent' do
+ it 'returns expected hash' do
+ expect(group_name_and_path_app_data(group)).to match(
+ { base_path: root_url, mattermost_enabled: 'true' }
+ )
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/email/receiver_spec.rb b/spec/lib/gitlab/email/receiver_spec.rb
index 16b55dd7c74..79476c63e66 100644
--- a/spec/lib/gitlab/email/receiver_spec.rb
+++ b/spec/lib/gitlab/email/receiver_spec.rb
@@ -90,19 +90,9 @@ RSpec.describe Gitlab::Email::Receiver do
let(:meta_key) { :received_recipients }
let(:meta_value) { ['incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com', 'incoming+gitlabhq/gitlabhq@example.com'] }
- context 'when use_received_header_for_incoming_emails is enabled' do
+ describe 'it uses receive headers to find the key' do
it_behaves_like 'successful receive'
end
-
- context 'when use_received_header_for_incoming_emails is disabled' do
- let(:expected_error) { Gitlab::Email::UnknownIncomingEmail }
-
- before do
- stub_feature_flags(use_received_header_for_incoming_emails: false)
- end
-
- it_behaves_like 'failed receive'
- end
end
end