summaryrefslogtreecommitdiff
path: root/app/views
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-10-20 08:43:02 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-10-20 08:43:02 +0000
commitd9ab72d6080f594d0b3cae15f14b3ef2c6c638cb (patch)
tree2341ef426af70ad1e289c38036737e04b0aa5007 /app/views
parentd6e514dd13db8947884cd58fe2a9c2a063400a9b (diff)
downloadgitlab-ce-d9ab72d6080f594d0b3cae15f14b3ef2c6c638cb.tar.gz
Add latest changes from gitlab-org/gitlab@14-4-stable-eev14.4.0-rc42
Diffstat (limited to 'app/views')
-rw-r--r--app/views/admin/application_settings/_abuse.html.haml2
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml18
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml7
-rw-r--r--app/views/admin/application_settings/_files_limits.html.haml34
-rw-r--r--app/views/admin/application_settings/_help_page.html.haml13
-rw-r--r--app/views/admin/application_settings/_mailgun.html.haml2
-rw-r--r--app/views/admin/application_settings/_network_rate_limits.html.haml33
-rw-r--r--app/views/admin/application_settings/_package_registry_limits.html.haml32
-rw-r--r--app/views/admin/application_settings/_performance.html.haml17
-rw-r--r--app/views/admin/application_settings/_snowplow.html.haml2
-rw-r--r--app/views/admin/application_settings/_spam.html.haml49
-rw-r--r--app/views/admin/application_settings/_terminal.html.haml2
-rw-r--r--app/views/admin/application_settings/_usage.html.haml22
-rw-r--r--app/views/admin/application_settings/appearances/preview_sign_in.html.haml7
-rw-r--r--app/views/admin/application_settings/general.html.haml3
-rw-r--r--app/views/admin/application_settings/metrics_and_profiling.html.haml2
-rw-r--r--app/views/admin/application_settings/network.html.haml19
-rw-r--r--app/views/admin/application_settings/reporting.html.haml7
-rw-r--r--app/views/admin/dashboard/_security_newsletter_callout.html.haml14
-rw-r--r--app/views/admin/dashboard/index.html.haml1
-rw-r--r--app/views/admin/hook_logs/_index.html.haml40
-rw-r--r--app/views/admin/projects/index.html.haml35
-rw-r--r--app/views/admin/projects/show.html.haml11
-rw-r--r--app/views/admin/runners/show.html.haml2
-rw-r--r--app/views/admin/serverless/domains/_form.html.haml99
-rw-r--r--app/views/admin/serverless/domains/index.html.haml25
-rw-r--r--app/views/admin/sessions/_new_base.html.haml2
-rw-r--r--app/views/admin/topics/_form.html.haml40
-rw-r--r--app/views/admin/topics/_topic.html.haml17
-rw-r--r--app/views/admin/topics/edit.html.haml4
-rw-r--r--app/views/admin/topics/index.html.haml19
-rw-r--r--app/views/admin/topics/new.html.haml4
-rw-r--r--app/views/admin/users/_access_levels.html.haml24
-rw-r--r--app/views/admin/users/_form.html.haml6
-rw-r--r--app/views/admin/users/_head.html.haml17
-rw-r--r--app/views/admin/users/show.html.haml3
-rw-r--r--app/views/authentication/_authenticate.html.haml3
-rw-r--r--app/views/authentication/_register.html.haml4
-rw-r--r--app/views/clusters/clusters/_advanced_settings_tab.html.haml5
-rw-r--r--app/views/clusters/clusters/_details_tab.html.haml5
-rw-r--r--app/views/clusters/clusters/_health_tab.html.haml5
-rw-r--r--app/views/clusters/clusters/_integrations_tab.html.haml8
-rw-r--r--app/views/clusters/clusters/_namespace.html.haml3
-rw-r--r--app/views/clusters/clusters/aws/_new.html.haml4
-rw-r--r--app/views/clusters/clusters/show.html.haml17
-rw-r--r--app/views/dashboard/_activity_head.html.haml14
-rw-r--r--app/views/dashboard/_groups_head.html.haml10
-rw-r--r--app/views/devise/confirmations/almost_there.haml11
-rw-r--r--app/views/devise/mailer/_confirmation_instructions_secondary.text.erb2
-rw-r--r--app/views/devise/passwords/edit.html.haml4
-rw-r--r--app/views/devise/registrations/new.html.haml1
-rw-r--r--app/views/devise/sessions/_new_base.html.haml8
-rw-r--r--app/views/devise/sessions/_new_crowd.html.haml2
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml2
-rw-r--r--app/views/devise/sessions/new.html.haml1
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml10
-rw-r--r--app/views/devise/shared/_signup_box.html.haml1
-rw-r--r--app/views/devise/shared/_signup_omniauth_provider_list.haml8
-rw-r--r--app/views/devise/shared/_signup_omniauth_providers.haml2
-rw-r--r--app/views/devise/shared/_signup_omniauth_providers_top.haml2
-rw-r--r--app/views/groups/_group_admin_settings.html.haml2
-rw-r--r--app/views/groups/_home_panel.html.haml12
-rw-r--r--app/views/groups/_import_group_from_another_instance_panel.html.haml13
-rw-r--r--app/views/groups/dependency_proxies/_url.html.haml12
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml31
-rw-r--r--app/views/groups/edit.html.haml7
-rw-r--r--app/views/groups/issues.html.haml2
-rw-r--r--app/views/groups/registry/repositories/index.html.haml3
-rw-r--r--app/views/groups/runners/_runner.html.haml2
-rw-r--r--app/views/groups/settings/_general.html.haml3
-rw-r--r--app/views/groups/settings/_lfs.html.haml4
-rw-r--r--app/views/groups/settings/_permissions.html.haml6
-rw-r--r--app/views/groups/settings/_two_factor_auth.html.haml10
-rw-r--r--app/views/groups/settings/packages_and_registries/show.html.haml5
-rw-r--r--app/views/help/instance_configuration/_gitlab_pages.html.haml2
-rw-r--r--app/views/help/instance_configuration/_rate_limits.html.haml1
-rw-r--r--app/views/import/_githubish_status.html.haml2
-rw-r--r--app/views/import/bitbucket_server/new.html.haml2
-rw-r--r--app/views/import/bulk_imports/history.html.haml6
-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/gitea/new.html.haml2
-rw-r--r--app/views/import/github/new.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/phabricator/new.html.haml2
-rw-r--r--app/views/layouts/_one_trust.html.haml16
-rw-r--r--app/views/layouts/_page.html.haml1
-rw-r--r--app/views/layouts/_startup_js.html.haml22
-rw-r--r--app/views/layouts/header/_default.html.haml3
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml3
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml13
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml2
-rw-r--r--app/views/profiles/_email_settings.html.haml3
-rw-r--r--app/views/profiles/passwords/edit.html.haml10
-rw-r--r--app/views/profiles/passwords/new.html.haml10
-rw-r--r--app/views/profiles/show.html.haml8
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml2
-rw-r--r--app/views/projects/_files.html.haml3
-rw-r--r--app/views/projects/_home_panel.html.haml9
-rw-r--r--app/views/projects/_import_project_pane.html.haml2
-rw-r--r--app/views/projects/_new_project_fields.html.haml46
-rw-r--r--app/views/projects/blob/show.html.haml1
-rw-r--r--app/views/projects/branches/index.html.haml24
-rw-r--r--app/views/projects/branches/new.html.haml1
-rw-r--r--app/views/projects/ci/pipeline_editor/show.html.haml2
-rw-r--r--app/views/projects/cluster_agents/show.html.haml4
-rw-r--r--app/views/projects/commits/_commit.html.haml10
-rw-r--r--app/views/projects/deployments/_deployment.html.haml2
-rw-r--r--app/views/projects/feature_flags/edit.html.haml8
-rw-r--r--app/views/projects/google_cloud/index.html.haml83
-rw-r--r--app/views/projects/hook_logs/_index.html.haml42
-rw-r--r--app/views/projects/hook_logs/show.html.haml4
-rw-r--r--app/views/projects/issues/_nav_btns.html.haml5
-rw-r--r--app/views/projects/issues/_related_branches.html.haml4
-rw-r--r--app/views/projects/issues/_related_issues.html.haml1
-rw-r--r--app/views/projects/issues/_related_issues_block.html.haml5
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml10
-rw-r--r--app/views/projects/merge_requests/_nav_btns.html.haml6
-rw-r--r--app/views/projects/merge_requests/_widget.html.haml2
-rw-r--r--app/views/projects/merge_requests/conflicts/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/show.html.haml2
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml4
-rw-r--r--app/views/projects/mirrors/_mirror_repos_push.html.haml2
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml6
-rw-r--r--app/views/projects/product_analytics/test.html.haml1
-rw-r--r--app/views/projects/registry/repositories/index.html.haml3
-rw-r--r--app/views/projects/settings/operations/_error_tracking.html.haml1
-rw-r--r--app/views/projects/snippets/show.html.haml2
-rw-r--r--app/views/projects/tags/index.html.haml3
-rw-r--r--app/views/projects/tags/new.html.haml1
-rw-r--r--app/views/projects/tree/show.html.haml1
-rw-r--r--app/views/projects/usage_quotas/index.html.haml2
-rw-r--r--app/views/search/results/_issuable.html.haml7
-rw-r--r--app/views/shared/_import_form.html.haml11
-rw-r--r--app/views/shared/_milestones_filter.html.haml28
-rw-r--r--app/views/shared/_web_ide_path.html.haml4
-rw-r--r--app/views/shared/boards/_show.html.haml2
-rw-r--r--app/views/shared/builds/_build_output.html.haml2
-rw-r--r--app/views/shared/builds/_tabs.html.haml41
-rw-r--r--app/views/shared/deploy_tokens/_form.html.haml1
-rw-r--r--app/views/shared/empty_states/_topics.html.haml7
-rw-r--r--app/views/shared/errors/_gitaly_unavailable.html.haml8
-rw-r--r--app/views/shared/hook_logs/_recent_deliveries_table.html.haml34
-rw-r--r--app/views/shared/hook_logs/_status_label.html.haml2
-rw-r--r--app/views/shared/integrations/_tabs.html.haml23
-rw-r--r--app/views/shared/issuable/_nav.html.haml24
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml11
-rw-r--r--app/views/shared/issuable/nav_links/_all.html.haml5
-rw-r--r--app/views/shared/issue_type/_emoji_block.html.haml2
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml6
-rw-r--r--app/views/shared/notes/_comment_button.html.haml29
-rw-r--r--app/views/shared/notes/_hints.html.haml56
-rw-r--r--app/views/shared/notes/_notes_with_form.html.haml1
-rw-r--r--app/views/shared/topics/_search_form.html.haml7
-rw-r--r--app/views/shared/web_hooks/_hook.html.haml6
-rw-r--r--app/views/shared/wikis/edit.html.haml2
-rw-r--r--app/views/snippets/show.html.haml2
-rw-r--r--app/views/users/show.html.haml10
160 files changed, 845 insertions, 790 deletions
diff --git a/app/views/admin/application_settings/_abuse.html.haml b/app/views/admin/application_settings/_abuse.html.haml
index fab3ce584f0..96fb848b568 100644
--- a/app/views/admin/application_settings/_abuse.html.haml
+++ b/app/views/admin/application_settings/_abuse.html.haml
@@ -5,7 +5,5 @@
.form-group
= f.label :abuse_notification_email, _('Abuse reports notification email'), class: 'label-bold'
= f.text_field :abuse_notification_email, class: 'form-control gl-form-input'
- .form-text.text-muted
- = _('Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.')
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_account_and_limit.html.haml b/app/views/admin/application_settings/_account_and_limit.html.haml
index eb30efabb98..19c38d7be62 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -23,11 +23,11 @@
.form-group
= f.label :max_import_size, _('Maximum import size (MB)'), class: 'label-light'
= f.number_field :max_import_size, class: 'form-control gl-form-input qa-receive-max-import-size-field', title: _('Maximum size of import files.'), data: { toggle: 'tooltip', container: 'body' }
- %span.form-text.text-muted= _('0 for unlimited, only effective with remote storage enabled.')
+ %span.form-text.text-muted= _('Only effective when remote storage is enabled. Set to 0 for no size limit.')
.form-group
= f.label :session_expire_delay, _('Session duration (minutes)'), class: 'label-light'
= f.number_field :session_expire_delay, class: 'form-control gl-form-input', title: _('Maximum duration of a session.'), data: { toggle: 'tooltip', container: 'body' }
- %span.form-text.text-muted#session_expire_delay_help_block= _('GitLab restart is required to apply changes.')
+ %span.form-text.text-muted#session_expire_delay_help_block= _('Restart GitLab to apply changes.')
= render_if_exists 'admin/application_settings/git_two_factor_session_expiry', form: f
= render_if_exists 'admin/application_settings/personal_access_token_expiration_policy', form: f
@@ -45,13 +45,13 @@
.form-check
= f.check_box :user_default_external, class: 'form-check-input'
= f.label :user_default_external, class: 'form-check-label' do
- = _('Newly registered users will by default be external')
+ = _('Newly-registered users are external by default')
.gl-mt-3
= _('Internal users')
= f.text_field :user_default_internal_regex, placeholder: _('Regex pattern'), class: 'form-control gl-form-input gl-mt-2'
.help-block
- = _('Specify an e-mail address regex pattern to identify default internal users.')
- = link_to _('More information'), help_page_path('user/permissions', anchor: 'setting-new-users-to-external'),
+ = _('Specify an email address regex pattern to identify default internal users.')
+ = link_to _('Learn more'), help_page_path('user/permissions', anchor: 'setting-new-users-to-external'),
target: '_blank'
- unless Gitlab.com?
.form-group
@@ -59,11 +59,13 @@
.form-check
= f.check_box :deactivate_dormant_users, class: 'form-check-input'
= f.label :deactivate_dormant_users, class: 'form-check-label' do
- = _('Deactivate dormant users after 90 days of inactivity. Users can return to active status by signing in to their account. While inactive, a user is not counted as an active user in the instance.')
- = link_to _('More information'), help_page_path('user/admin_area/moderate_users', anchor: 'automatically-deactivate-dormant-users'), target: '_blank'
+ = _('Deactivate dormant users after 90 days of inactivity')
+ .help-block
+ = _('Users can reactivate their account by signing in.')
+ = link_to _('Learn more'), help_page_path('user/admin_area/moderate_users', anchor: 'automatically-deactivate-dormant-users'), target: '_blank'
.form-group
= f.label :personal_access_token_prefix, _('Personal Access Token prefix'), class: 'label-light'
- = f.text_field :personal_access_token_prefix, placeholder: _('Max 20 characters'), class: 'form-control gl-form-input'
+ = f.text_field :personal_access_token_prefix, placeholder: _('Maximum 20 characters'), class: 'form-control gl-form-input'
.form-group
= f.label :user_show_add_ssh_key_message, _('Prompt users to upload SSH keys'), class: 'label-bold'
.form-check
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index fea116bd419..8026ec4702b 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -69,5 +69,12 @@
%p.form-text.text-muted
= _("The default CI/CD configuration file and path for new projects.").html_safe
= link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'specify-a-custom-cicd-configuration-file'), target: '_blank'
+ .form-group
+ .form-check
+ = f.check_box :suggest_pipeline_enabled, class: 'form-check-input'
+ = f.label :suggest_pipeline_enabled, class: 'form-check-label' do
+ = s_('AdminSettings|Enable pipeline suggestion banner')
+ .form-text.text-muted
+ = s_('AdminSettings|Display a banner on merge requests in projects with no pipelines to initiate steps to add a .gitlab-ci.yml file.')
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_files_limits.html.haml b/app/views/admin/application_settings/_files_limits.html.haml
deleted file mode 100644
index 9cd12fa1caa..00000000000
--- a/app/views/admin/application_settings/_files_limits.html.haml
+++ /dev/null
@@ -1,34 +0,0 @@
-= gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-files-limits-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
-
- %fieldset
- %legend.h5.gl-border-none
- = _('Unauthenticated API request rate limit')
- .form-group
- = f.gitlab_ui_checkbox_component :throttle_unauthenticated_files_api_enabled,
- _('Enable unauthenticated API request rate limit'),
- help_text: _('Helps reduce request volume (e.g. from crawlers or abusive bots)'),
- checkbox_options: { data: { qa_selector: 'throttle_unauthenticated_files_api_checkbox' } }
- .form-group
- = f.label :throttle_unauthenticated_files_api_requests_per_period, 'Max unauthenticated API requests per period per IP', class: 'label-bold'
- = f.number_field :throttle_unauthenticated_files_api_requests_per_period, class: 'form-control gl-form-input'
- .form-group
- = f.label :throttle_unauthenticated_files_api_period_in_seconds, 'Unauthenticated API rate limit period in seconds', class: 'label-bold'
- = f.number_field :throttle_unauthenticated_files_api_period_in_seconds, class: 'form-control gl-form-input'
-
- %fieldset
- %legend.h5.gl-border-none
- = _('Authenticated API request rate limit')
- .form-group
- = f.gitlab_ui_checkbox_component :throttle_authenticated_files_api_enabled,
- _('Enable authenticated API request rate limit'),
- help_text: _('Helps reduce request volume (e.g. from crawlers or abusive bots)'),
- checkbox_options: { data: { qa_selector: 'throttle_authenticated_files_api_checkbox' } }
- .form-group
- = f.label :throttle_authenticated_files_api_requests_per_period, 'Max authenticated API requests per period per user', class: 'label-bold'
- = f.number_field :throttle_authenticated_files_api_requests_per_period, class: 'form-control gl-form-input'
- .form-group
- = f.label :throttle_authenticated_files_api_period_in_seconds, 'Authenticated API rate limit period in seconds', class: 'label-bold'
- = f.number_field :throttle_authenticated_files_api_period_in_seconds, class: 'form-control gl-form-input'
-
- = f.submit 'Save changes', class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_help_page.html.haml b/app/views/admin/application_settings/_help_page.html.haml
index ecf3203df9a..cd7eaa1896a 100644
--- a/app/views/admin/application_settings/_help_page.html.haml
+++ b/app/views/admin/application_settings/_help_page.html.haml
@@ -18,11 +18,10 @@
= f.text_field :help_page_support_url, class: 'form-control gl-form-input', placeholder: 'https://company.example.com/getting-help', :'aria-describedby' => 'support_help_block'
%span.form-text.text-muted#support_help_block= _('Alternate support URL for Help page and Help dropdown.')
- - if show_documentation_base_url_field?
- .form-group
- = f.label :help_page_documentation_base_url, _('Documentation pages URL'), class: 'label-bold'
- = f.text_field :help_page_documentation_base_url, class: 'form-control gl-form-input', placeholder: 'https://docs.gitlab.com'
- - docs_link_url = help_page_path('user/admin_area/settings/help_page', anchor: 'destination-requirements')
- - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
- %span.form-text.text-muted#support_help_block= html_escape(_('Requests for pages at %{code_start}%{help_text_url}%{code_end} redirect to the URL. The destination must meet certain requirements. %{docs_link_start}Learn more.%{docs_link_end}')) % { code_start: '<code>'.html_safe, help_text_url: help_url, code_end: '</code>'.html_safe, docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+ .form-group
+ = f.label :help_page_documentation_base_url, _('Documentation pages URL'), class: 'gl-font-weight-bold'
+ = f.text_field :help_page_documentation_base_url, class: 'form-control gl-form-input', placeholder: 'https://docs.gitlab.com'
+ - docs_link_url = help_page_path('user/admin_area/settings/help_page', anchor: 'destination-requirements')
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
+ %span.form-text.text-muted#support_help_block= html_escape(_('Requests for pages at %{code_start}%{help_text_url}%{code_end} redirect to the URL. The destination must meet certain requirements. %{docs_link_start}Learn more.%{docs_link_end}')) % { code_start: '<code>'.html_safe, help_text_url: help_url, code_end: '</code>'.html_safe, docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_mailgun.html.haml b/app/views/admin/application_settings/_mailgun.html.haml
index 40b4d5cac6d..ad9e84ffdab 100644
--- a/app/views/admin/application_settings/_mailgun.html.haml
+++ b/app/views/admin/application_settings/_mailgun.html.haml
@@ -6,7 +6,7 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _('Configure the %{link} integration.').html_safe % { link: link_to(_('Mailgun events'), 'https://documentation.mailgun.com/en/latest/user_manual.html#webhooks', target: '_blank') }
+ = _('Configure the %{link} integration.').html_safe % { link: link_to(_('Mailgun events'), 'https://documentation.mailgun.com/en/latest/user_manual.html#webhooks', target: '_blank', rel: 'noopener noreferrer') }
.settings-content
= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-mailgun-settings'), html: { class: 'fieldset-form', id: 'mailgun-settings' } do |f|
= form_errors(@application_setting) if expanded
diff --git a/app/views/admin/application_settings/_network_rate_limits.html.haml b/app/views/admin/application_settings/_network_rate_limits.html.haml
new file mode 100644
index 00000000000..f1857a9749a
--- /dev/null
+++ b/app/views/admin/application_settings/_network_rate_limits.html.haml
@@ -0,0 +1,33 @@
+= gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: anchor), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting)
+
+ %fieldset
+ = _("Rate limits can help reduce request volume (like from crawlers or abusive bots).")
+
+ %fieldset
+ .form-group
+ = f.gitlab_ui_checkbox_component :"throttle_unauthenticated_#{setting_fragment}_enabled",
+ _('Enable unauthenticated API request rate limit'),
+ checkbox_options: { data: { qa_selector: "throttle_unauthenticated_#{setting_fragment}_checkbox" } },
+ label_options: { class: 'label-bold' }
+ .form-group
+ = f.label :"throttle_unauthenticated_#{setting_fragment}_requests_per_period", _('Maximum unauthenticated API requests per rate limit period per IP'), class: 'label-bold'
+ = f.number_field :"throttle_unauthenticated_#{setting_fragment}_requests_per_period", class: 'form-control gl-form-input'
+ .form-group
+ = f.label :"throttle_unauthenticated_#{setting_fragment}_period_in_seconds", _('Unauthenticated API rate limit period in seconds'), class: 'label-bold'
+ = f.number_field :"throttle_unauthenticated_#{setting_fragment}_period_in_seconds", class: 'form-control gl-form-input'
+
+ %fieldset
+ .form-group
+ = f.gitlab_ui_checkbox_component :"throttle_authenticated_#{setting_fragment}_enabled",
+ _('Enable authenticated API request rate limit'),
+ checkbox_options: { data: { qa_selector: "throttle_authenticated_#{setting_fragment}_checkbox" } },
+ label_options: { class: 'label-bold' }
+ .form-group
+ = f.label :"throttle_authenticated_#{setting_fragment}_requests_per_period", _('Maximum authenticated API requests per rate limit period per user'), class: 'label-bold'
+ = f.number_field :"throttle_authenticated_#{setting_fragment}_requests_per_period", class: 'form-control gl-form-input'
+ .form-group
+ = f.label :"throttle_authenticated_#{setting_fragment}_period_in_seconds", _('Authenticated API rate limit period in seconds'), class: 'label-bold'
+ = f.number_field :"throttle_authenticated_#{setting_fragment}_period_in_seconds", class: 'form-control gl-form-input'
+
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_package_registry_limits.html.haml b/app/views/admin/application_settings/_package_registry_limits.html.haml
deleted file mode 100644
index 8769171c9e0..00000000000
--- a/app/views/admin/application_settings/_package_registry_limits.html.haml
+++ /dev/null
@@ -1,32 +0,0 @@
-= form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-packages-limits-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
-
- %fieldset
- = _("The package registry rate limits can help reduce request volume (like from crawlers or abusive bots).")
-
- %fieldset
- .form-group
- .form-check
- = f.check_box :throttle_unauthenticated_packages_api_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_unauthenticated_packages_api_checkbox' }
- = f.label :throttle_unauthenticated_packages_api_enabled, class: 'form-check-label label-bold' do
- = _('Enable unauthenticated API request rate limit')
- .form-group
- = f.label :throttle_unauthenticated_packages_api_requests_per_period, _('Maximum unauthenticated API requests per rate limit period per IP'), class: 'label-bold'
- = f.number_field :throttle_unauthenticated_packages_api_requests_per_period, class: 'form-control gl-form-input'
- .form-group
- = f.label :throttle_unauthenticated_packages_api_period_in_seconds, _('Unauthenticated API rate limit period in seconds'), class: 'label-bold'
- = f.number_field :throttle_unauthenticated_packages_api_period_in_seconds, class: 'form-control gl-form-input'
- %hr
- .form-group
- .form-check
- = f.check_box :throttle_authenticated_packages_api_enabled, class: 'form-check-input', data: { qa_selector: 'throttle_authenticated_packages_api_checkbox' }
- = f.label :throttle_authenticated_packages_api_enabled, class: 'form-check-label label-bold' do
- = _('Enable authenticated API request rate limit')
- .form-group
- = f.label :throttle_authenticated_packages_api_requests_per_period, _('Maximum authenticated API requests per rate limit period per user'), class: 'label-bold'
- = f.number_field :throttle_authenticated_packages_api_requests_per_period, class: 'form-control gl-form-input'
- .form-group
- = f.label :throttle_authenticated_packages_api_period_in_seconds, _('Authenticated API rate limit period in seconds'), class: 'label-bold'
- = f.number_field :throttle_authenticated_packages_api_period_in_seconds, class: 'form-control gl-form-input'
-
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_performance.html.haml b/app/views/admin/application_settings/_performance.html.haml
index 50fc11ec7f3..82e56cf8b81 100644
--- a/app/views/admin/application_settings/_performance.html.haml
+++ b/app/views/admin/application_settings/_performance.html.haml
@@ -6,29 +6,24 @@
.form-check
= f.check_box :authorized_keys_enabled, class: 'form-check-input'
= f.label :authorized_keys_enabled, class: 'form-check-label' do
- = _('Write to "authorized_keys" file')
+ = _('Use authorized_keys file to authenticate SSH keys')
.form-text.text-muted
- By default, we write to the "authorized_keys" file to support Git
- over SSH without additional configuration. GitLab can be optimized
- to authenticate SSH keys via the database file. Only uncheck this
- if you have configured your OpenSSH server to use the
- AuthorizedKeysCommand. Click on the help icon for more details.
- = link_to sprite_icon('question-o'), help_page_path('administration/operations/fast_ssh_key_lookup')
-
+ = _('Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead.')
+ = link_to _('How do I configure authentication using the GitLab database?'), help_page_path('administration/operations/fast_ssh_key_lookup'), target: '_blank', rel: 'noopener noreferrer'
.form-group
= f.label :raw_blob_request_limit, _('Raw blob request rate limit per minute'), class: 'label-bold'
= f.number_field :raw_blob_request_limit, class: 'form-control gl-form-input'
.form-text.text-muted
- = _('Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0.')
+ = _('Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling.')
.form-group
= f.label :push_event_hooks_limit, class: 'label-bold'
= f.number_field :push_event_hooks_limit, class: 'form-control gl-form-input'
.form-text.text-muted
- = _("Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value.")
+ = _('Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3).')
.form-group
= f.label :push_event_activities_limit, class: 'label-bold'
= f.number_field :push_event_activities_limit, class: 'form-control gl-form-input'
.form-text.text-muted
- = _('Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value.')
+ = _('Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3).')
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_snowplow.html.haml b/app/views/admin/application_settings/_snowplow.html.haml
index 8c98778147e..756c0e770a6 100644
--- a/app/views/admin/application_settings/_snowplow.html.haml
+++ b/app/views/admin/application_settings/_snowplow.html.haml
@@ -7,7 +7,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
- link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('development/snowplow/index') }
- = html_escape(_('Configure %{link} to track events. %{link_start}Learn more.%{link_end}')) % { link: link_to('Snowplow', 'https://snowplowanalytics.com/', target: '_blank').html_safe, link_start: link_start, link_end: '</a>'.html_safe }
+ = html_escape(_('Configure %{link} to track events. %{link_start}Learn more.%{link_end}')) % { link: link_to('Snowplow', 'https://snowplowanalytics.com/', target: '_blank', rel: 'noopener noreferrer').html_safe, link_start: link_start, link_end: '</a>'.html_safe }
.settings-content
= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-snowplow-settings'), html: { class: 'fieldset-form', id: 'snowplow-settings' } do |f|
= form_errors(@application_setting) if expanded
diff --git a/app/views/admin/application_settings/_spam.html.haml b/app/views/admin/application_settings/_spam.html.haml
index 011bce3ca99..53ca4d4aa79 100644
--- a/app/views/admin/application_settings/_spam.html.haml
+++ b/app/views/admin/application_settings/_spam.html.haml
@@ -2,6 +2,11 @@
= form_errors(@application_setting)
%fieldset
+ %h5
+ = _('reCAPTCHA')
+ %p
+ = _('reCAPTCHA helps prevent credential stuffing.')
+ = link_to _('Only reCAPTCHA v2 is supported:'), 'https://developers.google.com/recaptcha/docs/versions', target: '_blank', rel: 'noopener noreferrer'
.form-group
.form-check
= f.check_box :recaptcha_enabled, class: 'form-check-input'
@@ -9,25 +14,31 @@
= _("Enable reCAPTCHA")
%span.form-text.text-muted#recaptcha_help_block
= _('Helps prevent bots from creating accounts.')
+ = link_to _('How do I configure it?'), help_page_path('integration/recaptcha.md'), target: '_blank', rel: 'noopener noreferrer'
.form-group
.form-check
= f.check_box :login_recaptcha_protection_enabled, class: 'form-check-input'
= f.label :login_recaptcha_protection_enabled, class: 'form-check-label' do
- = _("Enable reCAPTCHA for login")
+ = _('Enable reCAPTCHA for login.')
%span.form-text.text-muted#recaptcha_help_block
= _('Helps prevent bots from brute-force attacks.')
.form-group
- = f.label :recaptcha_site_key, _('reCAPTCHA Site Key'), class: 'label-bold'
+ = f.label :recaptcha_site_key, _('reCAPTCHA site key'), class: 'label-bold'
= f.text_field :recaptcha_site_key, class: 'form-control gl-form-input'
.form-text.text-muted
= _("Generate site and private keys at")
%a{ href: 'http://www.google.com/recaptcha', target: 'blank' } http://www.google.com/recaptcha
.form-group
- = f.label :recaptcha_private_key, _('reCAPTCHA Private Key'), class: 'label-bold'
- .form-group
+ = f.label :recaptcha_private_key, _('reCAPTCHA private key'), class: 'label-bold'
= f.text_field :recaptcha_private_key, class: 'form-control gl-form-input'
+ %h5
+ = _('Invisible Captcha')
+ %p
+ = _('Invisible Captcha helps prevent the creation of spam accounts. It adds a honeypot field and time-sensitive form submission to the account signup form.')
+ = link_to _('Read their documentation.'), 'https://github.com/markets/invisible_captcha', target: '_blank', rel: 'noopener noreferrer'
+
.form-group
.form-check
= f.check_box :invisible_captcha_enabled, class: 'form-check-input'
@@ -36,12 +47,18 @@
%span.form-text.text-muted
= _('Helps prevent bots from creating accounts.')
+ %h5
+ = _('Akismet')
+ %p
+ = _('Akismet helps prevent the creation of spam issues in public projects.')
+ = link_to _('How do I configure Akismet?'), help_page_path('integration/akismet.md'), target: '_blank', rel: 'noopener noreferrer'
+
.form-group
.form-check
= f.check_box :akismet_enabled, class: 'form-check-input'
= f.label :akismet_enabled, class: 'form-check-label' do
Enable Akismet
- %span.form-text.text-muted#akismet_help_block= _("Helps prevent bots from creating issues")
+ %span.form-text.text-muted#akismet_help_block= _("Helps prevent bots from creating issues.")
.form-group
= f.label :akismet_api_key, _('Akismet API Key'), class: 'label-bold'
@@ -50,25 +67,31 @@
Generate API key at
%a{ href: 'http://www.akismet.com', target: 'blank' } http://www.akismet.com
+ %h5
+ = _('IP address restrictions')
+
.form-group
.form-check
= f.check_box :unique_ips_limit_enabled, class: 'form-check-input'
= f.label :unique_ips_limit_enabled, class: 'form-check-label' do
- = _("Limit sign in from multiple ips")
+ = _("Limit sign in from multiple IP addresses")
%span.form-text.text-muted#unique_ip_help_block
- = _("Helps prevent malicious users hide their activity")
+ = _("Helps prevent malicious users hide their activity.")
.form-group
- = f.label :unique_ips_limit_per_user, _('IPs per user'), class: 'label-bold'
+ = f.label :unique_ips_limit_per_user, _('IP addresses per user'), class: 'label-bold'
= f.number_field :unique_ips_limit_per_user, class: 'form-control gl-form-input'
.form-text.text-muted
- = _("Maximum number of unique IPs per user")
+ = _("Maximum number of unique IP addresses per user.")
.form-group
- = f.label :unique_ips_limit_time_window, _('IP expiration time'), class: 'label-bold'
+ = f.label :unique_ips_limit_time_window, _('IP address expiration time'), class: 'label-bold'
= f.number_field :unique_ips_limit_time_window, class: 'form-control gl-form-input'
.form-text.text-muted
- = _("How many seconds an IP will be counted towards the limit")
+ = _("How many seconds an IP counts toward the IP address limit.")
+
+ %h5
+ = _('Spam Check')
.form-group
.form-check
@@ -79,8 +102,8 @@
= f.label :spam_check_endpoint_url, _('URL of the external Spam Check endpoint'), class: 'label-bold'
= f.text_field :spam_check_endpoint_url, class: 'form-control gl-form-input'
.form-group
- = f.label :spam_check_api_key, _('Spam Check API Key'), class: 'gl-font-weight-bold'
+ = f.label :spam_check_api_key, _('Spam Check API key'), class: 'gl-font-weight-bold'
= f.text_field :spam_check_api_key, class: 'form-control gl-form-input'
- .form-text.text-muted= _('The API key used by GitLab for accessing the Spam Check service endpoint')
+ .form-text.text-muted= _('The API key used by GitLab for accessing the Spam Check service endpoint.')
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_terminal.html.haml b/app/views/admin/application_settings/_terminal.html.haml
index d6e31a24cf6..c53f63e124b 100644
--- a/app/views/admin/application_settings/_terminal.html.haml
+++ b/app/views/admin/application_settings/_terminal.html.haml
@@ -6,5 +6,5 @@
= f.label :terminal_max_session_time, _('Max session time'), class: 'label-bold'
= f.number_field :terminal_max_session_time, class: 'form-control gl-form-input'
.form-text.text-muted
- = _('Maximum time for web terminal websocket connection (in seconds). 0 for unlimited.')
+ = _('Maximum time, in seconds, for a web terminal websocket connection. 0 for unlimited.')
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index ddd0abb4c34..5bdad50c161 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -10,21 +10,21 @@
= f.label :version_check_enabled, class: 'form-check-label' do
= _("Enable version check")
.form-text.text-muted
- = _("GitLab will inform you if a new version is available.")
- = _("%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc.").html_safe % { link_start: "<a href='#{help_page_path("user/admin_area/settings/usage_statistics", anchor: "version-check")}'>".html_safe, link_end: '</a>'.html_safe }
+ = _("GitLab informs you if a new version is available.")
+ = _("%{link_start}What information does GitLab Inc. collect?%{link_end}").html_safe % { link_start: "<a href='#{help_page_path("user/admin_area/settings/usage_statistics", anchor: "version-check")}'>".html_safe, link_end: '</a>'.html_safe }
.form-group
- can_be_configured = @application_setting.usage_ping_can_be_configured?
.form-check
= f.check_box :usage_ping_enabled, disabled: !can_be_configured, class: 'form-check-input'
= f.label :usage_ping_enabled, class: 'form-check-label' do
- = _('Enable service ping')
+ = _('Enable Service Ping')
.form-text.text-muted
- if can_be_configured
- %p.mb-2= _('To help improve GitLab and its user experience, GitLab will periodically collect usage information.')
+ %p.mb-2= _('To help improve GitLab and its user experience, GitLab periodically collects usage information.')
- - service_ping_path = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'service-ping')
+ - service_ping_path = help_page_path('development/service_ping/index.md')
- service_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: service_ping_path }
- %p.mb-2= s_('%{service_ping_link_start}Learn more%{service_ping_link_end} about what information is shared with GitLab Inc.').html_safe % { service_ping_link_start: service_ping_link_start, service_ping_link_end: '</a>'.html_safe }
+ %p.mb-2= s_('%{service_ping_link_start}What information is shared with GitLab Inc.?%{service_ping_link_end}').html_safe % { service_ping_link_start: service_ping_link_start, service_ping_link_end: '</a>'.html_safe }
%button.gl-button.btn.btn-default.js-payload-preview-trigger{ type: 'button', data: { payload_selector: ".#{payload_class}" } }
.gl-spinner.js-spinner.gl-display-none.gl-mr-2
@@ -46,15 +46,23 @@
- if usage_ping_enabled
%p.gl-mb-3.text-muted{ id: 'service_ping_features_helper_text' }= _('You can enable Registration Features because Service Ping is enabled. To continue using Registration Features in the future, you will also need to register with GitLab via a new cloud licensing service.')
- else
- %p.gl-mb-3.text-muted{ id: 'service_ping_features_helper_text' }= _('To enable Registration Features, make sure "Enable service ping" is checked.')
+ %p.gl-mb-3.text-muted{ id: 'service_ping_features_helper_text' }= _('To enable Registration Features, first enable Service Ping.')
%p.gl-mb-3.text-muted= _('Registration Features include:')
.form-text
- email_from_gitlab_path = help_page_path('tools/email.md')
+ - repo_size_limit_path = help_page_path('user/admin_area/settings/account_and_limit_settings.md', anchor: 'repository-size-limit')
+ - restrict_ip_path = help_page_path('user/group/index.md', anchor: 'restrict-group-access-by-ip-address')
- link_end = '</a>'.html_safe
- email_from_gitlab_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: email_from_gitlab_path }
+ - repo_size_limit_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: repo_size_limit_path }
+ - restrict_ip_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: restrict_ip_path }
%ul
%li
= _('Email from GitLab - email users right from the Admin Area. %{link_start}Learn more%{link_end}.').html_safe % { link_start: email_from_gitlab_link, link_end: link_end }
+ %li
+ = _('Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}.').html_safe % { link_start: repo_size_limit_link, link_end: link_end }
+ %li
+ = _('Restrict group access by IP address. %{link_start}Learn more%{link_end}.').html_safe % { link_start: restrict_ip_link, link_end: link_end }
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
diff --git a/app/views/admin/application_settings/appearances/preview_sign_in.html.haml b/app/views/admin/application_settings/appearances/preview_sign_in.html.haml
index 77c37abbeef..2e4ab714048 100644
--- a/app/views/admin/application_settings/appearances/preview_sign_in.html.haml
+++ b/app/views/admin/application_settings/appearances/preview_sign_in.html.haml
@@ -1,12 +1,13 @@
= render 'devise/shared/tab_single', tab_title: _('Sign in preview')
.login-box
%form.gl-show-field-errors
+ - title = _('This form is disabled in preview')
.form-group
= label_tag :login
- = text_field_tag :login, nil, class: "form-control gl-form-input top", title: _('Please provide your username or email address.')
+ = text_field_tag :login, nil, disabled: true, class: "form-control gl-form-input top", title: title
.form-group
= label_tag :password
- = password_field_tag :password, nil, class: "form-control gl-form-input bottom", title: _('This field is required.')
+ = password_field_tag :password, nil, disabled: true, class: "form-control gl-form-input bottom", title: title
.form-group
- = button_tag _("Sign in"), class: "btn gl-button btn-confirm", type: "button"
+ = button_tag _("Sign in"), disabled: true, class: "btn gl-button btn-confirm", type: "button", title: title
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index 9102769cc6e..a72c96bb577 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -79,7 +79,8 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Set max session time for web terminal.')
+ = _('Set the maximum session time for a web terminal.')
+ = link_to _('How do I use a web terminal?'), help_page_path('ci/environments/index.md', anchor: 'web-terminals'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'terminal'
diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml
index f1e37c76130..6087551d7c7 100644
--- a/app/views/admin/application_settings/metrics_and_profiling.html.haml
+++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml
@@ -49,7 +49,7 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Enable or disable version check and service ping.')
+ = _('Enable or disable version check and Service Ping.')
.settings-content
= render 'usage'
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index 8dff2bc36cb..58e3f3f1136 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -35,9 +35,10 @@
= _('Set rate limits for package registry API requests that supersede the general user and IP rate limits.')
= link_to _('Learn more.'), help_page_path('user/admin_area/settings/package_registry_rate_limits.md'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
- = render 'package_registry_limits'
+ = render partial: 'network_rate_limits', locals: { anchor: 'js-packages-limits-settings', setting_fragment: 'packages_api' }
+
- if Feature.enabled?(:files_api_throttling, default_enabled: :yaml)
- %section.settings.as-files-limits.no-animate#js-files-limits-settings{ class: ('expanded' if expanded_by_default?), data: { testid: 'files-limits-settings' } }
+ %section.settings.as-files-limits.no-animate#js-files-limits-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
= _('Files API Rate Limits')
@@ -46,7 +47,19 @@
%p
= _('Configure specific limits for Files API requests that supersede the general user and IP rate limits.')
.settings-content
- = render 'files_limits'
+ = render partial: 'network_rate_limits', locals: { anchor: 'js-files-limits-settings', setting_fragment: 'files_api' }
+
+%section.settings.as-deprecated-limits.no-animate#js-deprecated-limits-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4
+ = _('Deprecated API rate limits')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Configure specific limits for deprecated API requests that supersede the general user and IP rate limits.')
+ = link_to _('Which API requests are affected?'), help_page_path('user/admin_area/settings/deprecated_api_rate_limits.md'), target: '_blank', rel: 'noopener noreferrer'
+ .settings-content
+ = render partial: 'network_rate_limits', locals: { anchor: 'js-deprecated-limits-settings', setting_fragment: 'deprecated_api' }
%section.settings.as-git-lfs-limits.no-animate#js-git-lfs-limits-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'git_lfs_limits_content' } }
.settings-header
diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml
index 914a09ff5db..d2e118f0624 100644
--- a/app/views/admin/application_settings/reporting.html.haml
+++ b/app/views/admin/application_settings/reporting.html.haml
@@ -9,9 +9,7 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- - recaptcha_v2_link_url = 'https://developers.google.com/recaptcha/docs/versions'
- - recaptcha_v2_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: recaptcha_v2_link_url }
- = _('Enable reCAPTCHA, Invisible Captcha, Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}').html_safe % { recaptcha_v2_link_start: recaptcha_v2_link_start, recaptcha_v2_link_end: '</a>'.html_safe }
+ = _('Configure CAPTCHAs, IP address limits, and other anti-spam measures.')
.settings-content
= render 'spam'
@@ -22,6 +20,7 @@
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Set notification email for abuse reports.')
+ = _('Receive notification of abuse reports by email.')
+ = link_to _('Learn more.'), help_page_path('user/admin_area/review_abuse_reports.md'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'abuse'
diff --git a/app/views/admin/dashboard/_security_newsletter_callout.html.haml b/app/views/admin/dashboard/_security_newsletter_callout.html.haml
new file mode 100644
index 00000000000..ece0f7ca4d9
--- /dev/null
+++ b/app/views/admin/dashboard/_security_newsletter_callout.html.haml
@@ -0,0 +1,14 @@
+- return unless show_security_newsletter_user_callout?
+
+= render 'shared/global_alert',
+ title: s_('AdminArea|Get security updates from GitLab and stay up to date'),
+ variant: :tip,
+ alert_class: 'js-security-newsletter-callout',
+ is_contained: true,
+ alert_data: { feature_id: UserCalloutsHelper::SECURITY_NEWSLETTER_CALLOUT, dismiss_endpoint: user_callouts_path, defer_links: 'true' },
+ close_button_data: { testid: 'close-security-newsletter-callout' } do
+ .gl-alert-body
+ = s_('AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates.')
+ .gl-alert-actions
+ = link_to 'https://about.gitlab.com/company/preference-center/', target: '_blank', rel: 'noreferrer noopener', class: 'deferred-link gl-alert-action btn-confirm btn-md gl-button' do
+ = s_('AdminArea|Sign up for the GitLab newsletter')
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 97b3a757a3f..681e7ccb613 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -4,6 +4,7 @@
- billable_users_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer nofollow">'.html_safe % { url: billable_users_url }
= render_if_exists 'shared/qrtly_reconciliation_alert'
+= render 'admin/dashboard/security_newsletter_callout'
- if @notices
- @notices.each do |notice|
diff --git a/app/views/admin/hook_logs/_index.html.haml b/app/views/admin/hook_logs/_index.html.haml
index a7f947f96ea..6a46b0b3510 100644
--- a/app/views/admin/hook_logs/_index.html.haml
+++ b/app/views/admin/hook_logs/_index.html.haml
@@ -1,37 +1,11 @@
+- docs_link_url = help_page_path('user/project/integrations/webhooks', anchor: 'troubleshoot-webhooks')
+- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
+- link_end = '</a>'.html_safe
+
.row.gl-mt-3.gl-mb-3
.col-lg-3
%h4.gl-mt-0
- = _('Recent Deliveries')
- %p= _('When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong.')
+ = _('Recent events')
+ %p= _('GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}').html_safe % { link_start: link_start, link_end: link_end }
.col-lg-9
- - if hook_logs.present?
- %table.table
- %thead
- %tr
- %th= _('Status')
- %th= _('Trigger')
- %th= _('URL')
- %th= _('Elapsed time')
- %th= _('Request time')
- %th
- - hook_logs.each do |hook_log|
- %tr
- %td
- = render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log }
- %td.d-none.d-sm-block
- %span.badge.badge-gray.deploy-project-label
- = hook_log.trigger.singularize.titleize
- %td
- = truncate(hook_log.url, length: 50)
- %td.light
- #{number_with_precision(hook_log.execution_duration, precision: 2)} sec
- %td.light
- = time_ago_with_tooltip(hook_log.created_at)
- %td
- = link_to _('View details'), admin_hook_hook_log_path(hook, hook_log)
-
- = paginate hook_logs, theme: 'gitlab'
-
- - else
- .settings-message.text-center
- = _("You don't have any webhooks deliveries")
+ = render partial: 'shared/hook_logs/recent_deliveries_table', locals: { hook: hook, hook_logs: hook_logs }
diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml
index 5ebfd296e2b..f947e174990 100644
--- a/app/views/admin/projects/index.html.haml
+++ b/app/views/admin/projects/index.html.haml
@@ -1,33 +1,24 @@
- page_title _('Projects')
- params[:visibility_level] ||= []
-- active_tab_classes = 'active gl-tab-nav-item-active gl-tab-nav-item-active-indigo'
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
- %ul.nav.gl-tabs-nav.gl-overflow-x-auto.gl-display-flex.gl-flex-grow-1.gl-flex-shrink-1.gl-border-b-0.gl-flex-nowrap.gl-webkit-scrollbar-display-none
- = nav_link(html_options: { class: "nav-item" } ) do
- = link_to _('All'), admin_projects_path, class: "nav-link gl-tab-nav-item #{active_tab_classes if params[:visibility_level].empty?}"
- = nav_link(html_options: { class: "nav-item" } ) do
- = link_to _('Private'), admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE), class: "nav-link gl-tab-nav-item #{active_tab_classes if params[:visibility_level] == Gitlab::VisibilityLevel::PRIVATE.to_s}"
- = nav_link(html_options: { class: "nav-item" } ) do
- = link_to _('Internal'), admin_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL), class: "nav-link gl-tab-nav-item #{active_tab_classes if params[:visibility_level] == Gitlab::VisibilityLevel::INTERNAL.to_s}"
- = nav_link(html_options: { class: "nav-item" } ) do
- = link_to _('Public'), admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC), class: "nav-link gl-tab-nav-item #{active_tab_classes if params[:visibility_level] == Gitlab::VisibilityLevel::PUBLIC.to_s}"
+ = gl_tabs_nav({ class: 'gl-border-b-0 gl-overflow-x-auto gl-flex-grow-1 gl-flex-nowrap gl-webkit-scrollbar-display-none' }) do
+ = gl_tab_link_to _('All'), admin_projects_path(visibility_level: nil), { item_active: params[:visibility_level].empty? }
+ = gl_tab_link_to _('Private'), admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ = gl_tab_link_to _('Internal'), admin_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
+ = gl_tab_link_to _('Public'), admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
.nav-controls
.search-holder
= render 'shared/projects/search_form', autofocus: true, admin_view: true
- .dropdown
- - toggle_text = _('Namespace')
- - if params[:namespace_id].present?
- = hidden_field_tag :namespace_id, params[:namespace_id]
- - namespace = Namespace.find(params[:namespace_id])
- - toggle_text = "#{namespace.kind}: #{namespace.full_path}"
- = dropdown_toggle(toggle_text, { toggle: 'dropdown', is_filter: 'true' }, { toggle_class: 'js-namespace-select large' })
- .dropdown-menu.dropdown-select.dropdown-menu-right
- = dropdown_title(_('Namespaces'))
- = dropdown_filter(_("Search for Namespace"))
- = dropdown_content
- = dropdown_loading
+ - current_namespace = _('Namespace')
+ - if params[:namespace_id].present?
+ - namespace = Namespace.find(params[:namespace_id])
+ - current_namespace = "#{namespace.kind}: #{namespace.full_path}"
+ %button.dropdown-menu-toggle.btn.btn-default.btn-md.gl-button.js-namespace-select{ data: { show_any: 'true', field_name: 'namespace_id', placeholder: current_namespace, update_location: 'true' }, type: 'button' }
+ %span.gl-new-dropdown-button-text
+ = current_namespace
+
= render 'shared/projects/dropdown'
= link_to new_project_path, class: 'gl-button btn btn-confirm' do
= _('New Project')
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 1a87b21351c..3069aab2710 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -143,13 +143,10 @@
.col-sm-3.col-form-label
= f.label :new_namespace_id, _("Namespace")
.col-sm-9
- .dropdown
- = dropdown_toggle(_('Search for Namespace'), { toggle: 'dropdown', field_name: 'new_namespace_id' }, { toggle_class: 'js-namespace-select large' })
- .dropdown-menu.dropdown-select
- = dropdown_title(_('Namespaces'))
- = dropdown_filter(_('Search for Namespace'))
- = dropdown_content
- = dropdown_loading
+ - placeholder = _('Search for Namespace')
+ %button.dropdown-menu-toggle.btn.btn-default.btn-md.gl-button.js-namespace-select{ data: { field_name: 'new_namespace_id', placeholder: placeholder }, type: 'button' }
+ %span.gl-new-dropdown-button-text
+ = placeholder
.form-group.row
.offset-sm-3.col-sm-9
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index 59523ed3a0c..808b2bb4f8e 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -9,7 +9,7 @@
.row
.col-md-6
%h4= _('Restrict projects for this runner')
- - if @runner.projects.any?
+ - if @runner.runner_projects.any?
%table.table{ data: { testid: 'assigned-projects' } }
%thead
%tr
diff --git a/app/views/admin/serverless/domains/_form.html.haml b/app/views/admin/serverless/domains/_form.html.haml
deleted file mode 100644
index a3e1ccc5d4a..00000000000
--- a/app/views/admin/serverless/domains/_form.html.haml
+++ /dev/null
@@ -1,99 +0,0 @@
-- form_name = 'js-serverless-domain-settings'
-- form_url = @domain.persisted? ? admin_serverless_domain_path(@domain.id, anchor: form_name) : admin_serverless_domains_path(anchor: form_name)
-- show_certificate_card = @domain.persisted? && @domain.errors.blank?
-= form_for @domain, url: form_url, html: { class: 'fieldset-form' } do |f|
- = form_errors(@domain)
-
- %fieldset
- - if @domain.persisted?
- - dns_record = "*.#{@domain.domain} CNAME #{Settings.pages.host}."
- - verification_record = "#{@domain.verification_domain} TXT #{@domain.keyed_verification_code}"
- .form-group.row
- .col-sm-6.position-relative
- = f.label :domain, _('Domain'), class: 'label-bold'
- = f.text_field :domain, class: 'form-control has-floating-status-badge', readonly: true
- .status-badge.floating-status-badge
- - text, status = @domain.unverified? ? [_('Unverified'), 'badge-danger'] : [_('Verified'), 'badge-success']
- .badge{ class: status }
- = text
- = link_to sprite_icon("redo"), verify_admin_serverless_domain_path(@domain.id), method: :post, class: "gl-button btn has-tooltip", title: _("Retry verification")
-
- .col-sm-6
- = f.label :serverless_domain_dns, _('DNS'), class: 'label-bold'
- .input-group
- = text_field_tag :serverless_domain_dns, dns_record , class: "monospace js-select-on-focus form-control", readonly: true
- .input-group-append
- = clipboard_button(target: '#serverless_domain_dns', class: 'btn-default input-group-text d-none d-sm-block')
-
- .col-sm-12.form-text.text-muted
- = _("To access this domain create a new DNS record")
-
- .form-group
- = f.label :serverless_domain_verification, _('Verification status'), class: 'label-bold'
- .input-group
- = text_field_tag :serverless_domain_verification, verification_record, class: "monospace js-select-on-focus form-control", readonly: true
- .input-group-append
- = clipboard_button(target: '#serverless_domain_verification', class: 'btn-default d-none d-sm-block')
- %p.form-text.text-muted
- - link_to_help = link_to(_('verify ownership'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership'))
- = _("To %{link_to_help} of your domain, add the above key to a TXT record within your DNS configuration.").html_safe % { link_to_help: link_to_help }
-
- - else
- .form-group
- = f.label :domain, _('Domain'), class: 'label-bold'
- = f.text_field :domain, class: 'form-control'
-
- - if show_certificate_card
- .card.js-domain-cert-show
- .card-header
- = _('Certificate')
- .d-flex.justify-content-between.align-items-center.p-3
- %span
- = @domain.subject || _('missing')
- %button.gl-button.btn.btn-danger.btn-sm.js-domain-cert-replace-btn{ type: 'button' }
- = _('Replace')
-
- .js-domain-cert-inputs{ class: ('hidden' if show_certificate_card) }
- .form-group
- = f.label :user_provided_certificate, _('Certificate (PEM)'), class: 'label-bold'
- = f.text_area :user_provided_certificate, rows: 5, class: 'form-control', value: ''
- %span.form-text.text-muted
- = _("Upload a certificate for your domain with all intermediates")
- .form-group
- = f.label :user_provided_key, _('Key (PEM)'), class: 'label-bold'
- = f.text_area :user_provided_key, rows: 5, class: 'form-control', value: ''
- %span.form-text.text-muted
- = _("Upload a private key for your certificate")
-
- = f.submit @domain.persisted? ? _('Save changes') : _('Add domain'), class: "gl-button btn btn-confirm js-serverless-domain-submit", disabled: @domain.persisted?
- - if @domain.persisted?
- %button.gl-button.btn.btn-danger{ type: 'button', data: { toggle: 'modal', target: "#modal-delete-domain" } }
- = _('Delete domain')
-
--# haml-lint:disable NoPlainNodes
-- if @domain.persisted?
- - domain_attached = @domain.serverless_domain_clusters.count > 0
- .modal{ id: "modal-delete-domain", tabindex: -1 }
- .modal-dialog
- .modal-content
- .modal-header
- %h3.page-title= _('Delete serverless domain?')
- %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
- %span{ "aria-hidden": "true" } &times;
-
- .modal-body
- - if domain_attached
- = _("You must disassociate %{domain} from all clusters it is attached to before deletion.").html_safe % { domain: "<code>#{@domain.domain}</code>".html_safe }
- - else
- = _("You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application.").html_safe % { domain: "<code>#{@domain.domain}</code>".html_safe }
-
- .modal-footer
- %a{ href: '#', data: { dismiss: 'modal' }, class: 'gl-button btn btn-default' }
- = _('Cancel')
-
- = link_to _('Delete domain'),
- admin_serverless_domain_path(@domain.id),
- title: _('Delete'),
- method: :delete,
- class: "gl-button btn btn-danger",
- disabled: domain_attached
diff --git a/app/views/admin/serverless/domains/index.html.haml b/app/views/admin/serverless/domains/index.html.haml
deleted file mode 100644
index c2b6baed4de..00000000000
--- a/app/views/admin/serverless/domains/index.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-- breadcrumb_title _("Operations")
-- page_title _("Operations")
-- @content_class = "limit-container-width" unless fluid_layout
-
--# normally expanded_by_default? is used here, but since this is the only panel
--# in this settings page, let's leave it always open by default
-- expanded = true
-
-%section.settings.as-serverless-domain.no-animate#js-serverless-domain-settings{ class: ('expanded' if expanded) }
- .settings-header
- %h4
- = _('Serverless domain')
- %button.gl-button.btn.btn-default.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
- %p
- = _('Set an instance-wide domain that will be available to all clusters when installing Knative.')
- .settings-content
- - if Gitlab.config.pages.enabled
- = render 'form'
- - else
- .card
- .card-header
- = s_('GitLabPages|Domains')
- .nothing-here-block
- = s_("GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it.")
diff --git a/app/views/admin/sessions/_new_base.html.haml b/app/views/admin/sessions/_new_base.html.haml
index 47ef4f26889..c9b002a4dd2 100644
--- a/app/views/admin/sessions/_new_base.html.haml
+++ b/app/views/admin/sessions/_new_base.html.haml
@@ -1,7 +1,7 @@
= form_tag(admin_session_path, method: :post, class: 'new_user gl-show-field-errors', 'aria-live': 'assertive') do
.form-group
= label_tag :user_password, _('Password'), class: 'label-bold'
- = password_field_tag 'user[password]', nil, class: 'form-control', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' }
+ = password_field_tag 'user[password]', nil, class: 'form-control', autocomplete: 'current-password', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' }
.submit-container.move-submit-down
= submit_tag _('Enter Admin Mode'), class: 'gl-button btn btn-success', data: { qa_selector: 'enter_admin_mode_button' }
diff --git a/app/views/admin/topics/_form.html.haml b/app/views/admin/topics/_form.html.haml
new file mode 100644
index 00000000000..21a1d74a8c6
--- /dev/null
+++ b/app/views/admin/topics/_form.html.haml
@@ -0,0 +1,40 @@
+= gitlab_ui_form_for @topic, url: url, html: { multipart: true, class: 'js-project-topic-form gl-show-field-errors common-note-form js-quick-submit js-requires-input' }, authenticity_token: true do |f|
+ = form_errors(@topic)
+
+ .form-group
+ = f.label :name do
+ = _("Topic name")
+ = f.text_field :name, placeholder: _('My topic'), class: 'form-control input-lg', data: { qa_selector: 'topic_name_field' },
+ required: true,
+ title: _('Please fill in a name for your topic.'),
+ autofocus: true
+
+ .form-group
+ = f.label :description, _("Description")
+ = render layout: 'shared/md_preview', locals: { url: preview_markdown_admin_topics_path, referenced_users: false } do
+ = render 'shared/zen', f: f, attr: :description,
+ classes: 'note-textarea',
+ placeholder: _('Write a description…'),
+ supports_quick_actions: false,
+ supports_autocomplete: false,
+ qa_selector: 'topic_form_description'
+ = render 'shared/notes/hints', supports_file_upload: false
+
+ .form-group.gl-mt-3.gl-mb-3
+ = f.label :avatar, _('Topic avatar'), class: 'gl-display-block'
+ - if @topic.avatar?
+ .avatar-container.rect-avatar.s90
+ = topic_icon(@topic, alt: _('Topic avatar'), class: 'avatar topic-avatar s90')
+ = render 'shared/choose_avatar_button', f: f
+ - if @topic.avatar?
+ = link_to _('Remove avatar'), admin_topic_avatar_path(@topic), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'gl-button btn btn-danger-secondary gl-mt-2'
+
+ - if @topic.new_record?
+ .form-actions
+ = f.submit _('Create topic'), class: "gl-button btn btn-confirm"
+ = link_to _('Cancel'), admin_topics_path, class: "gl-button btn btn-default btn-cancel"
+
+ - else
+ .form-actions
+ = f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
+ = link_to _('Cancel'), admin_topics_path, class: "gl-button btn btn-cancel"
diff --git a/app/views/admin/topics/_topic.html.haml b/app/views/admin/topics/_topic.html.haml
new file mode 100644
index 00000000000..abf3cffa422
--- /dev/null
+++ b/app/views/admin/topics/_topic.html.haml
@@ -0,0 +1,17 @@
+- topic = local_assigns.fetch(:topic)
+
+%li.topic-row.gl-py-3.gl-align-items-center{ class: 'gl-display-flex!', data: { qa_selector: 'topic_row_content' } }
+ .avatar-container.rect-avatar.s40.gl-flex-shrink-0
+ = topic_icon(topic, class: "avatar s40")
+
+ .gl-min-w-0.gl-flex-grow-1
+ .title
+ = topic.name
+
+ .stats.gl-text-gray-500.gl-flex-shrink-0.gl-display-none.gl-sm-display-flex
+ %span.gl-ml-5.has-tooltip{ title: n_('%d project', '%d projects', topic.total_projects_count) % topic.total_projects_count }
+ = sprite_icon('bookmark', css_class: 'gl-vertical-align-text-bottom')
+ = number_with_delimiter(topic.total_projects_count)
+
+ .controls.gl-flex-shrink-0.gl-ml-5
+ = link_to _('Edit'), edit_admin_topic_path(topic), id: "edit_#{dom_id(topic)}", class: 'btn gl-button btn-default'
diff --git a/app/views/admin/topics/edit.html.haml b/app/views/admin/topics/edit.html.haml
new file mode 100644
index 00000000000..4416bb0fe18
--- /dev/null
+++ b/app/views/admin/topics/edit.html.haml
@@ -0,0 +1,4 @@
+- page_title _("Edit"), @topic.name, _("Topics")
+%h3.page-title= _('Edit topic: %{topic_name}') % { topic_name: @topic.name }
+%hr
+= render 'form', url: admin_topic_path(@topic)
diff --git a/app/views/admin/topics/index.html.haml b/app/views/admin/topics/index.html.haml
new file mode 100644
index 00000000000..6485b8aa411
--- /dev/null
+++ b/app/views/admin/topics/index.html.haml
@@ -0,0 +1,19 @@
+- page_title _("Topics")
+
+= form_tag admin_topics_path, method: :get do |f|
+ .gl-py-3.gl-display-flex.gl-flex-direction-column-reverse.gl-md-flex-direction-row.gl-border-b-solid.gl-border-gray-100.gl-border-b-1
+ .gl-flex-grow-1.gl-mt-3.gl-md-mt-0
+ .inline.gl-w-full.gl-md-w-auto
+ - search = params.fetch(:search, nil)
+ .search-field-holder
+ = search_field_tag :search, search, class: "form-control gl-form-input search-text-input js-search-input", autofocus: true, spellcheck: false, placeholder: _('Search by name'), data: { qa_selector: 'topic_search_field' }
+ = sprite_icon('search', css_class: 'search-icon')
+ .nav-controls
+ = link_to new_admin_topic_path, class: "gl-button btn btn-confirm gl-w-full gl-md-w-auto" do
+ = _('New topic')
+%ul.content-list
+ = render partial: 'topic', collection: @topics
+
+= paginate_collection @topics
+- if @topics.empty?
+ = render 'shared/empty_states/topics'
diff --git a/app/views/admin/topics/new.html.haml b/app/views/admin/topics/new.html.haml
new file mode 100644
index 00000000000..8b4a8ac269e
--- /dev/null
+++ b/app/views/admin/topics/new.html.haml
@@ -0,0 +1,4 @@
+- page_title _("New topic")
+%h3.page-title= _('New topic')
+%hr
+= render 'form', url: admin_topics_path(@topic)
diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml
index aeb274fe2cb..6a5f07dd2db 100644
--- a/app/views/admin/users/_access_levels.html.haml
+++ b/app/views/admin/users/_access_levels.html.haml
@@ -19,22 +19,20 @@
.col-sm-10
- editing_current_user = (current_user == @user)
- = f.radio_button :access_level, :regular, disabled: editing_current_user
- = f.label :access_level_regular, class: 'font-weight-bold' do
- = s_('AdminUsers|Regular')
- %p.light
- = s_('AdminUsers|Regular users have access to their groups and projects')
+ = f.gitlab_ui_radio_component :access_level, :regular,
+ s_('AdminUsers|Regular'),
+ radio_options: { disabled: editing_current_user },
+ help_text: s_('AdminUsers|Regular users have access to their groups and projects.')
= render_if_exists 'admin/users/auditor_access_level_radio', f: f, disabled: editing_current_user
- = f.radio_button :access_level, :admin, disabled: editing_current_user
- = f.label :access_level_admin, class: 'font-weight-bold' do
- = s_('AdminUsers|Admin')
- %p.light
- = s_('AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation')
- - if editing_current_user
- %p.light
- = s_('AdminUsers|You cannot remove your own admin rights.')
+ - help_text = s_('AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation.')
+ - help_text += ' ' + s_('AdminUsers|You cannot remove your own admin rights.') if editing_current_user
+ = f.gitlab_ui_radio_component :access_level, :admin,
+ s_('AdminUsers|Admin'),
+ radio_options: { disabled: editing_current_user },
+ help_text: help_text
+
.form-group.row
.col-sm-2.col-form-label.gl-pt-0
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 9d62c19e2fc..3869a2b6dcd 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -1,5 +1,5 @@
.user_new
- = form_for [:admin, @user], html: { class: 'fieldset-form' } do |f|
+ = gitlab_ui_form_for [:admin, @user], html: { class: 'fieldset-form' } do |f|
= form_errors(@user)
%fieldset
@@ -39,12 +39,12 @@
.col-sm-2.col-form-label
= f.label :password
.col-sm-10
- = f.password_field :password, disabled: f.object.force_random_password, class: 'form-control gl-form-input'
+ = f.password_field :password, disabled: f.object.force_random_password, autocomplete: 'new-password', class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :password_confirmation
.col-sm-10
- = f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control gl-form-input'
+ = f.password_field :password_confirmation, disabled: f.object.force_random_password, autocomplete: 'new-password', class: 'form-control gl-form-input'
= render partial: 'access_levels', locals: { f: f }
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index f4b1a2853f1..bafb2085589 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -33,16 +33,11 @@
- if can_force_email_confirmation?(@user)
%button.btn.gl-button.btn-info.js-confirm-modal-button{ data: confirm_user_data(@user) }
= _('Confirm user')
-%ul.nav-links.nav.nav-tabs
- = nav_link(path: 'users#show') do
- = link_to _("Account"), admin_user_path(@user)
- = nav_link(path: 'users#projects') do
- = link_to _("Groups and projects"), projects_admin_user_path(@user)
- = nav_link(path: 'users#keys') do
- = link_to _("SSH keys"), keys_admin_user_path(@user)
- = nav_link(controller: :identities) do
- = link_to _("Identities"), admin_user_identities_path(@user)
+= gl_tabs_nav do
+ = gl_tab_link_to _("Account"), admin_user_path(@user)
+ = gl_tab_link_to _("Groups and projects"), projects_admin_user_path(@user)
+ = gl_tab_link_to _("SSH keys"), keys_admin_user_path(@user)
+ = gl_tab_link_to _("Identities"), admin_user_identities_path(@user)
- if impersonation_enabled?
- = nav_link(controller: :impersonation_tokens) do
- = link_to _("Impersonation Tokens"), admin_user_impersonation_tokens_path(@user)
+ = gl_tab_link_to _("Impersonation Tokens"), admin_user_impersonation_tokens_path(@user)
.gl-mb-3
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index ad8d9d1f04f..2a9b4694e7b 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -61,7 +61,6 @@
= _('Disabled')
= render_if_exists 'admin/namespace_plan_info', namespace: @user.namespace
- = render_if_exists 'admin/users/credit_card_info', user: @user
%li
%span.light= _('External User:')
@@ -139,6 +138,8 @@
= render_if_exists 'namespaces/shared_runner_status', namespace: @user.namespace
+ = render_if_exists 'admin/users/credit_card_info', user: @user, link_to_match_page: true
+
= render 'shared/custom_attributes', custom_attributes: @user.custom_attributes
-# Rendered on desktop only so order of cards can be different on desktop vs mobile
diff --git a/app/views/authentication/_authenticate.html.haml b/app/views/authentication/_authenticate.html.haml
index 5a2ae3f44c2..7dcec50573f 100644
--- a/app/views/authentication/_authenticate.html.haml
+++ b/app/views/authentication/_authenticate.html.haml
@@ -1,14 +1,17 @@
#js-authenticate-token-2fa
%a.gl-button.btn.btn-block.btn-confirm#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
+-# haml-lint:disable InlineJavaScript
%script#js-authenticate-token-2fa-in-progress{ type: "text/template" }
%p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
+-# haml-lint:disable InlineJavaScript
%script#js-authenticate-token-2fa-error{ type: "text/template" }
%div
%p <%= error_message %> (<%= error_name %>)
%a.btn.btn-default.gl-button.btn-block#js-token-2fa-try-again= _("Try again?")
+-# haml-lint:disable InlineJavaScript
%script#js-authenticate-token-2fa-authenticated{ type: "text/template" }
%div
%p= _("We heard back from your device. You have been authenticated.")
diff --git a/app/views/authentication/_register.html.haml b/app/views/authentication/_register.html.haml
index 678fd3c8e8c..5eed969ed35 100644
--- a/app/views/authentication/_register.html.haml
+++ b/app/views/authentication/_register.html.haml
@@ -1,8 +1,10 @@
#js-register-token-2fa
+-# haml-lint:disable InlineJavaScript
%script#js-register-2fa-message{ type: "text/template" }
%p <%= message %>
+-# haml-lint:disable InlineJavaScript
%script#js-register-token-2fa-setup{ type: "text/template" }
- if current_user.two_factor_otp_enabled?
.row.gl-mb-3
@@ -17,12 +19,14 @@
.col-md-8
%p= _("You need to register a two-factor authentication app before you can set up a device.")
+-# haml-lint:disable InlineJavaScript
%script#js-register-token-2fa-error{ type: "text/template" }
%div
%p
%span <%= error_message %> (<%= error_name %>)
%a.btn.btn-default.gl-button#js-token-2fa-try-again= _("Try again?")
+-# haml-lint:disable InlineJavaScript
%script#js-register-token-2fa-registered{ type: "text/template" }
.row.gl-mb-3
.col-md-12
diff --git a/app/views/clusters/clusters/_advanced_settings_tab.html.haml b/app/views/clusters/clusters/_advanced_settings_tab.html.haml
index b491a64e43d..8c9d98604dd 100644
--- a/app/views/clusters/clusters/_advanced_settings_tab.html.haml
+++ b/app/views/clusters/clusters/_advanced_settings_tab.html.haml
@@ -1,6 +1,5 @@
- active = params[:tab] == 'settings'
- if can_admin_cluster?(current_user, @cluster)
- %li.nav-item{ role: 'presentation' }
- %a#cluster-settings-tab.nav-link{ class: active_when(active), href: clusterable.cluster_path(@cluster.id, params: {tab: 'settings'}) }
- %span= _('Advanced Settings')
+ = gl_tab_link_to clusterable.cluster_path(@cluster.id, params: { tab: 'settings' }), { item_active: active } do
+ = _('Advanced Settings')
diff --git a/app/views/clusters/clusters/_details_tab.html.haml b/app/views/clusters/clusters/_details_tab.html.haml
index 564c5103d34..734910686e7 100644
--- a/app/views/clusters/clusters/_details_tab.html.haml
+++ b/app/views/clusters/clusters/_details_tab.html.haml
@@ -1,5 +1,4 @@
- active = params[:tab] == 'details' || !params[:tab].present?
-%li.nav-item{ role: 'presentation' }
- %a#cluster-details-tab.nav-link.qa-details{ class: active_when(active), href: clusterable.cluster_path(@cluster.id, params: {tab: 'details'}) }
- %span= _('Details')
+= gl_tab_link_to clusterable.cluster_path(@cluster.id, params: { tab: 'details' }), { item_active: active } do
+ = _('Details')
diff --git a/app/views/clusters/clusters/_health_tab.html.haml b/app/views/clusters/clusters/_health_tab.html.haml
index fda392693f6..4292066cc6f 100644
--- a/app/views/clusters/clusters/_health_tab.html.haml
+++ b/app/views/clusters/clusters/_health_tab.html.haml
@@ -1,5 +1,4 @@
- active = params[:tab] == 'health'
-%li.nav-item{ role: 'presentation' }
- %a#cluster-health-tab.nav-link.qa-health{ class: active_when(active), href: clusterable.cluster_path(@cluster.id, params: {tab: 'health'}) }
- %span= _('Health')
+= gl_tab_link_to clusterable.cluster_path(@cluster.id, params: { tab: 'health' }), { item_active: active, data: { testid: 'cluster-health-tab' } } do
+ = _('Health')
diff --git a/app/views/clusters/clusters/_integrations_tab.html.haml b/app/views/clusters/clusters/_integrations_tab.html.haml
index 77b8b6ca3e6..e229c1fbe1e 100644
--- a/app/views/clusters/clusters/_integrations_tab.html.haml
+++ b/app/views/clusters/clusters/_integrations_tab.html.haml
@@ -1,6 +1,4 @@
-- tab_name = 'integrations'
-- active = params[:tab] == tab_name
+- active = params[:tab] == 'integrations'
-%li.nav-item{ role: 'presentation' }
- %a#cluster-apps-tab.nav-link{ class: active_when(active), href: clusterable.cluster_path(@cluster.id, params: {tab: tab_name}) }
- %span= _('Integrations')
+= gl_tab_link_to clusterable.cluster_path(@cluster.id, params: { tab: 'integrations' }), { item_active: active } do
+ = _('Integrations')
diff --git a/app/views/clusters/clusters/_namespace.html.haml b/app/views/clusters/clusters/_namespace.html.haml
index 9b728e7a89b..6412972e195 100644
--- a/app/views/clusters/clusters/_namespace.html.haml
+++ b/app/views/clusters/clusters/_namespace.html.haml
@@ -1,7 +1,6 @@
- managed_namespace_help_text = s_('ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared.')
- non_managed_namespace_help_text = s_('ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals.')
-- managed_namespace_help_link = link_to _('More information'), help_page_path('user/project/clusters/index.md',
- anchor: 'gitlab-managed-clusters'), target: '_blank'
+- managed_namespace_help_link = link_to _('More information'), help_page_path('user/project/clusters/gitlab_managed_clusters.md'), target: '_blank'
.js-namespace-prefixed
= platform_field.text_field :namespace,
diff --git a/app/views/clusters/clusters/aws/_new.html.haml b/app/views/clusters/clusters/aws/_new.html.haml
index 93db7db06b3..f6d50410e9a 100644
--- a/app/views/clusters/clusters/aws/_new.html.haml
+++ b/app/views/clusters/clusters/aws/_new.html.haml
@@ -12,6 +12,6 @@
'role-arn' => @aws_role.role_arn,
'instance-types' => @instance_types,
'kubernetes-integration-help-path' => help_page_path('user/project/clusters/index'),
- 'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'create-a-new-certificate-based-eks-cluster'),
- 'create-role-arn-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'create-a-new-certificate-based-eks-cluster'),
+ 'account-and-external-ids-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'how-to-create-a-new-cluster-on-eks-through-cluster-certificates-deprecated'),
+ 'create-role-arn-help-path' => help_page_path('user/project/clusters/add_eks_clusters.md', anchor: 'how-to-create-a-new-cluster-on-eks-through-cluster-certificates-deprecated'),
'external-link-icon' => sprite_icon('external-link') } }
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index 0a482f1eb01..2a09d8d8cc0 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -15,7 +15,7 @@
provider_type: @cluster.provider_type,
help_path: help_page_path('user/project/clusters/index.md'),
environments_help_path: help_page_path('ci/environments/index.md', anchor: 'create-a-static-environment'),
- clusters_help_path: help_page_path('user/project/clusters/index.md', anchor: 'deploying-to-a-kubernetes-cluster'),
+ clusters_help_path: help_page_path('user/project/clusters/deploy_to_cluster.md'),
deploy_boards_help_path: help_page_path('user/project/deploy_boards.md', anchor: 'enabling-deploy-boards'),
cluster_id: @cluster.id } }
@@ -24,11 +24,10 @@
.js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } }
- .d-flex.my-3
- %p.badge.badge-light.p-2.mr-2
+ %h4.gl-my-5
+ = @cluster.name
+ %span.badge.badge-info.badge-pill.gl-badge.md.gl-vertical-align-middle
= cluster_type_label(@cluster.cluster_type)
- %h4.m-0
- = @cluster.name
= render 'banner'
@@ -42,12 +41,12 @@
- if cluster_created?(@cluster)
.js-toggle-container
- %ul.nav-links.mobile-separator.nav.nav-tabs{ role: 'tablist' }
- = render 'details_tab'
+ = gl_tabs_nav do
+ = render 'clusters/clusters/details_tab'
= render_if_exists 'clusters/clusters/environments_tab'
= render 'clusters/clusters/health_tab'
- = render 'integrations_tab'
- = render 'advanced_settings_tab'
+ = render 'clusters/clusters/integrations_tab'
+ = render 'clusters/clusters/advanced_settings_tab'
.tab-content.py-3
.tab-pane.active{ role: 'tabpanel' }
diff --git a/app/views/dashboard/_activity_head.html.haml b/app/views/dashboard/_activity_head.html.haml
index 0daadd20f54..c65b947d1ba 100644
--- a/app/views/dashboard/_activity_head.html.haml
+++ b/app/views/dashboard/_activity_head.html.haml
@@ -2,13 +2,7 @@
%h1.page-title= _('Activity')
.top-area
- %ul.nav-links.nav.nav-tabs
- %li{ class: active_when(params[:filter].nil?) }>
- = link_to activity_dashboard_path, class: 'shortcuts-activity', data: {placement: 'right'} do
- = _('Your projects')
- %li{ class: active_when(params[:filter] == 'starred') }>
- = link_to activity_dashboard_path(filter: 'starred'), data: {placement: 'right'} do
- = _('Starred projects')
- %li{ class: active_when(params[:filter] == 'followed') }>
- = link_to activity_dashboard_path(filter: 'followed'), data: {placement: 'right'} do
- = _('Followed users')
+ = gl_tabs_nav({ class: 'gl-border-b-0', data: { testid: 'dashboard-activity-tabs' } }) do
+ = gl_tab_link_to _("Your projects"), activity_dashboard_path, { item_active: params[:filter].nil? }
+ = gl_tab_link_to _("Starred projects"), activity_dashboard_path(filter: 'starred')
+ = gl_tab_link_to _("Followed users"), activity_dashboard_path(filter: 'followed')
diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml
index b92f35c108c..7b1d25b9b43 100644
--- a/app/views/dashboard/_groups_head.html.haml
+++ b/app/views/dashboard/_groups_head.html.haml
@@ -6,13 +6,9 @@
= link_to _("New group"), new_group_path, class: "gl-button btn btn-confirm", data: { testid: "new-group-button" }
.top-area
- %ul.nav-links.mobile-separator.nav.nav-tabs
- = nav_link(page: dashboard_groups_path) do
- = link_to dashboard_groups_path, title: _("Your groups") do
- Your groups
- = nav_link(page: explore_groups_path) do
- = link_to explore_groups_path, title: _("Explore public groups") do
- Explore public groups
+ = gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
+ = gl_tab_link_to _("Your groups"), dashboard_groups_path
+ = gl_tab_link_to _("Explore public groups"), explore_groups_path
.nav-controls
= render 'shared/groups/search_form'
= render 'shared/groups/dropdown'
diff --git a/app/views/devise/confirmations/almost_there.haml b/app/views/devise/confirmations/almost_there.haml
index 037b2f247c1..9fb0fb734f9 100644
--- a/app/views/devise/confirmations/almost_there.haml
+++ b/app/views/devise/confirmations/almost_there.haml
@@ -1,16 +1,15 @@
- user_email = "(#{params[:email]})" if params[:email].present?
+- request_link_start = '<a href="%{new_user_confirmation_path}">'.html_safe % { new_user_confirmation_path: new_user_confirmation_path }
+- request_link_end = '</a>'.html_safe
.well-confirmation.gl-text-center.gl-mb-6
%h1.gl-mt-0
= _("Almost there...")
- %p.lead.gl-mb-6
+ %p{ class: 'gl-mb-6 gl-font-lg!' }
= _('Please check your email %{email} to confirm your account') % { email: user_email }
%hr
- if Gitlab::CurrentSettings.after_sign_up_text.present?
.well-confirmation.gl-text-center
= markdown_field(Gitlab::CurrentSettings, :after_sign_up_text)
-%p.text-center
- = _("No confirmation email received? Please check your spam folder or")
-.gl-mb-6.prepend-top-20.gl-text-center
- %a.gl-link{ href: new_user_confirmation_path }
- = _("Request new confirmation email")
+%p.gl-text-center
+ = _("No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}.").html_safe % { request_link_start: request_link_start, request_link_end: request_link_end }
diff --git a/app/views/devise/mailer/_confirmation_instructions_secondary.text.erb b/app/views/devise/mailer/_confirmation_instructions_secondary.text.erb
index ab46aaaca1a..32e88047a9c 100644
--- a/app/views/devise/mailer/_confirmation_instructions_secondary.text.erb
+++ b/app/views/devise/mailer/_confirmation_instructions_secondary.text.erb
@@ -1,4 +1,4 @@
-<%= _(" %{name}, confirm your email address now! ") % { name: @resource.user.name } %>
+<%= _("%{name}, confirm your email address now!") % { name: @resource.user.name } %>
<%= _("Use the link below to confirm your email address (%{email})") % { email: @resource.email } %>
diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml
index 10c04423589..56bd30fac73 100644
--- a/app/views/devise/passwords/edit.html.haml
+++ b/app/views/devise/passwords/edit.html.haml
@@ -7,10 +7,10 @@
= f.hidden_field :reset_password_token
.form-group
= f.label _('New password'), for: "user_password"
- = f.password_field :password, class: "form-control gl-form-input top", required: true, title: _('This field is required.'), data: { qa_selector: 'password_field'}
+ = f.password_field :password, autocomplete: 'new-password', class: "form-control gl-form-input top", required: true, title: _('This field is required.'), data: { qa_selector: 'password_field'}
.form-group
= f.label _('Confirm new password'), for: "user_password_confirmation"
- = f.password_field :password_confirmation, class: "form-control gl-form-input bottom", title: _('This field is required.'), data: { qa_selector: 'password_confirmation_field' }, required: true
+ = f.password_field :password_confirmation, autocomplete: 'new-password', class: "form-control gl-form-input bottom", title: _('This field is required.'), data: { qa_selector: 'password_confirmation_field' }, required: true
.clearfix
= f.submit _("Change your password"), class: "gl-button btn btn-confirm", data: { qa_selector: 'change_password_button' }
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 4ec3fcde337..87108c8ea78 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -2,6 +2,7 @@
- add_page_specific_style 'page_bundles/signup'
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
+ = render "layouts/one_trust"
= render "layouts/google_tag_manager_body"
.signup-page
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index 82c0df354d4..b40373ecc37 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -4,12 +4,12 @@
= f.text_field :login, value: @invite_email, class: 'form-control gl-form-input top', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', required: true, title: _('This field is required.'), data: { qa_selector: 'login_field' }
.form-group
= f.label :password, class: 'label-bold'
- = f.password_field :password, class: 'form-control gl-form-input bottom', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' }
+ = f.password_field :password, class: 'form-control gl-form-input bottom', autocomplete: 'current-password', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' }
- if devise_mapping.rememberable?
- .remember-me
+ %div
%label{ for: 'user_remember_me' }
- = f.check_box :remember_me, class: 'remember-me-checkbox'
- %span Remember me
+ = f.check_box :remember_me
+ %span= _('Remember me')
.float-right
- if unconfirmed_email?
= link_to _('Resend confirmation email'), new_user_confirmation_path
diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml
index 769268748f4..fb4c011dd49 100644
--- a/app/views/devise/sessions/_new_crowd.html.haml
+++ b/app/views/devise/sessions/_new_crowd.html.haml
@@ -4,7 +4,7 @@
= text_field_tag :username, nil, { class: "form-control top", title: _("This field is required."), autofocus: "autofocus", required: true }
.form-group
= label_tag :password
- = password_field_tag :password, nil, { class: "form-control bottom", title: _("This field is required."), required: true }
+ = password_field_tag :password, nil, { autocomplete: 'current-password', class: "form-control bottom", title: _("This field is required."), required: true }
- if devise_mapping.rememberable?
.remember-me
%label{ for: "remember_me" }
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index f599a652b71..fea58779c17 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -8,7 +8,7 @@
= text_field_tag :username, nil, { class: "form-control gl-form-input top", title: _("This field is required."), autofocus: "autofocus", data: { qa_selector: 'username_field' }, required: true }
.form-group
= label_tag :password
- = password_field_tag :password, nil, { class: "form-control gl-form-input bottom", title: _("This field is required."), data: { qa_selector: 'password_field' }, required: true }
+ = password_field_tag :password, nil, { autocomplete: 'current-password', class: "form-control gl-form-input bottom", title: _("This field is required."), data: { qa_selector: 'password_field' }, required: true }
- if !hide_remember_me && devise_mapping.rememberable?
.remember-me
%label{ for: "remember_me" }
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index 74f3e3e7e34..da6232b2a2b 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,6 +1,7 @@
- page_title _("Sign in")
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
+ = render "layouts/one_trust"
= render "layouts/google_tag_manager_body"
#signin-container
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 1752a43b032..bd7fe41ae8d 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -1,20 +1,20 @@
- hide_remember_me = local_assigns.fetch(:hide_remember_me, false)
.omniauth-container.gl-mt-5
- %label.label-bold.d-block
+ %label.gl-font-weight-bold
= _('Sign in with')
- providers = enabled_button_based_providers
- .d-flex.justify-content-between.flex-wrap
+ .gl-display-flex.gl-justify-content-between.gl-flex-wrap
- providers.each do |provider|
- has_icon = provider_has_icon?(provider)
- = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "btn gl-button btn-default omniauth-btn oauth-login #{qa_class_for_provider(provider)}", form: { class: 'gl-w-full' } do
+ = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "btn gl-button btn-default gl-w-full js-oauth-login #{qa_class_for_provider(provider)}", form: { class: 'gl-w-full gl-mb-3' } do
- if has_icon
= provider_image_tag(provider)
%span.gl-button-text
= label_for_provider(provider)
- unless hide_remember_me
- %fieldset.remember-me
+ %fieldset
%label
- = check_box_tag :remember_me, nil, false, class: 'remember-me-checkbox'
+ = check_box_tag :remember_me, nil, false
%span
= _('Remember me')
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index f9649875538..15143684b8b 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -53,6 +53,7 @@
= f.password_field :password,
class: 'form-control gl-form-input bottom',
data: { qa_selector: 'new_user_password_field' },
+ autocomplete: 'new-password',
required: true,
pattern: ".{#{@minimum_password_length},}",
title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
diff --git a/app/views/devise/shared/_signup_omniauth_provider_list.haml b/app/views/devise/shared/_signup_omniauth_provider_list.haml
index 43e0802ee2a..c24e8770f05 100644
--- a/app/views/devise/shared/_signup_omniauth_provider_list.haml
+++ b/app/views/devise/shared/_signup_omniauth_provider_list.haml
@@ -1,9 +1,9 @@
-%label.label-bold.d-block
+%label.gl-font-weight-bold
= _("Create an account using:")
-.d-flex.justify-content-between.flex-wrap
+.gl-display-flex.gl-justify-content-between.gl-flex-wrap
- providers.each do |provider|
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-display-flex gl-align-items-center gl-text-left gl-mb-2 gl-p-2 omniauth-btn oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
- if provider_has_icon?(provider)
= provider_image_tag(provider)
- %span.ml-2
+ %span.gl-button-text
= label_for_provider(provider)
diff --git a/app/views/devise/shared/_signup_omniauth_providers.haml b/app/views/devise/shared/_signup_omniauth_providers.haml
index a653d44d694..30a54ab86a6 100644
--- a/app/views/devise/shared/_signup_omniauth_providers.haml
+++ b/app/views/devise/shared/_signup_omniauth_providers.haml
@@ -1,3 +1,3 @@
-.omniauth-divider.d-flex.align-items-center.text-center
+.omniauth-divider.gl-display-flex.gl-align-items-center
= _("or")
= render 'devise/shared/signup_omniauth_provider_list', providers: enabled_button_based_providers
diff --git a/app/views/devise/shared/_signup_omniauth_providers_top.haml b/app/views/devise/shared/_signup_omniauth_providers_top.haml
index 9a2629443ed..8eb22c0b023 100644
--- a/app/views/devise/shared/_signup_omniauth_providers_top.haml
+++ b/app/views/devise/shared/_signup_omniauth_providers_top.haml
@@ -1,3 +1,3 @@
= render 'devise/shared/signup_omniauth_provider_list', providers: popular_enabled_button_based_providers
-.omniauth-divider.d-flex.align-items-center.text-center
+.omniauth-divider.gl-display-flex.gl-align-items-center
= _("or")
diff --git a/app/views/groups/_group_admin_settings.html.haml b/app/views/groups/_group_admin_settings.html.haml
index ea191449fe3..ab6861b5f24 100644
--- a/app/views/groups/_group_admin_settings.html.haml
+++ b/app/views/groups/_group_admin_settings.html.haml
@@ -36,4 +36,4 @@
.offset-sm-2.col-sm-10
.form-check
= f.text_field :two_factor_grace_period, class: 'form-control'
- .form-text.text-muted= _("Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication")
+ .form-text.text-muted= _("Time (in hours) that users are allowed to skip forced configuration of two-factor authentication.")
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index 0352f366f5d..e530d9c60b6 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -5,17 +5,19 @@
.group-home-panel
.row.mb-3
.home-panel-title-row.col-md-12.col-lg-6.d-flex
- .avatar-container.rect-avatar.s64.home-panel-avatar.gl-mr-3.float-none
+ .avatar-container.rect-avatar.s64.home-panel-avatar.gl-flex-shrink-0.float-none{ class: 'gl-mr-3!' }
= group_icon(@group, class: 'avatar avatar-tile s64', width: 64, height: 64, itemprop: 'logo')
.d-flex.flex-column.flex-wrap.align-items-baseline
.d-inline-flex.align-items-baseline
- %h1.home-panel-title.gl-mt-3.gl-mb-2{ itemprop: 'name' }
+ %h1.home-panel-title.gl-mt-3.gl-mb-2.gl-ml-3{ itemprop: 'name' }
= @group.name
%span.visibility-icon.text-secondary.gl-ml-2.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
= visibility_level_icon(@group.visibility_level, options: {class: 'icon'})
- .home-panel-metadata.text-secondary
- %span
- = _("Group ID: %{group_id}") % { group_id: @group.id }
+ .home-panel-metadata.text-secondary.gl-font-base.gl-font-weight-normal.gl-line-height-normal
+ - if can?(current_user, :read_group, @group)
+ - button_class = "btn gl-button btn-sm btn-tertiary btn-default-tertiary home-panel-metadata"
+ - button_text = s_('GroupPage|Group ID: %{group_id}') % { group_id: @group.id }
+ = clipboard_button(title: s_('GroupPage|Copy group ID'), text: @group.id, hide_button_icon: true, button_text: button_text, class: button_class, qa_selector: 'group_id_content', itemprop: 'identifier')
- if current_user
%span.gl-ml-3
= render 'shared/members/access_request_links', source: @group
diff --git a/app/views/groups/_import_group_from_another_instance_panel.html.haml b/app/views/groups/_import_group_from_another_instance_panel.html.haml
index 2b9277c67e9..06a86c2465f 100644
--- a/app/views/groups/_import_group_from_another_instance_panel.html.haml
+++ b/app/views/groups/_import_group_from_another_instance_panel.html.haml
@@ -1,16 +1,15 @@
= form_with url: configure_import_bulk_imports_path, class: 'group-form gl-show-field-errors' do |f|
.gl-border-l-solid.gl-border-r-solid.gl-border-gray-100.gl-border-1.gl-p-5
- %h4.gl-display-flex
- = s_('GroupsNew|Import groups from another instance of GitLab')
- %span.badge.badge-info.badge-pill.gl-badge.md.gl-ml-3
- = _('Beta')
+ .gl-display-flex.gl-align-items-center
+ %h4.gl-display-flex
+ = s_('GroupsNew|Import groups from another instance of GitLab')
+ = link_to _('History'), history_import_bulk_imports_path, class: 'gl-link gl-ml-auto'
.gl-alert.gl-alert-warning{ role: 'alert' }
= sprite_icon('warning', css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md') }
- - feedback_link_start = '<a href="https://gitlab.com/gitlab-org/gitlab/-/issues/284495" target="_blank" rel="noopener noreferrer">'.html_safe
- - link_end = '</a>'.html_safe
- = s_('GroupsNew|Not all related objects are migrated, as %{docs_link_start}described here%{docs_link_end}. Please %{feedback_link_start}leave feedback%{feedback_link_end} on this feature.').html_safe % { docs_link_start: docs_link_start, docs_link_end: link_end, feedback_link_start: feedback_link_start, feedback_link_end: link_end }
+ - docs_link_end = '</a>'.html_safe
+ = s_('GroupsNew|Not all related objects are migrated. %{docs_link_start}More info%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: docs_link_end }
%p.gl-mt-3
= s_('GroupsNew|Provide credentials for another instance of GitLab to import your groups directly.')
.form-group.gl-display-flex.gl-flex-direction-column
diff --git a/app/views/groups/dependency_proxies/_url.html.haml b/app/views/groups/dependency_proxies/_url.html.haml
deleted file mode 100644
index 9a76da63a72..00000000000
--- a/app/views/groups/dependency_proxies/_url.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-- proxy_url = @group.dependency_proxy_image_prefix
-
-%h5.prepend-top-20= _('Dependency proxy image prefix')
-
-.row
- .col-lg-8.col-md-12.input-group
- = text_field_tag :url, "#{proxy_url}", class: 'js-dependency-proxy-url form-control', readonly: true
- = clipboard_button(text: "#{proxy_url}", title: _("Copy %{proxy_url}") % { proxy_url: proxy_url })
-
-.row
- .col-12.help-block.gl-mt-3{ data: { qa_selector: 'dependency_proxy_count' } }
- = _('Contains %{count} blobs of images (%{size})') % { count: @blobs_count, size: number_to_human_size(@blobs_total_size) }
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
index 177018af830..8936c4dcbb4 100644
--- a/app/views/groups/dependency_proxies/show.html.haml
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -1,30 +1,5 @@
- page_title _("Dependency Proxy")
+- dependency_proxy_available = Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public?
-.settings-header
- %h4= _('Dependency proxy')
-
- %p
- - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('user/packages/dependency_proxy/index') }
- = _('Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
-
-- if Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public?
- - if can?(current_user, :admin_dependency_proxy, @group)
- = form_for(@dependency_proxy, method: :put, url: group_dependency_proxy_path(@group)) do |f|
- .form-group
- %h5.prepend-top-20= _('Enable proxy')
- .js-dependency-proxy-toggle-area
- = render "shared/buttons/project_feature_toggle", is_checked: @dependency_proxy.enabled?, label: s_("DependencyProxy|Toggle Dependency Proxy"), data: { qa_selector: 'dependency_proxy_setting_toggle' } do
- = f.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
-
- - if @dependency_proxy.enabled
- = render 'groups/dependency_proxies/url'
-
- - else
- - if @dependency_proxy.enabled
- = render 'groups/dependency_proxies/url'
-- else
- .gl-alert.gl-alert-info
- .gl-alert-container
- = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-content
- = _('Dependency proxy feature is limited to public groups for now.')
+#js-dependency-proxy{ data: { group_path: @group.full_path,
+ dependency_proxy_available: dependency_proxy_available.to_s } }
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 6e355d31204..420771257c9 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -1,5 +1,5 @@
-- breadcrumb_title _("General Settings")
-- page_title _("General Settings")
+- breadcrumb_title _("General settings")
+- page_title _("General settings")
- @content_class = "limit-container-width" unless fluid_layout
- expanded = expanded_by_default?
@@ -13,6 +13,7 @@
= _('Collapse')
%p
= _('Update your group name, description, avatar, and visibility.')
+ = link_to s_('Learn more about groups.'), help_page_path('user/group/index')
.settings-content
= render 'groups/settings/general'
@@ -23,7 +24,7 @@
%button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _('Advanced permissions, Large File Storage and Two-Factor authentication settings.')
+ = _('Configure advanced permissions, Large File Storage, and two-factor authentication settings.')
.settings-content
= render 'groups/settings/permissions'
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 1f746484b7d..0c6776a6038 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -6,7 +6,7 @@
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@group.name} issues")
- if Feature.enabled?(:vue_issues_list, @group, default_enabled: :yaml)
- .js-issues-list{ data: group_issues_list_data(@group, current_user, @issues) }
+ .js-issues-list{ data: group_issues_list_data(@group, current_user, @issues, @projects) }
- if @can_bulk_update
= render_if_exists 'shared/issuable/group_bulk_update_sidebar', group: @group, type: :issues
- else
diff --git a/app/views/groups/registry/repositories/index.html.haml b/app/views/groups/registry/repositories/index.html.haml
index fa6bd021e45..2901c8fa46b 100644
--- a/app/views/groups/registry/repositories/index.html.haml
+++ b/app/views/groups/registry/repositories/index.html.haml
@@ -16,7 +16,8 @@
is_group_page: "true",
"group_path": @group.full_path,
"gid_prefix": container_repository_gid_prefix,
- character_error: @character_error.to_s,
+ connection_error: (!!@connection_error).to_s,
+ invalid_path_error: (!!@invalid_path_error).to_s,
user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s } }
diff --git a/app/views/groups/runners/_runner.html.haml b/app/views/groups/runners/_runner.html.haml
index 66ffef98553..a76701ea5d2 100644
--- a/app/views/groups/runners/_runner.html.haml
+++ b/app/views/groups/runners/_runner.html.haml
@@ -39,7 +39,7 @@
- if runner.group_type?
= _('n/a')
- else
- = runner.projects.count(:all)
+ = runner.runner_projects.count(:all)
.table-section.section-5
.table-mobile-header{ role: 'rowheader' }= _('Jobs')
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index 7a2d5c91af6..ed76a9fe253 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -14,8 +14,9 @@
.row.gl-mt-3
.form-group.col-md-9
- = f.label :description, _('Group description (optional)'), class: 'label-bold'
+ = f.label :description, _('Group description'), class: 'label-bold'
= f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
+ .form-text.text-muted= _('Optional.')
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
diff --git a/app/views/groups/settings/_lfs.html.haml b/app/views/groups/settings/_lfs.html.haml
index 1255a2901ea..9f04b579a97 100644
--- a/app/views/groups/settings/_lfs.html.haml
+++ b/app/views/groups/settings/_lfs.html.haml
@@ -3,10 +3,10 @@
%h5= _('Large File Storage')
-%p= s_('Check the %{docs_link_start}documentation%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+%p= s_('%{docs_link_start}What is Large File Storage?%{docs_link_end}').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
.form-group.gl-mb-3
= f.gitlab_ui_checkbox_component :lfs_enabled,
_('Allow projects within this group to use Git LFS'),
- help_text: _('This setting can be overridden in each project.'),
+ help_text: _('Can be overridden in each project.'),
checkbox_options: { checked: @group.lfs_enabled?, data: { qa_selector: 'lfs_checkbox' } }
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index 8f428909e60..eb38aa43881 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -7,7 +7,7 @@
- if @group.root?
.form-group.gl-mb-3
= f.gitlab_ui_checkbox_component :prevent_sharing_groups_outside_hierarchy,
- s_('GroupSettings|Prevent members from sending invitations to groups outside of %{group} and its subgroups.').html_safe % { group: link_to_group(@group) },
+ s_('GroupSettings|Prevent members from sending invitations to groups outside of %{group} and its subgroups').html_safe % { group: link_to_group(@group) },
help_text: prevent_sharing_groups_outside_hierarchy_help_text(@group),
checkbox_options: { disabled: !can_change_prevent_sharing_groups_outside_hierarchy?(@group) }
@@ -21,13 +21,13 @@
= f.gitlab_ui_checkbox_component :emails_disabled,
s_('GroupSettings|Disable email notifications'),
checkbox_options: { checked: @group.emails_disabled?, disabled: !can_disable_group_emails?(@group) },
- help_text: s_('GroupSettings|This setting will override user notification preferences for all members of the group, subgroups, and projects.')
+ help_text: s_('GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects.')
.form-group.gl-mb-3
= f.gitlab_ui_checkbox_component :mentions_disabled,
s_('GroupSettings|Disable group mentions'),
checkbox_options: { checked: @group.mentions_disabled? },
- help_text: s_('GroupSettings|This setting will prevent group members from being notified if the group is mentioned.')
+ help_text: s_('GroupSettings|Prevents group members from being notified if the group is mentioned.')
= render 'groups/settings/project_access_token_creation', f: f, group: @group
= render_if_exists 'groups/settings/delayed_project_removal', f: f, group: @group
diff --git a/app/views/groups/settings/_two_factor_auth.html.haml b/app/views/groups/settings/_two_factor_auth.html.haml
index 8204cafcb44..f86bcb24e63 100644
--- a/app/views/groups/settings/_two_factor_auth.html.haml
+++ b/app/views/groups/settings/_two_factor_auth.html.haml
@@ -4,16 +4,16 @@
%h5= _('Two-factor authentication')
-%p= s_('Check the %{docs_link_start}documentation%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+%p= s_('%{docs_link_start}What is two-factor authentication?%{docs_link_end}').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
.form-group
= f.gitlab_ui_checkbox_component :require_two_factor_authentication,
- _('Require all users in this group to setup two-factor authentication'),
+ _('Require all users in this group to set up two-factor authentication'),
checkbox_options: { data: { qa_selector: 'require_2fa_checkbox' } }
.form-group
- = f.label :two_factor_grace_period, _('Time before enforced'), class: 'label-bold'
- = f.text_field :two_factor_grace_period, class: 'form-control form-control-sm w-auto'
- .form-text.text-muted= _('Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication')
+ = f.label :two_factor_grace_period, _('Time before enforced')
+ = f.text_field :two_factor_grace_period, class: 'form-control form-control-sm w-auto gl-form-input gl-mb-3'
+ .form-text.text-muted= _('Time (in hours) that users are allowed to skip forced configuration of two-factor authentication.')
- unless group.has_parent?
.form-group
= f.gitlab_ui_checkbox_component :allow_mfa_for_subgroups,
diff --git a/app/views/groups/settings/packages_and_registries/show.html.haml b/app/views/groups/settings/packages_and_registries/show.html.haml
index 1a12ad4902b..7be6dc73c49 100644
--- a/app/views/groups/settings/packages_and_registries/show.html.haml
+++ b/app/views/groups/settings/packages_and_registries/show.html.haml
@@ -1,5 +1,8 @@
- breadcrumb_title _('Packages & Registries')
- page_title _('Packages & Registries')
- @content_class = 'limit-container-width' unless fluid_layout
+- dependency_proxy_available = Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public?
-%section#js-packages-and-registries-settings{ data: { default_expanded: expanded_by_default?.to_s, group_path: @group.full_path } }
+%section#js-packages-and-registries-settings{ data: { default_expanded: expanded_by_default?.to_s,
+ group_path: @group.full_path,
+ dependency_proxy_available: dependency_proxy_available.to_s } }
diff --git a/app/views/help/instance_configuration/_gitlab_pages.html.haml b/app/views/help/instance_configuration/_gitlab_pages.html.haml
index 51835c202d6..1d8958c93e8 100644
--- a/app/views/help/instance_configuration/_gitlab_pages.html.haml
+++ b/app/views/help/instance_configuration/_gitlab_pages.html.haml
@@ -7,7 +7,7 @@
= _('GitLab Pages')
%p
- - link_to_gitlab_pages = link_to(_('GitLab Pages'), gitlab_pages[:url], target: '_blank')
+ - link_to_gitlab_pages = link_to(_('GitLab Pages'), gitlab_pages[:url], target: '_blank', rel: 'noopener noreferrer')
= _('Below are the settings for %{link_to_gitlab_pages}.').html_safe % { link_to_gitlab_pages: link_to_gitlab_pages }
.table-responsive
%table
diff --git a/app/views/help/instance_configuration/_rate_limits.html.haml b/app/views/help/instance_configuration/_rate_limits.html.haml
index d72bd845c5b..ed71b5a609c 100644
--- a/app/views/help/instance_configuration/_rate_limits.html.haml
+++ b/app/views/help/instance_configuration/_rate_limits.html.haml
@@ -24,6 +24,7 @@
= render 'help/instance_configuration/rate_limit_row', title: _('Protected Paths: requests'), rate_limit: rate_limits[:protected_paths]
= render 'help/instance_configuration/rate_limit_row', title: _('Package Registry: unauthenticated API requests'), rate_limit: rate_limits[:unauthenticated_packages_api], public_visible: true
= render 'help/instance_configuration/rate_limit_row', title: _('Package Registry: authenticated API requests'), rate_limit: rate_limits[:authenticated_packages_api]
+ = render 'help/instance_configuration/rate_limit_row', title: _('Authenticated Git LFS requests'), rate_limit: rate_limits[:authenticated_git_lfs_api]
= render 'help/instance_configuration/rate_limit_row', title: _('Issue creation requests'), rate_limit: rate_limits[:issue_creation]
= render 'help/instance_configuration/rate_limit_row', title: _('Note creation requests'), rate_limit: rate_limits[:note_creation]
= render 'help/instance_configuration/rate_limit_row', title: _('Project export requests'), rate_limit: rate_limits[:project_export]
diff --git a/app/views/import/_githubish_status.html.haml b/app/views/import/_githubish_status.html.haml
index 02a8f3142c6..8f18d68fd55 100644
--- a/app/views/import/_githubish_status.html.haml
+++ b/app/views/import/_githubish_status.html.haml
@@ -6,7 +6,7 @@
- provider_title = Gitlab::ImportSources.title(provider)
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
#import-projects-mount-element{ data: { provider: provider, provider_title: provider_title,
can_select_namespace: current_user.can_select_namespace?.to_s,
diff --git a/app/views/import/bitbucket_server/new.html.haml b/app/views/import/bitbucket_server/new.html.haml
index ce6bdd7a2fb..721447186a6 100644
--- a/app/views/import/bitbucket_server/new.html.haml
+++ b/app/views/import/bitbucket_server/new.html.haml
@@ -1,6 +1,6 @@
- page_title _('Bitbucket Server Import')
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/import/bulk_imports/history.html.haml b/app/views/import/bulk_imports/history.html.haml
new file mode 100644
index 00000000000..80eb0c7a764
--- /dev/null
+++ b/app/views/import/bulk_imports/history.html.haml
@@ -0,0 +1,6 @@
+- add_to_breadcrumbs _('New group'), new_group_path
+- add_to_breadcrumbs _('Import group'), new_group_path(anchor: 'import-group-pane')
+- add_page_specific_style 'page_bundles/import'
+- page_title _('Import history')
+
+#import-history-mount-element
diff --git a/app/views/import/fogbugz/new.html.haml b/app/views/import/fogbugz/new.html.haml
index 51156797270..d716d08529c 100644
--- a/app/views/import/fogbugz/new.html.haml
+++ b/app/views/import/fogbugz/new.html.haml
@@ -1,6 +1,6 @@
- page_title _("FogBugz Import")
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml
index 4281d77e833..93572e14a65 100644
--- a/app/views/import/fogbugz/new_user_map.html.haml
+++ b/app/views/import/fogbugz/new_user_map.html.haml
@@ -1,6 +1,6 @@
- page_title _('User map'), _('FogBugz import')
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/import/gitea/new.html.haml b/app/views/import/gitea/new.html.haml
index 288ae5f1cec..de717ce87eb 100644
--- a/app/views/import/gitea/new.html.haml
+++ b/app/views/import/gitea/new.html.haml
@@ -1,6 +1,6 @@
- page_title _("Gitea Import")
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
%h3.page-title
= custom_icon('gitea_logo')
diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml
index 3407f9202bf..3f7f929f766 100644
--- a/app/views/import/github/new.html.haml
+++ b/app/views/import/github/new.html.haml
@@ -1,7 +1,7 @@
- title = _('Authenticate with GitHub')
- page_title title
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
%h3.page-title
= title
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index 028268482cd..533d0d13be3 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -1,6 +1,6 @@
- page_title _("GitLab Import")
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/import/manifest/new.html.haml b/app/views/import/manifest/new.html.haml
index bfaff3bb300..a949e14e273 100644
--- a/app/views/import/manifest/new.html.haml
+++ b/app/views/import/manifest/new.html.haml
@@ -1,6 +1,6 @@
- page_title _("Manifest file import")
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
%h3.page-title
diff --git a/app/views/import/phabricator/new.html.haml b/app/views/import/phabricator/new.html.haml
index 9596fdb615a..0249dc446e4 100644
--- a/app/views/import/phabricator/new.html.haml
+++ b/app/views/import/phabricator/new.html.haml
@@ -1,6 +1,6 @@
- page_title _('Phabricator Server Import')
- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_projects_path(anchor: 'import_project')
+- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
%h3.page-title.d-flex
.gl-display-flex.gl-align-items-center.gl-justify-content-center
diff --git a/app/views/layouts/_one_trust.html.haml b/app/views/layouts/_one_trust.html.haml
new file mode 100644
index 00000000000..4fab017d273
--- /dev/null
+++ b/app/views/layouts/_one_trust.html.haml
@@ -0,0 +1,16 @@
+- if one_trust_enabled?
+ - one_trust_id = sanitize(extra_config.one_trust_id, scrubber: Rails::Html::TextOnlyScrubber.new)
+
+ <!-- OneTrust -->
+ = javascript_include_tag "https://cdn.cookielaw.org/consent/#{one_trust_id}/OtAutoBlock.js"
+ = javascript_tag nonce: content_security_policy_nonce do
+ :plain
+ const oneTrustScript = document.createElement('script');
+ oneTrustScript.src = 'https://cdn.cookielaw.org/scripttemplates/otSDKStub.js';
+ oneTrustScript.dataset.domainScript = '#{one_trust_id}';
+ oneTrustScript.nonce = '#{content_security_policy_nonce}'
+ oneTrustScript.charset = 'UTF-8';
+ oneTrustScript.defer = true;
+ document.head.appendChild(oneTrustScript);
+
+ function OptanonWrapper() { }
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index ec2904245d3..dff1b5e3d04 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -17,6 +17,7 @@
= render_two_factor_auth_recovery_settings_check
= render_if_exists "layouts/header/ee_subscribable_banner"
= render_if_exists "shared/namespace_storage_limit_alert"
+ = render_if_exists "shared/namespace_user_cap_reached_alert"
= render_if_exists "shared/new_user_signups_cap_reached_alert"
= yield :page_level_alert
= yield :customize_homepage_banner
diff --git a/app/views/layouts/_startup_js.html.haml b/app/views/layouts/_startup_js.html.haml
index 35cd191c600..0bf9c16b0d2 100644
--- a/app/views/layouts/_startup_js.html.haml
+++ b/app/views/layouts/_startup_js.html.haml
@@ -8,20 +8,30 @@
if (gl.startup_calls && window.fetch) {
Object.keys(gl.startup_calls).forEach(apiCall => {
- // fetch won’t send cookies in older browsers, unless you set the credentials init option.
- // We set to `same-origin` which is default value in modern browsers.
- // See https://github.com/whatwg/fetch/pull/585 for more information.
- gl.startup_calls[apiCall] = {
- fetchCall: fetch(apiCall, { credentials: 'same-origin' })
+ gl.startup_calls[apiCall] = {
+ fetchCall: fetch(apiCall, {
+ // Emulate XHR for Rails AJAX request checks
+ headers: {
+ 'X-Requested-With': 'XMLHttpRequest'
+ },
+ // fetch won’t send cookies in older browsers, unless you set the credentials init option.
+ // We set to `same-origin` which is default value in modern browsers.
+ // See https://github.com/whatwg/fetch/pull/585 for more information.
+ credentials: 'same-origin'
+ })
};
});
}
if (gl.startup_graphql_calls && window.fetch) {
+ const headers = #{page_startup_graphql_headers.to_json};
const url = `#{api_graphql_url}`
const opts = {
method: "POST",
- headers: { "Content-Type": "application/json", 'X-CSRF-Token': "#{form_authenticity_token}" },
+ headers: {
+ "Content-Type": "application/json",
+ ...headers,
+ }
};
gl.startup_graphql_calls = gl.startup_graphql_calls.map(call => ({
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 3e7155b2c0e..8d28823bfa4 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -34,7 +34,8 @@
#js-header-search.header-search{ data: { 'search-context' => search_context.to_json,
'search-path' => search_path,
'issues-path' => issues_dashboard_path,
- 'mr-path' => merge_requests_dashboard_path } }
+ 'mr-path' => merge_requests_dashboard_path,
+ 'autocomplete-path' => search_autocomplete_path } }
%input{ type: "text", placeholder: _('Search or jump to...'), class: 'form-control gl-form-input' }
- else
= render 'layouts/search'
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index c111714f552..02a37dac158 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -19,8 +19,9 @@
= render "layouts/nav/breadcrumbs/collapsed_dropdown", location: :after
- unless @skip_current_level_breadcrumb
%li
- %h2.breadcrumbs-sub-title
+ %h2.breadcrumbs-sub-title{ data: { qa_selector: 'breadcrumb_sub_title_content' } }
= link_to @breadcrumb_title, breadcrumb_title_link
+ -# haml-lint:disable InlineJavaScript
%script{ type: 'application/ld+json' }
:plain
#{schema_breadcrumb_json}
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index d0b73a3364a..842fb23d24a 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -1,13 +1,13 @@
%aside.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), 'aria-label': _('Admin navigation') }
.nav-sidebar-inner-scroll
.context-header
- = link_to admin_root_path, title: _('Admin Overview') do
+ = link_to admin_root_path, title: _('Admin Overview'), class: 'has-tooltip', data: { container: 'body', placement: 'right' } do
%span{ class: ['avatar-container', 'settings-avatar', 'rect-avatar', 's32'] }
= sprite_icon('admin', size: 18)
%span.sidebar-context-title
= _('Admin Area')
%ul.sidebar-top-level-items{ data: { qa_selector: 'admin_sidebar_overview_submenu_content' } }
- = nav_link(controller: %w(dashboard admin admin/projects users groups jobs runners gitaly_servers cohorts), html_options: {class: 'home'}) do
+ = nav_link(controller: %w(dashboard admin admin/projects users groups admin/topics jobs runners gitaly_servers cohorts), html_options: {class: 'home'}) do
= link_to admin_root_path, class: 'has-sub-items' do
.nav-icon-container
= sprite_icon('overview')
@@ -35,6 +35,10 @@
= link_to admin_groups_path, title: _('Groups'), data: { qa_selector: 'groups_overview_link' } do
%span
= _('Groups')
+ = nav_link(controller: [:admin, 'admin/topics']) do
+ = link_to admin_topics_path, title: _('Topics'), data: { qa_selector: 'topics_overview_link' } do
+ %span
+ = _('Topics')
= nav_link path: 'jobs#index' do
= link_to admin_jobs_path, title: _('Jobs') do
%span
@@ -257,11 +261,6 @@
= link_to ci_cd_admin_application_settings_path, title: _('CI/CD') do
%span
= _('CI/CD')
- - if Feature.enabled?(:serverless_domain)
- = nav_link(path: 'application_settings#operations') do
- = link_to admin_serverless_domains_path, title: _('Operations') do
- %span
- = _('Operations')
= nav_link(path: 'application_settings#reporting') do
= link_to reporting_admin_application_settings_path, title: _('Reporting') do
%span
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 4db1e532ba5..16c0c00ad3f 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -1,7 +1,7 @@
%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(current_user), 'aria-label': _('User settings') }
.nav-sidebar-inner-scroll
.context-header
- = link_to profile_path, title: _('Profile Settings') do
+ = link_to profile_path, title: _('Profile Settings'), class: 'has-tooltip', data: { container: 'body', placement: 'right' } do
%span{ class: ['avatar-container', 'settings-avatar', 's32'] }
= image_tag avatar_icon_for_user(current_user, 32), class: ['avatar', 'avatar-tile', 'js-sidebar-user-avatar', 's32'], alt: current_user.name, data: { testid: 'sidebar-user-avatar' }
%span.sidebar-context-title= _('User Settings')
diff --git a/app/views/profiles/_email_settings.html.haml b/app/views/profiles/_email_settings.html.haml
index bc678c2c429..1057e96f442 100644
--- a/app/views/profiles/_email_settings.html.haml
+++ b/app/views/profiles/_email_settings.html.haml
@@ -3,8 +3,11 @@
- email_change_disabled = local_assigns.fetch(:email_change_disabled, nil)
- read_only_help_text = readonly ? s_("Profiles|Your email address was automatically set based on your %{provider_label} account") % { provider_label: attribute_provider_label(:email) } : user_email_help_text(@user)
- help_text = email_change_disabled ? s_("Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO.") % { group_name: @user.managing_group.name } : read_only_help_text
+- password_automatically_set = @user.password_automatically_set?
= form.text_field :email, required: true, class: 'input-lg gl-form-input', value: (@user.email unless @user.temp_oauth_email?), help: help_text.html_safe, readonly: readonly || email_change_disabled
+- unless password_automatically_set
+ = hidden_field_tag 'user[validation_password]', :validation_password, class: 'js-password-prompt-field', help: s_("Profiles|Enter your password to confirm the email change")
= form.select :public_email, options_for_select(@user.public_verified_emails, selected: @user.public_email),
{ help: s_("Profiles|This email will be displayed on your public profile"), include_blank: s_("Profiles|Do not show on profile") },
control_class: 'select2 input-lg', disabled: email_change_disabled
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index 2cc919fc70e..5d3e0720176 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -19,16 +19,16 @@
- unless @user.password_automatically_set?
.form-group
- = f.label :current_password, _('Current password'), class: 'label-bold'
- = f.password_field :current_password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
+ = f.label :password, _('Current password'), class: 'label-bold'
+ = f.password_field :password, required: true, autocomplete: 'current-password', class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
%p.form-text.text-muted
= _('You must provide your current password in order to change it.')
.form-group
- = f.label :password, _('New password'), class: 'label-bold'
- = f.password_field :password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' }
+ = f.label :new_password, _('New password'), class: 'label-bold'
+ = f.password_field :new_password, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' }
.form-group
= f.label :password_confirmation, _('Password confirmation'), class: 'label-bold'
- = f.password_field :password_confirmation, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' }
+ = f.password_field :password_confirmation, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' }
.gl-mt-3.gl-mb-3
= f.submit _('Save password'), class: "gl-button btn btn-confirm gl-mr-3", data: { qa_selector: 'save_password_button' }
- unless @user.password_automatically_set?
diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml
index 7780ffe0cb4..9154c94abb6 100644
--- a/app/views/profiles/passwords/new.html.haml
+++ b/app/views/profiles/passwords/new.html.haml
@@ -14,18 +14,18 @@
- unless @user.password_automatically_set?
.form-group.row
.col-sm-2.col-form-label
- = f.label :current_password, _('Current password')
+ = f.label :password, _('Current password')
.col-sm-10
- = f.password_field :current_password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
+ = f.password_field :password, required: true, autocomplete: 'current-password', class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
.form-group.row
.col-sm-2.col-form-label
- = f.label :password, _('New password')
+ = f.label :new_password, _('New password')
.col-sm-10
- = f.password_field :password, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' }
+ = f.password_field :new_password, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'new_password_field' }
.form-group.row
.col-sm-2.col-form-label
= f.label :password_confirmation, _('Password confirmation')
.col-sm-10
- = f.password_field :password_confirmation, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' }
+ = f.password_field :password_confirmation, required: true, autocomplete: 'new-password', class: 'form-control gl-form-input', data: { qa_selector: 'confirm_password_field' }
.form-actions
= f.submit _('Set new password'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'set_new_password_button' }
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 0bb4859dd1e..3e41f107e04 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -5,7 +5,7 @@
- availability = availability_values
- custom_emoji = show_status_emoji?(@user.status)
-= bootstrap_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user gl-mt-3 js-quick-submit gl-show-field-errors' }, authenticity_token: true do |f|
+= bootstrap_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user gl-mt-3 js-quick-submit gl-show-field-errors js-password-prompt-form', remote: true }, authenticity_token: true do |f|
= form_errors(@user)
.row.js-search-settings-section
@@ -80,7 +80,7 @@
%p= s_("Profiles|Set your local time zone")
.col-lg-8
%h5= _("Time zone")
- = dropdown_tag(_("Select a time zone"), options: { toggle_class: 'gl-button btn js-timezone-dropdown input-lg', title: _("Select a time zone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
+ = dropdown_tag(_("Select a time zone"), options: { toggle_class: 'gl-button btn js-timezone-dropdown input-lg gl-w-full!', title: _("Select a time zone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
%input.hidden{ :type => 'hidden', :id => 'user_timezone', :name => 'user[timezone]', value: @user.timezone }
.col-lg-12
%hr
@@ -124,9 +124,11 @@
.help-block
= s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information")
%hr
- = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-confirm gl-mr-3'
+ = f.submit s_("Profiles|Update profile settings"), class: 'gl-button btn btn-confirm gl-mr-3 js-password-prompt-btn'
= link_to _("Cancel"), user_path(current_user), class: 'gl-button btn btn-default btn-cancel'
+#password-prompt-modal
+
.modal.modal-profile-crop{ data: { cropper_css_path: ActionController::Base.helpers.stylesheet_path('lazy_bundles/cropper.css') } }
.modal-dialog
.modal-content
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index bd3cb7e60f0..00df8608957 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -50,7 +50,7 @@
- if current_password_required?
.form-group
= label_tag :current_password, _('Current password'), class: 'label-bold'
- = password_field_tag :current_password, nil, required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
+ = password_field_tag :current_password, nil, autocomplete: 'current-password', required: true, class: 'form-control gl-form-input', data: { qa_selector: 'current_password_field' }
%p.form-text.text-muted
= _('Your current password is required to register a two-factor authenticator app.')
.gl-mt-3
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index 597a22bf34a..cdcc98552f9 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -20,5 +20,6 @@
= render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout), project_buttons: true
#js-tree-list{ data: vue_file_list_data(project, ref) }
- - if can_edit_tree?
+ - if !Feature.enabled?(:new_dir_modal, default_enabled: :yaml) && can_edit_tree?
= render 'projects/blob/new_dir'
+
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index f2cee618849..1f2c16324fb 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -45,11 +45,10 @@
- if can?(current_user, :download_code, @project)
= cache_if(cache_enabled, [@project, :download_code], expires_in: 1.minute) do
%nav.project-stats
- .nav-links.quick-links
- - if @project.empty_repo?
- = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_anchors
- - else
- = render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
+ - if @project.empty_repo?
+ = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_anchors
+ - else
+ = render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
.home-panel-home-desc.mt-1
- if @project.description.present?
diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml
index 815a3cf6966..81d9726fcdc 100644
--- a/app/views/projects/_import_project_pane.html.haml
+++ b/app/views/projects/_import_project_pane.html.haml
@@ -83,7 +83,7 @@
.js-toggle-content.toggle-import-form{ class: ('hide' if active_tab != 'import') }
- = form_for @project, html: { class: 'new_project' } do |f|
+ = form_for @project, html: { class: 'new_project gl-show-field-errors' } do |f|
%hr
= render "shared/import_form", f: f
= render 'projects/new_project_fields', f: f, project_name_id: "import-url-name", hide_init_with_readme: true, track_label: track_label
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index fb7a7ef8985..256c3ebad0a 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -16,7 +16,12 @@
- if current_user.can_select_namespace?
- namespace_id = namespace_id_from(params)
- if Feature.enabled?(:paginatable_namespace_drop_down_for_project_creation, current_user, default_enabled: :yaml)
- .js-vue-new-project-url-select{ data: { namespace_full_path: GroupFinder.new(current_user).execute(id: namespace_id)&.full_path, namespace_id: namespace_id, root_url: root_url, track_label: track_label } }
+ .js-vue-new-project-url-select{ data: { namespace_full_path: GroupFinder.new(current_user).execute(id: namespace_id)&.full_path,
+ namespace_id: namespace_id,
+ root_url: root_url,
+ track_label: track_label,
+ user_namespace_full_path: current_user.namespace.full_path,
+ user_namespace_id: current_user.namespace.id } }
- else
.input-group-prepend.flex-shrink-0.has-tooltip{ title: root_url }
.input-group-text
@@ -53,15 +58,36 @@
= render 'shared/visibility_level', f: f, visibility_level: visibility_level.to_i, can_change_visibility_level: true, form_model: @project, with_label: false
- if !hide_init_with_readme
- .form-group.row.initialize-with-readme-setting
- %div{ :class => "col-sm-12" }
- .form-check
- = check_box_tag 'project[initialize_with_readme]', '1', true, class: 'form-check-input', data: { qa_selector: "initialize_with_readme_checkbox", track_label: "#{track_label}", track_action: "activate_form_input", track_property: "init_with_readme", track_value: "" }
- = label_tag 'project[initialize_with_readme]', class: 'form-check-label' do
- .option-title
- %strong= s_('ProjectsNew|Initialize repository with a README')
- .option-description
- = s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
+ = f.label :project_configuration, class: 'label-bold' do
+ = s_('ProjectsNew|Project Configuration')
+
+ .form-group
+ .form-check.gl-mb-3
+ = check_box_tag 'project[initialize_with_readme]', '1', true, class: 'form-check-input', data: { qa_selector: 'initialize_with_readme_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_readme' }
+ = label_tag 'project[initialize_with_readme]', s_('ProjectsNew|Initialize repository with a README'), class: 'form-check-label'
+ .form-text.text-muted
+ = s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
+
+ - experiment(:new_project_sast_enabled, user: current_user) do |e|
+ - e.try do
+ .form-group
+ .form-check.gl-mb-3
+ = check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
+ = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
+ = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
+ .form-text.text-muted
+ = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
+ = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
+ - e.try(:free_indicator) do
+ .form-group
+ .form-check.gl-mb-3
+ = check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
+ = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
+ = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
+ %span.badge.badge-info.badge-pill.gl-badge.sm= _('Free')
+ .form-text.text-muted
+ = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
+ = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
= f.submit _('Create project'), class: "btn gl-button btn-confirm", data: { track_label: "#{track_label}", track_action: "click_button", track_property: "create_project", track_value: "" }
= link_to _('Cancel'), dashboard_projects_path, class: 'btn gl-button btn-default btn-cancel', data: { track_label: "#{track_label}", track_action: "click_button", track_property: "cancel", track_value: "" }
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index 66e9badbafb..168b240c657 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -18,3 +18,4 @@
= render 'projects/blob/upload', title: title, placeholder: title, button_title: 'Replace file', form_path: project_update_blob_path(@project, @id), method: :put
= render partial: 'pipeline_tour_success' if show_suggest_pipeline_creation_celebration?
+= render 'shared/web_ide_path'
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index b1d465d0e75..6733db69c34 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -1,19 +1,12 @@
- page_title _('Branches')
- add_to_breadcrumbs(_('Repository'), project_tree_path(@project))
-.top-area.adjust
- %ul.nav-links.issues-state-filters.nav.nav-tabs
- %li{ class: active_when(@mode == 'overview') }>
- = link_to s_('Branches|Overview'), project_branches_path(@project), title: s_('Branches|Show overview of the branches')
-
- %li{ class: active_when(@mode == 'active') }>
- = link_to s_('Branches|Active'), project_branches_filtered_path(@project, state: 'active'), title: s_('Branches|Show active branches')
-
- %li{ class: active_when(@mode == 'stale') }>
- = link_to s_('Branches|Stale'), project_branches_filtered_path(@project, state: 'stale'), title: s_('Branches|Show stale branches')
-
- %li{ class: active_when(!%w[overview active stale].include?(@mode)) }>
- = link_to s_('Branches|All'), project_branches_filtered_path(@project, state: 'all'), title: s_('Branches|Show all branches')
+.top-area.gl-border-0
+ = gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-b-0' }) do
+ = gl_tab_link_to s_('Branches|Overview'), project_branches_path(@project), { item_active: @mode == 'overview', title: s_('Branches|Show overview of the branches') }
+ = gl_tab_link_to s_('Branches|Active'), project_branches_filtered_path(@project, state: 'active'), { title: s_('Branches|Show active branches') }
+ = gl_tab_link_to s_('Branches|Stale'), project_branches_filtered_path(@project, state: 'stale'), { title: s_('Branches|Show stale branches') }
+ = gl_tab_link_to s_('Branches|All'), project_branches_filtered_path(@project, state: 'all'), { item_active: !%w[overview active stale].include?(@mode), title: s_('Branches|Show all branches') }
.nav-controls
#js-branches-sort-dropdown{ data: { project_branches_filtered_path: project_branches_path(@project, state: 'all'), sort_options: branches_sort_options_hash.to_json, mode: @mode } }
@@ -38,7 +31,10 @@
%h5
= s_('Branches|Protected branches can be managed in %{project_settings_link}.').html_safe % { project_settings_link: project_settings_link }
-- if @mode == 'overview' && (@active_branches.any? || @stale_branches.any?)
+- if @gitaly_unavailable
+ = render 'shared/errors/gitaly_unavailable', reason: s_('Branches|Unable to load branches')
+
+- elsif @mode == 'overview' && (@active_branches.any? || @stale_branches.any?)
= render "projects/branches/panel", branches: @active_branches, state: 'active', panel_title: s_('Branches|Active branches'), show_more_text: s_('Branches|Show more active branches'), project: @project, overview_max_branches: @overview_max_branches
= render "projects/branches/panel", branches: @stale_branches, state: 'stale', panel_title: s_('Branches|Stale branches'), show_more_text: s_('Branches|Show more stale branches'), project: @project, overview_max_branches: @overview_max_branches
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 27858932e5e..8ee7910de4b 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -31,4 +31,5 @@
.form-actions
= button_tag 'Create branch', class: 'gl-button btn btn-confirm'
= link_to _('Cancel'), project_branches_path(@project), class: 'gl-button btn btn-default btn-cancel'
+-# haml-lint:disable InlineJavaScript
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
diff --git a/app/views/projects/ci/pipeline_editor/show.html.haml b/app/views/projects/ci/pipeline_editor/show.html.haml
index 674765e9f89..ce6f7553ab4 100644
--- a/app/views/projects/ci/pipeline_editor/show.html.haml
+++ b/app/views/projects/ci/pipeline_editor/show.html.haml
@@ -1,3 +1,5 @@
+- add_page_specific_style 'page_bundles/pipelines'
+
- page_title s_('Pipelines|Pipeline Editor')
- content_for :prefetch_asset_tags do
- webpack_preload_asset_tag('monaco')
diff --git a/app/views/projects/cluster_agents/show.html.haml b/app/views/projects/cluster_agents/show.html.haml
new file mode 100644
index 00000000000..a2d3426d99c
--- /dev/null
+++ b/app/views/projects/cluster_agents/show.html.haml
@@ -0,0 +1,4 @@
+- add_to_breadcrumbs _('Kubernetes'), project_clusters_path(@project)
+- page_title @agent_name
+
+#js-cluster-agent-details{ data: js_cluster_agent_details_data(@agent_name, @project) }
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index bc0d14743b9..62ed50f5a0c 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -39,8 +39,14 @@
.committer
- commit_author_link = commit_author_link(commit, avatar: false, size: 24)
- - commit_timeago = time_ago_with_tooltip(commit.authored_date, placement: 'bottom')
- - commit_text = _('%{commit_author_link} authored %{commit_timeago}') % { commit_author_link: commit_author_link, commit_timeago: commit_timeago }
+ - commit_authored_timeago = time_ago_with_tooltip(commit.authored_date, placement: 'bottom')
+ - if commit.different_committer? && commit.committer
+ - commit_committer_link = commit_committer_link(commit)
+ - commit_committer_timeago = time_ago_with_tooltip(commit.committed_date, placement: 'bottom')
+ - commit_committer_avatar = commit_committer_avatar(commit.committer, size: 18, has_tooltip: false)
+ - commit_text = _('%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}') % { commit_author_link: commit_author_link, commit_authored_timeago: commit_authored_timeago, commit_committer_avatar: commit_committer_avatar, commit_committer_link: commit_committer_link, commit_committer_timeago: commit_committer_timeago }
+ - else
+ - commit_text = _('%{commit_author_link} authored %{commit_authored_timeago}') % { commit_author_link: commit_author_link, commit_authored_timeago: commit_authored_timeago }
#{ commit_text.html_safe }
= render_if_exists 'projects/commits/project_namespace', show_project_name: show_project_name, project: project
diff --git a/app/views/projects/deployments/_deployment.html.haml b/app/views/projects/deployments/_deployment.html.haml
index 8270477ed3f..57dfcb8cf4a 100644
--- a/app/views/projects/deployments/_deployment.html.haml
+++ b/app/views/projects/deployments/_deployment.html.haml
@@ -27,7 +27,7 @@
= link_to deployment_path(deployment), class: 'build-link' do
#{deployment.deployable.name} (##{deployment.deployable.id})
- else
- .badge.badge-info.suggestion-help-hover{ title: s_('Deployment|This deployment was created using the API') }
+ .badge.badge-info.gl-cursor-help{ title: s_('Deployment|This deployment was created using the API') }
= s_('Deployment|API')
.table-section.section-10{ role: 'gridcell' }
diff --git a/app/views/projects/feature_flags/edit.html.haml b/app/views/projects/feature_flags/edit.html.haml
index c1c9f58265d..ac8c0575077 100644
--- a/app/views/projects/feature_flags/edit.html.haml
+++ b/app/views/projects/feature_flags/edit.html.haml
@@ -4,10 +4,4 @@
- breadcrumb_title @feature_flag.name
- page_title s_('FeatureFlags|Edit Feature Flag')
-#js-edit-feature-flag{ data: { endpoint: project_feature_flag_path(@project, @feature_flag),
- project_id: @project.id,
- feature_flags_path: project_feature_flags_path(@project),
- environments_endpoint: search_project_environments_path(@project, format: :json),
- strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
- environments_scope_docs_path: help_page_path('ci/environments/index.md', anchor: 'scope-environments-with-specs'),
- feature_flag_issues_endpoint: feature_flag_issues_links_endpoint(@project, @feature_flag, current_user) } }
+#js-edit-feature-flag{ data: edit_feature_flag_data }
diff --git a/app/views/projects/google_cloud/index.html.haml b/app/views/projects/google_cloud/index.html.haml
new file mode 100644
index 00000000000..4fc66e17810
--- /dev/null
+++ b/app/views/projects/google_cloud/index.html.haml
@@ -0,0 +1,83 @@
+- breadcrumb_title _('Google Cloud')
+- page_title _('Google Cloud')
+
+- @content_class = "limit-container-width" unless fluid_layout
+
+#js-google-cloud
+
+ %h1.gl-font-size-h1 Google Cloud
+
+ %section#js-section-google-cloud-service-accounts
+
+ %h2.gl-font-size-h2 Service Accounts
+
+ %p= _('Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project.')
+
+ %table.table.b-table.gl-table
+
+ %thead
+ %tr
+ %th Environment
+ %th GCP Project ID
+ %th Service Account Key
+
+ %tbody
+
+ %tr
+ %td *
+ %td serving-salutes-453
+ %td .....
+
+ %tr
+ %td production
+ %td crimson-corey-234
+ %td .....
+
+ %tr
+ %td review/*
+ %td roving-river-379
+ %td .....
+
+ %a.gl-button.btn.btn-primary= _('Add new service account')
+
+ %br
+
+ %section#js-section-google-cloud-deployments
+
+ .row.row-fluid
+
+ .col-lg-4
+ %h2.gl-font-size-h2 Deployments
+ %p= _('Google Cloud offers several deployment targets. Select the one most suitable for your project.')
+ %p
+ = _('Deployments to Google Kubernetes Engine can be ')
+ %a{ href: '#' }= _('managed')
+ = _('in Infrastructure :: Kubernetes clusters')
+
+ .col-lg-8
+
+ %br
+
+ .gl-card.gl-mb-6
+ .gl-card-body
+ .gl-display-flex.gl-align-items-baseline
+ %strong.gl-font-lg App Engine
+ .gl-ml-auto.gl-text-gray-500 Disabled
+ %p= _('App Engine description and apps that are suitable for this deployment target')
+ %button.gl-button.btn.btn-default= _('Configure via Merge Request')
+
+ .gl-card.gl-mb-6
+ .gl-card-body
+ .gl-display-flex.gl-align-items-baseline
+ %strong.gl-font-lg Cloud Functions
+ .gl-ml-auto.gl-text-gray-500 Disabled
+ %p= _('Cloud Functions description and apps that are suitable for this deployment target')
+ %button.gl-button.btn.btn-default= _('Configure via Merge Request')
+
+ .gl-card.gl-mb-6
+ .gl-card-body
+ .gl-display-flex.gl-align-items-baseline
+ %strong.gl-font-lg Cloud Run
+ .gl-ml-auto.gl-text-gray-500 Disabled
+ %p= _('Cloud Run description and apps that are suitable for this deployment target')
+ %button.gl-button.btn.btn-default= _('Configure via Merge Request')
diff --git a/app/views/projects/hook_logs/_index.html.haml b/app/views/projects/hook_logs/_index.html.haml
index ee4dbf5c05c..6a46b0b3510 100644
--- a/app/views/projects/hook_logs/_index.html.haml
+++ b/app/views/projects/hook_logs/_index.html.haml
@@ -1,37 +1,11 @@
-.row.gl-mt-7.gl-mb-3
+- docs_link_url = help_page_path('user/project/integrations/webhooks', anchor: 'troubleshoot-webhooks')
+- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
+- link_end = '</a>'.html_safe
+
+.row.gl-mt-3.gl-mb-3
.col-lg-3
%h4.gl-mt-0
- Recent Deliveries
- %p When an event in GitLab triggers a webhook, you can use the request details to figure out if something went wrong.
+ = _('Recent events')
+ %p= _('GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}').html_safe % { link_start: link_start, link_end: link_end }
.col-lg-9
- - if hook_logs.present?
- %table.table
- %thead
- %tr
- %th Status
- %th Trigger
- %th URL
- %th Elapsed time
- %th Request time
- %th
- - hook_logs.each do |hook_log|
- %tr
- %td
- = render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log }
- %td.d-none.d-sm-block
- %span.badge.badge-gray.deploy-project-label
- = hook_log.trigger.singularize.titleize
- %td
- = truncate(hook_log.url, length: 50)
- %td.light
- #{number_with_precision(hook_log.execution_duration, precision: 2)} sec
- %td.light
- = time_ago_with_tooltip(hook_log.created_at)
- %td
- = link_to 'View details', hook_log.present.details_path
-
- = paginate hook_logs, theme: 'gitlab'
-
- - else
- .settings-message.text-center
- You don't have any webhooks deliveries
+ = render partial: 'shared/hook_logs/recent_deliveries_table', locals: { hook: hook, hook_logs: hook_logs }
diff --git a/app/views/projects/hook_logs/show.html.haml b/app/views/projects/hook_logs/show.html.haml
index ebe179c3454..86dfa1929d6 100644
--- a/app/views/projects/hook_logs/show.html.haml
+++ b/app/views/projects/hook_logs/show.html.haml
@@ -5,8 +5,8 @@
.row.gl-mt-3.gl-mb-3
.col-lg-3
%h4.gl-mt-0
- Request details
+ = _("Request details")
.col-lg-9
- = link_to 'Resend Request', @hook_log.present.retry_path, method: :post, class: "btn gl-button btn-default float-right gl-ml-3"
+ = link_to _('Resend Request'), @hook_log.present.retry_path, method: :post, class: "btn gl-button btn-default float-right gl-ml-3"
= render partial: 'shared/hook_logs/content', locals: { hook_log: @hook_log }
diff --git a/app/views/projects/issues/_nav_btns.html.haml b/app/views/projects/issues/_nav_btns.html.haml
index 0d69f6f69aa..8d16c3d978f 100644
--- a/app/views/projects/issues/_nav_btns.html.haml
+++ b/app/views/projects/issues/_nav_btns.html.haml
@@ -5,11 +5,11 @@
- can_edit = can?(current_user, :admin_project, @project)
- notification_email = @current_user.present? ? @current_user.notification_email_or_default : nil
-.nav-controls.issues-nav-controls
+.nav-controls.issues-nav-controls.gl-font-size-0
- if show_feed_buttons
= render 'shared/issuable/feed_buttons'
- .js-csv-import-export-buttons{ data: { show_export_button: show_export_button.to_s, show_import_button: show_import_button.to_s, issuable_type: issuable_type, issuable_count: issuables_count_for_state(issuable_type.to_sym, params[:state]), email: notification_email, export_csv_path: export_csv_project_issues_path(@project, request.query_parameters), import_csv_issues_path: import_csv_namespace_project_issues_path, container_class: 'gl-mr-3', can_edit: can_edit.to_s, project_import_jira_path: project_import_jira_path(@project) } }
+ .js-csv-import-export-buttons{ data: { show_export_button: show_export_button.to_s, show_import_button: show_import_button.to_s, issuable_type: issuable_type, issuable_count: issuables_count_for_state(issuable_type.to_sym, params[:state]), email: notification_email, export_csv_path: export_csv_project_issues_path(@project, request.query_parameters), import_csv_issues_path: import_csv_namespace_project_issues_path, container_class: 'gl-mr-3', can_edit: can_edit.to_s, project_import_jira_path: project_import_jira_path(@project), max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes) } }
- if @can_bulk_update
= button_tag _("Edit issues"), class: "gl-button btn btn-default gl-mr-3 js-bulk-update-toggle"
@@ -18,4 +18,3 @@
issue: { milestone_id: finder.milestones.first.try(:id) }),
class: "gl-button btn btn-confirm",
id: "new_issue_link"
-
diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml
index 0604e89be6e..c47257eec4a 100644
--- a/app/views/projects/issues/_related_branches.html.haml
+++ b/app/views/projects/issues/_related_branches.html.haml
@@ -1,9 +1,9 @@
- if @related_branches.any?
- %h2.related-branches-title
+ %h2.gl-font-lg
= pluralize(@related_branches.size, 'Related Branch')
%ul.unstyled-list.related-merge-requests
- @related_branches.each do |branch|
- %li
+ %li.gl-display-flex.gl-align-items-center
- if branch[:pipeline_status].present?
%span.related-branch-ci-status
= render 'ci/status/icon', status: branch[:pipeline_status]
diff --git a/app/views/projects/issues/_related_issues.html.haml b/app/views/projects/issues/_related_issues.html.haml
index d131d20f079..bab37609c20 100644
--- a/app/views/projects/issues/_related_issues.html.haml
+++ b/app/views/projects/issues/_related_issues.html.haml
@@ -3,4 +3,3 @@
can_add_related_issues: "#{can?(current_user, :admin_issue_link, @issue)}",
help_path: help_page_path('user/project/issues/related_issues'),
show_categorized_issues: "false" } }
- - render('projects/issues/related_issues_block')
diff --git a/app/views/projects/issues/_related_issues_block.html.haml b/app/views/projects/issues/_related_issues_block.html.haml
deleted file mode 100644
index 8d986b64b1d..00000000000
--- a/app/views/projects/issues/_related_issues_block.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-.related-issues-block
- .card.card-slim
- .card-header.panel-empty-heading.border-bottom-0
- %h3.card-title.mt-0.mb-0.h5
- = _('Linked issues')
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 5a983fb5565..0e8de3c2bb8 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -32,20 +32,20 @@
.dropdown-menu.dropdown-menu-right
%ul
- if can_update_merge_request
- %li= link_to 'Edit', edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
+ %li= link_to _('Edit'), edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)
- if @merge_request.opened?
%li
= link_to @merge_request.work_in_progress? ? _('Mark as ready') : _('Mark as draft'), toggle_draft_merge_request_path(@merge_request), method: :put, class: "js-draft-toggle-button"
%li{ class: [merge_request_button_visibility(@merge_request, true), 'js-close-item'] }
- = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, title: 'Close merge request'
+ = link_to _('Close'), merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, title: 'Close merge request'
- if can_reopen_merge_request
%li{ class: merge_request_button_visibility(@merge_request, false) }
- = link_to 'Reopen', merge_request_path(@merge_request, merge_request: { state_event: :reopen }), method: :put, title: 'Reopen merge request'
+ = link_to _('Reopen'), merge_request_path(@merge_request, merge_request: { state_event: :reopen }), method: :put, title: 'Reopen merge request'
- unless @merge_request.merged? || current_user == @merge_request.author
- %li= link_to 'Report abuse', new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request))
+ %li= link_to _('Report abuse'), new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request))
- if can_update_merge_request
- = link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-md-block btn gl-button btn-default btn-grouped js-issuable-edit", data: { qa_selector: "edit_button" }
+ = link_to _('Edit'), edit_project_merge_request_path(@project, @merge_request), class: "d-none d-md-block btn gl-button btn-default btn-grouped js-issuable-edit", data: { qa_selector: "edit_button" }
- if can_update_merge_request && !are_close_and_open_buttons_hidden
= render 'projects/merge_requests/close_reopen_draft_report_toggle'
diff --git a/app/views/projects/merge_requests/_nav_btns.html.haml b/app/views/projects/merge_requests/_nav_btns.html.haml
index b34cf23634c..00d12423eb9 100644
--- a/app/views/projects/merge_requests/_nav_btns.html.haml
+++ b/app/views/projects/merge_requests/_nav_btns.html.haml
@@ -5,7 +5,7 @@
.js-csv-import-export-buttons{ data: { show_export_button: "true", issuable_type: issuable_type, issuable_count: issuables_count_for_state(issuable_type.to_sym, params[:state]), email: notification_email, export_csv_path: export_csv_project_merge_requests_path(@project, request.query_parameters), container_class: 'gl-mr-3' } }
- if @can_bulk_update
- = button_tag "Edit merge requests", class: "gl-button btn btn-default gl-mr-3 js-bulk-update-toggle"
+ = button_tag _("Edit merge requests"), class: "gl-button btn btn-default gl-mr-3 js-bulk-update-toggle"
- if merge_project
- = link_to new_merge_request_path, class: "gl-button btn btn-confirm", title: "New merge request" do
- New merge request
+ = link_to new_merge_request_path, class: "gl-button btn btn-confirm", title: _("New merge request") do
+ = _('New merge request')
diff --git a/app/views/projects/merge_requests/_widget.html.haml b/app/views/projects/merge_requests/_widget.html.haml
index 47a0d05fc65..459742c3b81 100644
--- a/app/views/projects/merge_requests/_widget.html.haml
+++ b/app/views/projects/merge_requests/_widget.html.haml
@@ -19,6 +19,6 @@
window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/pipelines_empty.svg')}';
window.gl.mrWidgetData.codequality_help_path = '#{help_page_path("user/project/merge_requests/code_quality", anchor: "code-quality-reports")}';
window.gl.mrWidgetData.false_positive_doc_url = '#{help_page_path('user/application_security/vulnerabilities/index')}';
- window.gl.mrWidgetData.can_view_false_positive = '#{(Feature.enabled?(:vulnerability_flags, default_enabled: :yaml) && @merge_request.project.licensed_feature_available?(:sast_fp_reduction)).to_s}';
+ window.gl.mrWidgetData.can_view_false_positive = '#{@merge_request.project.licensed_feature_available?(:sast_fp_reduction).to_s}';
#js-vue-mr-widget.mr-widget
diff --git a/app/views/projects/merge_requests/conflicts/show.html.haml b/app/views/projects/merge_requests/conflicts/show.html.haml
index ee296258d04..5ba42ca7610 100644
--- a/app/views/projects/merge_requests/conflicts/show.html.haml
+++ b/app/views/projects/merge_requests/conflicts/show.html.haml
@@ -6,7 +6,7 @@
.merge-request-details.issuable-details
= render "projects/merge_requests/mr_box"
-= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, source_branch: @merge_request.source_branch
+= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, reviewers: @merge_request.reviewers, source_branch: @merge_request.source_branch
#conflicts{ data: { conflicts_path: conflicts_project_merge_request_path(@merge_request.project, @merge_request, format: :json),
resolve_conflicts_path: resolve_conflicts_project_merge_request_path(@merge_request.project, @merge_request),
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 7e260a03c5d..2154ef6b596 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -49,6 +49,7 @@
= render "projects/merge_requests/tabs/pane", id: "notes", class: "notes voting_notes" do
.row
%section.col-md-12
+ -# haml-lint:disable InlineJavaScript
%script.js-notes-data{ type: "application/json" }= initial_notes_data(true).to_json.html_safe
.issuable-discussion.js-vue-notes-event
- if @merge_request.description.present?
@@ -98,3 +99,4 @@
= render 'projects/invite_members_modal', project: @project
- if Gitlab::CurrentSettings.gitpod_enabled && !current_user&.gitpod_enabled
= render 'shared/gitpod/enable_gitpod_modal'
+= render 'shared/web_ide_path'
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index b89aa9d402e..d253ab8e32b 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -10,7 +10,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
= _('Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically.')
- = link_to _('How do I mirror repositories?'), help_page_path('user/project/repository/repository_mirroring'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('How do I mirror repositories?'), help_page_path('user/project/repository/mirror/index.md'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
- if mirror_settings_enabled
@@ -32,7 +32,7 @@
= label_tag :only_protected_branches, _('Mirror only protected branches'), class: 'form-check-label'
.form-text.text-muted
= _('If enabled, only protected branches will be mirrored.')
- = link_to _('Learn more.'), help_page_path('user/project/repository/repository_mirroring', anchor: 'mirror-only-protected-branches'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('Learn more.'), help_page_path('user/project/repository/mirror/index.md', anchor: 'mirror-only-protected-branches'), target: '_blank', rel: 'noopener noreferrer'
.panel-footer
= f.submit _('Mirror repository'), class: 'gl-button btn btn-confirm js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror
diff --git a/app/views/projects/mirrors/_mirror_repos_push.html.haml b/app/views/projects/mirrors/_mirror_repos_push.html.haml
index b3e0f71bf19..339c5d82919 100644
--- a/app/views/projects/mirrors/_mirror_repos_push.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_push.html.haml
@@ -12,4 +12,4 @@
= label_tag :keep_divergent_refs, _('Keep divergent refs'), class: 'form-check-label'
.form-text.text-muted
- link_opening_tag = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
- = html_escape(_('Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}')) % { mirroring_docs_link_start: link_opening_tag % {url: help_page_path('user/project/repository/repository_mirroring', anchor: 'keep-divergent-refs')}, mirroring_api_docs_link_start: link_opening_tag % {url: help_page_path('api/remote_mirrors')}, link_closing_tag: '</a>'.html_safe }
+ = html_escape(_('Do not force push over diverged refs. After the mirror is created, this setting can only be modified using the API. %{mirroring_docs_link_start}Learn more about this option%{link_closing_tag} and %{mirroring_api_docs_link_start}the API.%{link_closing_tag}')) % { mirroring_docs_link_start: link_opening_tag % {url: help_page_path('user/project/repository/mirror/push.md', anchor: 'keep-divergent-refs')}, mirroring_api_docs_link_start: link_opening_tag % {url: help_page_path('api/remote_mirrors')}, link_closing_tag: '</a>'.html_safe }
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index 23606e24563..93afddce779 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -70,10 +70,10 @@
= link_to retry_project_job_path(build.project, build, return_to: request.original_url), method: :post, title: _('Retry'), class: 'gl-button btn btn-default btn-icon' do
= sprite_icon('repeat', css_class: 'gl-icon')
- if can?(current_user, :read_build, job)
- %tr.build-trace-row.responsive-table-border-end
+ %tr.build-log-row.responsive-table-border-end
%td
- %td.responsive-table-cell.build-trace-container{ colspan: 4 }
- %pre.build-trace.build-trace-rounded
+ %td.responsive-table-cell.build-log-container{ colspan: 4 }
+ %pre.build-log.build-log-rounded
%code.bash.js-build-output
= build_summary(build)
diff --git a/app/views/projects/product_analytics/test.html.haml b/app/views/projects/product_analytics/test.html.haml
index 60d897ee138..3204cd5fbbe 100644
--- a/app/views/projects/product_analytics/test.html.haml
+++ b/app/views/projects/product_analytics/test.html.haml
@@ -12,5 +12,6 @@
%code
= @event.as_json_wo_empty
+-# haml-lint:disable InlineJavaScript
:javascript
#{render 'tracker'}
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index bdb5f021b70..cfdbf3410b1 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -20,7 +20,8 @@
"is_admin": current_user&.admin.to_s,
"show_cleanup_policy_on_alert": show_cleanup_policy_on_alert(@project).to_s,
"cleanup_policies_settings_path": project_settings_packages_and_registries_path(@project),
- character_error: @character_error.to_s,
+ connection_error: (!!@connection_error).to_s,
+ invalid_path_error: (!!@invalid_path_error).to_s,
user_callouts_path: user_callouts_path,
user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s, } }
diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml
index 6b2a1468eec..23b1ec4dea3 100644
--- a/app/views/projects/settings/operations/_error_tracking.html.haml
+++ b/app/views/projects/settings/operations/_error_tracking.html.haml
@@ -18,4 +18,5 @@
api_host: setting.api_host,
enabled: setting.enabled.to_json,
integrated: setting.integrated.to_json,
+ gitlab_dsn: setting.gitlab_dsn,
token: setting.token.present? ? '*' * 12 : nil } }
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index 8ef53c40b11..3e6acdb130a 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -3,7 +3,7 @@
- breadcrumb_title @snippet.to_reference
- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
-#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet) } }
+#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet), 'can-report-spam': @snippet.submittable_as_spam_by?(current_user).to_s } }
.row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true, api_awards_path: project_snippets_award_api_path(@snippet)
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 79205a51d71..d3cc409df1d 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -18,6 +18,9 @@
= render_if_exists 'projects/commits/mirror_status'
+ - if @tags_loading_error
+ = render 'shared/errors/gitaly_unavailable', reason: s_('TagsPage|Unable to load tags')
+
.tags
- if @tags.any?
%ul.flex-list.content-list
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index fe00772d1d6..4281152225a 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -54,4 +54,5 @@
.form-actions.gl-display-flex
= button_tag s_('TagsPage|Create tag'), class: 'gl-button btn btn-confirm gl-mr-3', data: { qa_selector: "create_tag_button" }
= link_to s_('TagsPage|Cancel'), project_tags_path(@project), class: 'gl-button btn btn-default btn-cancel'
+-# haml-lint:disable InlineJavaScript
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 2d0c4cc20a0..1553eda1cfb 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -11,3 +11,4 @@
= render 'projects/last_push'
= render 'projects/files', commit: @last_commit, project: @project, ref: @ref, content_url: project_tree_path(@project, @id)
+= render 'shared/web_ide_path'
diff --git a/app/views/projects/usage_quotas/index.html.haml b/app/views/projects/usage_quotas/index.html.haml
index dfd46af0499..6c7cccfb9b1 100644
--- a/app/views/projects/usage_quotas/index.html.haml
+++ b/app/views/projects/usage_quotas/index.html.haml
@@ -6,7 +6,7 @@
.row
.col-sm-12
= s_('UsageQuota|Usage of project resources across the %{strong_start}%{project_name}%{strong_end} project').html_safe % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, project_name: @project.name } + '.'
- %a{ href: help_page_path('user/usage_quotas.md') }
+ %a{ href: help_page_path('user/usage_quotas.md'), target: '_blank', rel: 'noopener noreferrer' }
= s_('UsageQuota|Learn more about usage quotas') + '.'
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
diff --git a/app/views/search/results/_issuable.html.haml b/app/views/search/results/_issuable.html.haml
index 5645fbfb238..41058034d6f 100644
--- a/app/views/search/results/_issuable.html.haml
+++ b/app/views/search/results/_issuable.html.haml
@@ -13,7 +13,8 @@
= highlight_and_truncate_issuable(issuable, @search_term, @search_highlight)
.col-sm-3.gl-mt-3.gl-sm-mt-0.gl-text-right
- if issuable.respond_to?(:upvotes_count) && issuable.upvotes_count > 0
- %li.issuable-upvotes.gl-list-style-none.has-tooltip{ title: _('Upvotes') }
- = sprite_icon('thumb-up', css_class: "gl-vertical-align-middle")
- = issuable.upvotes_count
+ %li.issuable-upvotes.gl-list-style-none
+ %span.has-tooltip{ title: _('Upvotes') }
+ = sprite_icon('thumb-up', css_class: "gl-vertical-align-middle")
+ = issuable.upvotes_count
%span.gl-text-gray-500= sprintf(s_('updated %{time_ago}'), { time_ago: time_ago_with_tooltip(issuable.updated_at, placement: 'bottom') }).html_safe
diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml
index f03314563cb..3ab2b969b75 100644
--- a/app/views/shared/_import_form.html.haml
+++ b/app/views/shared/_import_form.html.haml
@@ -9,17 +9,12 @@
= f.text_field :import_url, value: import_url.sanitized_url,
autocomplete: 'off', class: 'form-control gl-form-input', placeholder: 'https://gitlab.company.com/group/project.git', required: true
= render 'shared/global_alert',
- variant: :warning,
- alert_class: 'gl-mt-3 js-import-url-warning hide',
+ variant: :danger,
+ alert_class: 'gl-mt-3 js-import-url-error hide',
dismissible: false,
close_button_class: 'js-close-2fa-enabled-success-alert' do
.gl-alert-body
- = s_('Import|A repository URL usually ends in a .git suffix, although this is not required. Double check to make sure your repository URL is correct.')
-
- .gl-alert.gl-alert-not-dismissible.gl-alert-warning.gl-mt-3.hide#project_import_url_warning
- .gl-alert-container
- = sprite_icon('warning-solid', css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title')
- .gl-alert-content{ role: 'alert' }
+ = s_('Import|There is not a valid Git repository at this URL. If your HTTP repository is not publicly accessible, verify your credentials.')
.row
.form-group.col-md-6
= f.label :import_url_user, class: 'label-bold' do
diff --git a/app/views/shared/_milestones_filter.html.haml b/app/views/shared/_milestones_filter.html.haml
index eb50960202a..117ed212fd9 100644
--- a/app/views/shared/_milestones_filter.html.haml
+++ b/app/views/shared/_milestones_filter.html.haml
@@ -1,13 +1,15 @@
-%ul.nav-links.mobile-separator.nav.nav-tabs
- %li{ class: milestone_class_for_state(params[:state], 'opened', true) }>
- = link_to milestones_filter_path(state: 'opened') do
- = _('Open')
- %span.badge.badge-pill= counts[:opened]
- %li{ class: milestone_class_for_state(params[:state], 'closed') }>
- = link_to milestones_filter_path(state: 'closed', sort: 'due_date_desc') do
- = _('Closed')
- %span.badge.badge-pill= counts[:closed]
- %li{ class: milestone_class_for_state(params[:state], 'all') }>
- = link_to milestones_filter_path(state: 'all', sort: 'due_date_desc') do
- = _('All')
- %span.badge.badge-pill= counts[:all]
+- count_badge_classes = 'badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex'
+
+= gl_tabs_nav( {class: 'gl-border-b-0 gl-flex-grow-1', data: { testid: 'milestones-filter' } } ) do
+ = gl_tab_link_to milestones_filter_path(state: 'opened'), { item_active: params[:state].blank? || params[:state] == 'opened' } do
+ = _('Open')
+ %span{ class: count_badge_classes }
+ = counts[:opened]
+ = gl_tab_link_to milestones_filter_path(state: 'closed', sort: 'due_date_desc'), { item_active: params[:state] == 'closed' } do
+ = _('Closed')
+ %span{ class: count_badge_classes }
+ = counts[:closed]
+ = gl_tab_link_to milestones_filter_path(state: 'all', sort: 'due_date_desc'), { item_active: params[:state] == 'all' } do
+ = _('All')
+ %span{ class: count_badge_classes }
+ = counts[:all]
diff --git a/app/views/shared/_web_ide_path.html.haml b/app/views/shared/_web_ide_path.html.haml
new file mode 100644
index 00000000000..73d00bcd408
--- /dev/null
+++ b/app/views/shared/_web_ide_path.html.haml
@@ -0,0 +1,4 @@
+= javascript_tag do
+ :plain
+ window.gl = window.gl || {};
+ window.gl.webIDEPath = '#{web_ide_url}'
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index 98752345074..165564c5666 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -2,7 +2,7 @@
- @no_breadcrumb_container = true
- @no_container = true
- @content_wrapper_class = "#{@content_wrapper_class} gl-relative"
-- @content_class = "issue-boards-content js-focus-mode-board"
+- @content_class = "js-focus-mode-board"
- is_epic_board = board.to_type == "EpicBoard"
- if is_epic_board
- breadcrumb_title _("Epic Boards")
diff --git a/app/views/shared/builds/_build_output.html.haml b/app/views/shared/builds/_build_output.html.haml
index 380fac4d0e4..a3b7d4926f8 100644
--- a/app/views/shared/builds/_build_output.html.haml
+++ b/app/views/shared/builds/_build_output.html.haml
@@ -1,4 +1,4 @@
-%pre.build-trace#build-trace
+%pre.build-log
%code.bash.js-build-output
.build-loader-animation.js-build-refresh
.dot
diff --git a/app/views/shared/builds/_tabs.html.haml b/app/views/shared/builds/_tabs.html.haml
index 4973309edf5..498e9cc33ce 100644
--- a/app/views/shared/builds/_tabs.html.haml
+++ b/app/views/shared/builds/_tabs.html.haml
@@ -1,24 +1,19 @@
-%ul.nav-links.mobile-separator.nav.nav-tabs
- %li{ class: active_when(scope.nil?) }>
- = link_to build_path_proc.call(nil) do
- All
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm.js-totalbuilds-count
- = limited_counter_with_delimiter(all_builds)
+- count_badge_classes = 'badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex'
- %li{ class: active_when(scope == 'pending') }>
- = link_to build_path_proc.call('pending') do
- Pending
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
- = limited_counter_with_delimiter(all_builds.pending)
-
- %li{ class: active_when(scope == 'running') }>
- = link_to build_path_proc.call('running') do
- Running
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
- = limited_counter_with_delimiter(all_builds.running)
-
- %li{ class: active_when(scope == 'finished') }>
- = link_to build_path_proc.call('finished') do
- Finished
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm
- = limited_counter_with_delimiter(all_builds.finished)
+= gl_tabs_nav( {class: 'gl-border-b-0 gl-flex-grow-1', data: { testid: 'jobs-tabs' } } ) do
+ = gl_tab_link_to build_path_proc.call(nil), { item_active: scope.nil? } do
+ = _('All')
+ %span{ class: count_badge_classes }
+ = limited_counter_with_delimiter(all_builds)
+ = gl_tab_link_to build_path_proc.call('pending'), { item_active: scope == 'pending' } do
+ = _('Pending')
+ %span{ class: count_badge_classes }
+ = limited_counter_with_delimiter(all_builds.pending)
+ = gl_tab_link_to build_path_proc.call('running'), { item_active: scope == 'running' } do
+ = _('Running')
+ %span{ class: count_badge_classes }
+ = limited_counter_with_delimiter(all_builds.running)
+ = gl_tab_link_to build_path_proc.call('finished'), { item_active: scope == 'finished' } do
+ = _('Finished')
+ %span{ class: count_badge_classes }
+ = limited_counter_with_delimiter(all_builds.finished)
diff --git a/app/views/shared/deploy_tokens/_form.html.haml b/app/views/shared/deploy_tokens/_form.html.haml
index 652da4b396a..e049afbc40b 100644
--- a/app/views/shared/deploy_tokens/_form.html.haml
+++ b/app/views/shared/deploy_tokens/_form.html.haml
@@ -4,7 +4,6 @@
= s_('DeployTokens|Create a new deploy token for all projects in this group. %{link_start}What are deploy tokens?%{link_end}').html_safe % { link_start: group_deploy_tokens_help_link_start, link_end: '</a>'.html_safe }
= form_for token, url: create_deploy_token_path(group_or_project, anchor: 'js-deploy-tokens'), method: :post, remote: Feature.enabled?(:ajax_new_deploy_token, group_or_project) do |f|
- = form_errors(token)
.form-group
= f.label :name, class: 'label-bold'
diff --git a/app/views/shared/empty_states/_topics.html.haml b/app/views/shared/empty_states/_topics.html.haml
new file mode 100644
index 00000000000..fd82a853037
--- /dev/null
+++ b/app/views/shared/empty_states/_topics.html.haml
@@ -0,0 +1,7 @@
+.row.empty-state
+ .col-12
+ .svg-content
+ = image_tag 'illustrations/labels.svg', data: { qa_selector: 'svg_content' }
+ .text-content.gl-text-center.gl-pt-0!
+ %h4= _('There are no topics to show.')
+ %p= _('Add topics to projects to help users find them.')
diff --git a/app/views/shared/errors/_gitaly_unavailable.html.haml b/app/views/shared/errors/_gitaly_unavailable.html.haml
new file mode 100644
index 00000000000..96a68cbcdc6
--- /dev/null
+++ b/app/views/shared/errors/_gitaly_unavailable.html.haml
@@ -0,0 +1,8 @@
+.gl-alert.gl-alert-danger.gl-mb-5.gl-mt-5
+ .gl-alert-container
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-title
+ = reason
+ .gl-alert-body
+ = s_('The git server, Gitaly, is not available at this time. Please contact your administrator.')
diff --git a/app/views/shared/hook_logs/_recent_deliveries_table.html.haml b/app/views/shared/hook_logs/_recent_deliveries_table.html.haml
new file mode 100644
index 00000000000..31ef8560781
--- /dev/null
+++ b/app/views/shared/hook_logs/_recent_deliveries_table.html.haml
@@ -0,0 +1,34 @@
+%table.gl-table.gl-w-full
+ %thead
+ %tr
+ %th= _('Status')
+ %th.d-none.d-sm-table-cell= _('Trigger')
+ %th= _('Elapsed time')
+ %th= _('Request time')
+ %th
+
+ - if hook_logs.present?
+ - hook_logs.each do |hook_log|
+ %tr
+ %td
+ = render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log }
+ %td.d-none.d-sm-table-cell
+ %span.badge.badge-pill.gl-badge.badge-muted.sm
+ = hook_log.trigger.singularize.titleize
+ %td
+ #{number_with_precision(hook_log.execution_duration, precision: 2)} sec
+ %td
+ = time_ago_with_tooltip(hook_log.created_at)
+ %td
+ = link_to _('View details'), hook_log_path(hook, hook_log)
+
+
+- if hook_logs.present?
+ = paginate hook_logs, theme: 'gitlab'
+- else
+ .gl-text-center.gl-mt-7
+ %h4= _('No webhook events')
+ %p
+ %span.gl-display-block= _('Webhook events will be displayed here.')
+ %span= _('Use the %{strongStart}Test%{strongEnd} option above to create an event.').html_safe % { strongStart: '<strong>'.html_safe, strongEnd: '</strong>'.html_safe }
+
diff --git a/app/views/shared/hook_logs/_status_label.html.haml b/app/views/shared/hook_logs/_status_label.html.haml
index dfa5ecee448..b930074303c 100644
--- a/app/views/shared/hook_logs/_status_label.html.haml
+++ b/app/views/shared/hook_logs/_status_label.html.haml
@@ -1,3 +1,3 @@
- label_status = hook_log.success? ? 'badge-success' : 'badge-danger'
-%span{ class: "badge #{label_status}" }
+%span{ class: "badge badge-pill gl-badge sm #{label_status}" }
= hook_log.internal_error? ? _('Error') : hook_log.response_status
diff --git a/app/views/shared/integrations/_tabs.html.haml b/app/views/shared/integrations/_tabs.html.haml
index 553401e47bd..d6ca0bd7d1e 100644
--- a/app/views/shared/integrations/_tabs.html.haml
+++ b/app/views/shared/integrations/_tabs.html.haml
@@ -1,18 +1,11 @@
-- active_tab = local_assigns.fetch(:active_tab, 'edit')
-- active_classes = 'gl-tab-nav-item-active gl-tab-nav-item-active-indigo active'
-- tabs = integration_tabs(integration: integration)
-
-- if tabs.length <= 1
- = yield
-- else
+- if integration.instance_level?
.tabs.gl-tabs
%div
- %ul.nav.gl-tabs-nav{ role: 'tablist' }
- - tabs.each do |tab|
- %li.nav-item{ role: 'presentation' }
- %a.nav-link.gl-tab-nav-item{ role: 'tab', class: (active_classes if tab[:key] == active_tab), href: tab[:href] }
- = tab[:text]
+ = gl_tabs_nav({ class: 'gl-mb-5' }) do
+ = gl_tab_link_to _('Settings'), scoped_edit_integration_path(integration)
+ = gl_tab_link_to s_('Integrations|Projects using custom settings'), scoped_overrides_integration_path(integration)
- .tab-content.gl-tab-content
- .tab-pane.gl-pt-3.active{ role: 'tabpanel' }
- = yield
+ = yield
+
+- else
+ = yield
diff --git a/app/views/shared/issuable/_nav.html.haml b/app/views/shared/issuable/_nav.html.haml
index cff50eef88b..4a33f625347 100644
--- a/app/views/shared/issuable/_nav.html.haml
+++ b/app/views/shared/issuable/_nav.html.haml
@@ -2,22 +2,16 @@
- page_context_word = type.to_s.humanize(capitalize: false)
- display_count = local_assigns.fetch(:display_count, true)
-%ul.nav-links.issues-state-filters.mobile-separator.nav.nav-tabs
- %li{ class: active_when(params[:state] == 'opened') }>
- = link_to page_filter_path(state: 'opened'), id: 'state-opened', title: _("Filter by %{page_context_word} that are currently open.") % { page_context_word: page_context_word }, data: { state: 'opened' } do
- #{issuables_state_counter_text(type, :opened, display_count)}
-
+= gl_tabs_nav({ class: 'issues-state-filters gl-border-b-0 gl-flex-grow-1' }) do
+ = gl_tab_link_to page_filter_path(state: 'opened'), { item_active: params[:state] == 'opened', id: 'state-opened', title: _("Filter by %{page_context_word} that are currently open.") % { page_context_word: page_context_word }, data: { state: 'opened' } } do
+ #{issuables_state_counter_text(type, :opened, display_count)}
- if type == :merge_requests
- %li{ class: active_when(params[:state] == 'merged') }>
- = link_to page_filter_path(state: 'merged'), id: 'state-merged', title: _('Filter by merge requests that are currently merged.'), data: { state: 'merged' } do
- #{issuables_state_counter_text(type, :merged, display_count)}
-
- %li{ class: active_when(params[:state] == 'closed') }>
- = link_to page_filter_path(state: 'closed'), id: 'state-closed', title: _('Filter by merge requests that are currently closed and unmerged.'), data: { state: 'closed' } do
- #{issuables_state_counter_text(type, :closed, display_count)}
+ = gl_tab_link_to page_filter_path(state: 'merged'), item_active: params[:state] == 'merged', id: 'state-merged', title: _('Filter by merge requests that are currently merged.'), data: { state: 'merged' } do
+ #{issuables_state_counter_text(type, :merged, display_count)}
+ = gl_tab_link_to page_filter_path(state: 'closed'), item_active: params[:state] == 'closed', id: 'state-closed', title: _('Filter by merge requests that are currently closed and unmerged.'), data: { state: 'closed' } do
+ #{issuables_state_counter_text(type, :closed, display_count)}
- else
- %li{ class: active_when(params[:state] == 'closed') }>
- = link_to page_filter_path(state: 'closed'), id: 'state-closed', title: _('Filter by issues that are currently closed.'), data: { state: 'closed', qa_selector: 'closed_issues_link' } do
- #{issuables_state_counter_text(type, :closed, display_count)}
+ = gl_tab_link_to page_filter_path(state: 'closed'), item_active: params[:state] == 'closed', id: 'state-closed', title: _('Filter by issues that are currently closed.'), data: { state: 'closed', qa_selector: 'closed_issues_link' } do
+ #{issuables_state_counter_text(type, :closed, display_count)}
= render 'shared/issuable/nav_links/all', page_context_word: page_context_word, counter: issuables_state_counter_text(type, :all, display_count)
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index e6c4b3f4814..81a7581d392 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -19,7 +19,7 @@
- if params[:search].present?
= hidden_field_tag :search, params[:search]
- if @can_bulk_update
- .check-all-holder.d-none.d-sm-block.hidden
+ .check-all-holder.gl-display-none.gl-sm-display-block.hidden.gl-float-left.gl-mr-5.gl-line-height-36
- checkbox_id = 'check-all-issues'
%label.gl-sr-only{ for: checkbox_id }= _('Select all')
= check_box_tag checkbox_id, nil, false, class: "check-all-issues left"
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 1e8724c3448..62539bfeffd 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -7,6 +7,7 @@
- can_edit_issuable = issuable_sidebar.dig(:current_user, :can_edit)
- add_page_startup_api_call "#{issuable_sidebar[:issuable_json_path]}?serializer=sidebar_extras"
- reviewers = local_assigns.fetch(:reviewers, nil)
+- in_group_context_with_iterations = @project.group.present? && issuable_sidebar[:supports_iterations]
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite', 'aria-label': issuable_type }
.issuable-sidebar
@@ -28,11 +29,11 @@
= render_if_exists 'shared/issuable/sidebar_item_epic', issuable_sidebar: issuable_sidebar, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type
- if issuable_sidebar[:supports_milestone]
- .block.milestone{ :class => ("gl-border-b-0!" if issuable_sidebar[:supports_iterations]), data: { qa_selector: 'milestone_block' } }
+ .block.milestone{ :class => ("gl-border-b-0!" if in_group_context_with_iterations), data: { qa_selector: 'milestone_block' } }
.js-milestone-select{ data: { can_edit: can_edit_issuable.to_s, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid] } }
- - if @project.group.present? && issuable_sidebar[:supports_iterations]
- .block{ class: 'gl-pt-0!', data: { qa_selector: 'iteration_container' } }
+ - if in_group_context_with_iterations
+ .block{ class: 'gl-pt-0! gl-collapse-empty', data: { qa_selector: 'iteration_container', testid: 'iteration_container' } }<
= render_if_exists 'shared/issuable/iteration_select', can_edit: can_edit_issuable.to_s, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type
- if issuable_sidebar[:supports_time_tracking]
@@ -55,11 +56,13 @@
.js-sidebar-status-entry-point{ data: sidebar_status_data(issuable_sidebar, @project) }
- if issuable_sidebar.has_key?(:confidential)
+ -# haml-lint:disable InlineJavaScript
%script#js-confidential-issue-data{ type: "application/json" }= { is_confidential: issuable_sidebar[:confidential], is_editable: can_edit_issuable }.to_json.html_safe
#js-confidential-entry-point
= render_if_exists 'shared/issuable/sidebar_cve_id_request', issuable_sidebar: issuable_sidebar
+ -# haml-lint:disable InlineJavaScript
%script#js-lock-issue-data{ type: "application/json" }= { is_locked: !!issuable_sidebar[:discussion_locked], is_editable: can_edit_issuable }.to_json.html_safe
#js-lock-entry-point
@@ -72,7 +75,7 @@
#js-reference-entry-point
- if issuable_type == 'merge_request'
.sub-block.js-sidebar-source-branch
- .sidebar-collapsed-icon.dont-change-state
+ .sidebar-collapsed-icon.js-dont-change-state
= clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
.gl-display-flex.gl-align-items-center.gl-justify-content-space-between.gl-mb-2.hide-collapsed
%span.gl-overflow-hidden.gl-text-overflow-ellipsis.gl-white-space-nowrap
diff --git a/app/views/shared/issuable/nav_links/_all.html.haml b/app/views/shared/issuable/nav_links/_all.html.haml
index c92a50bcb70..7afa194d5db 100644
--- a/app/views/shared/issuable/nav_links/_all.html.haml
+++ b/app/views/shared/issuable/nav_links/_all.html.haml
@@ -1,6 +1,5 @@
- page_context_word = local_assigns.fetch(:page_context_word)
- counter = local_assigns.fetch(:counter)
-%li{ class: active_when(params[:state] == 'all') }>
- = link_to page_filter_path(state: 'all'), id: 'state-all', title: "Show all #{page_context_word}.", data: { state: 'all' } do
- #{counter}
+= gl_tab_link_to page_filter_path(state: 'all'), item_active: params[:state] == 'all', id: 'state-all', title: _("Show all %{issuable_type}.") % { issuable_type: page_context_word }, data: { state: 'all' } do
+ #{counter}
diff --git a/app/views/shared/issue_type/_emoji_block.html.haml b/app/views/shared/issue_type/_emoji_block.html.haml
index 26d30341999..d2c851a4e49 100644
--- a/app/views/shared/issue_type/_emoji_block.html.haml
+++ b/app/views/shared/issue_type/_emoji_block.html.haml
@@ -4,7 +4,7 @@
.row.gl-m-0.gl-justify-content-space-between
.js-noteable-awards
= render 'award_emoji/awards_block', awardable: issuable, inline: true, api_awards_path: api_awards_path
- .new-branch-col.gl-my-2
+ .new-branch-col.gl-my-2.gl-font-size-0
= render_if_exists "projects/issues/timeline_toggle", issuable: issuable
#js-vue-sort-issue-discussions
#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(issuable), notes_filters: UserPreference.notes_filters.to_json } }
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index 56b2b0d5801..c66ba5ba2e1 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -161,11 +161,11 @@
- milestone_ref = milestone.try(:to_reference, full: true)
- if milestone_ref.present?
.block.reference
- .sidebar-collapsed-icon.dont-change-state
+ .sidebar-collapsed-icon.js-dont-change-state
= clipboard_button(text: milestone_ref, title: s_('MilestoneSidebar|Copy reference'), placement: "left", boundary: 'viewport')
.cross-project-reference.hide-collapsed
- %span
+ %span.gl-display-inline-block.gl-text-truncate
= s_('MilestoneSidebar|Reference:')
%span{ title: milestone_ref }
= milestone_ref
- = clipboard_button(text: milestone_ref, title: s_('MilestoneSidebar|Copy reference'), placement: "left", boundary: 'viewport')
+ = clipboard_button(text: milestone_ref, title: s_('MilestoneSidebar|Copy reference'), placement: "left", boundary: 'viewport', class: 'btn-clipboard btn-transparent gl-float-right gl-bg-gray-10')
diff --git a/app/views/shared/notes/_comment_button.html.haml b/app/views/shared/notes/_comment_button.html.haml
index d0a2d97df0f..3e880a36e29 100644
--- a/app/views/shared/notes/_comment_button.html.haml
+++ b/app/views/shared/notes/_comment_button.html.haml
@@ -1,31 +1,4 @@
- noteable_name = @note.noteable.human_class_name
-.float-left.btn-group.gl-sm-mr-3.droplab-dropdown.comment-type-dropdown.js-comment-type-dropdown
+.js-comment-type-dropdown.float-left.gl-sm-mr-3{ data: { noteable_name: noteable_name } }
%input.btn.gl-button.btn-confirm.js-comment-button.js-comment-submit-button{ type: 'submit', value: _('Comment'), data: { qa_selector: 'comment_button' } }
-
- - if @note.can_be_discussion_note?
- = button_tag type: 'button', class: 'gl-button btn dropdown-toggle btn-confirm js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => _('Open comment type dropdown') do
- = sprite_icon('chevron-down')
-
- %ul#resolvable-comment-menu.dropdown-menu.dropdown-open-top{ data: { dropdown: true } }
- %li#comment.droplab-item-selected{ data: { value: '', 'submit-text' => _('Comment'), 'close-text' => _("Comment & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Comment & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
- %button.btn.gl-button.btn-default-tertiary
- = sprite_icon('check', css_class: 'icon')
- .description
- %strong= _("Comment")
- %p
- = _("Add a general comment to this %{noteable_name}.") % { noteable_name: noteable_name }
-
- %li.divider.droplab-item-ignore
-
- %li#discussion{ data: { value: 'DiscussionNote', 'submit-text' => _('Start thread'), 'close-text' => _("Start thread & close %{noteable_name}") % { noteable_name: noteable_name }, 'reopen-text' => _("Start thread & reopen %{noteable_name}") % { noteable_name: noteable_name } } }
- %button.btn.gl-button.btn-default-tertiary
- = sprite_icon('check', css_class: 'icon')
- .description
- %strong= _("Start thread")
- %p
- = succeed '.' do
- - if @note.noteable.supports_resolvable_notes?
- = _('Discuss a specific suggestion or question that needs to be resolved')
- - else
- = _('Discuss a specific suggestion or question')
diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml
index a03e8446f5d..6231f817704 100644
--- a/app/views/shared/notes/_hints.html.haml
+++ b/app/views/shared/notes/_hints.html.haml
@@ -1,4 +1,5 @@
- supports_quick_actions = local_assigns.fetch(:supports_quick_actions, false)
+- supports_file_upload = local_assigns.fetch(:supports_file_upload, true)
.comment-toolbar.clearfix
.toolbar-text
= link_to _('Markdown'), help_page_path('user/markdown'), target: '_blank'
@@ -10,33 +11,34 @@
is
supported
- %span.uploading-container
- %span.uploading-progress-container.hide
- = sprite_icon('media', css_class: 'gl-icon gl-vertical-align-text-bottom')
- %span.attaching-file-message
- -# Populated by app/assets/javascripts/dropzone_input.js
- %span.uploading-progress 0%
- = loading_icon(css_class: 'align-text-bottom gl-mr-2')
-
- %span.uploading-error-container.hide
- %span.uploading-error-icon
+ - if supports_file_upload
+ %span.uploading-container
+ %span.uploading-progress-container.hide
= sprite_icon('media', css_class: 'gl-icon gl-vertical-align-text-bottom')
- %span.uploading-error-message
- -# Populated by app/assets/javascripts/dropzone_input.js
- %button.btn.gl-button.btn-link.gl-vertical-align-baseline.retry-uploading-link
- %span.gl-button-text
- = _("Try again")
- = _("or")
- %button.btn.gl-button.btn-link.attach-new-file.markdown-selector.gl-vertical-align-baseline
- %span.gl-button-text
- = _("attach a new file")
- = _(".")
+ %span.attaching-file-message
+ -# Populated by app/assets/javascripts/dropzone_input.js
+ %span.uploading-progress 0%
+ = loading_icon(css_class: 'align-text-bottom gl-mr-2')
- %button.btn.gl-button.btn-link.button-attach-file.markdown-selector.button-attach-file.gl-vertical-align-text-bottom
- = sprite_icon('media')
- %span.gl-button-text
- = _("Attach a file")
+ %span.uploading-error-container.hide
+ %span.uploading-error-icon
+ = sprite_icon('media', css_class: 'gl-icon gl-vertical-align-text-bottom')
+ %span.uploading-error-message
+ -# Populated by app/assets/javascripts/dropzone_input.js
+ %button.btn.gl-button.btn-link.gl-vertical-align-baseline.retry-uploading-link
+ %span.gl-button-text
+ = _("Try again")
+ = _("or")
+ %button.btn.gl-button.btn-link.attach-new-file.markdown-selector.gl-vertical-align-baseline
+ %span.gl-button-text
+ = _("attach a new file")
+ = _(".")
- %button.btn.gl-button.btn-link.button-cancel-uploading-files.gl-vertical-align-baseline.hide
- %span.gl-button-text
- = _("Cancel")
+ %button.btn.gl-button.btn-link.button-attach-file.markdown-selector.button-attach-file.gl-vertical-align-text-bottom
+ = sprite_icon('media')
+ %span.gl-button-text
+ = _("Attach a file")
+
+ %button.btn.gl-button.btn-link.button-cancel-uploading-files.gl-vertical-align-baseline.hide
+ %span.gl-button-text
+ = _("Cancel")
diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml
index f7f5c02370d..e34f412baa4 100644
--- a/app/views/shared/notes/_notes_with_form.html.haml
+++ b/app/views/shared/notes/_notes_with_form.html.haml
@@ -25,4 +25,5 @@
= sprite_icon('lock', css_class: 'icon')
%span
= html_escape(_("This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment.")) % { issuable: issuable.class.to_s.titleize.downcase, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
+-# haml-lint:disable InlineJavaScript
%script.js-notes-data{ type: "application/json" }= initial_notes_data(autocomplete).to_json.html_safe
diff --git a/app/views/shared/topics/_search_form.html.haml b/app/views/shared/topics/_search_form.html.haml
new file mode 100644
index 00000000000..97343983b3c
--- /dev/null
+++ b/app/views/shared/topics/_search_form.html.haml
@@ -0,0 +1,7 @@
+= form_tag page_filter_path, method: :get, class: "topic-filter-form js-topic-filter-form", id: 'topic-filter-form' do |f|
+ = search_field_tag :search, params[:search],
+ placeholder: s_('Filter by name'),
+ class: 'topic-filter-form-field form-control input-short',
+ spellcheck: false,
+ id: 'topic-filter-form-field',
+ autofocus: local_assigns[:autofocus]
diff --git a/app/views/shared/web_hooks/_hook.html.haml b/app/views/shared/web_hooks/_hook.html.haml
index abe23d0be78..fd124c2967d 100644
--- a/app/views/shared/web_hooks/_hook.html.haml
+++ b/app/views/shared/web_hooks/_hook.html.haml
@@ -5,12 +5,12 @@
%div
- hook.class.triggers.each_value do |trigger|
- if hook.public_send(trigger)
- %span.gl-badge.gl-bg-gray-10.gl-mt-2.rounded.deploy-project-label= trigger.to_s.titleize
- %span.gl-badge.gl-bg-gray-10.gl-mt-2.rounded
+ %span.gl-badge.badge-muted.badge-pill.sm.gl-mt-2.deploy-project-label= trigger.to_s.titleize
+ %span.gl-badge.badge-muted.badge-pill.sm.gl-mt-2
= _('SSL Verification:')
= hook.enable_ssl_verification ? _('enabled') : _('disabled')
.col-md-4.col-lg-5.text-right-md.gl-mt-2
%span>= render 'shared/web_hooks/test_button', hook: hook, button_class: 'btn-sm btn-default gl-mr-3'
%span>= link_to _('Edit'), edit_hook_path(hook), class: 'btn gl-button btn-default btn-sm gl-mr-3'
- = link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'btn gl-button btn-default btn-sm'
+ = link_to _('Delete'), destroy_hook_path(hook), data: { confirm: _('Are you sure?') }, method: :delete, class: 'btn gl-button btn-secondary btn-danger-secondary btn-sm'
diff --git a/app/views/shared/wikis/edit.html.haml b/app/views/shared/wikis/edit.html.haml
index 15710f0df49..e0860bc473d 100644
--- a/app/views/shared/wikis/edit.html.haml
+++ b/app/views/shared/wikis/edit.html.haml
@@ -4,7 +4,7 @@
- if @error
#js-wiki-error{ data: { error: @error, wiki_page_path: wiki_page_path(@wiki, @page) } }
-.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
+.js-wiki-edit-page.wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row
= wiki_sidebar_toggle_button
%h3.page-title.gl-flex-grow-1
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index ca52a1f8f46..f1093a3b730 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -12,7 +12,7 @@
- content_for :prefetch_asset_tags do
- webpack_preload_asset_tag('monaco', prefetch: true)
-#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet) } }
+#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet), 'can-report-spam': @snippet.submittable_as_spam_by?(current_user).to_s } }
.row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 20cbe08225e..522f0f771cd 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -84,10 +84,12 @@
= sprite_icon('location', css_class: 'fgray')
%span{ itemprop: 'addressLocality' }
= @user.location
- = render 'middle_dot_divider', stacking: true do
- = sprite_icon('clock', css_class: 'fgray')
- %span
- = local_time(@user.timezone)
+ - user_local_time = local_time(@user.timezone)
+ - unless user_local_time.nil?
+ = render 'middle_dot_divider', stacking: true, data: { testid: 'user-local-time' } do
+ = sprite_icon('clock', css_class: 'fgray')
+ %span
+ = user_local_time
- unless work_information(@user).blank?
= render 'middle_dot_divider', stacking: true do
= sprite_icon('work', css_class: 'fgray')