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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app/views
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
commit43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch)
treedceebdc68925362117480a5d672bcff122fb625b /app/views
parent20c84b99005abd1c82101dfeff264ac50d2df211 (diff)
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'app/views')
-rw-r--r--app/views/abuse_reports/new.html.haml11
-rw-r--r--app/views/admin/abuse_reports/_abuse_report.html.haml37
-rw-r--r--app/views/admin/abuse_reports/index.html.haml58
-rw-r--r--app/views/admin/abuse_reports/show.html.haml6
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml5
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml24
-rw-r--r--app/views/admin/application_settings/_localization.html.haml2
-rw-r--r--app/views/admin/application_settings/_outbound.html.haml27
-rw-r--r--app/views/admin/application_settings/_projects_api_limits.html.haml21
-rw-r--r--app/views/admin/application_settings/_realtime.html.haml4
-rw-r--r--app/views/admin/application_settings/_registry.html.haml8
-rw-r--r--app/views/admin/application_settings/_repository_check.html.haml4
-rw-r--r--app/views/admin/application_settings/_runner_registrars_form.html.haml11
-rw-r--r--app/views/admin/application_settings/_slack.html.haml33
-rw-r--r--app/views/admin/application_settings/_visibility_and_access.html.haml6
-rw-r--r--app/views/admin/application_settings/appearances/_form.html.haml12
-rw-r--r--app/views/admin/application_settings/appearances/show.html.haml2
-rw-r--r--app/views/admin/application_settings/ci_cd.html.haml4
-rw-r--r--app/views/admin/application_settings/general.html.haml2
-rw-r--r--app/views/admin/application_settings/integrations.html.haml2
-rw-r--r--app/views/admin/application_settings/metrics_and_profiling.html.haml4
-rw-r--r--app/views/admin/application_settings/network.html.haml6
-rw-r--r--app/views/admin/application_settings/preferences.html.haml2
-rw-r--r--app/views/admin/application_settings/reporting.html.haml2
-rw-r--r--app/views/admin/application_settings/repository.html.haml2
-rw-r--r--app/views/admin/application_settings/service_usage_data.html.haml4
-rw-r--r--app/views/admin/applications/_form.html.haml25
-rw-r--r--app/views/admin/applications/index.html.haml10
-rw-r--r--app/views/admin/applications/show.html.haml1
-rw-r--r--app/views/admin/background_migrations/index.html.haml5
-rw-r--r--app/views/admin/broadcast_messages/_preview.html.haml3
-rw-r--r--app/views/admin/broadcast_messages/edit.html.haml13
-rw-r--r--app/views/admin/broadcast_messages/index.html.haml2
-rw-r--r--app/views/admin/dashboard/_security_newsletter_callout.html.haml4
-rw-r--r--app/views/admin/dashboard/index.html.haml26
-rw-r--r--app/views/admin/dev_ops_report/show.html.haml13
-rw-r--r--app/views/admin/groups/_form.html.haml18
-rw-r--r--app/views/admin/groups/_group.html.haml5
-rw-r--r--app/views/admin/groups/show.html.haml23
-rw-r--r--app/views/admin/health_check/show.html.haml9
-rw-r--r--app/views/admin/labels/_label.html.haml24
-rw-r--r--app/views/admin/labels/index.html.haml59
-rw-r--r--app/views/admin/labels/new.html.haml1
-rw-r--r--app/views/admin/projects/_form.html.haml38
-rw-r--r--app/views/admin/projects/_projects.html.haml7
-rw-r--r--app/views/admin/projects/edit.html.haml4
-rw-r--r--app/views/admin/projects/show.html.haml30
-rw-r--r--app/views/admin/runners/edit.html.haml4
-rw-r--r--app/views/admin/runners/new.html.haml2
-rw-r--r--app/views/admin/runners/register.html.haml7
-rw-r--r--app/views/admin/runners/show.html.haml6
-rw-r--r--app/views/admin/sessions/_new_base.html.haml4
-rw-r--r--app/views/admin/sessions/_signin_box.html.haml2
-rw-r--r--app/views/admin/sessions/_two_factor_otp.html.haml8
-rw-r--r--app/views/admin/sessions/new.html.haml9
-rw-r--r--app/views/admin/sessions/two_factor.html.haml10
-rw-r--r--app/views/admin/spam_logs/index.html.haml2
-rw-r--r--app/views/admin/system_info/show.html.haml81
-rw-r--r--app/views/admin/topics/_topic.html.haml5
-rw-r--r--app/views/admin/users/_form.html.haml4
-rw-r--r--app/views/admin/users/_head.html.haml6
-rw-r--r--app/views/admin/users/_profile.html.haml59
-rw-r--r--app/views/admin/users/_projects.html.haml8
-rw-r--r--app/views/admin/users/_user_detail_note.html.haml4
-rw-r--r--app/views/admin/users/_users.html.haml2
-rw-r--r--app/views/admin/users/projects.html.haml8
-rw-r--r--app/views/admin/users/show.html.haml8
-rw-r--r--app/views/authentication/_authenticate.html.haml11
-rw-r--r--app/views/authentication/_register.html.haml89
-rw-r--r--app/views/ci/variables/_index.html.haml8
-rw-r--r--app/views/clusters/clusters/_advanced_settings.html.haml1
-rw-r--r--app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml5
-rw-r--r--app/views/clusters/clusters/_integrations.html.haml4
-rw-r--r--app/views/clusters/clusters/connect.html.haml1
-rw-r--r--app/views/clusters/clusters/new_cluster_docs.html.haml1
-rw-r--r--app/views/clusters/clusters/show.html.haml5
-rw-r--r--app/views/dashboard/_groups_head.html.haml11
-rw-r--r--app/views/dashboard/_no_filter_selected.html.haml (renamed from app/views/shared/dashboard/_no_filter_selected.html.haml)0
-rw-r--r--app/views/dashboard/_projects_head.html.haml5
-rw-r--r--app/views/dashboard/_projects_nav.html.haml7
-rw-r--r--app/views/dashboard/_snippets_head.html.haml15
-rw-r--r--app/views/dashboard/activity.html.haml5
-rw-r--r--app/views/dashboard/groups/index.html.haml2
-rw-r--r--app/views/dashboard/issues.html.haml18
-rw-r--r--app/views/dashboard/merge_requests.html.haml3
-rw-r--r--app/views/dashboard/milestones/index.html.haml2
-rw-r--r--app/views/dashboard/projects/_blank_state_admin_welcome.html.haml8
-rw-r--r--app/views/dashboard/projects/_blank_state_welcome.html.haml8
-rw-r--r--app/views/dashboard/projects/_starred_empty_state.html.haml4
-rw-r--r--app/views/dashboard/projects/index.html.haml5
-rw-r--r--app/views/dashboard/projects/shared/_common.html.haml4
-rw-r--r--app/views/dashboard/snippets/index.html.haml6
-rw-r--r--app/views/dashboard/todos/index.html.haml17
-rw-r--r--app/views/devise/confirmations/almost_there.haml7
-rw-r--r--app/views/devise/confirmations/new.html.haml7
-rw-r--r--app/views/devise/mailer/user_admin_approval.text.erb4
-rw-r--r--app/views/devise/registrations/new.html.haml4
-rw-r--r--app/views/devise/sessions/_new_base.html.haml27
-rw-r--r--app/views/devise/sessions/_new_crowd.html.haml4
-rw-r--r--app/views/devise/sessions/_new_ldap.html.haml6
-rw-r--r--app/views/devise/sessions/new.html.haml3
-rw-r--r--app/views/devise/sessions/two_factor.html.haml15
-rw-r--r--app/views/devise/shared/_error_messages.html.haml9
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml34
-rw-r--r--app/views/devise/shared/_sign_in_link.html.haml2
-rw-r--r--app/views/devise/shared/_signup_box.html.haml20
-rw-r--r--app/views/devise/shared/_signup_omniauth_provider_list.haml6
-rw-r--r--app/views/doorkeeper/applications/edit.html.haml1
-rw-r--r--app/views/doorkeeper/applications/show.html.haml4
-rw-r--r--app/views/events/_events.html.haml2
-rw-r--r--app/views/explore/_head.html.haml6
-rw-r--r--app/views/explore/groups/_nav.html.haml4
-rw-r--r--app/views/explore/groups/index.html.haml17
-rw-r--r--app/views/explore/projects/_head.html.haml11
-rw-r--r--app/views/explore/projects/_nav.html.haml6
-rw-r--r--app/views/explore/projects/index.html.haml11
-rw-r--r--app/views/explore/projects/page_out_of_bounds.html.haml14
-rw-r--r--app/views/explore/projects/starred.html.haml12
-rw-r--r--app/views/explore/projects/topic.html.haml30
-rw-r--r--app/views/explore/projects/topics.html.haml9
-rw-r--r--app/views/explore/projects/trending.html.haml12
-rw-r--r--app/views/explore/snippets/index.html.haml14
-rw-r--r--app/views/explore/topics/_head.html.haml10
-rw-r--r--app/views/groups/_flash_messages.html.haml2
-rw-r--r--app/views/groups/_group_admin_settings.html.haml7
-rw-r--r--app/views/groups/_group_readme.html.haml3
-rw-r--r--app/views/groups/_import_group_from_another_instance_panel.html.haml8
-rw-r--r--app/views/groups/_import_group_from_file_panel.html.haml8
-rw-r--r--app/views/groups/_invite_members_modal.html.haml2
-rw-r--r--app/views/groups/_invite_members_side_nav_link.html.haml8
-rw-r--r--app/views/groups/_invite_members_top_nav_link.html.haml5
-rw-r--r--app/views/groups/_new_group_fields.html.haml3
-rw-r--r--app/views/groups/achievements/index.html.haml14
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml2
-rw-r--r--app/views/groups/edit.html.haml7
-rw-r--r--app/views/groups/group_members/index.html.haml1
-rw-r--r--app/views/groups/harbor/repositories/index.html.haml1
-rw-r--r--app/views/groups/imports/show.html.haml1
-rw-r--r--app/views/groups/labels/index.html.haml12
-rw-r--r--app/views/groups/milestones/_form.html.haml49
-rw-r--r--app/views/groups/milestones/new.html.haml5
-rw-r--r--app/views/groups/new.html.haml20
-rw-r--r--app/views/groups/packages/index.html.haml2
-rw-r--r--app/views/groups/projects.html.haml6
-rw-r--r--app/views/groups/registry/repositories/index.html.haml1
-rw-r--r--app/views/groups/runners/edit.html.haml2
-rw-r--r--app/views/groups/runners/index.html.haml2
-rw-r--r--app/views/groups/runners/new.html.haml5
-rw-r--r--app/views/groups/runners/register.html.haml7
-rw-r--r--app/views/groups/runners/show.html.haml6
-rw-r--r--app/views/groups/settings/_export.html.haml9
-rw-r--r--app/views/groups/settings/_general.html.haml8
-rw-r--r--app/views/groups/settings/_git_access_protocols.html.haml2
-rw-r--r--app/views/groups/settings/_permissions.html.haml5
-rw-r--r--app/views/groups/settings/_remove_button.html.haml2
-rw-r--r--app/views/groups/settings/_transfer.html.haml4
-rw-r--r--app/views/groups/settings/access_tokens/index.html.haml8
-rw-r--r--app/views/groups/settings/applications/edit.html.haml1
-rw-r--r--app/views/groups/settings/applications/index.html.haml1
-rw-r--r--app/views/groups/settings/applications/show.html.haml4
-rw-r--r--app/views/groups/settings/ci_cd/_auto_devops_form.html.haml7
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml3
-rw-r--r--app/views/groups/settings/integrations/index.html.haml2
-rw-r--r--app/views/groups/settings/packages_and_registries/show.html.haml2
-rw-r--r--app/views/groups/settings/repository/show.html.haml2
-rw-r--r--app/views/groups/show.html.haml8
-rw-r--r--app/views/help/instance_configuration/_ci_cd_limits.html.haml18
-rw-r--r--app/views/ide/_show.html.haml4
-rw-r--r--app/views/import/_githubish_status.html.haml4
-rw-r--r--app/views/import/github/details.html.haml4
-rw-r--r--app/views/import/github/status.html.haml2
-rw-r--r--app/views/import/phabricator/new.html.haml26
-rw-r--r--app/views/jira_connect/branches/new.html.haml1
-rw-r--r--app/views/jira_connect/users/show.html.haml21
-rw-r--r--app/views/layouts/_head.html.haml41
-rw-r--r--app/views/layouts/_loading_hints.html.haml3
-rw-r--r--app/views/layouts/_page.html.haml19
-rw-r--r--app/views/layouts/_search.html.haml42
-rw-r--r--app/views/layouts/_snowplow.html.haml14
-rw-r--r--app/views/layouts/component_preview.html.haml4
-rw-r--r--app/views/layouts/dashboard.html.haml5
-rw-r--r--app/views/layouts/devise.html.haml40
-rw-r--r--app/views/layouts/devise_empty.html.haml1
-rw-r--r--app/views/layouts/explore.html.haml11
-rw-r--r--app/views/layouts/group.html.haml5
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml8
-rw-r--r--app/views/layouts/header/_current_user_dropdown_item.html.haml2
-rw-r--r--app/views/layouts/header/_default.html.haml9
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml1
-rw-r--r--app/views/layouts/header/_new_dropdown.html.haml15
-rw-r--r--app/views/layouts/help.html.haml2
-rw-r--r--app/views/layouts/minimal.html.haml7
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml27
-rw-r--r--app/views/layouts/nav/_top_bar.html.haml14
-rw-r--r--app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml20
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml299
-rw-r--r--app/views/layouts/nav/sidebar/_explore.html.haml1
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml3
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml170
-rw-r--r--app/views/layouts/nav/sidebar/_search.html.haml1
-rw-r--r--app/views/layouts/nav/sidebar/_user_profile.html.haml1
-rw-r--r--app/views/layouts/nav/sidebar/_your_work.html.haml2
-rw-r--r--app/views/layouts/project.html.haml4
-rw-r--r--app/views/layouts/search.html.haml2
-rw-r--r--app/views/layouts/signup_onboarding.html.haml1
-rw-r--r--app/views/layouts/simple_registration.html.haml1
-rw-r--r--app/views/layouts/snippets.html.haml5
-rw-r--r--app/views/layouts/terms.html.haml2
-rw-r--r--app/views/notify/_issuable_csv_export.html.haml6
-rw-r--r--app/views/notify/_issuable_csv_export.text.erb7
-rw-r--r--app/views/notify/_note_email.text.erb6
-rw-r--r--app/views/notify/access_token_created_email.html.haml2
-rw-r--r--app/views/notify/export_work_items_csv_email.html.haml1
-rw-r--r--app/views/notify/export_work_items_csv_email.text.erb1
-rw-r--r--app/views/notify/import_work_items_csv_email.html.haml49
-rw-r--r--app/views/notify/import_work_items_csv_email.text.erb48
-rw-r--r--app/views/notify/issues_csv_email.text.erb6
-rw-r--r--app/views/notify/merge_request_status_email.text.haml2
-rw-r--r--app/views/notify/merge_requests_csv_email.text.erb6
-rw-r--r--app/views/notify/new_achievement_email.html.haml7
-rw-r--r--app/views/notify/new_achievement_email.text.erb4
-rw-r--r--app/views/notify/new_review_email.text.erb1
-rw-r--r--app/views/notify/pages_domain_auto_ssl_failed_email.html.haml2
-rw-r--r--app/views/notify/pages_domain_auto_ssl_failed_email.text.haml2
-rw-r--r--app/views/notify/reassigned_issue_email.text.erb2
-rw-r--r--app/views/notify/service_desk_custom_email_verification_email.text.erb4
-rw-r--r--app/views/notify/service_desk_verification_result_email.html.haml58
-rw-r--r--app/views/notify/service_desk_verification_result_email.text.erb38
-rw-r--r--app/views/notify/service_desk_verification_triggered_email.html.haml18
-rw-r--r--app/views/notify/service_desk_verification_triggered_email.text.erb10
-rw-r--r--app/views/notify/two_factor_otp_attempt_failed_email.html.haml4
-rw-r--r--app/views/notify/two_factor_otp_attempt_failed_email.text.haml4
-rw-r--r--app/views/notify/unknown_sign_in_email.html.haml5
-rw-r--r--app/views/notify/unknown_sign_in_email.text.haml2
-rw-r--r--app/views/peek/_bar.html.haml3
-rw-r--r--app/views/profiles/accounts/show.html.haml2
-rw-r--r--app/views/profiles/active_sessions/index.html.haml2
-rw-r--r--app/views/profiles/audit_log.html.haml2
-rw-r--r--app/views/profiles/chat_names/_chat_name.html.haml16
-rw-r--r--app/views/profiles/chat_names/index.html.haml9
-rw-r--r--app/views/profiles/chat_names/new.html.haml40
-rw-r--r--app/views/profiles/comment_templates/index.html.haml10
-rw-r--r--app/views/profiles/emails/index.html.haml4
-rw-r--r--app/views/profiles/gpg_keys/_key.html.haml2
-rw-r--r--app/views/profiles/gpg_keys/index.html.haml2
-rw-r--r--app/views/profiles/keys/_key.html.haml2
-rw-r--r--app/views/profiles/keys/index.html.haml2
-rw-r--r--app/views/profiles/keys/show.html.haml1
-rw-r--r--app/views/profiles/notifications/show.html.haml2
-rw-r--r--app/views/profiles/passwords/edit.html.haml2
-rw-r--r--app/views/profiles/personal_access_tokens/index.html.haml2
-rw-r--r--app/views/profiles/preferences/show.html.haml43
-rw-r--r--app/views/profiles/saved_replies/index.html.haml10
-rw-r--r--app/views/profiles/show.html.haml26
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml84
-rw-r--r--app/views/projects/_commit_button.html.haml2
-rw-r--r--app/views/projects/_deletion_failed.html.haml2
-rw-r--r--app/views/projects/_files.html.haml12
-rw-r--r--app/views/projects/_flash_messages.html.haml2
-rw-r--r--app/views/projects/_home_panel.html.haml46
-rw-r--r--app/views/projects/_import_project_pane.html.haml12
-rw-r--r--app/views/projects/_invite_members_empty_project.html.haml6
-rw-r--r--app/views/projects/_invite_members_modal.html.haml2
-rw-r--r--app/views/projects/_invite_members_side_nav_link.html.haml8
-rw-r--r--app/views/projects/_invite_members_top_nav_link.html.haml5
-rw-r--r--app/views/projects/_last_push.html.haml4
-rw-r--r--app/views/projects/_new_project_fields.html.haml12
-rw-r--r--app/views/projects/_remove.html.haml1
-rw-r--r--app/views/projects/_remove_fork.html.haml3
-rw-r--r--app/views/projects/_service_desk_settings.html.haml2
-rw-r--r--app/views/projects/_terraform_banner.html.haml2
-rw-r--r--app/views/projects/airflow/dags/index.html.haml11
-rw-r--r--app/views/projects/artifacts/browse.html.haml2
-rw-r--r--app/views/projects/aws/configuration/index.html.haml7
-rw-r--r--app/views/projects/blame/show.html.haml34
-rw-r--r--app/views/projects/blob/_blob.html.haml12
-rw-r--r--app/views/projects/blob/_breadcrumb.html.haml2
-rw-r--r--app/views/projects/blob/_editor.html.haml27
-rw-r--r--app/views/projects/blob/edit.html.haml18
-rw-r--r--app/views/projects/blob/viewers/_csv.html.haml2
-rw-r--r--app/views/projects/branch_defaults/_branch_names_fields.html.haml3
-rw-r--r--app/views/projects/branch_rules/_show.html.haml8
-rw-r--r--app/views/projects/branches/_branch.html.haml91
-rw-r--r--app/views/projects/branches/_branch_rules_info.haml12
-rw-r--r--app/views/projects/branches/_commit.html.haml2
-rw-r--r--app/views/projects/branches/_panel.html.haml13
-rw-r--r--app/views/projects/branches/index.html.haml17
-rw-r--r--app/views/projects/branches/new.html.haml31
-rw-r--r--app/views/projects/buttons/_clone.html.haml8
-rw-r--r--app/views/projects/commit/_pipelines_list.haml3
-rw-r--r--app/views/projects/commit/_signature_badge.html.haml2
-rw-r--r--app/views/projects/commit/diff_files.html.haml6
-rw-r--r--app/views/projects/commit/show.html.haml4
-rw-r--r--app/views/projects/commits/_commit.html.haml8
-rw-r--r--app/views/projects/commits/_commit_list.html.haml4
-rw-r--r--app/views/projects/commits/_commits.html.haml9
-rw-r--r--app/views/projects/commits/show.html.haml2
-rw-r--r--app/views/projects/compare/index.html.haml4
-rw-r--r--app/views/projects/compare/show.html.haml4
-rw-r--r--app/views/projects/cycle_analytics/show.html.haml1
-rw-r--r--app/views/projects/diffs/_content.html.haml2
-rw-r--r--app/views/projects/diffs/_diffs.html.haml12
-rw-r--r--app/views/projects/edit.html.haml16
-rw-r--r--app/views/projects/empty.html.haml1
-rw-r--r--app/views/projects/environments/index.html.haml3
-rw-r--r--app/views/projects/environments/new.html.haml5
-rw-r--r--app/views/projects/environments/show.html.haml4
-rw-r--r--app/views/projects/feature_flags/edit.html.haml4
-rw-r--r--app/views/projects/feature_flags/index.html.haml4
-rw-r--r--app/views/projects/feature_flags/new.html.haml4
-rw-r--r--app/views/projects/feature_flags_user_lists/edit.html.haml2
-rw-r--r--app/views/projects/feature_flags_user_lists/index.html.haml4
-rw-r--r--app/views/projects/feature_flags_user_lists/new.html.haml2
-rw-r--r--app/views/projects/feature_flags_user_lists/show.html.haml4
-rw-r--r--app/views/projects/find_file/show.html.haml4
-rw-r--r--app/views/projects/forks/error.html.haml4
-rw-r--r--app/views/projects/google_cloud/configuration/index.html.haml2
-rw-r--r--app/views/projects/google_cloud/databases/cloudsql_form.html.haml2
-rw-r--r--app/views/projects/google_cloud/databases/index.html.haml2
-rw-r--r--app/views/projects/google_cloud/deployments/index.html.haml2
-rw-r--r--app/views/projects/google_cloud/gcp_regions/index.html.haml2
-rw-r--r--app/views/projects/google_cloud/service_accounts/index.html.haml2
-rw-r--r--app/views/projects/graphs/show.html.haml2
-rw-r--r--app/views/projects/harbor/repositories/index.html.haml1
-rw-r--r--app/views/projects/hook_logs/show.html.haml1
-rw-r--r--app/views/projects/hooks/edit.html.haml1
-rw-r--r--app/views/projects/hooks/index.html.haml2
-rw-r--r--app/views/projects/imports/new.html.haml2
-rw-r--r--app/views/projects/imports/show.html.haml1
-rw-r--r--app/views/projects/issues/_design_management.html.haml5
-rw-r--r--app/views/projects/issues/_discussion.html.haml3
-rw-r--r--app/views/projects/issues/_issue.html.haml4
-rw-r--r--app/views/projects/issues/_new_branch.html.haml14
-rw-r--r--app/views/projects/issues/_related_branches.html.haml34
-rw-r--r--app/views/projects/issues/_related_issues.html.haml3
-rw-r--r--app/views/projects/issues/_work_item_links.html.haml4
-rw-r--r--app/views/projects/issues/new.html.haml2
-rw-r--r--app/views/projects/issues/service_desk/_alert_moved_from_service_desk.html.haml2
-rw-r--r--app/views/projects/issues/service_desk/_nav_btns.html.haml30
-rw-r--r--app/views/projects/issues/show.html.haml1
-rw-r--r--app/views/projects/labels/index.html.haml34
-rw-r--r--app/views/projects/mattermosts/_team_selection.html.haml7
-rw-r--r--app/views/projects/mattermosts/new.html.haml3
-rw-r--r--app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml3
-rw-r--r--app/views/projects/merge_requests/_code_dropdown.html.haml2
-rw-r--r--app/views/projects/merge_requests/_description.html.haml2
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml40
-rw-r--r--app/views/projects/merge_requests/_mr_box.html.haml2
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml8
-rw-r--r--app/views/projects/merge_requests/_nav_btns.html.haml25
-rw-r--r--app/views/projects/merge_requests/_page.html.haml14
-rw-r--r--app/views/projects/merge_requests/_widget.html.haml6
-rw-r--r--app/views/projects/merge_requests/conflicts/show.html.haml3
-rw-r--r--app/views/projects/merge_requests/creations/_new_submit.html.haml22
-rw-r--r--app/views/projects/merge_requests/invalid.html.haml2
-rw-r--r--app/views/projects/milestones/_form.html.haml54
-rw-r--r--app/views/projects/milestones/show.html.haml2
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml2
-rw-r--r--app/views/projects/mirrors/_mirror_repos_list.html.haml8
-rw-r--r--app/views/projects/ml/candidates/show.html.haml4
-rw-r--r--app/views/projects/ml/experiments/_experiment.html.haml3
-rw-r--r--app/views/projects/ml/experiments/_experiment_list.html.haml7
-rw-r--r--app/views/projects/ml/experiments/_incubation_banner.html.haml8
-rw-r--r--app/views/projects/ml/experiments/index.html.haml3
-rw-r--r--app/views/projects/ml/experiments/show.html.haml10
-rw-r--r--app/views/projects/new.html.haml18
-rw-r--r--app/views/projects/packages/infrastructure_registry/index.html.haml1
-rw-r--r--app/views/projects/packages/infrastructure_registry/show.html.haml5
-rw-r--r--app/views/projects/packages/packages/index.html.haml2
-rw-r--r--app/views/projects/pages/_access.html.haml14
-rw-r--r--app/views/projects/pages/_destroy.haml17
-rw-r--r--app/views/projects/pages/_header.html.haml7
-rw-r--r--app/views/projects/pages/_list.html.haml80
-rw-r--r--app/views/projects/pages/_no_domains.html.haml9
-rw-r--r--app/views/projects/pages/_pages_settings.html.haml11
-rw-r--r--app/views/projects/pages/_use.html.haml4
-rw-r--r--app/views/projects/pages_domains/_certificate.html.haml6
-rw-r--r--app/views/projects/pages_domains/_dns.html.haml3
-rw-r--r--app/views/projects/pages_domains/_form.html.haml2
-rw-r--r--app/views/projects/pages_domains/show.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml2
-rw-r--r--app/views/projects/pipelines/_info.html.haml20
-rw-r--r--app/views/projects/pipelines/_pipeline_stats_text.html.haml1
-rw-r--r--app/views/projects/pipelines/new.html.haml6
-rw-r--r--app/views/projects/pipelines/show.html.haml16
-rw-r--r--app/views/projects/project_members/index.html.haml1
-rw-r--r--app/views/projects/protected_tags/_create_protected_tag.html.haml4
-rw-r--r--app/views/projects/protected_tags/_protected_tag.html.haml4
-rw-r--r--app/views/projects/protected_tags/_protected_tag_create_access_levels.haml8
-rw-r--r--app/views/projects/protected_tags/shared/_create_protected_tag.html.haml6
-rw-r--r--app/views/projects/readme_templates/default.md.tt4
-rw-r--r--app/views/projects/registry/repositories/index.html.haml2
-rw-r--r--app/views/projects/releases/new.html.haml4
-rw-r--r--app/views/projects/runners/_project_runners.html.haml30
-rw-r--r--app/views/projects/runners/edit.html.haml7
-rw-r--r--app/views/projects/runners/new.html.haml5
-rw-r--r--app/views/projects/runners/register.html.haml6
-rw-r--r--app/views/projects/runners/show.html.haml3
-rw-r--r--app/views/projects/security/configuration/show.html.haml5
-rw-r--r--app/views/projects/settings/_general.html.haml4
-rw-r--r--app/views/projects/settings/access_tokens/index.html.haml2
-rw-r--r--app/views/projects/settings/branch_rules/index.html.haml7
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml6
-rw-r--r--app/views/projects/settings/ci_cd/_badge.html.haml6
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml4
-rw-r--r--app/views/projects/settings/integrations/_form.html.haml5
-rw-r--r--app/views/projects/settings/integrations/edit.html.haml1
-rw-r--r--app/views/projects/settings/integrations/index.html.haml4
-rw-r--r--app/views/projects/settings/members/show.html.haml2
-rw-r--r--app/views/projects/settings/merge_requests/show.html.haml2
-rw-r--r--app/views/projects/settings/operations/show.html.haml11
-rw-r--r--app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml5
-rw-r--r--app/views/projects/settings/packages_and_registries/show.html.haml2
-rw-r--r--app/views/projects/settings/repository/show.html.haml2
-rw-r--r--app/views/projects/show.html.haml3
-rw-r--r--app/views/projects/snippets/edit.html.haml1
-rw-r--r--app/views/projects/snippets/index.html.haml2
-rw-r--r--app/views/projects/snippets/new.html.haml2
-rw-r--r--app/views/projects/starrers/_starrer.html.haml4
-rw-r--r--app/views/projects/tags/_edit_release_button.html.haml4
-rw-r--r--app/views/projects/tags/_release_link.html.haml6
-rw-r--r--app/views/projects/tags/_tag.html.haml18
-rw-r--r--app/views/projects/tags/new.html.haml6
-rw-r--r--app/views/projects/tags/show.html.haml8
-rw-r--r--app/views/projects/terraform/index.html.haml4
-rw-r--r--app/views/projects/tree/_tree_header.html.haml2
-rw-r--r--app/views/projects/tree/show.html.haml1
-rw-r--r--app/views/projects/triggers/_index.html.haml6
-rw-r--r--app/views/projects/usage_quotas/index.html.haml8
-rw-r--r--app/views/projects/work_items/index.html.haml4
-rw-r--r--app/views/protected_branches/shared/_branches_list.html.haml2
-rw-r--r--app/views/protected_branches/shared/_create_protected_branch.html.haml2
-rw-r--r--app/views/protected_branches/shared/_update_protected_branch.html.haml24
-rw-r--r--app/views/registrations/welcome/show.html.haml8
-rw-r--r--app/views/search/_results.html.haml10
-rw-r--r--app/views/search/_results_list.html.haml29
-rw-r--r--app/views/search/_results_status.html.haml49
-rw-r--r--app/views/search/results/_blob.html.haml8
-rw-r--r--app/views/search/show.html.haml13
-rw-r--r--app/views/shared/_auto_devops_callout.html.haml2
-rw-r--r--app/views/shared/_broadcast_message.html.haml4
-rw-r--r--app/views/shared/_captcha_check.html.haml4
-rw-r--r--app/views/shared/_commit_message_container.html.haml25
-rw-r--r--app/views/shared/_file_highlight.html.haml10
-rw-r--r--app/views/shared/_file_picker_button.html.haml5
-rw-r--r--app/views/shared/_issues.html.haml8
-rw-r--r--app/views/shared/_label.html.haml101
-rw-r--r--app/views/shared/_label_full_path.html.haml6
-rw-r--r--app/views/shared/_label_row.html.haml35
-rw-r--r--app/views/shared/_md_preview.html.haml21
-rw-r--r--app/views/shared/_mobile_clone_panel.html.haml4
-rw-r--r--app/views/shared/_model_version_conflict.html.haml6
-rw-r--r--app/views/shared/_new_commit_form.html.haml11
-rw-r--r--app/views/shared/_ref_switcher.html.haml22
-rw-r--r--app/views/shared/_remote_mirror_update_button.html.haml2
-rw-r--r--app/views/shared/_zen.html.haml1
-rw-r--r--app/views/shared/blob/_markdown_buttons.html.haml70
-rw-r--r--app/views/shared/boards/_show.html.haml2
-rw-r--r--app/views/shared/deploy_keys/_form.html.haml5
-rw-r--r--app/views/shared/deploy_keys/_project_group_form.html.haml4
-rw-r--r--app/views/shared/doorkeeper/applications/_form.html.haml2
-rw-r--r--app/views/shared/doorkeeper/applications/_index.html.haml2
-rw-r--r--app/views/shared/doorkeeper/applications/_show.html.haml15
-rw-r--r--app/views/shared/empty_states/_issues.html.haml3
-rw-r--r--app/views/shared/empty_states/_labels.html.haml4
-rw-r--r--app/views/shared/empty_states/_merge_requests.html.haml4
-rw-r--r--app/views/shared/empty_states/_priority_labels.html.haml10
-rw-r--r--app/views/shared/empty_states/_snippets.html.haml4
-rw-r--r--app/views/shared/empty_states/_topics.html.haml4
-rw-r--r--app/views/shared/empty_states/_wikis.html.haml3
-rw-r--r--app/views/shared/form_elements/_description.html.haml24
-rw-r--r--app/views/shared/groups/_list.html.haml2
-rw-r--r--app/views/shared/hook_logs/_index.html.haml2
-rw-r--r--app/views/shared/icons/_mr_widget_empty_state.svg1
-rw-r--r--app/views/shared/integrations/_slack_notifications_deprecation_alert.html.haml20
-rw-r--r--app/views/shared/integrations/edit.html.haml1
-rw-r--r--app/views/shared/integrations/overrides.html.haml1
-rw-r--r--app/views/shared/integrations/prometheus/_custom_metrics.html.haml10
-rw-r--r--app/views/shared/integrations/prometheus/_metrics.html.haml18
-rw-r--r--app/views/shared/issuable/_feed_buttons.html.haml12
-rw-r--r--app/views/shared/issuable/_form.html.haml14
-rw-r--r--app/views/shared/issuable/_label_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_label_page_create.html.haml6
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml11
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml35
-rw-r--r--app/views/shared/issuable/_sidebar_user_dropdown.html.haml4
-rw-r--r--app/views/shared/issuable/form/_default_templates.html.haml2
-rw-r--r--app/views/shared/issuable/form/_merge_params.html.haml29
-rw-r--r--app/views/shared/issuable/form/_metadata.html.haml15
-rw-r--r--app/views/shared/issuable/form/_title.html.haml4
-rw-r--r--app/views/shared/issuable/form/_type_selector.html.haml26
-rw-r--r--app/views/shared/issue_type/_details_content.html.haml8
-rw-r--r--app/views/shared/issue_type/_details_header.html.haml4
-rw-r--r--app/views/shared/labels/_form.html.haml10
-rw-r--r--app/views/shared/milestones/_delete_button.html.haml8
-rw-r--r--app/views/shared/milestones/_description.html.haml4
-rw-r--r--app/views/shared/milestones/_form_dates.html.haml21
-rw-r--r--app/views/shared/milestones/_header.html.haml73
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml2
-rw-r--r--app/views/shared/nav/_admin_scope_header.html.haml6
-rw-r--r--app/views/shared/nav/_explore_scope_header.html.haml6
-rw-r--r--app/views/shared/nav/_user_settings_scope_header.html.haml4
-rw-r--r--app/views/shared/notes/_edit_form.html.haml3
-rw-r--r--app/views/shared/notes/_hints.html.haml6
-rw-r--r--app/views/shared/notes/_note.html.haml2
-rw-r--r--app/views/shared/projects/_list.html.haml7
-rw-r--r--app/views/shared/projects/_project.html.haml23
-rw-r--r--app/views/shared/projects/_search_form.html.haml2
-rw-r--r--app/views/shared/projects/_topics.html.haml52
-rw-r--r--app/views/shared/runners/_runner_details.html.haml5
-rw-r--r--app/views/shared/topics/_topic.html.haml5
-rw-r--r--app/views/shared/users/index.html.haml4
-rw-r--r--app/views/shared/web_hooks/_web_hook_disabled_alert.html.haml2
-rw-r--r--app/views/shared/wikis/_sidebar_wiki_page.html.haml8
-rw-r--r--app/views/shared/wikis/_wiki_directory.html.haml10
-rw-r--r--app/views/shared/wikis/diff.html.haml2
-rw-r--r--app/views/shared/wikis/empty.html.haml10
-rw-r--r--app/views/snippets/_snippets.html.haml2
-rw-r--r--app/views/snippets/show.html.haml5
-rw-r--r--app/views/time_tracking/timelogs/index.html.haml7
-rw-r--r--app/views/users/_overview.html.haml7
-rw-r--r--app/views/users/_profile_basic_info.html.haml8
-rw-r--r--app/views/users/show.html.haml253
524 files changed, 2940 insertions, 2906 deletions
diff --git a/app/views/abuse_reports/new.html.haml b/app/views/abuse_reports/new.html.haml
index 8b9bbfd0a59..39b8fe26c7b 100644
--- a/app/views/abuse_reports/new.html.haml
+++ b/app/views/abuse_reports/new.html.haml
@@ -26,6 +26,17 @@
= f.label :reported_from
= f.text_field :reported_from_url, class: "form-control", readonly: true
#js-links-to-spam{ data: { links: Array(@abuse_report.links_to_spam) } }
+
+ .form-group.row
+ .col-lg-8
+ = f.label :screenshot do
+ %span
+ = s_('ReportAbuse|Screenshot')
+ .gl-font-weight-normal
+ = s_('ReportAbuse|Screenshot of abuse')
+ %div
+ = render 'shared/file_picker_button', f: f, field: :screenshot, help_text: _("Screenshot must be less than 1 MB."), mime_types: valid_image_mimetypes
+
.form-group.row
.col-lg-8
= f.label :reason
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml
index eeedd58ec15..aa5543700a7 100644
--- a/app/views/admin/abuse_reports/_abuse_report.html.haml
+++ b/app/views/admin/abuse_reports/_abuse_report.html.haml
@@ -7,30 +7,33 @@
- if user
= link_to user.name, user
.light.small
- = _('Joined %{time_ago}').html_safe % { time_ago: time_ago_with_tooltip(user.created_at) }
+ = html_escape(_('Joined %{time_ago}')) % { time_ago: time_ago_with_tooltip(user.created_at).html_safe }
- else
= _('(removed)')
%td
- %strong.subheading.d-block.d-sm-none
- = _('Reported by %{reporter}').html_safe % { reporter: reporter ? link_to(reporter.name, reporter) : _('(removed)') }
- .light.gl-display-none.gl-sm-display-block
- = link_to(reporter.name, reporter)
- .light.small
- = time_ago_with_tooltip(abuse_report.created_at)
+ - if reporter
+ %strong.subheading.d-block.d-sm-none
+ = _('Reported by %{reporter}').html_safe % { reporter: reporter ? link_to(reporter.name, reporter) : _('(removed)') }
+ .light.gl-display-none.gl-sm-display-block
+ = link_to(reporter.name, reporter)
+ .light.small
+ = time_ago_with_tooltip(abuse_report.created_at)
+ - else
+ = _('(removed)')
%td
%strong.subheading.d-block.d-sm-none
= _('Message')
.message
= markdown_field(abuse_report, :message)
%td
- - if user
- = render Pajamas::ButtonComponent.new(href: admin_abuse_report_path(abuse_report, remove_user: true), variant: :danger, block: true, button_options: { data: { confirm: _("USER %{user} WILL BE REMOVED! Are you sure?") % { user: user.name }, confirm_btn_variant: "danger", remote: true, method: :delete }, class: "js-remove-tr gl-mb-5" }) do
+ - if user && user != current_user
+ = render Pajamas::ButtonComponent.new(href: admin_abuse_report_path(abuse_report, remove_user: true), variant: :danger, block: true, button_options: { data: { confirm: _("USER %{user} WILL BE REMOVED! Are you sure?") % { user: user.name }, confirm_btn_variant: "danger", remote: true, method: :delete }, class: "js-remove-tr" }) do
= _('Remove user & report')
- - if user && !user.blocked?
- = render Pajamas::ButtonComponent.new(href: block_admin_user_path(user), block: true, button_options: { data: { confirm: _('USER WILL BE BLOCKED! Are you sure?'), method: :put }, class: "gl-mb-5" }) do
- = _('Block user')
- - else
- = render Pajamas::ButtonComponent.new(href: block_admin_user_path(user), block: true, disabled: true, button_options: { data: { confirm: _('USER WILL BE BLOCKED! Are you sure?'), method: :put }, class: "gl-mb-5" }) do
- = _('Already blocked')
- = render Pajamas::ButtonComponent.new(href: [:admin, abuse_report], block: true, button_options: { data: { remote: true, method: :delete }, class: "js-remove-tr" }) do
- = _('Remove report')
+ - if user.blocked?
+ = render Pajamas::ButtonComponent.new(href: block_admin_user_path(user), block: true, disabled: true, button_options: { data: { confirm: _('USER WILL BE BLOCKED! Are you sure?'), method: :put } }) do
+ = _('Already blocked')
+ - else
+ = render Pajamas::ButtonComponent.new(href: block_admin_user_path(user), block: true, button_options: { data: { confirm: _('USER WILL BE BLOCKED! Are you sure?'), method: :put } }) do
+ = _('Block user')
+ = render Pajamas::ButtonComponent.new(href: [:admin, abuse_report], block: true, button_options: { data: { remote: true, method: :delete }, class: "js-remove-tr" }) do
+ = _('Remove report')
diff --git a/app/views/admin/abuse_reports/index.html.haml b/app/views/admin/abuse_reports/index.html.haml
index 20499a2e3bf..fee3a846849 100644
--- a/app/views/admin/abuse_reports/index.html.haml
+++ b/app/views/admin/abuse_reports/index.html.haml
@@ -2,31 +2,35 @@
%h1.page-title.gl-font-size-h-display= _('Abuse Reports')
-.row-content-block.second-block
- = form_tag admin_abuse_reports_path, method: :get, class: 'filter-form' do
- .filter-categories.flex-fill
- .filter-item.inline
- = dropdown_tag(user_dropdown_label(params[:user_id], 'User'),
- options: { toggle_class: 'js-filter-submit js-user-search',
- title: _('Filter by user'), filter: true, filterInput: 'input#user-search',
- dropdown_class: 'dropdown-menu-selectable dropdown-menu-user js-filter-submit',
- placeholder: _('Search users'),
- data: { current_user: true, field_name: 'user_id' }})
+- if Feature.enabled?(:abuse_reports_list)
+ #js-abuse-reports-list-app{ data: abuse_reports_list_data(@abuse_reports) }
+ = gl_loading_icon(css_class: 'gl-my-5', size: 'md')
+- else
+ .row-content-block.second-block
+ = form_tag admin_abuse_reports_path, method: :get, class: 'filter-form' do
+ .filter-categories.flex-fill
+ .filter-item.inline
+ = dropdown_tag(user_dropdown_label(params[:user_id], 'User'),
+ options: { toggle_class: 'js-filter-submit js-user-search',
+ title: _('Filter by user'), filter: true, filterInput: 'input#user-search',
+ dropdown_class: 'dropdown-menu-selectable dropdown-menu-user js-filter-submit',
+ placeholder: _('Search users'),
+ data: { current_user: true, field_name: 'user_id' }})
-.abuse-reports
- - if @abuse_reports.present?
- .table-holder
- %table.table.responsive-table
- %thead.d-none.d-md-table-header-group
- %tr
- %th= _('User')
- %th= _('Reported by')
- %th.wide= _('Message')
- %th= _('Action')
- = render @abuse_reports
- = paginate @abuse_reports, theme: 'gitlab'
- - else
- .empty-state
- .text-center
- %h4= _("There are no abuse reports!")
- %h3= emoji_icon('tada')
+ .abuse-reports
+ - if @abuse_reports.present?
+ .table-holder
+ %table.table.responsive-table
+ %thead.d-none.d-md-table-header-group
+ %tr
+ %th= _('User')
+ %th= _('Reported by')
+ %th.wide= _('Message')
+ %th= _('Action')
+ = render @abuse_reports
+ = paginate @abuse_reports, theme: 'gitlab'
+ - else
+ .empty-state
+ .text-center
+ %h4= _("There are no abuse reports!")
+ %h3= emoji_icon('tada')
diff --git a/app/views/admin/abuse_reports/show.html.haml b/app/views/admin/abuse_reports/show.html.haml
new file mode 100644
index 00000000000..bd7a1054b5d
--- /dev/null
+++ b/app/views/admin/abuse_reports/show.html.haml
@@ -0,0 +1,6 @@
+- add_to_breadcrumbs _('Abuse Reports'), admin_abuse_reports_path
+- breadcrumb_title @abuse_report.user&.name
+- page_title @abuse_report.user&.name, _('Abuse Reports')
+
+#js-abuse-reports-detail-view{ data: abuse_report_data(@abuse_report) }
+ = gl_loading_icon(css_class: 'gl-my-5', size: 'md')
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 87c251aa10c..df08a1123c7 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -30,6 +30,11 @@
= 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= _('Restart GitLab to apply changes.')
+ .form-group
+ = f.label :remember_me_enabled, _('Remember me'), class: 'label-light'
+ - remember_me_help_link = help_page_path('user/profile/index.md', anchor: 'stay-signed-in-for-two-weeks')
+ - remember_me_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: remember_me_help_link }
+ = f.gitlab_ui_checkbox_component :remember_me_enabled, _('Allow users to extend their session'), help_text: _("Users can select 'Remember me' on sign-in to keep their session active beyond the session duration. %{link_start}Learn more.%{link_end}").html_safe % { link_start: remember_me_help_link_start, link_end: '</a>'.html_safe }
= 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
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index 8fafa52cd4c..0c9d5a5a8df 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -46,6 +46,11 @@
.form-group
= f.gitlab_ui_checkbox_component :protected_ci_variables, s_('AdminSettings|Protect CI/CD variables by default'), help_text: s_('AdminSettings|New CI/CD variables in projects and groups default to protected.')
.form-group
+ = f.label :ci_max_includes, s_('AdminSettings|Maximum includes'), class: 'label-bold'
+ = f.number_field :ci_max_includes, class: 'form-control gl-form-input'
+ .form-text.text-muted
+ = s_('AdminSettings|The maximum number of included files per pipeline.')
+ .form-group
= f.label :ci_config_path, _('Default CI/CD configuration file'), class: 'label-bold'
= f.text_field :default_ci_config_path, class: 'form-control gl-form-input', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
@@ -77,31 +82,28 @@
%fieldset
= f.hidden_field(:plan_id, value: plan.id)
.form-group
- = f.label :ci_pipeline_size, s_('AdminSettings|Maximum number of jobs in a single pipeline')
+ = f.label :ci_pipeline_size, plan_limit_setting_description(:ci_pipeline_size)
= f.number_field :ci_pipeline_size, class: 'form-control gl-form-input'
.form-group
- = f.label :ci_active_jobs, s_('AdminSettings|Total number of jobs in currently active pipelines')
+ = f.label :ci_active_jobs, plan_limit_setting_description(:ci_active_jobs)
= f.number_field :ci_active_jobs, class: 'form-control gl-form-input'
.form-group
- = f.label :ci_active_pipelines, s_('AdminSettings|Maximum number of active pipelines per project')
- = f.number_field :ci_active_pipelines, class: 'form-control gl-form-input'
- .form-group
- = f.label :ci_project_subscriptions, s_('AdminSettings|Maximum number of pipeline subscriptions to and from a project')
+ = f.label :ci_project_subscriptions, plan_limit_setting_description(:ci_project_subscriptions)
= f.number_field :ci_project_subscriptions, class: 'form-control gl-form-input'
.form-group
- = f.label :ci_pipeline_schedules, s_('AdminSettings|Maximum number of pipeline schedules')
+ = f.label :ci_pipeline_schedules, plan_limit_setting_description(:ci_pipeline_schedules)
= f.number_field :ci_pipeline_schedules, class: 'form-control gl-form-input'
.form-group
- = f.label :ci_needs_size_limit, s_('AdminSettings|Maximum number of DAG dependencies that a job can have')
+ = f.label :ci_needs_size_limit, plan_limit_setting_description(:ci_needs_size_limit)
= f.number_field :ci_needs_size_limit, class: 'form-control gl-form-input'
.form-text.text-muted= s_('AdminSettings|This limit cannot be disabled. Set to 0 to block all DAG dependencies.')
.form-group
- = f.label :ci_registered_group_runners, s_('AdminSettings|Maximum number of runners registered per group')
+ = f.label :ci_registered_group_runners, plan_limit_setting_description(:ci_registered_group_runners)
= f.number_field :ci_registered_group_runners, class: 'form-control gl-form-input'
.form-group
- = f.label :ci_registered_project_runners, s_('AdminSettings|Maximum number of runners registered per project')
+ = f.label :ci_registered_project_runners, plan_limit_setting_description(:ci_registered_project_runners)
= f.number_field :ci_registered_project_runners, class: 'form-control gl-form-input'
.form-group
- = f.label :pipeline_hierarchy_size, s_("AdminSettings|Maximum number of downstream pipelines in a pipeline's hierarchy tree")
+ = f.label :pipeline_hierarchy_size, plan_limit_setting_description(:pipeline_hierarchy_size)
= f.number_field :pipeline_hierarchy_size, class: 'form-control gl-form-input'
= f.submit s_('AdminSettings|Save %{name} limits').html_safe % { name: plan.name.capitalize }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_localization.html.haml b/app/views/admin/application_settings/_localization.html.haml
index 9ec4afec484..669c47bafba 100644
--- a/app/views/admin/application_settings/_localization.html.haml
+++ b/app/views/admin/application_settings/_localization.html.haml
@@ -20,7 +20,7 @@
= _('Default language')
= f.select :default_preferred_language, default_preferred_language_choices, {}, class: 'gl-form-select custom-select'
.form-text.text-muted
- = s_('Default language for users who are not logged in.')
+ = _('Default language for users who are not logged in.')
= f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_outbound.html.haml b/app/views/admin/application_settings/_outbound.html.haml
index 1821c8ef4bb..8cb25627dfa 100644
--- a/app/views/admin/application_settings/_outbound.html.haml
+++ b/app/views/admin/application_settings/_outbound.html.haml
@@ -1,25 +1,36 @@
+- deny_all_requests = @application_setting.deny_all_requests_except_allowed
+
= gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-outbound-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
.form-group
+ = f.gitlab_ui_checkbox_component :deny_all_requests_except_allowed,
+ s_('OutboundRequests|Block all requests, except for IP addresses, IP ranges, and domain names defined in the allowlist'),
+ checkbox_options: { class: 'js-deny-all-requests' }
+ = render Pajamas::AlertComponent.new(variant: :warning,
+ dismissible: false,
+ alert_options: { class: "gl-mb-3 js-deny-all-requests-warning #{'gl-display-none' unless deny_all_requests}" }) do |c|
+ - c.with_body do
+ = s_('OutboundRequests|Webhooks and integrations might not work properly.')
= f.gitlab_ui_checkbox_component :allow_local_requests_from_web_hooks_and_services,
- s_('OutboundRequests|Allow requests to the local network from web hooks and services'),
- checkbox_options: { data: { qa_selector: 'allow_requests_from_services_checkbox' } }
+ s_('OutboundRequests|Allow requests to the local network from webhooks and integrations'),
+ checkbox_options: { disabled: deny_all_requests, class: 'js-allow-local-requests', data: { qa_selector: 'allow_requests_from_services_checkbox' } }
= f.gitlab_ui_checkbox_component :allow_local_requests_from_system_hooks,
- s_('OutboundRequests|Allow requests to the local network from system hooks')
+ s_('OutboundRequests|Allow requests to the local network from system hooks'),
+ checkbox_options: { disabled: deny_all_requests, class: 'js-allow-local-requests' }
.form-group
= f.label :outbound_local_requests_allowlist_raw, class: 'label-bold' do
- = s_('OutboundRequests|Local IP addresses and domain names that hooks and services may access')
+ = s_('OutboundRequests|Local IP addresses and domain names that hooks and integrations can access')
= f.text_area :outbound_local_requests_allowlist_raw, placeholder: "example.com, 192.168.1.1, xn--itlab-j1a.com", class: 'form-control gl-form-input', rows: 8
%span.form-text.text-muted
- = s_('OutboundRequests|Requests to these domains and IP addresses are accessible to both system hooks and web hooks even when local requests are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 and 127.0.0.0/28 are supported. Domain wildcards are not supported. To separate entries use commas, semicolons, or newlines. The allowlist can hold a maximum of 1000 entries. Domains must be IDNA encoded.')
- = link_to _('Learn more.'), help_page_path('security/webhooks.md', anchor: 'create-an-allowlist-for-local-requests'), target: '_blank', rel: 'noopener noreferrer'
+ = s_('OutboundRequests|Requests can be made to these IP addresses and domains even when local requests are not allowed. IP ranges such as %{code_start}1:0:0:0:0:0:0:0/124%{code_end} and %{code_start}127.0.0.0/28%{code_end} are supported. Domain wildcards are not supported. To separate entries, use commas, semicolons, or newlines. The allowlist can have a maximum of 1000 entries. Domains must be IDNA-encoded.').html_safe % { code_start: '<code>'.html_safe, code_end: '</code>'.html_safe }
+ = link_to _('Learn more.'), help_page_path('security/webhooks.md', anchor: 'allow-outbound-requests-to-certain-ip-addresses-and-domains'), target: '_blank', rel: 'noopener noreferrer'
.form-group
= f.gitlab_ui_checkbox_component :dns_rebinding_protection_enabled,
- s_('OutboundRequests|Enforce DNS rebinding attack protection'),
- help_text: s_('OutboundRequests|Resolve IP addresses once and uses them to submit requests.')
+ s_('OutboundRequests|Enforce DNS-rebinding attack protection'),
+ help_text: s_('OutboundRequests|Resolve IP addresses for outbound requests to prevent DNS-rebinding attacks.')
= f.submit _('Save changes'), pajamas_button: true, data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/_projects_api_limits.html.haml b/app/views/admin/application_settings/_projects_api_limits.html.haml
new file mode 100644
index 00000000000..4efab4d77a9
--- /dev/null
+++ b/app/views/admin/application_settings/_projects_api_limits.html.haml
@@ -0,0 +1,21 @@
+%section.settings.as-projects-api-limits.no-animate#js-projects-api-limits-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
+ = _('Projects API rate limit')
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Set the per-IP address rate limit applicable to unauthenticated requests for getting a list of projects via the API.')
+ = link_to _('Learn more.'), help_page_path('user/admin_area/settings/rate_limit_on_projects_api.md'), target: '_blank', rel: 'noopener noreferrer'
+ .settings-content
+ = gitlab_ui_form_for @application_setting, url: network_admin_application_settings_path(anchor: 'js-projects-api-limits-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting)
+
+ %fieldset
+ .form-group
+ = f.label :projects_api_rate_limit_unauthenticated, _('Maximum requests per 10 minutes per IP address'), class: 'label-bold'
+ = f.number_field :projects_api_rate_limit_unauthenticated, class: 'form-control gl-form-input'
+ .form-text.gl-text-gray-600
+ = _("Set this number to 0 to disable the limit.")
+
+ = f.submit _('Save changes'), data: { qa_selector: 'save_changes_button' }, pajamas_button: true
diff --git a/app/views/admin/application_settings/_realtime.html.haml b/app/views/admin/application_settings/_realtime.html.haml
index 6a7ec05d206..2b8b023baea 100644
--- a/app/views/admin/application_settings/_realtime.html.haml
+++ b/app/views/admin/application_settings/_realtime.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-realtime-settings'), html: { class: 'fieldset-form' } do |f|
+= gitlab_ui_form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-realtime-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
@@ -8,4 +8,4 @@
.form-text.text-muted
= _('Multiplier to apply to polling intervals. Decimal values are supported. Defaults to 1.')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_registry.html.haml b/app/views/admin/application_settings/_registry.html.haml
index 6a8ef86a56e..16b2a0b8fc6 100644
--- a/app/views/admin/application_settings/_registry.html.haml
+++ b/app/views/admin/application_settings/_registry.html.haml
@@ -6,9 +6,9 @@
= f.label :container_registry_token_expire_delay, _('Authorization token duration (minutes)'), class: 'label-bold'
= f.number_field :container_registry_token_expire_delay, class: 'form-control gl-form-input'
.form-group
- - label = _("Enable container expiration and retention policies for projects created earlier than GitLab 12.7.")
+ - label = _("Enable cleanup policies for projects created earlier than GitLab 12.7.")
- label_link = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy')
- - help_text = _("Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project.")
+ - help_text = _("Existing projects will be able to use cleanup policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project.")
- help_link = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'use-with-external-container-registries')
= f.gitlab_ui_checkbox_component :container_expiration_policies_enable_historic_entries,
'%{label} %{label_link}'.html_safe % { label: label, label_link: label_link },
@@ -29,9 +29,9 @@
.form-text.text-muted
= _("The maximum number of tags that a single worker accepts for cleanup. If the number of tags goes above this limit, the list of tags to delete is truncated to this number. To remove this limit, set it to 0.")
.form-group
- - help_text = _("When enabled, cleanup polices execute faster but put more load on Redis.")
+ - help_text = _("When enabled, cleanup policies execute faster but put more load on Redis.")
- help_link = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'set-cleanup-limits-to-conserve-resources')
- = f.gitlab_ui_checkbox_component :container_registry_expiration_policies_caching, _("Enable container expiration caching."),
+ = f.gitlab_ui_checkbox_component :container_registry_expiration_policies_caching, _("Enable cleanup policy caching."),
help_text: '%{help_text} %{help_link}'.html_safe % { help_text: help_text, help_link: help_link }
= f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_repository_check.html.haml b/app/views/admin/application_settings/_repository_check.html.haml
index b67cc29f296..5751ae9059a 100644
--- a/app/views/admin/application_settings/_repository_check.html.haml
+++ b/app/views/admin/application_settings/_repository_check.html.haml
@@ -13,7 +13,9 @@
= _("If you get a lot of false alarms from repository checks, you can clear all repository check information from the database.")
- clear_repository_checks_link = _('Clear all repository checks')
- clear_repository_checks_message = _('This clears repository check states for all projects in the database and cannot be undone. Are you sure?')
- = link_to clear_repository_checks_link, clear_repository_check_states_admin_application_settings_path, data: { confirm: clear_repository_checks_message, confirm_btn_variant: 'danger' }, aria: { label: _('Clear repository checks') }, method: :put, class: "gl-button btn btn-sm btn-danger gl-mt-3"
+ = render Pajamas::ButtonComponent.new(variant: :danger, href: clear_repository_check_states_admin_application_settings_path, method: :put, button_options: { class: 'btn-sm gl-mt-3', data: { confirm: clear_repository_checks_message, confirm_btn_variant: 'danger' }, aria: { label: _('Clear repository checks') } }) do
+ = clear_repository_checks_link
+
.sub-section
%h4= _("Housekeeping")
diff --git a/app/views/admin/application_settings/_runner_registrars_form.html.haml b/app/views/admin/application_settings/_runner_registrars_form.html.haml
index baf7c5de7b9..53832e93ed2 100644
--- a/app/views/admin/application_settings/_runner_registrars_form.html.haml
+++ b/app/views/admin/application_settings/_runner_registrars_form.html.haml
@@ -2,7 +2,18 @@
= form_errors(@application_setting)
%fieldset
+ .form-group
+ %h5
+ = s_('Runners|Runner version management')
+ %span.form-text.gl-mb-3.gl-mt-0
+ - help_text = s_('Runners|Official runner version data is periodically fetched from GitLab.com to determine whether the runners need upgrades.')
+ - learn_more_link = link_to _('Learn more.'), help_page_path('ci/runners/configure_runners.md', anchor: 'determine-which-runners-need-to-be-upgraded'), target: '_blank', rel: 'noopener noreferrer'
+ = f.gitlab_ui_checkbox_component :update_runner_versions_enabled,
+ s_('Runners|Fetch GitLab Runner release version data from GitLab.com'),
+ help_text: '%{help_text} %{learn_more_link}'.html_safe % { help_text: help_text, learn_more_link: learn_more_link }
.gl-form-group
+ %h5
+ = s_('Runners|Runner registration')
%span.form-text.gl-mb-3.gl-mt-0
= s_('Runners|If both settings are disabled, new runners cannot be registered.')
= link_to _('Learn more.'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/admin/application_settings/_slack.html.haml b/app/views/admin/application_settings/_slack.html.haml
new file mode 100644
index 00000000000..69a5e284b4c
--- /dev/null
+++ b/app/views/admin/application_settings/_slack.html.haml
@@ -0,0 +1,33 @@
+- return unless Gitlab.dev_or_test_env? || Gitlab.com?
+
+- expanded = integration_expanded?('slack_app_')
+%section.settings.as-slack.no-animate#js-slack-settings{ class: ('expanded' if expanded) }
+ .settings-header
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
+ = _('Slack application')
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
+ = expanded ? _('Collapse') : _('Expand')
+ %p
+ = _('Slack integration allows you to interact with GitLab via slash commands in a chat window.')
+ .settings-content
+ = gitlab_ui_form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-slack-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting) if expanded
+
+ %fieldset
+ .form-group
+ = f.gitlab_ui_checkbox_component :slack_app_enabled, s_('ApplicationSettings|Enable Slack application'),
+ help_text: s_('ApplicationSettings|This option is only available on GitLab.com')
+ .form-group
+ = f.label :slack_app_id, s_('SlackIntegration|Client ID'), class: 'label-bold'
+ = f.text_field :slack_app_id, class: 'form-control gl-form-input'
+ .form-group
+ = f.label :slack_app_secret, s_('SlackIntegration|Client secret'), class: 'label-bold'
+ = f.text_field :slack_app_secret, class: 'form-control gl-form-input'
+ .form-group
+ = f.label :slack_app_signing_secret, s_('SlackIntegration|Signing secret'), class: 'label-bold'
+ = f.text_field :slack_app_signing_secret, class: 'form-control gl-form-input'
+ .form-group
+ = f.label :slack_app_verification_token, s_('SlackIntegration|Verification token'), class: 'label-bold'
+ = f.text_field :slack_app_verification_token, class: 'form-control gl-form-input'
+
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml
index 0305a9487ca..7142128d2cd 100644
--- a/app/views/admin/application_settings/_visibility_and_access.html.haml
+++ b/app/views/admin/application_settings/_visibility_and_access.html.haml
@@ -28,16 +28,16 @@
%span.form-text.gl-mt-0.gl-mb-3#import-sources-help
= _('Code can be imported from enabled sources during project creation. OmniAuth must be configured for GitHub')
= link_to sprite_icon('question-o'), help_page_path("integration/github")
- , Bitbucket
+ and Bitbucket
= link_to sprite_icon('question-o'), help_page_path("integration/bitbucket")
- and GitLab.com
- = link_to sprite_icon('question-o'), help_page_path("integration/gitlab")
= hidden_field_tag 'application_setting[import_sources][]'
- import_sources_checkboxes(f).each do |source|
= source
= render_if_exists 'admin/application_settings/ldap_access_setting', form: f
+ = render_if_exists 'admin/application_settings/saml_group_locks_setting', form: f
+
.form-group{ data: { testid: 'project-export' } }
= f.label :project_export, s_('AdminSettings|Project export'), class: 'label-bold'
= f.gitlab_ui_checkbox_component :project_export_enabled, s_('AdminSettings|Enabled')
diff --git a/app/views/admin/application_settings/appearances/_form.html.haml b/app/views/admin/application_settings/appearances/_form.html.haml
index 6c6334905ca..1b0e974a0ca 100644
--- a/app/views/admin/application_settings/appearances/_form.html.haml
+++ b/app/views/admin/application_settings/appearances/_form.html.haml
@@ -16,7 +16,8 @@
= image_tag @appearance.header_logo_path, class: 'appearance-light-logo-preview'
- if @appearance.persisted?
%br
- = link_to _('Remove header logo'), header_logos_admin_application_settings_appearances_path, data: { confirm: _("Header logo will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove header logo') }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm"
+ = render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: header_logos_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Header logo will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove header logo') } }) do
+ = _('Remove header logo')
%hr
= f.hidden_field :header_logo_cache
= f.file_field :header_logo, class: "", accept: 'image/*'
@@ -35,7 +36,8 @@
= image_tag @appearance.favicon_path, class: 'appearance-light-logo-preview'
- if @appearance.persisted?
%br
- = link_to _('Remove favicon'), favicon_admin_application_settings_appearances_path, data: { confirm: _("Favicon will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove favicon') }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm"
+ = render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: favicon_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Favicon will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove favicon') } }) do
+ = _('Remove favicon')
%hr
= f.hidden_field :favicon_cache
= f.file_field :favicon, class: '', accept: 'image/*'
@@ -67,7 +69,8 @@
= image_tag @appearance.logo_path, class: 'appearance-logo-preview'
- if @appearance.persisted?
%br
- = link_to _('Remove logo'), logo_admin_application_settings_appearances_path, data: { confirm: _("Logo will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove logo') }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm remove-logo"
+ = render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: logo_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Logo will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove logo') } }) do
+ = _('Remove logo')
%hr
= f.hidden_field :logo_cache
= f.file_field :logo, class: "", accept: 'image/*'
@@ -98,7 +101,8 @@
= image_tag @appearance.pwa_icon_path, class: 'appearance-pwa-icon-preview'
- if @appearance.persisted?
%br
- = link_to _('Remove icon'), pwa_icon_admin_application_settings_appearances_path, data: { confirm: _("Icon will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove icon') }, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm remove-logo"
+ = render Pajamas::ButtonComponent.new(variant: :danger, category: :secondary, size: :small, method: :delete, href: pwa_icon_admin_application_settings_appearances_path, button_options: { data: { confirm: _("Icon will be removed. Are you sure?"), confirm_btn_variant: "danger" }, aria: { label: _('Remove icon') } }) do
+ = _('Remove icon')
%hr
= f.hidden_field :pwa_icon_cache
= f.file_field :pwa_icon, class: "", accept: 'image/*'
diff --git a/app/views/admin/application_settings/appearances/show.html.haml b/app/views/admin/application_settings/appearances/show.html.haml
index 1e55190d53b..82fdd13672a 100644
--- a/app/views/admin/application_settings/appearances/show.html.haml
+++ b/app/views/admin/application_settings/appearances/show.html.haml
@@ -1,5 +1,5 @@
- page_title _("Appearance")
-- @content_class = "limit-container-width" unless fluid_layout
- add_page_specific_style 'page_bundles/settings'
+- @force_desktop_expanded_sidebar = true
= render 'form'
diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml
index bd0ce766f81..a9a16f72ebe 100644
--- a/app/views/admin/application_settings/ci_cd.html.haml
+++ b/app/views/admin/application_settings/ci_cd.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("CI/CD")
- page_title _("CI/CD")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) }
.settings-header
@@ -42,7 +42,7 @@
%section.settings.as-runner.no-animate#js-runner-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
- = s_('Runners|Runner registration')
+ = s_('Runners|Runners')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded_by_default? ? 'Collapse' : 'Expand'
.settings-content
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index a4af1913d22..e6c27c1bc84 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("General")
- page_title _("General")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.settings.as-visibility-access.no-animate#js-visibility-settings{ class: ('expanded' if expanded_by_default?), data: { testid: 'admin-visibility-access-settings' } }
.settings-header
diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml
index fd1ad5cd304..68c62eb98ee 100644
--- a/app/views/admin/application_settings/integrations.html.haml
+++ b/app/views/admin/application_settings/integrations.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title s_('Integrations|Instance-level integration management')
- page_title s_('Integrations|Instance-level integration management')
- add_page_specific_style 'page_bundles/settings'
-- @content_class = 'limit-container-width' unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%h3= s_('Integrations|Instance-level integration management')
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 b5981578866..8bc5d5cbaa6 100644
--- a/app/views/admin/application_settings/metrics_and_profiling.html.haml
+++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml
@@ -3,7 +3,7 @@
- breadcrumb_title _("Metrics and profiling")
- page_title _("Metrics and profiling")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.settings.as-prometheus.no-animate#js-prometheus-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
@@ -41,8 +41,6 @@
.settings-content
= render 'performance_bar'
-.js-self-monitoring-settings{ data: self_monitoring_project_data }
-
%section.settings.as-usage.no-animate#js-usage-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'usage_statistics_settings_content' } }
.settings-header#usage-statistics
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index 779263b439f..18ce7c1ceba 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Network")
- page_title _("Network")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.settings.as-performance.no-animate#js-performance-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
@@ -92,7 +92,7 @@
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = s_('OutboundRequests|Allow requests to the local network from hooks and services.')
+ = s_('OutboundRequests|Allow requests to the local network from hooks and integrations.')
= link_to _('Learn more.'), help_page_path('security/webhooks.md'), target: '_blank', rel: 'noopener noreferrer'
.settings-content
= render 'outbound'
@@ -146,6 +146,8 @@
.settings-content
= render 'users_api_limits'
+= render 'projects_api_limits'
+
%section.settings.as-import-export-limits.no-animate#js-import-export-limits-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
diff --git a/app/views/admin/application_settings/preferences.html.haml b/app/views/admin/application_settings/preferences.html.haml
index dd6666542ca..ab59e05c10f 100644
--- a/app/views/admin/application_settings/preferences.html.haml
+++ b/app/views/admin/application_settings/preferences.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Preferences")
- page_title _("Preferences")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.settings.as-email.no-animate#js-email-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'email_content' } }
.settings-header
diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml
index 3d803e95cd0..6ea2fb80505 100644
--- a/app/views/admin/application_settings/reporting.html.haml
+++ b/app/views/admin/application_settings/reporting.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Reporting")
- page_title _("Reporting")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.settings.as-spam.no-animate#js-spam-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/application_settings/repository.html.haml b/app/views/admin/application_settings/repository.html.haml
index 50798ad476c..1907544ea14 100644
--- a/app/views/admin/application_settings/repository.html.haml
+++ b/app/views/admin/application_settings/repository.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Repository")
- page_title _("Repository")
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.settings.as-default-branch-name.no-animate#js-default-branch-name{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/application_settings/service_usage_data.html.haml b/app/views/admin/application_settings/service_usage_data.html.haml
index d6860cc08ac..e42c1091bf2 100644
--- a/app/views/admin/application_settings/service_usage_data.html.haml
+++ b/app/views/admin/application_settings/service_usage_data.html.haml
@@ -3,8 +3,8 @@
- breadcrumb_title name
- page_title name
- add_page_specific_style 'page_bundles/settings'
-- @content_class = "limit-container-width" unless fluid_layout
- payload_class = 'js-service-ping-payload'
+- @force_desktop_expanded_sidebar = true
%section.js-search-settings-section
%h3= name
@@ -22,7 +22,7 @@
dismissible: false,
title: _('Service Ping payload not found in the application cache')) do |c|
- = c.body do
+ - c.with_body do
- enable_service_ping_link_url = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'enable-or-disable-usage-statistics')
- enable_service_ping_link = '<a href="%{url}">'.html_safe % { url: enable_service_ping_link_url }
- generate_manually_link_url = help_page_path('development/service_ping/troubleshooting', anchor: 'generate-service-ping')
diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml
index 83347034cc5..a8d5a45041d 100644
--- a/app/views/admin/applications/_form.html.haml
+++ b/app/views/admin/applications/_form.html.haml
@@ -2,39 +2,34 @@
= form_errors(application)
= content_tag :div, class: 'form-group row' do
- .col-sm-2.col-form-label
+ .col-12
= f.label :name
- .col-sm-10
- = f.text_field :name, class: 'form-control gl-form-input'
+ = f.text_field :name, class: 'form-control gl-form-input', data: { qa_selector: 'name_field' }
= doorkeeper_errors_for application, :name
= content_tag :div, class: 'form-group row' do
- .col-sm-2.col-form-label
+ .col-12
= f.label :redirect_uri
- .col-sm-10
- = f.text_area :redirect_uri, class: 'form-control gl-form-input'
+ = f.text_area :redirect_uri, class: 'form-control gl-form-input', data: { qa_selector: 'redirect_uri_field' }
= doorkeeper_errors_for application, :redirect_uri
%span.form-text.text-muted
Use one line per URI
= content_tag :div, class: 'form-group row' do
- .col-sm-2.col-form-label.pt-0
+ .col-12
= f.label :trusted
- .col-sm-10
- = f.gitlab_ui_checkbox_component :trusted, _('Trusted applications are automatically authorized on GitLab OAuth flow. It\'s highly recommended for the security of users that trusted applications have the confidential setting set to true.')
+ = f.gitlab_ui_checkbox_component :trusted, _('Trusted applications are automatically authorized on GitLab OAuth flow. It\'s highly recommended for the security of users that trusted applications have the confidential setting set to true.'), checkbox_options: { data: { qa_selector: 'trusted_checkbox' } }
= content_tag :div, class: 'form-group row' do
- .col-sm-2.col-form-label.pt-0
+ .col-12
= f.label :confidential
- .col-sm-10
= f.gitlab_ui_checkbox_component :confidential, _('The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.')
.form-group.row
- .col-sm-2.col-form-label.pt-0
+ .col-12
= f.label :scopes
- .col-sm-10
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes, f: f
- .form-actions
- = f.submit _('Save application'), pajamas_button: true
+ .gl-mt-5
+ = f.submit _('Save application'), pajamas_button: true, data: { qa_selector: 'save_application_button' }
= link_to _('Cancel'), admin_applications_path, class: "gl-button btn btn-default btn-cancel"
diff --git a/app/views/admin/applications/index.html.haml b/app/views/admin/applications/index.html.haml
index d6a0974d10f..e32a50e252d 100644
--- a/app/views/admin/applications/index.html.haml
+++ b/app/views/admin/applications/index.html.haml
@@ -10,17 +10,17 @@
- if @applications.empty?
%section.empty-state.gl-text-center.gl-display-flex.gl-flex-direction-column
.svg-content.svg-150
- = image_tag 'illustrations/empty-state/empty-admin-apps.svg', class: 'gl-max-w-full'
+ = image_tag 'illustrations/empty-state/empty-admin-apps-md.svg', class: 'gl-max-w-full'
.gl-max-w-full.gl-m-auto
%h1.h4.gl-font-size-h-display= s_('AdminArea|No applications found')
- = render Pajamas::ButtonComponent.new(href: new_admin_application_path, variant: :confirm) do
- = s_('New application')
+ = render Pajamas::ButtonComponent.new(href: new_admin_application_path, variant: :confirm, button_options: { data: { qa_selector: 'new_application_button' } }) do
+ = _('New application')
- else
%hr
- = render Pajamas::ButtonComponent.new(href: new_admin_application_path, variant: :confirm) do
- = s_('New application')
+ = render Pajamas::ButtonComponent.new(href: new_admin_application_path, variant: :confirm, button_options: { data: { qa_selector: 'new_application_button' } }) do
+ = _('New application')
.table-responsive
%table.b-table.gl-table.gl-w-full{ role: 'table' }
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
index 212e3eeb951..b93a3c5d7fe 100644
--- a/app/views/admin/applications/show.html.haml
+++ b/app/views/admin/applications/show.html.haml
@@ -7,4 +7,5 @@
edit_path: edit_admin_application_path(@application),
delete_path: admin_application_path(@application),
index_path: admin_applications_path,
+ renew_path: renew_admin_application_path(@application),
show_trusted_row: true
diff --git a/app/views/admin/background_migrations/index.html.haml b/app/views/admin/background_migrations/index.html.haml
index 0f76fdce416..9550ea2884e 100644
--- a/app/views/admin/background_migrations/index.html.haml
+++ b/app/views/admin/background_migrations/index.html.haml
@@ -5,7 +5,7 @@
.gl-flex-grow-1
%h3= s_('BackgroundMigrations|Background Migrations')
%p.light.gl-mb-0
- - learnmore_link = help_page_path('user/admin_area/monitoring/background_migrations')
+ - learnmore_link = help_page_path('update/background_migrations')
- learnmore_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: learnmore_link }
= html_escape(s_('BackgroundMigrations|Background migrations are used to perform data migrations whenever a migration exceeds the time limits in our guidelines. %{linkStart}Learn more%{linkEnd}')) % { linkStart: learnmore_link_start, linkEnd: '</a>'.html_safe }
@@ -17,6 +17,9 @@
= gl_tab_link_to admin_background_migrations_path({ tab: nil, database: params[:database] }), item_active: @current_tab == 'queued' do
= _('Queued')
= gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['queued'])
+ = gl_tab_link_to admin_background_migrations_path({ tab: 'finalizing', database: params[:database] }), item_active: @current_tab == 'finalizing' do
+ = _('Finalizing')
+ = gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['finalizing'])
= gl_tab_link_to admin_background_migrations_path({ tab: 'failed', database: params[:database] }), item_active: @current_tab == 'failed' do
= _('Failed')
= gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['failed'])
diff --git a/app/views/admin/broadcast_messages/_preview.html.haml b/app/views/admin/broadcast_messages/_preview.html.haml
deleted file mode 100644
index 56168926a6e..00000000000
--- a/app/views/admin/broadcast_messages/_preview.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-.js-broadcast-banner-message-preview
- = render "shared/broadcast_message", { message: @broadcast_message, preview: true } do
- = _('Your message here')
diff --git a/app/views/admin/broadcast_messages/edit.html.haml b/app/views/admin/broadcast_messages/edit.html.haml
index 212cc437d3d..63ce08eef85 100644
--- a/app/views/admin/broadcast_messages/edit.html.haml
+++ b/app/views/admin/broadcast_messages/edit.html.haml
@@ -2,15 +2,4 @@
- breadcrumb_title @broadcast_message.id
- page_title _("Broadcast Messages")
-#js-broadcast-message{ data: {
- id: @broadcast_message.id,
- message: @broadcast_message.message,
- broadcast_type: @broadcast_message.broadcast_type,
- theme: @broadcast_message.theme,
- dismissable: @broadcast_message.dismissable.to_s,
- target_access_levels: @broadcast_message.target_access_levels,
- target_path: @broadcast_message.target_path,
- starts_at: @broadcast_message.starts_at,
- ends_at: @broadcast_message.ends_at,
- target_access_level_options: target_access_level_options.to_json,
-} }
+#js-broadcast-message{ data: broadcast_message_data(@broadcast_message) }
diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml
index 010cc493ddf..fb63e761f69 100644
--- a/app/views/admin/broadcast_messages/index.html.haml
+++ b/app/views/admin/broadcast_messages/index.html.haml
@@ -9,5 +9,7 @@
#js-broadcast-messages{ data: {
page: params[:page] || 1,
target_access_level_options: target_access_level_options.to_json,
+ messages_path: admin_broadcast_messages_path,
+ preview_path: preview_admin_broadcast_messages_path,
messages_count: @broadcast_messages.total_count,
messages: admin_broadcast_messages_data(@broadcast_messages) } }
diff --git a/app/views/admin/dashboard/_security_newsletter_callout.html.haml b/app/views/admin/dashboard/_security_newsletter_callout.html.haml
index 7495298936d..0bdeef9acea 100644
--- a/app/views/admin/dashboard/_security_newsletter_callout.html.haml
+++ b/app/views/admin/dashboard/_security_newsletter_callout.html.haml
@@ -7,8 +7,8 @@
dismiss_endpoint: callouts_path,
defer_links: 'true' }},
close_button_options: { data: { testid: 'close-security-newsletter-callout' }}) do |c|
- = c.body do
+ - c.with_body do
= s_('AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates.')
- = c.actions do
+ - c.with_actions do
= render Pajamas::ButtonComponent.new(variant: :confirm, href: 'https://about.gitlab.com/company/preference-center/', target: '_blank', button_options: { class: 'deferred-link gl-alert-action', rel: 'noreferrer noopener' }) 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 8afddd99451..4973c0f985c 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -26,7 +26,7 @@
footer_options: { class: 'gl-bg-transparent'} }
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new(**component_params) do |c|
- = c.body do
+ - c.with_body do
%span
.d-flex.align-items-center
= sprite_icon('project', size: 16, css_class: 'gl-text-gray-700')
@@ -34,13 +34,13 @@
.gl-mt-3.text-uppercase= s_('AdminArea|Projects')
= render Pajamas::ButtonComponent.new(href: new_project_path) do
= s_('AdminArea|New project')
- = c.footer do
+ - c.with_footer do
.d-flex.align-items-center
= link_to(s_('AdminArea|View latest projects'), admin_projects_path(sort: 'created_desc'))
= sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new(**component_params) do |c|
- = c.body do
+ - c.with_body do
%span
.d-flex.align-items-center
= sprite_icon('users', size: 16, css_class: 'gl-text-gray-700')
@@ -58,13 +58,13 @@
= link_to(s_('AdminArea|Users statistics'), admin_dashboard_stats_path, class: "text-capitalize gl-ml-2")
= render Pajamas::ButtonComponent.new(href: new_admin_user_path) do
= s_('AdminArea|New user')
- = c.footer do
+ - c.with_footer do
.d-flex.align-items-center
= link_to(s_('AdminArea|View latest users'), admin_users_path({ sort: 'created_desc' }))
= sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new(**component_params) do |c|
- = c.body do
+ - c.with_body do
%span
.d-flex.align-items-center
= sprite_icon('group', size: 16, css_class: 'gl-text-gray-700')
@@ -72,7 +72,7 @@
.gl-mt-3.text-uppercase= s_('AdminArea|Groups')
= render Pajamas::ButtonComponent.new(href: new_admin_group_path) do
= s_('AdminArea|New group')
- = c.footer do
+ - c.with_footer do
.d-flex.align-items-center
= link_to(s_('AdminArea|View latest groups'), admin_groups_path(sort: 'created_desc'))
= sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
@@ -81,7 +81,7 @@
#js-admin-statistics-container
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new do |c|
- = c.body do
+ - c.with_body do
%h4= s_('AdminArea|Features')
= feature_entry(_('Sign up'),
href: general_admin_application_settings_path(anchor: 'js-signup-settings'),
@@ -101,7 +101,7 @@
doc_href: help_page_path('integration/omniauth'))
= feature_entry(_('Reply by email'),
- enabled: Gitlab::IncomingEmail.enabled?,
+ enabled: Gitlab::Email::IncomingEmail.enabled?,
doc_href: help_page_path('administration/reply_by_email'))
= render_if_exists 'admin/dashboard/elastic_and_geo'
@@ -120,13 +120,13 @@
enabled: Gitlab.config.gitlab_ci.shared_runners_enabled)
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new do |c|
- = c.body do
+ - c.with_body do
%h4
= s_('AdminArea|Components')
- if show_version_check?
.float-right
.js-gitlab-version-check-badge{ data: { "size": "lg", "actionable": "true", "version": gitlab_version_check.to_json } }
- = link_to(sprite_icon('question'), "https://gitlab.com/gitlab-org/gitlab/-/blob/master/CHANGELOG.md", class: 'gl-ml-2', target: '_blank', rel: 'noopener noreferrer')
+ = link_to(sprite_icon('question-o'), "https://gitlab.com/gitlab-org/gitlab/-/blob/master/CHANGELOG.md", class: 'gl-ml-2', target: '_blank', rel: 'noopener noreferrer')
%p
= link_to _('GitLab'), general_admin_application_settings_path
%span.float-right
@@ -178,7 +178,7 @@
.row
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new do |c|
- = c.body do
+ - c.with_body do
%h4= s_('AdminArea|Latest projects')
- @projects.each do |project|
.gl-display-flex.gl-py-3
@@ -188,7 +188,7 @@
#{time_ago_with_tooltip(project.created_at)}
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new do |c|
- = c.body do
+ - c.with_body do
%h4= s_('AdminArea|Latest users')
- @users.each do |user|
.gl-display-flex.gl-py-3
@@ -199,7 +199,7 @@
#{time_ago_with_tooltip(user.created_at)}
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new do |c|
- = c.body do
+ - c.with_body do
%h4= s_('AdminArea|Latest groups')
- @groups.each do |group|
.gl-display-flex.gl-py-3
diff --git a/app/views/admin/dev_ops_report/show.html.haml b/app/views/admin/dev_ops_report/show.html.haml
index a2425b93ad3..c079dd6b581 100644
--- a/app/views/admin/dev_ops_report/show.html.haml
+++ b/app/views/admin/dev_ops_report/show.html.haml
@@ -1,10 +1,9 @@
- page_title _('DevOps Reports')
-- add_page_specific_style 'page_bundles/dev_ops_report'
+- add_page_specific_style 'page_bundles/dev_ops_reports'
-.container
- .gl-mt-3
- - if show_adoption?
- = render_if_exists 'admin/dev_ops_report/devops_tabs'
- - else
- = render 'score'
+.gl-mt-3
+ - if show_adoption?
+ = render_if_exists 'admin/dev_ops_report/devops_tabs'
+ - else
+ = render 'score'
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 20ee8c9f310..b708564e23a 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -1,11 +1,11 @@
= gitlab_ui_form_for [:admin, @group] do |f|
= form_errors(@group)
= render ::Layouts::HorizontalSectionComponent.new(options: { class: 'gl-mb-6' }) do |c|
- = c.title { _('Naming, visibility') }
- = c.description do
+ - c.with_title { _('Naming, visibility') }
+ - c.with_description do
= _('Update your group name, description, avatar, and visibility.')
= link_to _('Learn more about groups.'), help_page_path('user/group/index')
- = c.body do
+ - c.with_body do
= render 'shared/groups/group_name_and_path_fields', f: f
= render 'shared/group_form_description', f: f
.form-group.gl-form-group{ role: 'group' }
@@ -14,10 +14,10 @@
= render 'shared/old_visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group, with_label: false
= render ::Layouts::HorizontalSectionComponent.new(options: { class: 'gl-pb-3 gl-mb-6' }) do |c|
- = c.title { _('Permissions and group features') }
- = c.description do
+ - c.with_title { _('Permissions and group features') }
+ - c.with_description do
= _('Configure advanced permissions, Large File Storage, two-factor authentication, and CI/CD settings.')
- = c.body do
+ - c.with_body do
= render_if_exists 'shared/old_repository_size_limit_setting', form: f, type: :group
= render_if_exists 'admin/namespace_plan', f: f
.form-group.gl-form-group{ role: 'group' }
@@ -26,13 +26,13 @@
= render_if_exists 'namespaces/shared_runners_minutes_settings', group: @group, form: f
= render ::Layouts::HorizontalSectionComponent.new(border: false, options: { class: 'gl-pb-3' }) do |c|
- = c.title { _('Admin notes') }
- = c.body do
+ - c.with_title { _('Admin notes') }
+ - c.with_body do
= render 'shared/admin/admin_note_form', f: f
- if @group.new_record?
= render Pajamas::AlertComponent.new(dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= render 'shared/group_tips'
.gl-mt-5
= f.submit _('Create group'), pajamas_button: true
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index f9ebda2bc21..20d24161c57 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -1,10 +1,9 @@
- group = local_assigns.fetch(:group)
%li.group-row.gl-py-3.gl-align-items-center{ class: 'gl-display-flex!', data: { qa_selector: 'group_row_content' } }
- .avatar-container.rect-avatar.s40.gl-flex-shrink-0
- = group_icon(group, class: "avatar s40")
+ = render Pajamas::AvatarComponent.new(group, size: 32, alt: '')
- .gl-min-w-0.gl-flex-grow-1
+ .gl-min-w-0.gl-flex-grow-1.gl-ml-3
.title
= link_to [:admin, group], class: 'group-name', data: { qa_selector: 'group_name_link' } do
= group.full_name
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index c8b0704c35d..4ba69126906 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -15,13 +15,12 @@
.row
.col-md-6
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
- - c.header do
+ - c.with_header do
= _('Group info:')
- - c.body do
+ - c.with_body do
%ul.content-list.content-list-items-padding
%li
- .avatar-container.rect-avatar.s60
- = group_icon(@group, class: "avatar s60")
+ = render Pajamas::AvatarComponent.new(@group, size: 64, alt: '')
%li
%span.light= _('Name:')
%strong
@@ -70,10 +69,10 @@
= render_if_exists 'ldap_group_links/ldap_group_links_show', group: @group
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
- - c.header do
+ - c.with_header do
= _('Projects')
= gl_badge_tag @group.projects.count
- - c.body do
+ - c.with_body do
%ul.content-list.content-list-items-padding
- @projects.each do |project|
%li
@@ -83,16 +82,16 @@
%span.float-right.light
%span.monospace= project.full_path + '.git'
- unless @projects.size < Kaminari.config.default_per_page
- - c.footer do
+ - c.with_footer do
= paginate @projects, param_name: 'projects_page', theme: 'gitlab'
- shared_projects = @group.shared_projects.sort_by(&:name)
- unless shared_projects.empty?
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
- - c.header do
+ - c.with_header do
= _('Projects shared with %{group_name}') % { group_name: @group.name }
= gl_badge_tag shared_projects.size
- - c.body do
+ - c.with_body do
%ul.content-list.content-list-items-padding
- shared_projects.each do |project|
%li
@@ -109,11 +108,11 @@
= render 'shared/members/requests', membership_source: @group, group: @group, requesters: @requesters, force_mobile_view: true
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
- - c.header do
+ - c.with_header do
= html_escape(_("%{group_name} group members")) % { group_name: "<strong>#{html_escape(@group.name)}</strong>".html_safe }
= gl_badge_tag @group.users_count
= render 'shared/members/manage_access_button', path: group_group_members_path(@group)
- - c.body do
+ - c.with_body do
%ul.content-list.group-users-list.members-list
= render partial: 'shared/members/member',
collection: @members, as: :member,
@@ -121,5 +120,5 @@
group: @group,
current_user_is_group_owner: current_user_is_group_owner }
- unless @members.size < Kaminari.config.default_per_page
- - c.footer do
+ - c.with_footer do
= paginate @members, param_name: 'members_page', theme: 'gitlab'
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
index 98427cb6419..662234bf56a 100644
--- a/app/views/admin/health_check/show.html.haml
+++ b/app/views/admin/health_check/show.html.haml
@@ -8,9 +8,8 @@
#{ s_('HealthCheck|Access token is') }
%code#health-check-token= Gitlab::CurrentSettings.health_check_access_token
.gl-mt-3
- = button_to _("Reset health check access token"), reset_health_check_token_admin_application_settings_path,
- method: :put, class: 'gl-button btn btn-default',
- data: { confirm: _('Are you sure you want to reset the health check token?') }
+ = render Pajamas::ButtonComponent.new(href: reset_health_check_token_admin_application_settings_path, method: :put, button_options: { data: { confirm: _('Are you sure you want to reset the health check token?') } }) do
+ = _("Reset health check access token")
%p.light
#{ _('Health information can be retrieved from the following endpoints. More information is available') }
= link_to s_('More information is available|here'), help_page_path('user/admin_area/monitoring/health_check')
@@ -24,7 +23,7 @@
= render_if_exists 'admin/health_check/health_check_url'
%hr
= render Pajamas::CardComponent.new do |c|
- = c.header do
+ - c.with_header do
Current Status:
- if no_errors
= sprite_icon('check', css_class: 'cgreen')
@@ -32,7 +31,7 @@
- else
= sprite_icon('warning-solid', css_class: 'cred')
#{ s_('HealthCheck|Unhealthy') }
- = c.body do
+ - c.with_body do
- if no_errors
#{ s_('HealthCheck|No Health Problems Detected') }
- else
diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml
index 333c865629f..f4f64eadf21 100644
--- a/app/views/admin/labels/_label.html.haml
+++ b/app/views/admin/labels/_label.html.haml
@@ -1,7 +1,17 @@
-%li.label-list-item{ id: dom_id(label) }
- = render "shared/label_row", label: label.present(issuable_subject: nil)
- .label-actions-list
- = link_to edit_admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary label-action has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria: { label: _('Edit') } do
- = sprite_icon('pencil')
- = link_to admin_label_path(label), class: 'btn btn-default gl-button btn-default-tertiary hover-red js-remove-label label-action has-tooltip', title: _('Delete'), data: { placement: 'bottom', confirm: _('Are you sure you want to delete this label?'), confirm_btn_variant: 'danger' }, aria: { label: _('Delete label') }, method: :delete, remote: true do
- = sprite_icon('remove')
+%li.label-list-item.gl-list-style-none.gl-py-3{ id: dom_id(label) }
+ .label-content.gl-px-3.gl-py-2.gl-rounded-base
+ = render "shared/label_row", label: label.present(issuable_subject: nil)
+ .label-actions-list.gl-display-inline-block
+ .dropdown
+ = render Pajamas::ButtonComponent.new(category: :tertiary,
+ size: :small,
+ icon: 'ellipsis_v',
+ button_options: { class: 'js-label-options-dropdown gl-ml-3', 'aria_label': _('Label actions dropdown'), title: _('Label actions dropdown'), data: { toggle: 'dropdown' } })
+ .dropdown-menu.dropdown-menu-right
+ %ul
+ %li
+ = link_to edit_admin_label_path(label), class: 'btn gl-btn label-action dropdown-item btn-link' do
+ = _('Edit')
+ %li
+ = link_to admin_label_path(label), class: 'btn gl-btn js-remove-label dropdown-item btn-link gl-text-red-500!', data: { confirm: _('Are you sure you want to delete this label?'), confirm_btn_variant: 'danger' }, aria: { label: _('Delete label') }, method: :delete, remote: true do
+ = _('Delete')
diff --git a/app/views/admin/labels/index.html.haml b/app/views/admin/labels/index.html.haml
index 8d6df064c3c..8680bae5207 100644
--- a/app/views/admin/labels/index.html.haml
+++ b/app/views/admin/labels/index.html.haml
@@ -1,33 +1,34 @@
- page_title _("Labels")
-%div
- = render Pajamas::ButtonComponent.new(variant: :confirm,
- href: new_admin_label_path,
- button_options: { class: 'float-right' }) do
- = _('New label')
- %h1.page-title.gl-font-size-h-display
- = _('Labels')
-%hr
-- if @labels.present?
- .labels.labels-container.admin-labels.js-admin-labels-container.gl-bg-gray-10.gl-border-solid.gl-border-1.gl-border-gray-100
- %ul.manage-labels-list
- = render @labels
+.gl-sm-display-flex.gl-border-bottom-0.gl-mt-4.gl-lg-align-items-center
+ .gl-text-gray-600.gl-flex-grow-1
+ = s_('AdminLabels|Labels created here will be automatically added to new projects.')
+ .nav-controls.gl-mt-2.gl-sm-mt-0.gl-display-flex.gl-align-items-center
+ = render Pajamas::ButtonComponent.new(variant: :confirm,
+ href: new_admin_label_path) do
+ = _('New label')
- = paginate @labels, theme: 'gitlab'
+.labels.labels-container.admin-labels.js-admin-labels-container.gl-mt-4
+ .other-labels.gl-rounded-base.gl-border.gl-bg-gray-10
+ .gl-px-5.gl-py-4.gl-bg-white.gl-rounded-base.gl-border-b{ class: 'gl-rounded-bottom-left-none! gl-rounded-bottom-right-none!' }
+ %h3.card-title.h5.gl-m-0.gl-relative.gl-line-height-24
+ = _('Labels')
+ %ul.manage-labels-list.js-other-labels.gl-px-3.gl-rounded-base
+ - if @labels.present?
+ = render @labels
+ .js-admin-labels-empty-state{ class: ('gl-display-none' if @labels.present?) }
+ %section.row.empty-state.gl-text-center
+ .col-12
+ .svg-content.svg-150
+ = image_tag 'illustrations/empty-state/empty-labels-md.svg'
+ .col-12
+ .gl-mx-auto.gl-my-0.gl-p-5
+ %h1.gl-font-size-h-display.gl-line-height-36.h4
+ = s_('AdminLabels|Define your default set of project labels')
+ %p
+ = s_('AdminLabels|They can be used to categorize issues and merge requests.')
+ .gl-display-flex.gl-flex-wrap.gl-justify-content-center
+ = render Pajamas::ButtonComponent.new(href: new_admin_label_path) do
+ = _('New label')
-.js-admin-labels-empty-state{ class: ('gl-display-none' if @labels.present?) }
- %section.row.empty-state.gl-text-center
- .col-12
- .svg-content
- = image_tag 'illustrations/labels.svg'
- .col-12
- .gl-mx-auto.gl-my-0.gl-p-5
- %h1.gl-font-size-h-display.gl-line-height-36.h4
- = s_('AdminLabels|Define your default set of project labels')
- %p.gl-mb-0
- = s_('AdminLabels|Labels created here will be automatically added to new projects.')
- %p
- = s_('AdminLabels|They can be used to categorize issues and merge requests.')
- .gl-display-flex.gl-flex-wrap.gl-justify-content-center
- = render Pajamas::ButtonComponent.new(href: new_admin_label_path) do
- = _('New label')
+ = paginate @labels, theme: 'gitlab'
diff --git a/app/views/admin/labels/new.html.haml b/app/views/admin/labels/new.html.haml
index 76f9eee717e..c8c3fe7b9af 100644
--- a/app/views/admin/labels/new.html.haml
+++ b/app/views/admin/labels/new.html.haml
@@ -1,5 +1,4 @@
- page_title _("New Label")
%h1.page-title.gl-font-size-h-display
= _('New Label')
-%hr
= render 'shared/labels/form', url: admin_labels_path, back_path: admin_labels_path
diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml
new file mode 100644
index 00000000000..61bf97d8214
--- /dev/null
+++ b/app/views/admin/projects/_form.html.haml
@@ -0,0 +1,38 @@
+= gitlab_ui_form_for [:admin, @project] do |f|
+ = form_errors(@project)
+ = render ::Layouts::HorizontalSectionComponent.new(options: { class: 'gl-pb-3 gl-mb-6' }) do |c|
+ - c.with_title { _('Naming') }
+ - c.with_description do
+ = _('Update your project name and description.')
+ - c.with_body do
+ .form-group.gl-form-group
+ = f.label :name, _('Project name')
+ = f.text_field :name, class: 'form-control gl-form-input gl-md-form-input-md'
+
+ .form-group.gl-form-group
+ = f.label :id, _('Project ID')
+ = f.text_field :id, class: 'form-control gl-form-input gl-md-form-input-sm', readonly: true
+
+ .form-group.gl-form-group
+ = f.label :description, _('Project description (optional)')
+ = f.text_area :description, class: 'form-control gl-form-input gl-form-textarea gl-lg-form-input-xl', rows: 5
+
+ = render ::Layouts::HorizontalSectionComponent.new(options: { class: 'gl-pb-3 gl-mb-6' }) do |c|
+ - c.with_title { _('Permissions and project features') }
+ - c.with_description do
+ = _('Configure advanced permissions')
+ - c.with_body do
+ - if @project.project_setting.present?
+ .form-group.gl-form-group
+ %legend.col-form-label.col-form-label
+ = s_('Runners|Runner Registration')
+ - all_disabled = Gitlab::CurrentSettings.valid_runner_registrars.exclude?('project')
+ = f.gitlab_ui_checkbox_component :runner_registration_enabled,
+ s_('Runners|New project runners can be registered'),
+ checkbox_options: { checked: @project.runner_registration_enabled, disabled: all_disabled },
+ help_text: html_escape_once(s_('Runners|Existing runners are not affected. To permit runner registration for all projects, enable this setting in the Admin Area in Settings &gt; CI/CD.')).html_safe
+
+ .gl-mt-5
+ = f.submit _('Save changes'), pajamas_button: true
+ = render Pajamas::ButtonComponent.new(href: admin_project_path(@project)) do
+ = _('Cancel')
diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml
index cf1bd2a8022..df1653cdd71 100644
--- a/app/views/admin/projects/_projects.html.haml
+++ b/app/views/admin/projects/_projects.html.haml
@@ -3,9 +3,8 @@
%ul.content-list
- @projects.each do |project|
%li.project-row.gl-align-items-center{ class: 'gl-display-flex!' }
- .avatar-container.rect-avatar.s40.gl-flex-shrink-0
- = project_icon(project, alt: '', class: 'avatar project-avatar s40', width: 40, height: 40)
- .gl-min-w-0.gl-flex-grow-1
+ = render Pajamas::AvatarComponent.new(project, size: 32, alt: '')
+ .gl-min-w-0.gl-flex-grow-1.gl-ml-3
.title
= link_to(admin_project_path(project)) do
%span.project-full-name
@@ -24,7 +23,7 @@
= render_if_exists 'admin/projects/archived', project: project
.controls.gl-flex-shrink-0.gl-ml-5
- = render Pajamas::ButtonComponent.new(href: edit_project_path(project), button_options: { id: dom_id(project, :edit) }) do
+ = render Pajamas::ButtonComponent.new(href: edit_admin_namespace_project_path({ id: project.to_param, namespace_id: project.namespace.to_param }), button_options: { id: dom_id(project) }) do
= _('Edit')
= render Pajamas::ButtonComponent.new(variant: :danger, button_options: { class: 'delete-project-button', data: { delete_project_url: admin_project_path(project), project_name: project.name } }) do
= s_('AdminProjects|Delete')
diff --git a/app/views/admin/projects/edit.html.haml b/app/views/admin/projects/edit.html.haml
new file mode 100644
index 00000000000..ade0f543d58
--- /dev/null
+++ b/app/views/admin/projects/edit.html.haml
@@ -0,0 +1,4 @@
+- page_title _("Edit"), @project.name, _("Projects")
+%h1.page-title.gl-font-size-h-display= _('Edit project: %{project_name}') % { project_name: @project.name }
+%hr
+= render 'form'
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 464027e73f4..8eb72fa281e 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -6,7 +6,9 @@
%h1.page-title.gl-font-size-h-display
= _('Project: %{name}') % { name: @project.full_name }
- = render Pajamas::ButtonComponent.new(href: edit_project_path(@project), icon: 'pencil', button_options: { class: 'gl-float-right' }) do
+ = render Pajamas::ButtonComponent.new(href: edit_admin_namespace_project_path({ id: @project.to_param, namespace_id: @project.namespace.to_param }),
+ icon: 'pencil',
+ button_options: { class: 'gl-float-right'}) do
= _('Edit')
%hr
- if @project.last_repository_check_failed?
@@ -15,16 +17,16 @@
= render Pajamas::AlertComponent.new(variant: :danger,
alert_options: { class: 'gl-mb-5',
data: { testid: 'last-repository-check-failed-alert' }}) do |c|
- = c.body do
+ - c.with_body do
- last_check_message = _("Last repository check (%{last_check_timestamp}) failed. See the 'repocheck.log' file for error messages.")
- last_check_message = last_check_message % { last_check_timestamp: time_ago_with_tooltip(@project.last_repository_check_at) }
= last_check_message.html_safe
.row
.col-md-6
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }) do |c|
- - c.header do
+ - c.with_header do
= _('Project info:')
- - c.body do
+ - c.with_body do
%ul.content-list
%li{ class: 'gl-px-5!' }
%span.light
@@ -132,9 +134,9 @@
= render_if_exists 'admin/projects/geo_status_widget', locals: { project: @project }
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }) do |c|
- - c.header do
+ - c.with_header do
= s_('ProjectSettings|Transfer project')
- - c.body do
+ - c.with_body do
= gitlab_ui_form_for @project, url: transfer_admin_project_path(@project), method: :put do |f|
.form-group.row
.col-sm-3.col-form-label
@@ -147,9 +149,9 @@
= f.submit _('Transfer'), pajamas_button: true
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5 repository-check' }) do |c|
- - c.header do
+ - c.with_header do
= _("Repository check")
- - c.body do
+ - c.with_body do
= gitlab_ui_form_for @project, url: repository_check_admin_project_path(@project), method: :post do |f|
.form-group
- if @project.last_repository_check_at.nil?
@@ -169,35 +171,35 @@
.col-md-6
- if @group
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }, footer_options: { class: 'gl-p-4' }) do |c|
- - c.header do
+ - c.with_header do
%strong= @group.name
= _('group members')
= gl_badge_tag @group_members.size
= render 'shared/members/manage_access_button', path: group_group_members_path(@group)
- - c.body do
+ - c.with_body do
%ul.content-list.members-list
= render partial: 'shared/members/member',
collection: @group_members, as: :member,
locals: { membership_source: @project,
group: @group,
current_user_is_group_owner: current_user_is_group_owner }
- - c.footer do
+ - c.with_footer do
= paginate @group_members, param_name: 'group_members_page', theme: 'gitlab'
= render 'shared/members/requests', membership_source: @project, group: @group, requesters: @requesters
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-p-0' }, footer_options: { class: 'gl-p-4' }) do |c|
- - c.header do
+ - c.with_header do
%strong= @project.name
= _('project members')
= gl_badge_tag @project.users.size
= render 'shared/members/manage_access_button', path: project_project_members_path(@project)
- - c.body do
+ - c.with_body do
%ul.content-list.project_members.members-list
= render partial: 'shared/members/member',
collection: @project_members, as: :member,
locals: { membership_source: @project,
group: @group,
current_user_is_group_owner: current_user_is_group_owner }
- - c.footer do
+ - c.with_footer do
= paginate @project_members, param_name: 'project_members_page', theme: 'gitlab'
diff --git a/app/views/admin/runners/edit.html.haml b/app/views/admin/runners/edit.html.haml
index e586a7a965e..3d245722270 100644
--- a/app/views/admin/runners/edit.html.haml
+++ b/app/views/admin/runners/edit.html.haml
@@ -1,4 +1,4 @@
-- runner_name = "##{@runner.id} (#{@runner.short_sha})"
+- runner_name = runner_short_name(@runner)
- breadcrumb_title _('Edit')
- page_title _('Edit'), runner_name
- add_to_breadcrumbs _('Runners'), admin_runners_path
@@ -23,7 +23,7 @@
= render Pajamas::AlertComponent.new(variant: :danger,
dismissible: false,
title: project.full_name) do |c|
- = c.actions do
+ - c.with_actions do
= render Pajamas::ButtonComponent.new(variant: :confirm, href: admin_namespace_project_runner_project_path(project.namespace, project, runner_project), method: :delete) do
= _('Disable')
diff --git a/app/views/admin/runners/new.html.haml b/app/views/admin/runners/new.html.haml
index dd93ecfcf8c..c4e87761fee 100644
--- a/app/views/admin/runners/new.html.haml
+++ b/app/views/admin/runners/new.html.haml
@@ -2,4 +2,4 @@
- breadcrumb_title s_('Runners|New')
- page_title s_('Runners|Create an instance runner')
-#js-admin-new-runner{ data: { legacy_registration_token: Gitlab::CurrentSettings.runners_registration_token } }
+#js-admin-new-runner
diff --git a/app/views/admin/runners/register.html.haml b/app/views/admin/runners/register.html.haml
new file mode 100644
index 00000000000..7aa58f9078e
--- /dev/null
+++ b/app/views/admin/runners/register.html.haml
@@ -0,0 +1,7 @@
+- runner_name = runner_short_name(@runner)
+- breadcrumb_title s_('Runners|Register')
+- page_title s_('Runners|Register'), runner_name
+- add_to_breadcrumbs _('Runners'), admin_runners_path
+- add_to_breadcrumbs runner_name, register_admin_runner_path(@runner)
+
+#js-admin-register-runner{ data: { runner_id: @runner.id, runners_path: admin_runners_path } }
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index a9dbcf4a6a5..3942c427cc4 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -1,9 +1,9 @@
- add_page_specific_style 'page_bundles/ci_status'
- add_page_specific_style 'page_bundles/runner_details'
-- title = "##{@runner.id} (#{@runner.short_sha})"
-- breadcrumb_title title
-- page_title title
+- runner_name = runner_short_name(@runner)
+- breadcrumb_title runner_name
+- page_title runner_name
- add_to_breadcrumbs _('Runners'), admin_runners_path
#js-admin-runner-show{ data: {runner_id: @runner.id, runners_path: admin_runners_path} }
diff --git a/app/views/admin/sessions/_new_base.html.haml b/app/views/admin/sessions/_new_base.html.haml
index b755b4a442c..13c647cd45f 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', autocomplete: 'current-password', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field', testid: 'password-field' }
+ = password_field_tag 'user[password]', nil, { class: 'form-control js-password', data: { id: 'user_password', name: 'user[password]', qa_selector: 'password_field', testid: 'password-field' } }
.submit-container.move-submit-down
- = submit_tag _('Enter Admin Mode'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'enter_admin_mode_button' }
+ = submit_tag _('Enter admin mode'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'enter_admin_mode_button' }
diff --git a/app/views/admin/sessions/_signin_box.html.haml b/app/views/admin/sessions/_signin_box.html.haml
index c7382266480..15005bb9224 100644
--- a/app/views/admin/sessions/_signin_box.html.haml
+++ b/app/views/admin/sessions/_signin_box.html.haml
@@ -7,7 +7,7 @@
- ldap_servers.each_with_index do |server, i|
.login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i == 0 && form_based_auth_provider_has_active_class?(:ldapmain)) }
.login-body
- = render 'devise/sessions/new_ldap', server: server, hide_remember_me: true, submit_message: _('Enter Admin Mode')
+ = render 'devise/sessions/new_ldap', server: server, render_remember_me: false, submit_message: _('Enter admin mode')
= render_if_exists 'devise/sessions/new_smartcard'
diff --git a/app/views/admin/sessions/_two_factor_otp.html.haml b/app/views/admin/sessions/_two_factor_otp.html.haml
index 40ba79d1a65..f7b4035488d 100644
--- a/app/views/admin/sessions/_two_factor_otp.html.haml
+++ b/app/views/admin/sessions/_two_factor_otp.html.haml
@@ -1,9 +1,9 @@
-= form_tag(admin_session_path, { method: :post, class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if current_user.two_factor_webauthn_u2f_enabled?}" }) do
+= form_tag(admin_session_path, { method: :post, class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if current_user.two_factor_webauthn_enabled?}" }) do
.form-group
- = label_tag :user_otp_attempt, _('Two-Factor Authentication code')
- = text_field_tag 'user[otp_attempt]', nil, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', title: _('This field is required.')
+ = label_tag :user_otp_attempt, _('Enter verification code')
+ = text_field_tag 'user[otp_attempt]', nil, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', inputmode: 'numeric', title: _('This field is required.')
%p.form-text.text-muted.hint
- = _("Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.")
+ = _("Enter the code from your two-factor authenticator app. If you've lost your device, you can enter one of your recovery codes.")
.submit-container.move-submit-down
= submit_tag 'Verify code', class: 'gl-button btn btn-confirm'
diff --git a/app/views/admin/sessions/new.html.haml b/app/views/admin/sessions/new.html.haml
index 7d07b49c98e..4fc30cbaecf 100644
--- a/app/views/admin/sessions/new.html.haml
+++ b/app/views/admin/sessions/new.html.haml
@@ -1,10 +1,10 @@
-- @hide_breadcrumbs = true
-- page_title _('Enter Admin Mode')
+- page_title _('Enter admin mode')
+- add_page_specific_style 'page_bundles/login'
.row.justify-content-center
.col-md-5.new-session-forms-container
.login-page
- #signin-container
+ #signin-container{ class: ('borderless' if Feature.enabled?(:restyle_login_page, @project)) }
- if any_form_based_providers_enabled?
= render 'devise/shared/tabs_ldap', show_password_form: allow_admin_mode_password_authentication_for_web?, render_signup_link: false
- else
@@ -19,5 +19,4 @@
= _('No authentication methods configured.')
- if omniauth_enabled? && button_based_providers_enabled?
- .clearfix
- = render 'devise/shared/omniauth_box', hide_remember_me: true
+ = render 'devise/shared/omniauth_box', render_remember_me: false
diff --git a/app/views/admin/sessions/two_factor.html.haml b/app/views/admin/sessions/two_factor.html.haml
index 3f915846dd8..3bbf768d7be 100644
--- a/app/views/admin/sessions/two_factor.html.haml
+++ b/app/views/admin/sessions/two_factor.html.haml
@@ -1,15 +1,15 @@
-- @hide_breadcrumbs = true
- page_title _('Enter 2FA for Admin Mode')
+- add_page_specific_style 'page_bundles/login'
.row.justify-content-center
.col-md-5.new-session-forms-container
.login-page
- #signin-container
- = render 'devise/shared/tab_single', tab_title: _('Enter Admin Mode')
+ #signin-container{ class: ('borderless' if Feature.enabled?(:restyle_login_page, @project)) }
+ = render 'devise/shared/tab_single', tab_title: _('Enter admin mode')
.tab-content
.login-box.tab-pane.gl-p-5.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
- - if current_user.two_factor_otp_enabled?
+ - if current_user.two_factor_enabled?
= render 'admin/sessions/two_factor_otp'
- - if current_user.two_factor_webauthn_u2f_enabled?
+ - if current_user.two_factor_webauthn_enabled?
= render 'authentication/authenticate', render_remember_me: false, target_path: admin_session_path
diff --git a/app/views/admin/spam_logs/index.html.haml b/app/views/admin/spam_logs/index.html.haml
index c974f455112..001662c4015 100644
--- a/app/views/admin/spam_logs/index.html.haml
+++ b/app/views/admin/spam_logs/index.html.haml
@@ -17,6 +17,6 @@
%th= _('Primary Action')
%th
= render @spam_logs
- = paginate @spam_logs, theme: 'gitlab'
+ = paginate_collection @spam_logs
- else
%h4= _('There are no Spam Logs')
diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml
index 049f3d61294..d3d2ebb90da 100644
--- a/app/views/admin/system_info/show.html.haml
+++ b/app/views/admin/system_info/show.html.haml
@@ -3,45 +3,46 @@
.gl-mt-3
.row
.col-sm
- .bg-light.info-well.p-3
- %h4.page-title.d-flex
- .gl-display-flex.gl-align-items-center.gl-justify-content-center
- = sprite_icon('pod', size: 18, css_class: 'pod-icon gl-mr-3')
- = _('CPU')
- .data
- - if @cpus
- %h2= _('%{cores} cores') % { cores: @cpus.length }
- - else
- = sprite_icon('warning-solid', css_class: 'text-warning')
- = _('Unable to collect CPU info')
- .bg-light.info-well.p-3.gl-mt-3
- %h4.page-title.d-flex
- .gl-display-flex.gl-align-items-center.gl-justify-content-center
- = sprite_icon('status-health', size: 18, css_class: 'pod-icon gl-mr-3')
- = _('Memory Usage')
- .data
- - if @memory
- %h2 #{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)}
- - else
- = sprite_icon('warning-solid', css_class: 'text-warning')
- = _('Unable to collect memory info')
- .bg-light.info-well.p-3.gl-mt-3
- %h4.page-title.d-flex
- .gl-display-flex.gl-align-items-center.gl-justify-content-center
- = sprite_icon('clock', size: 18, css_class: 'pod-icon gl-mr-3')
- = _('System started')
- .data
- %h2= time_ago_with_tooltip(Rails.application.config.booted_at)
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-3' }) do |c|
+ - c.with_body do
+ %h4
+ = sprite_icon('pod', size: 18, css_class: 'gl-text-gray-700')
+ = _('CPU')
+ .data
+ - if @cpus
+ %h2= _('%{cores} cores') % { cores: @cpus.length }
+ - else
+ = sprite_icon('warning-solid', css_class: 'text-warning')
+ = _('Unable to collect CPU info')
+
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-3' }) do |c|
+ - c.with_body do
+ %h4
+ = sprite_icon('status-health', size: 18, css_class: 'gl-text-gray-700')
+ = _('Memory Usage')
+ .data
+ - if @memory
+ %h2 #{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)}
+ - else
+ = sprite_icon('warning-solid', css_class: 'text-warning')
+ = _('Unable to collect memory info')
+
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-3' }) do |c|
+ - c.with_body do
+ %h4
+ = sprite_icon('clock', size: 18, css_class: 'gl-text-gray-700')
+ = _('System started')
+ .data
+ %h2= time_ago_with_tooltip(Rails.application.config.booted_at)
.col-sm
- .bg-light.info-well.p-3
- %h4.page-title.d-flex
- .gl-display-flex.gl-align-items-center.gl-justify-content-center
- = sprite_icon('disk', size: 18, css_class: 'pod-icon gl-mr-3')
- = _('Disk Usage')
- .data
- %ul
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-3' }) do |c|
+ - c.with_body do
+ %h4
+ = sprite_icon('disk', size: 18, css_class: 'gl-text-gray-700')
+ = _('Disk Usage')
+ .data
- @disks.each do |disk|
- %li
- %h2 #{number_to_human_size(disk[:bytes_used])} / #{number_to_human_size(disk[:bytes_total])}
- %p= disk[:disk_name]
- %p= disk[:mount_path]
+ %h2 #{number_to_human_size(disk[:bytes_used])} / #{number_to_human_size(disk[:bytes_total])}
+ %ul
+ %li= disk[:disk_name]
+ %li= disk[:mount_path]
diff --git a/app/views/admin/topics/_topic.html.haml b/app/views/admin/topics/_topic.html.haml
index 869194a21f6..c63828cf41f 100644
--- a/app/views/admin/topics/_topic.html.haml
+++ b/app/views/admin/topics/_topic.html.haml
@@ -2,10 +2,9 @@
- title = topic.title || topic.name
%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")
+ = render Pajamas::AvatarComponent.new(topic, size: 32, alt: '')
- .gl-min-w-0.gl-flex-grow-1
+ .gl-min-w-0.gl-flex-grow-1.gl-ml-3
.title
= link_to title, topic_explore_projects_path(topic_name: topic.name)
%div
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index eb151b40a65..8822d52c3c0 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -28,7 +28,7 @@
.col-lg-8
- if @user.new_record?
= render Pajamas::AlertComponent.new(variant: :info, dismissible: false, alert_options: { class: 'gl-mb-5' }) do |c|
- = c.body do
+ - c.with_body do
= s_('AdminUsers|Reset link will be generated and sent to the user. User will be forced to set the password on first sign in.')
- else
.form-group.gl-form-group{ role: 'group' }
@@ -71,6 +71,8 @@
= f.label :website_url, s_('AdminUsers|Website URL'), class: 'gl-display-block col-form-label'
= f.text_field :website_url, class: 'form-control gl-form-input'
+ = render_if_exists 'admin/users/custom_attributes', f: f
+
= render 'admin/users/admin_notes', f: f
%div
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index 6b5ec62bc77..8f7741b8a32 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -1,4 +1,4 @@
-.gl-display-flex.gl-flex-wrap.gl-justify-content-space-between.gl-align-items-center.gl-py-3.gl-mb-5.gl-border-b-solid.gl-border-gray-100.gl-border-b-1
+.gl-display-flex.gl-flex-wrap.gl-justify-content-space-between.gl-align-items-center.gl-pt-3
.gl-my-3
%h1.page-title.gl-font-size-h-display.gl-m-0
= @user.name
@@ -27,8 +27,6 @@
= render_if_exists 'admin/users/gma_user_badge'
.gl-my-3.gl-display-flex.gl-flex-wrap.gl-my-n2.gl-mx-n2
- .gl-p-2
- #js-admin-user-actions{ data: admin_user_actions_data_attributes(@user) }
- if @user != current_user
- if impersonation_enabled?
.gl-p-2
@@ -42,6 +40,8 @@
.gl-p-2
= render Pajamas::ButtonComponent.new(variant: :confirm, href: new_admin_user_identity_path(@user)) do
= _('New identity')
+ .gl-p-2
+ #js-admin-user-actions{ data: admin_user_actions_data_attributes(@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)
diff --git a/app/views/admin/users/_profile.html.haml b/app/views/admin/users/_profile.html.haml
index e90dab68b39..b4f61a1b665 100644
--- a/app/views/admin/users/_profile.html.haml
+++ b/app/views/admin/users/_profile.html.haml
@@ -1,31 +1,32 @@
-.card
- .card-header
+= render Pajamas::CardComponent.new(body_options: { class: 'gl-py-0' }) do |c|
+ - c.with_header do
= _('Profile')
- %ul.content-list
- %li
- %span.light= _('Member since')
- %strong= user.created_at.to_s(:medium)
- - unless user.public_email.blank?
+ - c.with_body do
+ %ul.content-list
%li
- %span.light= _('E-mail:')
- %strong= link_to user.public_email, "mailto:#{user.public_email}"
- - unless user.skype.blank?
- %li
- %span.light= _('Skype:')
- %strong= link_to user.skype, "skype:#{user.skype}"
- - unless user.linkedin.blank?
- %li
- %span.light= _('LinkedIn:')
- %strong= link_to user.linkedin, "https://www.linkedin.com/in/#{user.linkedin}"
- - unless user.twitter.blank?
- %li
- %span.light= _('Twitter:')
- %strong= link_to user.twitter, "https://twitter.com/#{user.twitter}"
- - unless user.website_url.blank?
- %li
- %span.light= _('Website:')
- %strong= link_to user.short_website_url, user.full_website_url
- - unless user.location.blank?
- %li
- %span.light= _('Location:')
- %strong= user.location
+ %span.light= _('Member since')
+ %strong= user.created_at.to_s(:medium)
+ - unless user.public_email.blank?
+ %li
+ %span.light= _('E-mail:')
+ %strong= link_to user.public_email, "mailto:#{user.public_email}"
+ - unless user.skype.blank?
+ %li
+ %span.light= _('Skype:')
+ %strong= link_to user.skype, "skype:#{user.skype}"
+ - unless user.linkedin.blank?
+ %li
+ %span.light= _('LinkedIn:')
+ %strong= link_to user.linkedin, "https://www.linkedin.com/in/#{user.linkedin}"
+ - unless user.twitter.blank?
+ %li
+ %span.light= _('Twitter:')
+ %strong= link_to user.twitter, "https://twitter.com/#{user.twitter}"
+ - unless user.website_url.blank?
+ %li
+ %span.light= _('Website:')
+ %strong= link_to user.short_website_url, user.full_website_url
+ - unless user.location.blank?
+ %li
+ %span.light= _('Location:')
+ %strong= user.location
diff --git a/app/views/admin/users/_projects.html.haml b/app/views/admin/users/_projects.html.haml
index 2f77e83ac49..ce2d684b046 100644
--- a/app/views/admin/users/_projects.html.haml
+++ b/app/views/admin/users/_projects.html.haml
@@ -1,17 +1,17 @@
- if local_assigns.has_key?(:contributed_projects) && contributed_projects.present?
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0' }) do |c|
- - c.header do
+ - c.with_header do
= _('Projects contributed to')
- - c.body do
+ - c.with_body do
= render 'shared/projects/list',
projects: contributed_projects.sort_by(&:star_count).reverse,
projects_limit: 5, stars: true, avatar: false, compact_mode: true
- if local_assigns.has_key?(:projects) && projects.present?
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0' }) do |c|
- - c.header do
+ - c.with_header do
= _('Personal projects')
- - c.body do
+ - c.with_body do
= render 'shared/projects/list',
projects: projects.sort_by(&:star_count).reverse,
projects_limit: 10, stars: true, avatar: false, compact_mode: true
diff --git a/app/views/admin/users/_user_detail_note.html.haml b/app/views/admin/users/_user_detail_note.html.haml
index c8625833a70..65ef1c0710d 100644
--- a/app/views/admin/users/_user_detail_note.html.haml
+++ b/app/views/admin/users/_user_detail_note.html.haml
@@ -1,7 +1,7 @@
- if @user.note.present?
- text = @user.note
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-pb-0'}) do |c|
- - c.header do
+ - c.with_header do
= _('Admin Note')
- - c.body do
+ - c.with_body do
%p= text
diff --git a/app/views/admin/users/_users.html.haml b/app/views/admin/users/_users.html.haml
index 96dd16a96da..c9264535a13 100644
--- a/app/views/admin/users/_users.html.haml
+++ b/app/views/admin/users/_users.html.haml
@@ -4,7 +4,7 @@
= render Pajamas::AlertComponent.new(variant: :tip,
alert_options: { class: 'gl-my-5' },
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= render 'shared/registration_features_discovery_message', feature_title: s_('RegistrationFeatures|send emails to users')
.top-area
diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml
index ff87cf8f866..1f3e8f4bba2 100644
--- a/app/views/admin/users/projects.html.haml
+++ b/app/views/admin/users/projects.html.haml
@@ -5,9 +5,9 @@
- if @user.groups.any?
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0 gl-px-0'}) do |c|
- - c.header do
+ - c.with_header do
= _('Groups')
- - c.body do
+ - c.with_body do
%ul.hover-list
- @user.group_members.includes(:source).each do |group_member| # rubocop: disable CodeReuse/ActiveRecord
- group = group_member.group
@@ -31,9 +31,9 @@
.col-md-6
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0 gl-px-0'}) do |c|
- - c.header do
+ - c.with_header do
= _('Joined projects (%{projects_count})') % { projects_count: @joined_projects.count }
- - c.body do
+ - c.with_body do
%ul.hover-list
- @joined_projects.sort_by(&:full_name).each do |project|
- member = project.team.find_member(@user.id)
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index f7d4121e6e0..ea6525e1b96 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -6,9 +6,9 @@
.row
.col-md-6
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-2'}) do |c|
- - c.header do
+ - c.with_header do
= @user.name
- - c.body do
+ - c.with_body do
%ul.content-list
%li
= render Pajamas::AvatarComponent.new(@user, size: 64, class: 'gl-mr-3')
@@ -22,9 +22,9 @@
= render 'admin/users/profile', user: @user
= render 'admin/users/user_detail_note'
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-2'}) do |c|
- - c.header do
+ - c.with_header do
= _('Account:')
- - c.body do
+ - c.with_body do
%ul.content-list
%li
%span.light= _('Name:')
diff --git a/app/views/authentication/_authenticate.html.haml b/app/views/authentication/_authenticate.html.haml
index 7dcec50573f..9e09bcd6e54 100644
--- a/app/views/authentication/_authenticate.html.haml
+++ b/app/views/authentication/_authenticate.html.haml
@@ -1,5 +1,8 @@
#js-authenticate-token-2fa
-%a.gl-button.btn.btn-block.btn-confirm#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
+= render Pajamas::ButtonComponent.new(variant: :confirm,
+ block: true,
+ button_options: { id: 'js-login-2fa-device' }) do
+ = _("Sign in via 2FA code")
-# haml-lint:disable InlineJavaScript
%script#js-authenticate-token-2fa-in-progress{ type: "text/template" }
@@ -9,14 +12,16 @@
%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?")
+ = render Pajamas::ButtonComponent.new(block: true,
+ button_options: { id: 'js-token-2fa-try-again', class: 'gl-mb-3' }) do
+ = _("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.")
= form_tag(target_path, method: :post, id: 'js-login-token-2fa-form') do |f|
- - if render_remember_me
+ - if remember_me_enabled? && render_remember_me
- resource_params = params[resource_name].presence || params
= hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0)
= hidden_field_tag 'user[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
diff --git a/app/views/authentication/_register.html.haml b/app/views/authentication/_register.html.haml
index d6fe20e48bf..f8a03f085ff 100644
--- a/app/views/authentication/_register.html.haml
+++ b/app/views/authentication/_register.html.haml
@@ -1,47 +1,50 @@
-#js-register-token-2fa
+- if Feature.enabled?(:webauthn_without_totp)
+ #js-device-registration{ data: device_registration_data(current_password_required: current_password_required?, target_path: target_path, webauthn_error: @webauthn_error) }
+- else
+ #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-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
- .col-md-5
- = render Pajamas::ButtonComponent.new(variant: :confirm,
- button_options: { id: 'js-setup-token-2fa-device' }) do
- = _("Set up new device")
- .col-md-7
- %p= _("Your device needs to be set up. Plug it in (if needed) and click the button on the left.")
- - else
- .row.gl-mb-3
- .col-md-4
- = render Pajamas::ButtonComponent.new(variant: :confirm,
- disabled: true,
- button_options: { id: 'js-setup-token-2fa-device' }) do
- = _("Set up new device")
- .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-setup{ type: "text/template" }
+ - if current_user.two_factor_otp_enabled?
+ .row.gl-mb-3
+ .col-md-5
+ = render Pajamas::ButtonComponent.new(variant: :confirm,
+ button_options: { id: 'js-setup-token-2fa-device' }) do
+ = _("Set up new device")
+ .col-md-7
+ %p= _("Your device needs to be set up. Plug it in (if needed) and click the button on the left.")
+ - else
+ .row.gl-mb-3
+ .col-md-4
+ = render Pajamas::ButtonComponent.new(variant: :confirm,
+ disabled: true,
+ button_options: { id: 'js-setup-token-2fa-device' }) do
+ = _("Set up new device")
+ .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 %>)
- = render Pajamas::ButtonComponent.new(button_options: { id: 'js-token-2fa-try-again' }) do
- = _("Try again?")
+ -# haml-lint:disable InlineJavaScript
+ %script#js-register-token-2fa-error{ type: "text/template" }
+ %div
+ %p
+ %span <%= error_message %> (<%= error_name %>)
+ = render Pajamas::ButtonComponent.new(button_options: { id: 'js-token-2fa-try-again' }) do
+ = _("Try again?")
--# haml-lint:disable InlineJavaScript
-%script#js-register-token-2fa-registered{ type: "text/template" }
- .row.gl-mb-3
- .col-md-12
- %p= _("Your device was successfully set up! Give it a name and register it with the GitLab server.")
- = form_tag(target_path, method: :post) do
- .row.gl-mb-3
- .col-md-3
- = text_field_tag 'device_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name")
- .col-md-3
- = hidden_field_tag 'device_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
- = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm) do
- = _("Register device")
+ -# haml-lint:disable InlineJavaScript
+ %script#js-register-token-2fa-registered{ type: "text/template" }
+ .row.gl-mb-3
+ .col-md-12
+ %p= _("Your device was successfully set up! Give it a name and register it with the GitLab server.")
+ = form_tag(target_path, method: :post) do
+ .row.gl-mb-3
+ .col-md-3
+ = text_field_tag 'device_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name")
+ .col-md-3
+ = hidden_field_tag 'device_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
+ = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm) do
+ = _("Register device")
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index 8aaa09b7862..da2c8a71dcd 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -1,12 +1,4 @@
- save_endpoint = local_assigns.fetch(:save_endpoint, nil)
-
-- if ci_variable_protected_by_default?
- = render Pajamas::AlertComponent.new(variant: :warning, show_icon: false, dismissible: false,
- alert_options: { class: 'gl-mb-3'}) do |c|
- = c.body do
- - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/index', anchor: 'protect-a-cicd-variable') }
- = _('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
-
- is_group = !@group.nil?
- is_project = !@project.nil?
diff --git a/app/views/clusters/clusters/_advanced_settings.html.haml b/app/views/clusters/clusters/_advanced_settings.html.haml
index b49f1aa061a..a818f8a5c26 100644
--- a/app/views/clusters/clusters/_advanced_settings.html.haml
+++ b/app/views/clusters/clusters/_advanced_settings.html.haml
@@ -24,6 +24,7 @@
order_by: 'last_activity_at',
group_id: group_id,
user_id: user_id,
+ with_shared: true.to_s,
include_subgroups: true.to_s,
membership: true.to_s,
selected: @cluster.management_project_id } }
diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
index af4c934fd72..40632e27fa7 100644
--- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
+++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
@@ -2,9 +2,10 @@
= render Pajamas::AlertComponent.new(title: s_('ClusterIntegration|Did you know?'),
alert_options: { class: 'gcp-signup-offer',
- data: { feature_id: Users::CalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: callouts_path }}) do |c|
+ data: { feature_id: Users::CalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: callouts_path }},
+ close_button_options: { data: { track_action: 'click_dismiss', track_label: 'gcp_signup_offer_banner' }}) do |c|
= c.body do
= s_('ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab\'s Google Kubernetes Engine Integration.').html_safe % { sign_up_link: link }
= c.actions do
- = render Pajamas::ButtonComponent.new(variant: :confirm, href: 'https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form', target: '_blank', button_options: { rel: 'noopener noreferrer' }) do
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: 'https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form', target: '_blank', button_options: { rel: 'noopener noreferrer', data: { track_action: 'click_button', track_label: 'gcp_signup_offer_banner' } }) do
= s_("ClusterIntegration|Apply for credit")
diff --git a/app/views/clusters/clusters/_integrations.html.haml b/app/views/clusters/clusters/_integrations.html.haml
index 4a3062def8c..4d36c5094a3 100644
--- a/app/views/clusters/clusters/_integrations.html.haml
+++ b/app/views/clusters/clusters/_integrations.html.haml
@@ -6,10 +6,10 @@
- if can?(current_user, :admin_cluster, @cluster)
.sub-section.form-group
= gitlab_ui_form_for @prometheus_integration, as: :integration, namespace: :prometheus, url: @cluster.integrations_path, method: :post, html: { class: 'js-cluster-integrations-form' } do |prometheus_form|
- = prometheus_form.hidden_field :application_type
+ = prometheus_form.hidden_field :application_type, value: @prometheus_integration.application_type
.form-group.gl-form-group
- help_text = s_('ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics.')
- - help_link = link_to(_('More information.'), help_page_path("user/clusters/integrations", anchor: "prometheus-cluster-integration"), target: '_blank', rel: 'noopener noreferrer')
+ - help_link = link_to(_('More information.'), help_page_path("user/clusters/integrations"), target: '_blank', rel: 'noopener noreferrer')
= prometheus_form.gitlab_ui_checkbox_component :enabled,
s_('ClusterIntegration|Enable Prometheus integration'),
help_text: '%{help_text} %{help_link}'.html_safe % { help_text: help_text, help_link: help_link }
diff --git a/app/views/clusters/clusters/connect.html.haml b/app/views/clusters/clusters/connect.html.haml
index 82750974803..a6e1837badf 100644
--- a/app/views/clusters/clusters/connect.html.haml
+++ b/app/views/clusters/clusters/connect.html.haml
@@ -1,4 +1,3 @@
-- @content_class = 'limit-container-width' unless fluid_layout
- add_to_breadcrumbs _('Kubernetes Clusters'), clusterable.index_path
- breadcrumb_title _('Connect a cluster')
- page_title _('Connect a Kubernetes Cluster')
diff --git a/app/views/clusters/clusters/new_cluster_docs.html.haml b/app/views/clusters/clusters/new_cluster_docs.html.haml
index bff371b8d51..72c70f35e22 100644
--- a/app/views/clusters/clusters/new_cluster_docs.html.haml
+++ b/app/views/clusters/clusters/new_cluster_docs.html.haml
@@ -1,4 +1,3 @@
-- @content_class = 'limit-container-width' unless fluid_layout
- add_to_breadcrumbs _('Kubernetes Clusters'), clusterable.index_path
- breadcrumb_title _('Create a cluster')
- page_title _('Create a Kubernetes cluster')
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index 58e0ef96333..19ca9407513 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -1,4 +1,3 @@
-- @content_class = "limit-container-width" unless fluid_layout
- add_to_breadcrumbs _('Kubernetes Clusters'), clusterable.index_path
- breadcrumb_title @cluster.name
- page_title _('Kubernetes Cluster')
@@ -33,8 +32,8 @@
= gl_tabs_nav do
= render 'clusters/clusters/details_tab'
= render_if_exists 'clusters/clusters/environments_tab'
- = render 'clusters/clusters/health_tab'
- = render 'clusters/clusters/integrations_tab'
+ = render 'clusters/clusters/health_tab' if !Feature.enabled?(:remove_monitor_metrics)
+ = render 'clusters/clusters/integrations_tab' if !Feature.enabled?(:remove_monitor_metrics)
= render 'clusters/clusters/advanced_settings_tab'
.tab-content.py-3
diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml
index 09e2e35c617..62ca4a3bab6 100644
--- a/app/views/dashboard/_groups_head.html.haml
+++ b/app/views/dashboard/_groups_head.html.haml
@@ -1,14 +1,13 @@
.page-title-holder.d-flex.align-items-center
%h1.page-title.gl-font-size-h-display= _('Groups')
- - if current_user.can_create_group?
- .page-title-controls
+ .page-title-controls.gl-display-flex.gl-align-items-center.gl-gap-5
+ = link_to _("Explore groups"), explore_groups_path
+ - if current_user.can_create_group?
= render Pajamas::ButtonComponent.new(href: new_group_path, variant: :confirm, button_options: { data: { qa_selector: "new_group_button", testid: "new-group-button" } }) do
= _("New group")
-.top-area
- = 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, data: { qa_selector: "public_groups_tab" }
+
+.top-area.gl-py-3.gl-justify-content-end.gl-border-bottom-0
.nav-controls
= render 'shared/groups/search_form'
= render 'shared/groups/dropdown'
diff --git a/app/views/shared/dashboard/_no_filter_selected.html.haml b/app/views/dashboard/_no_filter_selected.html.haml
index 48c844d93e8..48c844d93e8 100644
--- a/app/views/shared/dashboard/_no_filter_selected.html.haml
+++ b/app/views/dashboard/_no_filter_selected.html.haml
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index c58d4cff034..e600d84f492 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -4,8 +4,9 @@
.page-title-holder.gl-display-flex.gl-align-items-center
%h1.page-title.gl-font-size-h-display= _('Projects')
- - if current_user.can_create_project?
- .page-title-controls
+ .page-title-controls.gl-display-flex.gl-align-items-center.gl-gap-5
+ = link_to _("Explore projects"), explore_projects_path
+ - if current_user.can_create_project?
= render Pajamas::ButtonComponent.new(href: new_project_path, variant: :confirm, button_options: { data: { qa_selector: 'new_project_button' } }) do
= _("New project")
diff --git a/app/views/dashboard/_projects_nav.html.haml b/app/views/dashboard/_projects_nav.html.haml
index 7cbd2fb14ec..4367d201190 100644
--- a/app/views/dashboard/_projects_nav.html.haml
+++ b/app/views/dashboard/_projects_nav.html.haml
@@ -1,13 +1,10 @@
- is_your_projects_path = current_page?(dashboard_projects_path) || current_page?(root_path)
-- is_explore_projects_path = current_page?(explore_root_path) || current_page?(trending_explore_projects_path) || current_page?(starred_explore_projects_path) || current_page?(explore_projects_path)
= gl_tabs_nav({ class: 'scrolling-tabs nav-links gl-display-flex gl-flex-grow-1 gl-w-full nav gl-tabs-nav' }) do
= gl_tab_link_to dashboard_projects_path, { item_active: is_your_projects_path, class: 'shortcuts-activity', data: { placement: 'right' } } do
= s_("ProjectList|Yours")
- = gl_tab_counter_badge(limited_counter_with_delimiter(@total_user_projects_count))
+ = gl_tab_counter_badge(limited_counter_with_delimiter(@all_user_projects))
= gl_tab_link_to starred_dashboard_projects_path, { data: { placement: 'right' } } do
= s_("ProjectList|Starred")
- = gl_tab_counter_badge(limited_counter_with_delimiter(@total_starred_projects_count))
- = gl_tab_link_to s_("ProjectList|Explore"), explore_root_path, { item_active: is_explore_projects_path, data: { placement: 'right' } }
- = gl_tab_link_to s_("ProjectList|Topics"), topics_explore_projects_path, { data: { placement: 'right' } }
+ = gl_tab_counter_badge(limited_counter_with_delimiter(@all_starred_projects))
= render_if_exists "dashboard/removed_projects_tab"
diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml
index 5a798c249d1..e0e8aaa0fd9 100644
--- a/app/views/dashboard/_snippets_head.html.haml
+++ b/app/views/dashboard/_snippets_head.html.haml
@@ -1,13 +1,8 @@
.page-title-holder.d-flex.align-items-center
%h1.page-title.gl-font-size-h-display= _('Snippets')
- - if current_user && current_user.snippets.any? || @snippets.any?
- .page-title-controls
- - if can?(current_user, :create_snippet)
- = render Pajamas::ButtonComponent.new(href: new_snippet_path, variant: :confirm, button_options: { title: _("New snippet") }) do
- = _("New snippet")
-
-.top-area
- = gl_tabs_nav({ class: 'gl-border-0' }) do
- = gl_tab_link_to _('Your snippets'), dashboard_snippets_path, { title: _('Your snippets') }
- = gl_tab_link_to _('Explore snippets'), explore_snippets_path, { title: _('Explore snippets') }
+ .page-title-controls.gl-display-flex.gl-align-items-center.gl-gap-5
+ = link_to _("Explore snippets"), explore_snippets_path
+ - if can?(current_user, :create_snippet)
+ = render Pajamas::ButtonComponent.new(href: new_snippet_path, variant: :confirm, button_options: { title: _("New snippet") }) do
+ = _("New snippet")
diff --git a/app/views/dashboard/activity.html.haml b/app/views/dashboard/activity.html.haml
index 0ddee68e93f..ff9f13ba2de 100644
--- a/app/views/dashboard/activity.html.haml
+++ b/app/views/dashboard/activity.html.haml
@@ -1,12 +1,9 @@
-- @hide_top_links = true
-
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
= render_dashboard_ultimate_trial(current_user)
-- page_title _("Activity")
-- header_title _("Activity"), activity_dashboard_path
+- page_title _("Activity")
= render "projects/last_push"
= render 'dashboard/activity_head'
diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml
index fdfc2c5adb8..7f004e405a7 100644
--- a/app/views/dashboard/groups/index.html.haml
+++ b/app/views/dashboard/groups/index.html.haml
@@ -1,6 +1,4 @@
-- @hide_top_links = true
- page_title _("Groups")
-- header_title _("Groups"), dashboard_groups_path
= render_dashboard_ultimate_trial(current_user)
= render 'dashboard/groups_head'
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 0933f6d6a94..78c3270114e 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -1,4 +1,3 @@
-- @hide_top_links = true
- page_title _("Issues")
- @breadcrumb_link = issues_dashboard_path(assignee_username: current_user.username)
- add_page_specific_style 'page_bundles/issuable_list'
@@ -8,24 +7,11 @@
= render_dashboard_ultimate_trial(current_user)
-.page-title-holder.d-flex.align-items-center
+.page-title-holder.gl-display-flex.gl-align-items-center
%h1.page-title.gl-font-size-h-display= _('Issues')
- if current_user
.page-title-controls
= render 'shared/new_project_item_vue_select'
-- if ::Feature.enabled?(:vue_issues_dashboard)
- .js-issues-dashboard{ data: dashboard_issues_list_data(current_user) }
-- else
- .top-area
- = render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set
- .nav-controls
- = render 'shared/issuable/feed_buttons'
-
- = render 'shared/issuable/search_bar', type: :issues
-
- - if current_user && @no_filters_set
- = render 'shared/dashboard/no_filter_selected'
- - else
- = render 'shared/issues'
+.js-issues-dashboard{ data: dashboard_issues_list_data(current_user) }
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index 712f987a783..de34c709ff3 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -1,4 +1,3 @@
-- @hide_top_links = true
- page_title _("Merge requests")
- @breadcrumb_link = merge_requests_dashboard_path(assignee_username: current_user.username)
- add_page_specific_style 'page_bundles/issuable_list'
@@ -18,7 +17,7 @@
= render 'shared/issuable/search_bar', type: :merge_requests, disable_target_branch: true
- if current_user && @no_filters_set
- = render 'shared/dashboard/no_filter_selected'
+ = render 'no_filter_selected'
- elsif @search_timeout_occurred
= render 'shared/dashboard/search_timeout_occurred'
- else
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index 2556791da12..682dfa8458e 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -1,6 +1,4 @@
-- @hide_top_links = true
- page_title _('Milestones')
-- header_title _('Milestones'), dashboard_milestones_path
- add_page_specific_style 'page_bundles/milestone'
.page-title-holder.d-flex.align-items-center
diff --git a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
index eba5e7c6e9b..855177fd836 100644
--- a/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_admin_welcome.html.haml
@@ -7,7 +7,7 @@
= link_to new_project_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_project", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Create a project')
%p
@@ -17,7 +17,7 @@
= link_to new_group_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_group", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Create a group')
%p
@@ -26,7 +26,7 @@
= link_to new_admin_user_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_user", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Add people')
%p
@@ -35,7 +35,7 @@
= link_to admin_root_path, class: link_classes do
.blank-state-icon
= custom_icon("configure_server", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Configure GitLab')
%p
diff --git a/app/views/dashboard/projects/_blank_state_welcome.html.haml b/app/views/dashboard/projects/_blank_state_welcome.html.haml
index a9a34af3f96..c5fdc31a775 100644
--- a/app/views/dashboard/projects/_blank_state_welcome.html.haml
+++ b/app/views/dashboard/projects/_blank_state_welcome.html.haml
@@ -5,7 +5,7 @@
= link_to new_project_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_project", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Create a project')
%p
@@ -19,7 +19,7 @@
= link_to new_group_path, class: link_classes do
.blank-state-icon
= custom_icon("add_new_group", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Create a group')
%p
@@ -28,7 +28,7 @@
= link_to trending_explore_projects_path, class: link_classes do
.blank-state-icon
= custom_icon("globe", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Explore public projects')
%p
@@ -37,7 +37,7 @@
= link_to Gitlab::Saas::doc_url, class: link_classes do
.blank-state-icon
= custom_icon("lightbulb", size: 50)
- .blank-state-body.gl-sm-pl-0.gl-pl-6
+ .blank-state-body.gl-sm-pl-6
%h3.gl-font-size-h2.gl-mt-0
= _('Learn more about GitLab')
%p
diff --git a/app/views/dashboard/projects/_starred_empty_state.html.haml b/app/views/dashboard/projects/_starred_empty_state.html.haml
index 6db018d72da..dafa3b4dc8d 100644
--- a/app/views/dashboard/projects/_starred_empty_state.html.haml
+++ b/app/views/dashboard/projects/_starred_empty_state.html.haml
@@ -1,7 +1,7 @@
.row.empty-state
.col-12
- .svg-content.svg-250
- = image_tag 'illustrations/starred_empty.svg'
+ .svg-content.svg-150
+ = image_tag 'illustrations/empty-state/empty-projects-starred-md.svg'
.text-content
%h4.gl-text-center
= s_("StarredProjectsEmptyState|You don't have starred projects yet.")
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index f427c347dd3..140bc6e06c3 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -1,12 +1,9 @@
-- @hide_top_links = true
-
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
= render_dashboard_ultimate_trial(current_user)
-- page_title _("Projects")
-- header_title _("Projects"), dashboard_projects_path
+- page_title _("Projects")
- add_page_specific_style 'page_bundles/dashboard_projects'
= render "projects/last_push"
diff --git a/app/views/dashboard/projects/shared/_common.html.haml b/app/views/dashboard/projects/shared/_common.html.haml
index 17dcb072152..f6f67ad7712 100644
--- a/app/views/dashboard/projects/shared/_common.html.haml
+++ b/app/views/dashboard/projects/shared/_common.html.haml
@@ -1,6 +1,4 @@
-- @hide_top_links = true
-- breadcrumb_title _("Projects")
-- header_title _("Projects"), dashboard_projects_path
+- page_title _("Projects")
= render_dashboard_ultimate_trial(current_user)
diff --git a/app/views/dashboard/snippets/index.html.haml b/app/views/dashboard/snippets/index.html.haml
index 68457ab33f7..667ed617849 100644
--- a/app/views/dashboard/snippets/index.html.haml
+++ b/app/views/dashboard/snippets/index.html.haml
@@ -1,11 +1,9 @@
-- @hide_top_links = true
-- page_title _("Snippets")
-- header_title _("Snippets"), dashboard_snippets_path
+- page_title _("Snippets")
- button_path = new_snippet_path if can?(current_user, :create_snippet)
= render 'dashboard/snippets_head'
- if current_user.snippets.exists?
- = render partial: 'snippets/snippets_scope_menu', locals: { include_private: true, counts: @snippet_counts }
+ .top-area= render partial: 'snippets/snippets_scope_menu', locals: { include_private: true, counts: @snippet_counts }
= render partial: 'shared/snippets/list', locals: { link_project: true }
- else
= render 'shared/empty_states/snippets', button_path: button_path
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 9e59f9d700f..ca6b1071f03 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -1,9 +1,8 @@
-- @hide_top_links = true
- page_title _("To-Do List")
-- header_title _("To-Do List"), dashboard_todos_path
= render_two_factor_auth_recovery_settings_check
= render_dashboard_ultimate_trial(current_user)
+= render_if_exists 'dashboard/todos/saml_reauth_notice'
- add_page_specific_style 'page_bundles/todos'
- add_page_specific_style 'page_bundles/issuable'
@@ -62,7 +61,7 @@
= sort_options_hash[@sort]
- else
= sort_title_recently_created
- = sprite_icon('chevron-down', css_class: 'dropdown-menu-toggle-icon gl-top-3')
+ = sprite_icon('chevron-down', css_class: 'dropdown-menu-toggle-icon')
%ul.dropdown-menu.dropdown-menu-sort.dropdown-menu-right
%li
= link_to todos_filter_path(sort: sort_value_label_priority) do
@@ -82,15 +81,15 @@
= render @allowed_todos
= paginate @todos, theme: "gitlab"
.js-nothing-here-container.empty-state.hidden
- .svg-content
- = image_tag 'illustrations/todos_all_done.svg'
+ .svg-content.svg-150
+ = image_tag 'illustrations/empty-todos-all-done-md.svg'
.text-content.gl-text-center
%h4
= s_("Todos|You're all done!")
- elsif current_user.todos.any?
.col.todos-all-done.empty-state
- .svg-content.svg-250
- = image_tag 'illustrations/todos_all_done.svg'
+ .svg-content.svg-150
+ = image_tag 'illustrations/empty-todos-all-done-md.svg'
.text-content.gl-text-center
- if todos_filter_empty?
%h4
@@ -102,8 +101,8 @@
= s_("Todos|Nothing is on your to-do list. Nice work!")
- else
.col.empty-state
- .svg-content
- = image_tag 'illustrations/todos_empty.svg'
+ .svg-content.svg-150
+ = image_tag 'illustrations/empty-todos-md.svg'
.text-content.gl-text-center
%h4
= s_("Todos|Your To-Do List shows what to work on next")
diff --git a/app/views/devise/confirmations/almost_there.haml b/app/views/devise/confirmations/almost_there.haml
index 01f9595f35c..c22eeba2f01 100644
--- a/app/views/devise/confirmations/almost_there.haml
+++ b/app/views/devise/confirmations/almost_there.haml
@@ -1,6 +1,7 @@
- user_email = "(#{params[:email]})" if Devise.email_regexp.match?(params[:email])
- 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
+- registration_link_start = '<a href="%{new_user_registration_path}">'.html_safe % { new_user_registration_path: new_user_registration_path }
+- link_end = '</a>'.html_safe
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
@@ -12,9 +13,11 @@
= _("Almost there...")
%p{ class: 'gl-mb-6 gl-font-lg!' }
= _('Please check your email %{email} to confirm your account') % { email: user_email }
+ %br
+ = _('If the email address is incorrect, you can %{registration_link_start}register again with a different email%{registration_link_end}.').html_safe % { registration_link_start: registration_link_start, registration_link_end: link_end }
%hr
- if Gitlab::CurrentSettings.after_sign_up_text.present?
.well-confirmation.gl-text-center
= markdown_field(Gitlab::CurrentSettings, :after_sign_up_text)
%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 }
+ = _("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: link_end }
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
index d3bd1d58d21..5af247703f6 100644
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -1,19 +1,22 @@
= render 'devise/shared/tab_single', tab_title: 'Resend confirmation instructions'
.login-box.gl-p-5
.login-body
- = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
+ = gitlab_ui_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
.devise-errors
= render "devise/shared/error_messages", resource: resource
.form-group
= f.label :email
= f.email_field :email, class: "form-control gl-form-input", required: true, autocomplete: 'off', title: _('Please provide a valid email address.'), value: nil
+ .form-text.gl-text-secondary
+ = _('Requires your primary GitLab email address.')
%div
- if recaptcha_enabled?
= recaptcha_tags nonce: content_security_policy_nonce
.gl-mt-5
- = f.submit _("Resend"), class: 'gl-button btn btn-confirm'
+ = render Pajamas::ButtonComponent.new(block: true, type: :submit, variant: :confirm) do
+ = _("Resend")
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
diff --git a/app/views/devise/mailer/user_admin_approval.text.erb b/app/views/devise/mailer/user_admin_approval.text.erb
index 5242981e514..bce56d59c68 100644
--- a/app/views/devise/mailer/user_admin_approval.text.erb
+++ b/app/views/devise/mailer/user_admin_approval.text.erb
@@ -2,6 +2,6 @@
<%= _('Your GitLab account request has been approved!') %>
-<%= _('Your username is %{username}.' % { username: @resource.username }) %>
+<%= _('Your username is %{username}.') % { username: @resource.username } %>
-<%= _('Your sign-in page is %{url}.' % { url: Gitlab.config.gitlab.url }) %>
+<%= _('Your sign-in page is %{url}.') % { url: Gitlab.config.gitlab.url } %>
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index 8a960602536..e75449bf320 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -8,8 +8,8 @@
= render "layouts/google_tag_manager_body"
.signup-page
- = render 'devise/shared/signup_box',
- url: registration_path(resource_name, glm_tracking_params.to_hash),
+ = render signup_box_template,
+ url: registration_path(resource_name, registration_path_params),
button_text: _('Register'),
borderless: Feature.enabled?(:restyle_login_page, @project),
show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index 3aeb89979bb..698e8c89a08 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -4,16 +4,19 @@
= f.text_field :login, value: @invite_email, class: 'form-control gl-form-input top js-username-field', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', required: true, title: _('This field is required.'), data: { qa_selector: 'login_field', testid: 'username-field' }
.form-group.gl-px-5
= f.label :password, class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
- = 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', testid: 'password-field' }
- - if devise_mapping.rememberable?
- .gl-px-5
- .gl-display-inline-block
+ = f.password_field :password, class: 'form-control gl-form-input js-password', data: { id: "#{resource_name}_password",
+ qa_selector: 'password_field',
+ testid: 'password-field',
+ name: "#{resource_name}[password]" }
+ .gl-px-5
+ .gl-display-inline-block
+ - if remember_me_enabled?
= f.gitlab_ui_checkbox_component :remember_me, _('Remember me')
- .gl-float-right
- - if unconfirmed_email?
- = link_to _('Resend confirmation email'), new_user_confirmation_path
- - else
- = link_to _('Forgot your password?'), new_password_path(:user)
+ .gl-float-right
+ - if unconfirmed_email?
+ = link_to _('Resend confirmation email'), new_user_confirmation_path
+ - else
+ = link_to _('Forgot your password?'), new_password_path(:user)
%div
- if Feature.enabled?(:arkose_labs_login_challenge)
= render_if_exists 'devise/sessions/arkose_labs'
@@ -21,8 +24,8 @@
.gl-px-5
= recaptcha_tags nonce: content_security_policy_nonce
- .submit-container.move-submit-down.gl-px-5
+ .submit-container.move-submit-down.gl-px-5.gl-pb-5
= f.button _('Sign in'), type: :submit, class: "gl-button btn btn-block btn-confirm js-sign-in-button#{' js-no-auto-disable' if Feature.enabled?(:arkose_labs_login_challenge)}", data: { qa_selector: 'sign_in_button', testid: 'sign-in-button' }
- - if Gitlab::CurrentSettings.sign_in_text.present? && Feature.enabled?(:restyle_login_page, @project)
- .gl-px-5
+ - if Gitlab::CurrentSettings.sign_in_text.present? && Feature.enabled?(:restyle_login_page, @project)
+ .gl-px-5
= markdown_field(Gitlab::CurrentSettings.current_application_settings, :sign_in_text)
diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml
index bdf357c5f74..293e287371a 100644
--- a/app/views/devise/sessions/_new_crowd.html.haml
+++ b/app/views/devise/sessions/_new_crowd.html.haml
@@ -4,8 +4,8 @@
= text_field_tag :username, nil, { class: "form-control top", title: _("This field is required."), autofocus: "autofocus", required: true }
.form-group.gl-px-5
= label_tag :password
- = password_field_tag :password, nil, { autocomplete: 'current-password', class: "form-control bottom", title: _("This field is required."), required: true }
- - if devise_mapping.rememberable?
+ = password_field_tag :password, nil, { class: 'form-control gl-form-input js-password', data: { id: 'password', name: 'password' } }
+ - if remember_me_enabled?
.remember-me.gl-px-5
%label{ for: "remember_me" }
= check_box_tag :remember_me, '1', false, id: 'remember_me'
diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml
index 7affbafbdeb..fb5a57b509c 100644
--- a/app/views/devise/sessions/_new_ldap.html.haml
+++ b/app/views/devise/sessions/_new_ldap.html.haml
@@ -1,5 +1,5 @@
- server = local_assigns.fetch(:server)
-- hide_remember_me = local_assigns.fetch(:hide_remember_me, false)
+- render_remember_me = remember_me_enabled? && local_assigns.fetch(:render_remember_me, true)
- submit_message = local_assigns.fetch(:submit_message, _('Sign in'))
= form_tag(omniauth_callback_path(:user, server['provider_name']), id: 'new_ldap_user', class: "gl-show-field-errors") do
@@ -8,8 +8,8 @@
= 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.gl-px-5
= label_tag :password
- = 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?
+ = password_field_tag :password, nil, { class: 'form-control gl-form-input js-password', data: { id: 'password', name: 'password', qa_selector: 'password_field' } }
+ - if render_remember_me
.gl-px-5
= render Pajamas::CheckboxTagComponent.new(name: 'remember_me') do |c|
= c.label do
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index a4edf165a89..fd96d5dc1c4 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -26,5 +26,4 @@
= _("Don't have an account yet?")
= link_to _("Register now"), new_registration_path(:user, invite_email: @invite_email), data: { qa_selector: 'register_link' }
- if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled?
- .clearfix
- = render 'devise/shared/omniauth_box'
+ = render 'devise/shared/omniauth_box'
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index f63f1aa9197..06152e3dac5 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -2,15 +2,16 @@
= render 'devise/shared/tab_single', tab_title: _('Two-Factor Authentication') if Feature.disabled?(:restyle_login_page, @project)
.login-box.gl-p-5
.login-body
- - if @user.two_factor_otp_enabled?
- = gitlab_ui_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_u2f_enabled?}" }) do |f|
+ - if @user.two_factor_enabled?
+ = gitlab_ui_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_enabled?}" }) do |f|
- resource_params = params[resource_name].presence || params
- = f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
+ - if remember_me_enabled?
+ = f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
%div
- = f.label _('Two-Factor Authentication code'), name: :otp_attempt, class: Feature.enabled?(:restyle_login_page, @project) ? 'gl-mb-1' : ''
- = f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', title: _('This field is required.'), data: { qa_selector: 'two_fa_code_field' }
- %p.form-text.text-muted.hint= _("Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.")
+ = f.label _('Enter verification code'), name: :otp_attempt, class: Feature.enabled?(:restyle_login_page, @project) ? 'gl-mb-1' : ''
+ = f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', inputmode: 'numeric', title: _('This field is required.'), data: { qa_selector: 'two_fa_code_field' }
+ %p.form-text.text-muted.hint= _("Enter the code from your two-factor authenticator app. If you've lost your device, you can enter one of your recovery codes.")
.prepend-top-20
= f.submit _("Verify code"), pajamas_button: true, data: { qa_selector: 'verify_code_button' }
- - if @user.two_factor_webauthn_u2f_enabled?
+ - if @user.two_factor_webauthn_enabled?
= render "authentication/authenticate", params: params, resource: resource, resource_name: resource_name, render_remember_me: true, target_path: new_user_session_path
diff --git a/app/views/devise/shared/_error_messages.html.haml b/app/views/devise/shared/_error_messages.html.haml
new file mode 100644
index 00000000000..b7589a4460e
--- /dev/null
+++ b/app/views/devise/shared/_error_messages.html.haml
@@ -0,0 +1,9 @@
+- if resource.errors.any?
+ = render Pajamas::AlertComponent.new(title: I18n.t("errors.messages.not_saved", count: resource.errors.count, resource: resource.class.model_name.human.downcase),
+ variant: :danger,
+ dismissible: false,
+ alert_options: { id: 'error_explanation', class: 'gl-mb-3'}) do |c|
+ = c.body do
+ %ul.gl-pl-4
+ - resource.errors.full_messages.each do |message|
+ %li= message
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 439a2fc4d96..14a9bde2d9e 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -1,18 +1,22 @@
-- hide_remember_me = local_assigns.fetch(:hide_remember_me, false)
+- render_remember_me = remember_me_enabled? && local_assigns.fetch(:render_remember_me, true)
- restyle_login_page_enabled = Feature.enabled?(:restyle_login_page, @project)
-%div{ class: restyle_login_page_enabled ? 'omniauth-container gl-mt-5 gl-p-5 gl-text-center gl-w-90p gl-ml-auto gl-mr-auto' : 'omniauth-container gl-mt-5 gl-p-5' }
- %label{ class: restyle_login_page_enabled ? 'gl-font-weight-normal' : 'gl-font-weight-bold' }
- = _('Sign in with')
- - providers = enabled_button_based_providers
- .gl-display-flex.gl-flex-wrap{ class: restyle_login_page_enabled ? 'gl-justify-content-center' : 'gl-justify-content-between' }
- - 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 gl-ml-2 gl-mr-2 gl-mb-2 js-oauth-login #{qa_class_for_provider(provider)} #{'gl-w-full' unless restyle_login_page_enabled}", form: { class: restyle_login_page_enabled ? 'gl-mb-3' : '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
- = render Pajamas::CheckboxTagComponent.new(name: 'remember_me', value: nil) do |c|
+
+- if restyle_login_page_enabled && (any_form_based_providers_enabled? || password_authentication_enabled_for_web?)
+ .omniauth-divider.gl-display-flex.gl-align-items-center
+ = _("or")
+
+.gl-mt-5.gl-px-5{ class: restyle_login_page_enabled ? 'omniauth-container gl-text-center gl-ml-auto gl-mr-auto' : 'omniauth-container gl-py-5' }
+ - if !restyle_login_page_enabled
+ %label.gl-font-weight-bold
+ = _('Sign in with')
+ - enabled_button_based_providers.each do |provider|
+ - has_icon = provider_has_icon?(provider)
+ = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", data: { qa_selector: "#{qa_selector_for_provider(provider)}" }, class: "btn gl-button btn-default gl-mb-2 js-oauth-login gl-w-full", form: { class: restyle_login_page_enabled ? 'gl-mb-3' : 'gl-w-full gl-mb-3' } do
+ - if has_icon
+ = provider_image_tag(provider)
+ %span.gl-button-text
+ = label_for_provider(provider)
+ - if render_remember_me
+ = render Pajamas::CheckboxTagComponent.new(name: 'remember_me_omniauth', value: nil) do |c|
= c.label do
= _('Remember me')
diff --git a/app/views/devise/shared/_sign_in_link.html.haml b/app/views/devise/shared/_sign_in_link.html.haml
index 0a48c342502..a1d10898c5b 100644
--- a/app/views/devise/shared/_sign_in_link.html.haml
+++ b/app/views/devise/shared/_sign_in_link.html.haml
@@ -1,6 +1,6 @@
%p.text-center
%span.light
- = _('Already have login and password?')
+ = _('Already have an account?')
- path_params = { redirect_to_referer: 'yes' }
- path_params[:invite_email] = @invite_email if @invite_email.present?
= link_to _('Sign in'), new_session_path(:user, path_params)
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index f4f3965bdc1..31c541eebde 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -1,12 +1,13 @@
- max_first_name_length = max_last_name_length = 127
- omniauth_providers_placement ||= :bottom
- borderless ||= false
+- form_resource_name = "new_#{resource_name}"
.gl-mb-3.gl-p-4{ class: (borderless ? '' : 'gl-border-gray-100 gl-border-1 gl-border-solid gl-rounded-base') }
- if show_omniauth_providers && omniauth_providers_placement == :top
= render 'devise/shared/signup_omniauth_providers_top'
- = gitlab_ui_form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors js-arkose-labs-form', 'aria-live' => 'assertive' }, data: { testid: 'signup-form' }) do |f|
+ = gitlab_ui_form_for(resource, as: form_resource_name, url: url, html: { class: 'new_user gl-show-field-errors js-arkose-labs-form', 'aria-live' => 'assertive' }, data: { testid: 'signup-form' }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- if Gitlab::CurrentSettings.invisible_captcha_enabled
@@ -52,21 +53,20 @@
%p.validation-warning.gl-field-error-ignore.text-secondary.hide= _('This email address does not look right, are you sure you typed it correctly?')
-# This is used for providing entry to Jihu on email verification
= render_if_exists 'devise/shared/signup_email_additional_info'
- .form-group.gl-mb-5#password-strength
+ .form-group.gl-mb-5
= f.label :password, class: "label-bold #{'gl-mb-1' if Feature.enabled?(:restyle_login_page, @project)}"
- = f.password_field :password,
- class: 'form-control gl-form-input bottom js-password-complexity-validation',
- data: { qa_selector: 'new_user_password_field' },
+ %input.form-control.gl-form-input.js-password{ data: { id: "#{form_resource_name}_password",
+ title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length },
+ minimum_password_length: @minimum_password_length,
+ 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 }
- %p.gl-field-hint.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
+ name: "#{form_resource_name}[password]" } }
+ %p.gl-field-hint-valid.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
= render_if_exists 'shared/password_requirements_list'
= render_if_exists 'devise/shared/phone_verification', form: f
%div
- - if arkose_labs_challenge_enabled?
+ - if arkose_labs_enabled?
= render_if_exists 'devise/registrations/arkose_labs'
- elsif show_recaptcha_sign_up?
= recaptcha_tags nonce: content_security_policy_nonce
diff --git a/app/views/devise/shared/_signup_omniauth_provider_list.haml b/app/views/devise/shared/_signup_omniauth_provider_list.haml
index a96c8d6358b..6294a93808b 100644
--- a/app/views/devise/shared/_signup_omniauth_provider_list.haml
+++ b/app/views/devise/shared/_signup_omniauth_provider_list.haml
@@ -3,9 +3,9 @@
.gl-text-center.gl-pt-5
%label.gl-font-weight-normal
= _("Register with:")
- .gl-text-center.gl-w-90p.gl-ml-auto.gl-mr-auto
+ .gl-text-center.gl-ml-auto.gl-mr-auto
- providers.each do |provider|
- = link_to omniauth_authorize_path(:user, provider, register_omniauth_params), method: :post, class: "btn gl-button btn-default gl-ml-2 gl-mr-2 gl-mb-2 js-oauth-login #{qa_class_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
+ = link_to omniauth_authorize_path(:user, provider, register_omniauth_params), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-4 js-oauth-login #{qa_selector_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
- if provider_has_icon?(provider)
= provider_image_tag(provider)
%span.gl-button-text
@@ -15,7 +15,7 @@
= _("Create an account using:")
.gl-display-flex.gl-justify-content-between.gl-flex-wrap
- providers.each do |provider|
- = link_to omniauth_authorize_path(:user, provider, register_omniauth_params), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
+ = link_to omniauth_authorize_path(:user, provider, register_omniauth_params), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-4 js-oauth-login #{qa_selector_for_provider(provider)}", data: { provider: provider }, id: "oauth-login-#{provider}" do
- if provider_has_icon?(provider)
= provider_image_tag(provider)
%span.gl-button-text
diff --git a/app/views/doorkeeper/applications/edit.html.haml b/app/views/doorkeeper/applications/edit.html.haml
index c48e2cd4db0..f1c3ea6aab1 100644
--- a/app/views/doorkeeper/applications/edit.html.haml
+++ b/app/views/doorkeeper/applications/edit.html.haml
@@ -1,5 +1,4 @@
- page_title _("Edit"), @application.name, _("Applications")
-- @content_class = "limit-container-width" unless fluid_layout
%h1.page-title.gl-font-size-h-display= _('Edit application')
= render 'shared/doorkeeper/applications/form', url: doorkeeper_submit_path(@application)
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index 0428b9c340c..5fc1384f6ee 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -1,7 +1,6 @@
- add_to_breadcrumbs _("Applications"), oauth_applications_path
- breadcrumb_title @application.name
- page_title @application.name, _("Applications")
-- @content_class = "limit-container-width" unless fluid_layout
%h1.page-title.gl-font-size-h-display
= _("Application: %{name}") % { name: @application.name }
@@ -9,4 +8,5 @@
= render 'shared/doorkeeper/applications/show',
edit_path: edit_oauth_application_path(@application),
delete_path: oauth_application_path(@application),
- index_path: oauth_applications_path
+ index_path: oauth_applications_path,
+ renew_path: renew_oauth_application_path(@application)
diff --git a/app/views/events/_events.html.haml b/app/views/events/_events.html.haml
index e1b7804c5a7..eb6154a446e 100644
--- a/app/views/events/_events.html.haml
+++ b/app/views/events/_events.html.haml
@@ -1,4 +1,4 @@
-- illustration_path = 'illustrations/profile-page/activity.svg'
+- illustration_path = 'illustrations/empty-state/empty-activity-md.svg'
- current_user_empty_message_header = s_('UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!')
- primary_button_label = _('New group')
- primary_button_link = new_group_path
diff --git a/app/views/explore/_head.html.haml b/app/views/explore/_head.html.haml
deleted file mode 100644
index eefc797cf03..00000000000
--- a/app/views/explore/_head.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-.explore-title.text-center
- %h2
- = _("Explore GitLab")
- %p.lead
- = _("Discover projects, groups and snippets. Share your projects with others")
- %br
diff --git a/app/views/explore/groups/_nav.html.haml b/app/views/explore/groups/_nav.html.haml
index 3c9c4e9f76b..176bfd307b2 100644
--- a/app/views/explore/groups/_nav.html.haml
+++ b/app/views/explore/groups/_nav.html.haml
@@ -1,6 +1,4 @@
-.top-area
- = gl_tabs_nav({ class: 'gl-display-flex gl-flex-grow-1 gl-border-none'}) do
- = gl_tab_link_to _("Explore Groups"), explore_groups_path
+.top-area.gl-p-3.gl-justify-content-end
.nav-controls
= render 'shared/groups/search_form'
= render 'shared/groups/dropdown'
diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml
index 60132818193..213346b4cc2 100644
--- a/app/views/explore/groups/index.html.haml
+++ b/app/views/explore/groups/index.html.haml
@@ -1,14 +1,17 @@
-- @hide_top_links = true
-- page_title _("Groups")
+- breadcrumb_title _("Groups")
+- page_title _("Explore groups")
- header_title _("Groups"), dashboard_groups_path
= render_dashboard_ultimate_trial(current_user)
-- if current_user
- = render 'dashboard/groups_head'
-- else
- = render 'explore/head'
- = render 'nav'
+.page-title-holder.gl-display-flex.gl-align-items-center
+ %h1.page-title.gl-font-size-h-display= page_title
+ .page-title-controls
+ - if current_user&.can_create_group?
+ = render Pajamas::ButtonComponent.new(href: new_group_path, variant: :confirm) do
+ = _("New group")
+
+= render 'nav'
- if cookies[:explore_groups_landing_dismissed] != 'true'
.explore-groups.landing.content-block.js-explore-groups-landing.hide
diff --git a/app/views/explore/projects/_head.html.haml b/app/views/explore/projects/_head.html.haml
new file mode 100644
index 00000000000..605d85f49e0
--- /dev/null
+++ b/app/views/explore/projects/_head.html.haml
@@ -0,0 +1,11 @@
+- breadcrumb_title _("Projects")
+- page_title _("Explore projects")
+
+= render_dashboard_ultimate_trial(current_user)
+
+.page-title-holder.gl-display-flex.gl-align-items-center
+ %h1.page-title.gl-font-size-h-display= page_title
+ .page-title-controls
+ - if current_user&.can_create_project?
+ = render Pajamas::ButtonComponent.new(href: new_project_path, variant: :confirm) do
+ = _("New project")
diff --git a/app/views/explore/projects/_nav.html.haml b/app/views/explore/projects/_nav.html.haml
index 9119026320a..ab565279238 100644
--- a/app/views/explore/projects/_nav.html.haml
+++ b/app/views/explore/projects/_nav.html.haml
@@ -1,10 +1,8 @@
.top-area
= gl_tabs_nav({ class: 'gl-display-flex gl-flex-grow-1 gl-border-none'}) do
= gl_tab_link_to _('All'), explore_projects_path, { item_active: current_page?(explore_projects_path) || current_page?(explore_root_path) }
- = gl_tab_link_to _('Most stars'), starred_explore_projects_path
+ = gl_tab_link_to _('Most starred'), starred_explore_projects_path
= gl_tab_link_to _('Trending'), trending_explore_projects_path
.nav-controls
- - unless current_user
- = render 'shared/projects/search_form'
- = render 'filter'
+ = render 'shared/projects/search_form'
diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml
index 9585eb76912..50d79eeefdb 100644
--- a/app/views/explore/projects/index.html.haml
+++ b/app/views/explore/projects/index.html.haml
@@ -1,14 +1,5 @@
-- @hide_top_links = true
-- page_title _("Projects")
-- header_title _("Projects"), dashboard_projects_path
- page_canonical_link explore_projects_url
-= render_dashboard_ultimate_trial(current_user)
-
-- if current_user
- = render 'dashboard/projects_head', project_tab_filter: :explore
-- else
- = render 'explore/head'
-
+= render 'explore/projects/head'
= render 'explore/projects/nav'
= render 'projects', projects: @projects
diff --git a/app/views/explore/projects/page_out_of_bounds.html.haml b/app/views/explore/projects/page_out_of_bounds.html.haml
index e13768a3ccb..dc92787a41f 100644
--- a/app/views/explore/projects/page_out_of_bounds.html.haml
+++ b/app/views/explore/projects/page_out_of_bounds.html.haml
@@ -1,19 +1,9 @@
-- @hide_top_links = true
-- page_title _("Projects")
-- header_title _("Projects"), dashboard_projects_path
-
-= render_dashboard_ultimate_trial(current_user)
-
-- if current_user
- = render 'dashboard/projects_head', project_tab_filter: :explore
-- else
- = render 'explore/head'
-
+= render 'explore/projects/head'
= render 'explore/projects/nav'
.nothing-here-block
.svg-content
- = image_tag 'illustrations/profile-page/personal-project.svg', size: '75'
+ = image_tag 'illustrations/empty-state/empty-projects-md.svg', size: '75'
.text-content
%h5= _("Maximum page reached")
%p= _("Sorry, you have exceeded the maximum browsable page number. Please use the API to explore further.")
diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml
index ec7eefea264..8840a2dc0e3 100644
--- a/app/views/explore/projects/starred.html.haml
+++ b/app/views/explore/projects/starred.html.haml
@@ -1,13 +1,3 @@
-- @hide_top_links = true
-- page_title _("Projects")
-- header_title _("Projects"), dashboard_projects_path
-
-= render_dashboard_ultimate_trial(current_user)
-
-- if current_user
- = render 'dashboard/projects_head', project_tab_filter: :starred
-- else
- = render 'explore/head'
-
+= render 'explore/projects/head'
= render 'explore/projects/nav'
= render 'projects', projects: @projects
diff --git a/app/views/explore/projects/topic.html.haml b/app/views/explore/projects/topic.html.haml
index 7b2c5683482..b26abefcb0e 100644
--- a/app/views/explore/projects/topic.html.haml
+++ b/app/views/explore/projects/topic.html.haml
@@ -1,23 +1,23 @@
-- @hide_top_links = false
-- @no_container = true
+- add_to_breadcrumbs _("Topics"), topics_explore_projects_path
+- breadcrumb_title @topic.title_or_name
- page_title @topic.title_or_name, _("Topics")
- max_topic_title_length = 50
= render_dashboard_ultimate_trial(current_user)
-.gl-text-center.gl-bg-gray-10.gl-pb-2.gl-pt-6
- .gl-pb-5.gl-align-items-center.gl-justify-content-center.gl-display-flex
- .avatar-container.rect-avatar.s60.gl-flex-shrink-0
- = topic_icon(@topic, alt: _('Topic avatar'), class: 'avatar topic-avatar s60')
- - if @topic.title_or_name.length > max_topic_title_length
- %h1.gl-mt-3.gl-str-truncated.has-tooltip{ title: @topic.title_or_name }
- = truncate(@topic.title_or_name, length: max_topic_title_length)
- - else
- %h1.gl-mt-3
- = @topic.title_or_name
- - if @topic.description.present?
- .topic-description.gl-ml-4.gl-mr-4
- = markdown(@topic.description)
+.gl-text-center.gl-bg-gray-10.gl-pb-3.gl-pt-6
+ %div{ class: container_class }
+ .gl-pb-5.gl-align-items-center.gl-justify-content-center.gl-display-flex
+ = render Pajamas::AvatarComponent.new(@topic, size: 64, alt: '')
+ - if @topic.title_or_name.length > max_topic_title_length
+ %h1.gl-mt-3.gl-ml-5.gl-str-truncated.has-tooltip{ title: @topic.title_or_name }
+ = truncate(@topic.title_or_name, length: max_topic_title_length)
+ - else
+ %h1.gl-mt-3.gl-ml-5
+ = @topic.title_or_name
+ - if @topic.description.present?
+ .topic-description
+ = markdown(@topic.description)
%div{ class: container_class }
.gl-py-5.gl-border-gray-100.gl-border-b-solid.gl-border-b-1
diff --git a/app/views/explore/projects/topics.html.haml b/app/views/explore/projects/topics.html.haml
index 228304d25b6..08cd122c6aa 100644
--- a/app/views/explore/projects/topics.html.haml
+++ b/app/views/explore/projects/topics.html.haml
@@ -1,12 +1,9 @@
-- @hide_top_links = true
-- page_title _("Topics")
+- breadcrumb_title _("Topics")
+- page_title _("Explore topics")
- header_title _("Topics"), topics_explore_projects_path
= render_dashboard_ultimate_trial(current_user)
-- if current_user
- = render 'explore/topics/head'
-- else
- = render 'explore/head'
+= render 'explore/topics/head'
= render partial: 'shared/topics/list'
diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml
index 8a92ec31b22..8840a2dc0e3 100644
--- a/app/views/explore/projects/trending.html.haml
+++ b/app/views/explore/projects/trending.html.haml
@@ -1,13 +1,3 @@
-- @hide_top_links = true
-- page_title _("Projects")
-- header_title _("Projects"), dashboard_projects_path
-
-= render_dashboard_ultimate_trial(current_user)
-
-- if current_user
- = render 'dashboard/projects_head', project_tab_filter: :explore_trending
-- else
- = render 'explore/head'
-
+= render 'explore/projects/head'
= render 'explore/projects/nav'
= render 'projects', projects: @projects
diff --git a/app/views/explore/snippets/index.html.haml b/app/views/explore/snippets/index.html.haml
index bf861e30b3a..bd8b9c29389 100644
--- a/app/views/explore/snippets/index.html.haml
+++ b/app/views/explore/snippets/index.html.haml
@@ -1,10 +1,12 @@
-- @hide_top_links = true
-- page_title _("Snippets")
+- breadcrumb_title _("Snippets")
+- page_title _("Explore snippets")
- header_title _("Snippets"), snippets_path
-- if current_user
- = render 'dashboard/snippets_head'
-- else
- = render 'explore/head'
+.page-title-holder.gl-display-flex.gl-align-items-center
+ %h1.page-title.gl-font-size-h-display= page_title
+ .page-title-controls
+ - if can?(current_user, :create_snippet)
+ = render Pajamas::ButtonComponent.new(href: new_snippet_path, variant: :confirm) do
+ = _("New snippet")
= render partial: 'shared/snippets/list', locals: { link_project: true }
diff --git a/app/views/explore/topics/_head.html.haml b/app/views/explore/topics/_head.html.haml
index f7d80d63c45..db8de333517 100644
--- a/app/views/explore/topics/_head.html.haml
+++ b/app/views/explore/topics/_head.html.haml
@@ -1,10 +1,6 @@
-.page-title-holder.d-flex.align-items-center
- %h1.page-title.gl-font-size-h-display= _('Projects')
+.page-title-holder.gl-display-flex.gl-align-items-center
+ %h1.page-title.gl-font-size-h-display= page_title
-.top-area
- .scrolling-tabs-container.inner-page-scroll-tabs.gl-flex-grow-1.gl-min-w-0.gl-w-full
- .fade-left= sprite_icon('chevron-lg-left', size: 12)
- .fade-right= sprite_icon('chevron-lg-right', size: 12)
- = render 'dashboard/projects_nav'
+.top-area.gl-p-4
.nav-controls
= render 'shared/topics/search_form'
diff --git a/app/views/groups/_flash_messages.html.haml b/app/views/groups/_flash_messages.html.haml
index fa1a9d2cca4..b6b409967b0 100644
--- a/app/views/groups/_flash_messages.html.haml
+++ b/app/views/groups/_flash_messages.html.haml
@@ -1,2 +1,2 @@
= content_for :flash_message do
- = render_if_exists 'shared/shared_runners_minutes_limit', namespace: @group, classes: [container_class, ("limit-container-width" unless fluid_layout)]
+ = render_if_exists 'shared/shared_runners_minutes_limit', namespace: @group, classes: [container_class]
diff --git a/app/views/groups/_group_admin_settings.html.haml b/app/views/groups/_group_admin_settings.html.haml
index 8547795b4b7..7f113a1cfd4 100644
--- a/app/views/groups/_group_admin_settings.html.haml
+++ b/app/views/groups/_group_admin_settings.html.haml
@@ -2,10 +2,10 @@
%legend.col-form-label.col-form-label
= _('Large File Storage')
= f.gitlab_ui_checkbox_component :lfs_enabled, checkbox_options: { checked: @group.lfs_enabled? } do |c|
- = c.label do
+ - c.with_label do
= _('Projects in this group can use Git LFS')
= link_to sprite_icon('question-o'), help_page_path('topics/git/lfs/index'), class: 'gl-ml-2'
- = c.help_text do
+ - c.with_help_text do
= _('This setting can be overridden in each project.')
.form-group.gl-form-group{ role: 'group' }
= f.label s_('ProjectCreationLevel|Allowed to create projects'), class: 'gl-display-block col-form-label'
@@ -32,8 +32,7 @@
.form-group.gl-form-group
%legend.col-form-label.col-form-label
= s_('Runners|Runner Registration')
- - parent_disabled = Gitlab::CurrentSettings.valid_runner_registrars.exclude?('group') || !@group.all_ancestors_have_runner_registration_enabled?
= f.gitlab_ui_checkbox_component :runner_registration_enabled,
s_('Runners|New group runners can be registered'),
- checkbox_options: { checked: @group.runner_registration_enabled && !parent_disabled, disabled: parent_disabled },
+ checkbox_options: { checked: @group.runner_registration_enabled?, disabled: !@group.all_ancestors_have_runner_registration_enabled? },
help_text: s_('Runners|Existing runners are not affected. To permit runner registration for all groups, enable this setting in the Admin Area in Settings &gt; CI/CD.').html_safe
diff --git a/app/views/groups/_group_readme.html.haml b/app/views/groups/_group_readme.html.haml
new file mode 100644
index 00000000000..724e82594e6
--- /dev/null
+++ b/app/views/groups/_group_readme.html.haml
@@ -0,0 +1,3 @@
+- return unless show_group_readme?(group)
+
+#js-group-readme{ data: group_readme_app_data(group.group_readme) }
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 24ba060a89a..9fbb7f3c9ed 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
@@ -9,7 +9,7 @@
- if bulk_imports_disabled
= render Pajamas::AlertComponent.new(dismissible: false, variant: :tip) do |c|
- = c.body do
+ - c.with_body do
= s_('GroupsNew|Importing groups by direct transfer is currently disabled.')
- if current_user.admin?
@@ -24,10 +24,10 @@
- else
= render Pajamas::AlertComponent.new(dismissible: false,
variant: :warning) do |c|
- = c.body do
- - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md') }
+ - c.with_body do
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md', anchor: 'migrated-group-items') }
- 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 }
+ = s_('GroupsNew|Not all group items are migrated. %{docs_link_start}What items are migrated%{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 the source instance to import from. You can provide this instance as a source to move groups in this instance.')
diff --git a/app/views/groups/_import_group_from_file_panel.html.haml b/app/views/groups/_import_group_from_file_panel.html.haml
index 35e8b7dc977..91f7b574dbf 100644
--- a/app/views/groups/_import_group_from_file_panel.html.haml
+++ b/app/views/groups/_import_group_from_file_panel.html.haml
@@ -9,15 +9,15 @@
= render Pajamas::AlertComponent.new(variant: :warning,
alert_options: { class: 'gl-mb-5' },
dismissible: false) do |c|
- = c.body do
- - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md') }
+ - c.with_body do
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md', anchor: 'migrate-groups-by-direct-transfer-recommended') }
- link_end = '</a>'.html_safe
- = s_('GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: link_end }
+ = s_('GroupsNew|This feature is deprecated and replaced by group migration by direct transfer. %{docs_link_start}Learn more%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: link_end }
= render 'shared/groups/group_name_and_path_fields', f: f
.form-group
= f.label :file, s_('GroupsNew|Upload file')
.gl-font-weight-normal
- - import_export_link_start = '<a href="%{url}" target="_blank">'.html_safe % { url: help_page_path('user/group/settings/import_export') }
+ - import_export_link_start = '<a href="%{url}" target="_blank">'.html_safe % { url: help_page_path('user/group/import/index') }
= s_('GroupsNew|To import a group, navigate to the group settings for the GitLab source instance, %{link_start}generate an export file%{link_end}, and upload it here.').html_safe % { link_start: import_export_link_start, link_end: '</a>'.html_safe }
.gl-mt-3
= render 'shared/file_picker_button', f: f, field: :file, help_text: nil, classes: 'gl-button btn-confirm-secondary gl-mr-2'
diff --git a/app/views/groups/_invite_members_modal.html.haml b/app/views/groups/_invite_members_modal.html.haml
index f0fd9026b30..cd3327ba9ec 100644
--- a/app/views/groups/_invite_members_modal.html.haml
+++ b/app/views/groups/_invite_members_modal.html.haml
@@ -2,5 +2,5 @@
.js-invite-members-modal{ data: { is_project: 'false',
access_levels: group.access_level_roles.to_json,
- reload_page_on_submit: local_assigns.fetch(:reload_page_on_submit, false).to_s,
+ reload_page_on_submit: current_path?('group_members#index').to_s,
help_link: help_page_url('user/permissions') }.merge(common_invite_modal_dataset(group)).merge(users_filter_data(group)) }
diff --git a/app/views/groups/_invite_members_side_nav_link.html.haml b/app/views/groups/_invite_members_side_nav_link.html.haml
deleted file mode 100644
index 978ef01984c..00000000000
--- a/app/views/groups/_invite_members_side_nav_link.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-.js-invite-members-trigger{ data: { trigger_source: 'group-side-nav',
- icon: 'users',
- display_text: title,
- trigger_element: 'side-nav',
- qa_selector: 'invite_members_sidebar_button' } }
-
-= render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu }
-= render 'groups/invite_members_modal', group: group
diff --git a/app/views/groups/_invite_members_top_nav_link.html.haml b/app/views/groups/_invite_members_top_nav_link.html.haml
new file mode 100644
index 00000000000..35a8d4d9944
--- /dev/null
+++ b/app/views/groups/_invite_members_top_nav_link.html.haml
@@ -0,0 +1,5 @@
+- data = local_assigns.fetch(:data)
+- data[:display_text] = local_assigns.fetch(:display_text)
+- data[:icon] = local_assigns.fetch(:icon)
+
+.js-invite-members-trigger{ data: data }
diff --git a/app/views/groups/_new_group_fields.html.haml b/app/views/groups/_new_group_fields.html.haml
index 95990e8937c..ddf6e52796f 100644
--- a/app/views/groups/_new_group_fields.html.haml
+++ b/app/views/groups/_new_group_fields.html.haml
@@ -31,6 +31,5 @@
.row
.col-sm-12
= f.submit submit_label, pajamas_button: true, data: { qa_selector: 'create_group_button' }
- = render Pajamas::ButtonComponent.new(href: dashboard_groups_path) do
+ = render Pajamas::ButtonComponent.new(href: @parent_group || dashboard_groups_path) do
= _('Cancel')
-
diff --git a/app/views/groups/achievements/index.html.haml b/app/views/groups/achievements/index.html.haml
new file mode 100644
index 00000000000..d93448b430a
--- /dev/null
+++ b/app/views/groups/achievements/index.html.haml
@@ -0,0 +1,14 @@
+- breadcrumb_title _('Achievements')
+- page_title _('Achievements')
+- @content_wrapper_class = "gl-relative"
+
+= content_for :after_content do
+ #js-achievements-form-portal
+
+#js-achievements-app{ data: { base_path: group_achievements_path(@group), view_model: Gitlab::Json.generate({
+ can_admin_achievement: can?(current_user, :admin_achievement, @group),
+ can_award_achievement: can?(current_user, :award_achievement, @group),
+ group_full_path: @group.full_path,
+ group_id: @group.id,
+ text_query: params[:search]
+ }) } }
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
index 178d8980ab8..8416cb81c95 100644
--- a/app/views/groups/dependency_proxies/show.html.haml
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -1,7 +1,7 @@
- page_title _("Dependency Proxy")
-- @content_class = "limit-container-width" unless fluid_layout
#js-dependency-proxy{ data: { group_path: @group.full_path,
no_manifests_illustration: image_path('illustrations/docker-empty-state.svg'),
group_id: @group.id,
+ settings_path: group_settings_packages_and_registries_path(@group),
can_clear_cache: can?(current_user, :admin_group, @group).to_s } }
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 0c416d57b75..dedff502a87 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("General settings")
- page_title _("General settings")
-- @content_class = "limit-container-width" unless fluid_layout
- expanded = expanded_by_default?
+- @force_desktop_expanded_sidebar = true
= render 'shared/namespaces/cascading_settings/lock_popovers'
@@ -17,7 +17,7 @@
.settings-content
= render 'groups/settings/general'
-%section.settings.gs-permissions.no-animate#js-permissions-settings{ class: ('expanded' if expanded), data: { qa_selector: 'permission_lfs_2fa_content' } }
+%section.settings.gs-permissions.no-animate#js-permissions-settings{ class: ('expanded' if expanded), data: { qa_selector: 'permission_lfs_2fa_content', testid: 'permissions-settings' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
= _('Permissions and group features')
@@ -30,8 +30,7 @@
= render_if_exists 'groups/merge_requests', expanded: expanded, group: @group
= render_if_exists 'groups/merge_request_approval_settings', expanded: expanded, group: @group, user: current_user
-= render_if_exists 'groups/insights', expanded: expanded
-= render_if_exists 'groups/analytics_dashboards', expanded: expanded
+= render_if_exists 'groups/analytics', expanded: expanded
%section.settings.no-animate#js-badge-settings{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 298ed2c0806..04bf3f98a1e 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -16,7 +16,6 @@
trigger_source: 'group-members-page',
display_text: _('Invite members') } }
= render 'groups/invite_groups_modal', group: @group, reload_page_on_submit: true
- = render 'groups/invite_members_modal', group: @group, reload_page_on_submit: true
= render_if_exists 'groups/group_members/ldap_sync'
diff --git a/app/views/groups/harbor/repositories/index.html.haml b/app/views/groups/harbor/repositories/index.html.haml
index 59ad29ccabd..3f9073e358d 100644
--- a/app/views/groups/harbor/repositories/index.html.haml
+++ b/app/views/groups/harbor/repositories/index.html.haml
@@ -1,5 +1,4 @@
- page_title _("Harbor Registry")
-- @content_class = "limit-container-width" unless fluid_layout
#js-harbor-registry-list-group{ data: { endpoint: group_harbor_repositories_path(@group),
"no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
diff --git a/app/views/groups/imports/show.html.haml b/app/views/groups/imports/show.html.haml
index 9cfb58da7e4..6a5c266f74d 100644
--- a/app/views/groups/imports/show.html.haml
+++ b/app/views/groups/imports/show.html.haml
@@ -1,5 +1,4 @@
- page_title _('Import in progress')
-- @content_class = "limit-container-width" unless fluid_layout
.save-group-loader
.center
diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml
index a03c406acc6..80da61847ef 100644
--- a/app/views/groups/labels/index.html.haml
+++ b/app/views/groups/labels/index.html.haml
@@ -12,9 +12,11 @@
- if @labels.any?
.text-muted.gl-mb-5
= labels_function_introduction
- .other-labels
- %h4= _('Labels')
- %ul.manage-labels-list.js-other-labels
+ .other-labels.gl-rounded-base.gl-border.gl-bg-gray-10
+ .gl-px-5.gl-py-4.gl-bg-white.gl-rounded-base.gl-border-b{ class: 'gl-rounded-bottom-left-none! gl-rounded-bottom-right-none!' }
+ %h3.card-title.h5.gl-m-0.gl-relative.gl-line-height-24
+ = _('Labels')
+ %ul.manage-labels-list.js-other-labels.gl-px-3.gl-rounded-base
= render partial: 'shared/label', collection: @labels, as: :label, locals: { use_label_priority: false, subject: @group }
= paginate @labels, theme: 'gitlab'
- elsif search.present?
@@ -27,5 +29,5 @@
= render 'shared/empty_states/labels'
%template#js-badge-item-template
- %li.js-priority-badge.inline.gl-ml-3
- .label-badge.gl-bg-blue-50= _('Prioritized label')
+ %li.js-priority-badge.inline.gl-mr-3
+ .label-badge.gl-bg-blue-50= _('Prioritized')
diff --git a/app/views/groups/milestones/_form.html.haml b/app/views/groups/milestones/_form.html.haml
index a99d76f99a7..89f460606cb 100644
--- a/app/views/groups/milestones/_form.html.haml
+++ b/app/views/groups/milestones/_form.html.haml
@@ -1,30 +1,31 @@
= gitlab_ui_form_for [@group, @milestone], html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
= form_errors(@milestone)
- .form-group.row
- .col-form-label.col-sm-2
- = f.label :title, _("Title")
- .col-sm-10
- = f.text_field :title, maxlength: 255, class: "form-control", data: { qa_selector: "milestone_title_field" }, required: true, autofocus: true
+
+ - if @conflict
+ = render 'shared/model_version_conflict', model_name: _('milestone'), link_path: group_milestone_path(@group, @milestone)
+
+ .form-group
+ = f.label :title, _("Title")
+ = f.text_field :title, maxlength: 255, class: "form-control", data: { qa_selector: "milestone_title_field" }, required: true, autofocus: true
= render "shared/milestones/form_dates", f: f
- .form-group.row.milestone-description
- .col-form-label.col-sm-2
- = f.label :description, _("Description")
- .col-sm-10
- = render layout: 'shared/md_preview', locals: { url: group_preview_markdown_path } do
- = render 'shared/zen', f: f, attr: :description,
- classes: 'note-textarea',
- qa_selector: 'milestone_description_field',
- supports_autocomplete: true,
- placeholder: _('Write milestone description...')
+ .form-group
+ = f.label :description, _("Description")
+ = render layout: 'shared/md_preview', locals: { url: group_preview_markdown_path } do
+ = render 'shared/zen', f: f, attr: :description,
+ classes: 'note-textarea',
+ qa_selector: 'milestone_description_field',
+ supports_autocomplete: true,
+ placeholder: _('Write milestone description...')
.clearfix
.error-alert
- .form-actions
- - if @milestone.new_record?
- = f.submit _('Create milestone'), data: { qa_selector: "create_milestone_button" }, pajamas_button: true
- = render Pajamas::ButtonComponent.new(href: group_milestones_path(@group)) do
- = _("Cancel")
- - else
- = f.submit _('Update milestone'), pajamas_button: true
- = render Pajamas::ButtonComponent.new(href: group_milestone_path(@group, @milestone)) do
- = _("Cancel")
+ = f.hidden_field :lock_version
+
+ - if @milestone.new_record?
+ = f.submit _('Create milestone'), data: { qa_selector: "create_milestone_button" }, class: 'gl-mr-2', pajamas_button: true
+ = render Pajamas::ButtonComponent.new(href: group_milestones_path(@group)) do
+ = _("Cancel")
+ - else
+ = f.submit _('Save changes'), class: 'gl-mr-2', pajamas_button: true
+ = render Pajamas::ButtonComponent.new(href: group_milestone_path(@group, @milestone)) do
+ = _("Cancel")
diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml
index 8bceb1ddd5c..e1837bdd6fa 100644
--- a/app/views/groups/milestones/new.html.haml
+++ b/app/views/groups/milestones/new.html.haml
@@ -5,6 +5,5 @@
%h1.page-title.gl-font-size-h-display
= _("New Milestone")
-%hr
-
-= render "form"
+.gl-mt-3
+ = render "form"
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index b75fda2f344..88cb8d989fa 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -1,13 +1,14 @@
-- @hide_breadcrumbs = true
+- @hide_top_bar = true
- @hide_top_links = true
- page_title _('New Group')
- header_title _("Groups"), dashboard_groups_path
- add_page_specific_style 'page_bundles/new_namespace'
-.group-edit-container.gl-mt-5
+.group-edit-container
- .js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s }.merge(subgroup_creation_data(@group),
- verification_for_group_creation_data) }
+ .js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s,
+ root_path: root_path,
+ groups_url: dashboard_groups_url }.merge(subgroup_creation_data(@group)) }
.row{ 'v-cloak': true }
#create-group-pane.tab-pane
@@ -15,11 +16,6 @@
= render 'new_group_fields', f: f, group_name_id: 'create-group-name'
#import-group-pane.tab-pane
- - if import_sources_enabled?
- = render 'import_group_from_another_instance_panel'
- .gl-mt-7.gl-border-b-solid.gl-border-gray-100.gl-border-1
- = render 'import_group_from_file_panel'
- - else
- .nothing-here-block
- %h4= s_('GroupsNew|No import options available')
- %p= s_('GroupsNew|Contact an administrator to enable options for importing your group.')
+ = render 'import_group_from_another_instance_panel'
+ .gl-mt-7.gl-border-b-solid.gl-border-gray-100.gl-border-1
+ = render 'import_group_from_file_panel'
diff --git a/app/views/groups/packages/index.html.haml b/app/views/groups/packages/index.html.haml
index 1c0627779ec..b6cf26c3677 100644
--- a/app/views/groups/packages/index.html.haml
+++ b/app/views/groups/packages/index.html.haml
@@ -1,5 +1,4 @@
- page_title _("Package Registry")
-- @content_class = "limit-container-width" unless fluid_layout
.row
.col-12
@@ -10,4 +9,5 @@
empty_list_illustration: image_path('illustrations/no-packages.svg'),
npm_instance_url: package_registry_instance_url(:npm),
project_list_url: '',
+ settings_path: show_group_package_registry_settings(@group) ? group_settings_packages_and_registries_path(@group) : '',
group_list_url: group_packages_path(@group) } }
diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml
index aaa42aaea3a..ed078230349 100644
--- a/app/views/groups/projects.html.haml
+++ b/app/views/groups/projects.html.haml
@@ -1,16 +1,16 @@
- breadcrumb_title _("Projects")
- page_title _("Projects")
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mt-3 js-search-settings-section' }, header_options: { class: 'gl-display-flex' }, body_options: { class: 'gl-py-0' }) do |c|
- - c.header do
+ - c.with_header do
.gl-flex-grow-1
= html_escape(_("%{strong_open}%{group_name}%{strong_close} projects:")) % { strong_open: '<strong>'.html_safe, group_name: @group.name, strong_close: '</strong>'.html_safe }
- if can? current_user, :admin_group, @group
.controls
= render Pajamas::ButtonComponent.new(href: new_project_path(namespace_id: @group.id), size: :small, variant: :confirm) do
= _("New project")
- - c.body do
+ - c.with_body do
%ul.content-list
- @projects.each_with_index do |project, idx|
%li.project-row.gl-align-items-center{ class: 'gl-display-flex!', data: { qa_selector: 'project_row_container', qa_index: idx } }
diff --git a/app/views/groups/registry/repositories/index.html.haml b/app/views/groups/registry/repositories/index.html.haml
index efd2e53e100..c906beb631b 100644
--- a/app/views/groups/registry/repositories/index.html.haml
+++ b/app/views/groups/registry/repositories/index.html.haml
@@ -1,5 +1,4 @@
- page_title _("Container Registry")
-- @content_class = "limit-container-width" unless fluid_layout
- add_page_startup_graphql_call('container_registry/get_container_repositories', { fullPath: @group.full_path, first: 10, name: nil, isGroupPage: true, sort: nil})
%section
diff --git a/app/views/groups/runners/edit.html.haml b/app/views/groups/runners/edit.html.haml
index 4bd550eaa47..93f2f395df6 100644
--- a/app/views/groups/runners/edit.html.haml
+++ b/app/views/groups/runners/edit.html.haml
@@ -1,4 +1,4 @@
-- runner_name = "##{@runner.id} (#{@runner.short_sha})"
+- runner_name = runner_short_name(@runner)
- breadcrumb_title _('Edit')
- page_title _('Edit'), runner_name
- add_to_breadcrumbs _('Runners'), group_runners_path(@group)
diff --git a/app/views/groups/runners/index.html.haml b/app/views/groups/runners/index.html.haml
index 7e98f6035a6..d619635d3e0 100644
--- a/app/views/groups/runners/index.html.haml
+++ b/app/views/groups/runners/index.html.haml
@@ -1,3 +1,3 @@
- page_title s_('Runners|Runners')
-#js-group-runners{ data: group_runners_data_attributes(@group).merge({ registration_token: @group_runner_registration_token }) }
+#js-group-runners{ data: group_runners_data_attributes(@group).merge({ registration_token: @group_runner_registration_token, new_runner_path: @group_new_runner_path }) }
diff --git a/app/views/groups/runners/new.html.haml b/app/views/groups/runners/new.html.haml
new file mode 100644
index 00000000000..db48e66185c
--- /dev/null
+++ b/app/views/groups/runners/new.html.haml
@@ -0,0 +1,5 @@
+- add_to_breadcrumbs _('Runners'), group_runners_path(@group)
+- breadcrumb_title s_('Runners|New')
+- page_title s_('Runners|Create a group runner')
+
+#js-group-new-runner{ data: { group_id: @group.to_global_id } }
diff --git a/app/views/groups/runners/register.html.haml b/app/views/groups/runners/register.html.haml
new file mode 100644
index 00000000000..15d96bb80b6
--- /dev/null
+++ b/app/views/groups/runners/register.html.haml
@@ -0,0 +1,7 @@
+- runner_name = runner_short_name(@runner)
+- breadcrumb_title s_('Runners|Register')
+- page_title s_('Runners|Register'), runner_name
+- add_to_breadcrumbs _('Runners'), group_runners_path(@group)
+- add_to_breadcrumbs runner_name, register_group_runner_path(@group, @runner)
+
+#js-group-register-runner{ data: { runner_id: @runner.id, runners_path: group_runners_path(@group) } }
diff --git a/app/views/groups/runners/show.html.haml b/app/views/groups/runners/show.html.haml
index 43673d54478..53ca704ecb7 100644
--- a/app/views/groups/runners/show.html.haml
+++ b/app/views/groups/runners/show.html.haml
@@ -1,9 +1,9 @@
- add_page_specific_style 'page_bundles/ci_status'
- add_page_specific_style 'page_bundles/runner_details'
-- title = "##{@runner.id} (#{@runner.short_sha})"
-- breadcrumb_title title
-- page_title title
+- runner_name = runner_short_name(@runner)
+- breadcrumb_title runner_name
+- page_title runner_name
- add_to_breadcrumbs _('Runners'), group_runners_path(@group)
#js-group-runner-show{ data: {runner_id: @runner.id, runners_path: group_runners_path(@group), edit_group_runner_path: edit_group_runner_path(@group, @runner)} }
diff --git a/app/views/groups/settings/_export.html.haml b/app/views/groups/settings/_export.html.haml
index 5d79d0f8e79..1e80c1846a4 100644
--- a/app/views/groups/settings/_export.html.haml
+++ b/app/views/groups/settings/_export.html.haml
@@ -4,16 +4,15 @@
%h4= s_('GroupSettings|Export group')
%p= _('Export this group with all related data.')
= render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_options: { class: 'gl-mb-4' }) do |c|
- = c.body do
- - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md') }
+ - c.with_body do
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index', anchor: 'migrate-groups-by-direct-transfer-recommended') }
- docs_link_end = '</a>'.html_safe
- = s_('GroupsNew|This feature is deprecated and replaced by %{docs_link_start}group migration%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: docs_link_end }
+ = s_('GroupsNew|This feature is deprecated and replaced by group migration by direct transfer. %{docs_link_start}Learn more%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: docs_link_end }
%p
- export_information = _('After the export is complete, download the data file from a notification email or from this page. You can then import the data file from the %{strong_text_start}Create new group%{strong_text_end} page of another GitLab instance.') % { strong_text_start: '<strong>'.html_safe, strong_text_end: '</strong>'.html_safe}
= export_information.html_safe
- = link_to _('Learn more.'), help_page_path('user/group/settings/import_export.md'), target: '_blank', rel: 'noopener noreferrer'
= render Pajamas::AlertComponent.new(dismissible: false, alert_options: { class: 'gl-mb-5' }) do |c|
- = c.body do
+ - c.with_body do
%p.gl-mb-0
%p= _('The following items will be exported:')
%ul
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index 658109fde64..8c73fc95544 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -19,12 +19,16 @@
= f.label :description, s_('Groups|Group description (optional)'), class: 'label-bold'
= f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
+ .row.gl-mt-3
+ .form-group.col-md-5
+ = f.label :description, s_('Groups|Group README'), class: 'label-bold'
+ #js-group-settings-readme{ data: group_settings_readme_app_data(@group) }
+
= render 'shared/repository_size_limit_setting_registration_features_cta', form: f
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
.form-group.gl-mt-3.gl-mb-6
- .avatar-container.rect-avatar.s90
- = group_icon(@group, alt: '', class: 'avatar group-avatar s90')
+ = render Pajamas::AvatarComponent.new(@group, size: 96, alt: '', class: 'gl-float-left gl-mr-5')
= f.label :avatar, s_('Groups|Group avatar'), class: 'label-bold d-block'
= render 'shared/choose_avatar_button', f: f
- if @group.avatar?
diff --git a/app/views/groups/settings/_git_access_protocols.html.haml b/app/views/groups/settings/_git_access_protocols.html.haml
index 01e8536c7ad..db177da1d84 100644
--- a/app/views/groups/settings/_git_access_protocols.html.haml
+++ b/app/views/groups/settings/_git_access_protocols.html.haml
@@ -1,4 +1,4 @@
-- if group.root? && Feature.enabled?(:group_level_git_protocol_control, group)
+- if group.root?
.form-group
= f.label _('Enabled Git access protocols'), class: 'label-bold'
= f.select :enabled_git_access_protocol, options_for_select(enabled_git_access_protocol_options_for_group, group.enabled_git_access_protocol), {}, class: 'form-control', data: { qa_selector: 'enabled_git_access_protocol_dropdown' }, disabled: !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index a18789b52a3..6fa76297679 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -30,13 +30,16 @@
help_text: s_('GroupSettings|Group members are not notified if the group is mentioned.')
= render 'groups/settings/resource_access_token_creation', f: f, group: @group
- = render_if_exists 'groups/settings/delayed_project_removal', f: f, group: @group
+ - unless Feature.enabled?(:always_perform_delayed_deletion)
+ = render_if_exists 'groups/settings/delayed_project_removal', f: f, group: @group
= render 'groups/settings/ip_restriction_registration_features_cta', f: f
= render_if_exists 'groups/settings/ip_restriction', f: f, group: @group
= render_if_exists 'groups/settings/allowed_email_domain', f: f, group: @group
- if @group.licensed_feature_available?(:group_wikis)
= render_if_exists 'groups/settings/wiki', f: f, group: @group
= render 'groups/settings/lfs', f: f
+ = render_if_exists 'groups/settings/code_suggestions', f: f, group: @group
+ = render_if_exists 'groups/settings/ai_related_settings', f: f, group: @group
= render 'groups/settings/git_access_protocols', f: f, group: @group
= render 'groups/settings/project_creation_level', f: f, group: @group
= render 'groups/settings/subgroup_creation_level', f: f, group: @group
diff --git a/app/views/groups/settings/_remove_button.html.haml b/app/views/groups/settings/_remove_button.html.haml
index cb05076b39d..acf11fd8858 100644
--- a/app/views/groups/settings/_remove_button.html.haml
+++ b/app/views/groups/settings/_remove_button.html.haml
@@ -2,7 +2,7 @@
- if group.prevent_delete?
= render Pajamas::AlertComponent.new(dismissible: false, alert_options: { class: 'gl-mb-5', data: { testid: 'group-has-linked-subscription-alert' }}) do |c|
- = c.body do
+ - c.with_body do
= html_escape(_("This group can't be removed because it is linked to a subscription. To remove this group, %{linkStart}link the subscription%{linkEnd} with a different group.")) % { linkStart: "<a href=\"#{help_page_path('subscriptions/gitlab_com/index', anchor: 'change-the-linked-namespace')}\">".html_safe, linkEnd: '</a>'.html_safe }
.js-confirm-danger{ data: group_settings_confirm_modal_data(group, remove_form_id) }
diff --git a/app/views/groups/settings/_transfer.html.haml b/app/views/groups/settings/_transfer.html.haml
index a4a83330fa9..9ebe3a740b3 100644
--- a/app/views/groups/settings/_transfer.html.haml
+++ b/app/views/groups/settings/_transfer.html.haml
@@ -10,11 +10,11 @@
- learn_more_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: learn_more_link }
- warning_text = s_("GroupSettings|Be careful. Changing a group's parent can have unintended side effects. %{learn_more_link_start}Learn more.%{learn_more_link_end}") % { learn_more_link_start: learn_more_link_start, learn_more_link_end: '</a>'.html_safe }
%li= warning_text.html_safe
- %li= s_('GroupSettings|You can only transfer the group to a group you manage.')
+ %li= s_('GroupSettings|You must have the Owner role in the target group')
%li= s_('GroupSettings|You will need to update your local repositories to point to the new location.')
%li= s_("GroupSettings|If the parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.")
- if group.paid?
= render Pajamas::AlertComponent.new(dismissible: false, alert_options: { class: 'gl-mb-5' }) do |c|
- = c.body do
+ - c.with_body do
= html_escape(_("This group can't be transferred because it is linked to a subscription. To transfer this group, %{linkStart}link the subscription%{linkEnd} with a different group.")) % { linkStart: "<a href=\"#{help_page_path('subscriptions/gitlab_com/index', anchor: 'change-the-linked-namespace')}\">".html_safe, linkEnd: '</a>'.html_safe }
.js-transfer-group-form{ data: initial_data }
diff --git a/app/views/groups/settings/access_tokens/index.html.haml b/app/views/groups/settings/access_tokens/index.html.haml
index 309633471a5..96a492e599e 100644
--- a/app/views/groups/settings/access_tokens/index.html.haml
+++ b/app/views/groups/settings/access_tokens/index.html.haml
@@ -2,7 +2,7 @@
- page_title _('Group Access Tokens')
- type = _('group access token')
- type_plural = _('group access tokens')
-- @content_class = 'limit-container-width' unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4
@@ -13,15 +13,15 @@
- if current_user.can?(:create_resource_access_tokens, @group)
= _('Generate group access tokens scoped to this group for your applications that need access to the GitLab API.')
%p
- = _('You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = html_escape(_('You can also use group access tokens with Git to authenticate over HTTP(S). %{link_start}Learn more.%{link_end}')) % { link_start: link_start, link_end: '</a>'.html_safe }
- else
- = _('Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = html_escape(_('Group access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}')) % { link_start: link_start, link_end: '</a>'.html_safe }
%p
- root_group = @group.root_ancestor
- if current_user.can?(:admin_group, root_group)
- group_settings_link = edit_group_path(root_group)
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: group_settings_link }
- = _('You can enable group access token creation in %{link_start}group settings%{link_end}.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+ = html_escape(_('You can enable group access token creation in %{link_start}group settings%{link_end}.')) % { link_start: link_start, link_end: '</a>'.html_safe }
.col-lg-8
#js-new-access-token-app{ data: { access_token_type: type } }
diff --git a/app/views/groups/settings/applications/edit.html.haml b/app/views/groups/settings/applications/edit.html.haml
index ee71fd5d886..0dec3906bf2 100644
--- a/app/views/groups/settings/applications/edit.html.haml
+++ b/app/views/groups/settings/applications/edit.html.haml
@@ -1,5 +1,4 @@
- page_title _("Edit"), @application.name, _("Group applications")
-- @content_class = "limit-container-width" unless fluid_layout
%h1.page-title.gl-font-size-h-display= _('Edit group application')
= render 'shared/doorkeeper/applications/form', url: group_settings_application_path(@group, @application)
diff --git a/app/views/groups/settings/applications/index.html.haml b/app/views/groups/settings/applications/index.html.haml
index 95bf2151bda..da3257ca27d 100644
--- a/app/views/groups/settings/applications/index.html.haml
+++ b/app/views/groups/settings/applications/index.html.haml
@@ -1,5 +1,6 @@
- page_title _("Group applications")
- add_page_specific_style 'page_bundles/settings'
+- @force_desktop_expanded_sidebar = true
= render 'shared/doorkeeper/applications/index',
oauth_applications_enabled: user_oauth_applications?,
diff --git a/app/views/groups/settings/applications/show.html.haml b/app/views/groups/settings/applications/show.html.haml
index 4a83d96aae4..06c678b1187 100644
--- a/app/views/groups/settings/applications/show.html.haml
+++ b/app/views/groups/settings/applications/show.html.haml
@@ -1,7 +1,6 @@
- add_to_breadcrumbs _("Group applications"), group_settings_applications_path(@group)
- breadcrumb_title @application.name
- page_title @application.name, _("Group applications")
-- @content_class = "limit-container-width" unless fluid_layout
%h1.page-title.gl-font-size-h-display
= _("Group application: %{name}") % { name: @application.name }
@@ -9,4 +8,5 @@
= render 'shared/doorkeeper/applications/show',
edit_path: edit_group_settings_application_path(@group, @application),
delete_path: group_settings_application_path(@group, @application),
- index_path: group_settings_applications_path
+ index_path: group_settings_applications_path,
+ renew_path: renew_group_settings_application_path(@group, @application)
diff --git a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
index 06cb9893196..b0a5d0bd4fa 100644
--- a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
+++ b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
@@ -2,8 +2,8 @@
= form_errors(group)
%fieldset
.form-group
- .card.gl-mb-3
- .card-body
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-3' }) do |c|
+ - c.with_body do
- learn_more_link = link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer'
- help_text = s_('GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found.')
- badge = gl_badge_tag badge_for_auto_devops_scope(group), variant: :info
@@ -13,4 +13,5 @@
help_text: '%{help_text} %{learn_more_link}'.html_safe % { help_text: help_text, learn_more_link: learn_more_link },
checkbox_options: { checked: group.auto_devops_enabled? }
- = f.submit _('Save changes'), class: 'gl-mt-5', pajamas_button: true
+ = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, button_options: { class: 'gl-mt-5' }) do
+ = _('Save changes')
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index 67b87f842f9..7b6e50ffd36 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -1,5 +1,6 @@
- breadcrumb_title _("CI/CD Settings")
- page_title _("CI/CD")
+- @force_desktop_expanded_sidebar = true
- expanded = expanded_by_default?
- general_expanded = @group.errors.empty? ? expanded : true
@@ -47,7 +48,7 @@
- quickstart_url = help_page_path('topics/autodevops/cloud_deployments/auto_devops_with_gke')
- auto_devops_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auto_devops_url }
- quickstart_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: quickstart_url }
- = s_('AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}').html_safe % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe, quickstart_start: quickstart_start, quickstart_end: '</a>'.html_safe }
+ = html_escape(s_('AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}')) % { auto_devops_start: auto_devops_start, auto_devops_end: '</a>'.html_safe, quickstart_start: quickstart_start, quickstart_end: '</a>'.html_safe }
.settings-content
= render 'groups/settings/ci_cd/auto_devops_form', group: @group
diff --git a/app/views/groups/settings/integrations/index.html.haml b/app/views/groups/settings/integrations/index.html.haml
index ec99ceb5f8d..3c1a38d9997 100644
--- a/app/views/groups/settings/integrations/index.html.haml
+++ b/app/views/groups/settings/integrations/index.html.haml
@@ -1,6 +1,6 @@
- breadcrumb_title s_('Integrations|Group-level integration management')
- page_title s_('Integrations|Group-level integration management')
-- @content_class = 'limit-container-width' unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.js-search-settings-section
%h3= s_('Integrations|Group-level integration management')
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 faed486b20f..d5e02f141b3 100644
--- a/app/views/groups/settings/packages_and_registries/show.html.haml
+++ b/app/views/groups/settings/packages_and_registries/show.html.haml
@@ -1,6 +1,6 @@
- breadcrumb_title _('Packages and registries settings')
- page_title _('Packages and registries settings')
-- @content_class = 'limit-container-width' unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section#js-packages-and-registries-settings{ data: { group_path: @group.full_path,
group_dependency_proxy_path: group_dependency_proxy_path(@group) } }
diff --git a/app/views/groups/settings/repository/show.html.haml b/app/views/groups/settings/repository/show.html.haml
index c6bf2d66683..fc81d22391a 100644
--- a/app/views/groups/settings/repository/show.html.haml
+++ b/app/views/groups/settings/repository/show.html.haml
@@ -1,6 +1,6 @@
- breadcrumb_title _('Repository Settings')
- page_title _('Repository')
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
- if can?(current_user, :admin_group, @group)
- deploy_token_description = s_('DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group.')
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 72b7bec1b92..e42f524467d 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,5 +1,4 @@
-- @content_class = "limit-container-width" unless fluid_layout
-- page_itemtype 'https://schema.org/Organization'
+- page_itemtype 'https://schema.org/Organization'
- @skip_current_level_breadcrumb = true
- add_page_specific_style 'page_bundles/group'
@@ -8,13 +7,12 @@
- if show_invite_banner?(@group)
= content_for :group_invite_members_banner do
.container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{@content_class}" }
- .js-group-invite-members-banner{ data: { svg_path: image_path('illustrations/merge_requests.svg'),
+ .js-group-invite-members-banner{ data: { svg_path: image_path('illustrations/empty-state/empty-merge-requests-md.svg'),
track_label: 'invite_members_banner',
invite_members_path: group_group_members_path(@group),
callouts_path: group_callouts_path,
callouts_feature_id: Users::GroupCalloutsHelper::INVITE_MEMBERS_BANNER,
group_id: @group.id } }
- = render 'groups/invite_members_modal', group: @group
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
@@ -30,3 +28,5 @@
= render_if_exists 'groups/group_activity_analytics', group: @group
#js-group-overview-tabs{ data: group_overview_tabs_app_data(@group) }
+
+= render partial: 'groups/group_readme', locals: { group: @group }
diff --git a/app/views/help/instance_configuration/_ci_cd_limits.html.haml b/app/views/help/instance_configuration/_ci_cd_limits.html.haml
index bd5b8a6f10d..8496d354ee1 100644
--- a/app/views/help/instance_configuration/_ci_cd_limits.html.haml
+++ b/app/views/help/instance_configuration/_ci_cd_limits.html.haml
@@ -19,34 +19,30 @@
%th= title.to_s.humanize
%tbody
%tr
- %td= s_('AdminSettings|Maximum number of jobs in a single pipeline')
+ %td= plan_limit_setting_description(:ci_pipeline_size)
- ci_cd_limits.each_value do |limits|
%td= instance_configuration_disabled_cell_html(limits[:ci_pipeline_size])
%tr
- %td= s_('AdminSettings|Total number of jobs in currently active pipelines')
+ %td= plan_limit_setting_description(:ci_active_jobs)
- ci_cd_limits.each_value do |limits|
%td= instance_configuration_disabled_cell_html(limits[:ci_active_jobs])
%tr
- %td= s_('AdminSettings|Maximum number of active pipelines per project')
- - ci_cd_limits.each_value do |limits|
- %td= instance_configuration_disabled_cell_html(limits[:ci_active_pipelines])
- %tr
- %td= s_('AdminSettings|Maximum number of pipeline subscriptions to and from a project')
+ %td= plan_limit_setting_description(:ci_project_subscriptions)
- ci_cd_limits.each_value do |limits|
%td= instance_configuration_disabled_cell_html(limits[:ci_project_subscriptions])
%tr
- %td= s_('AdminSettings|Maximum number of pipeline schedules')
+ %td= plan_limit_setting_description(:ci_pipeline_schedules)
- ci_cd_limits.each_value do |limits|
%td= instance_configuration_disabled_cell_html(limits[:ci_pipeline_schedules])
%tr
- %td= s_('AdminSettings|Maximum number of DAG dependencies that a job can have')
+ %td= plan_limit_setting_description(:ci_needs_size_limit)
- ci_cd_limits.each_value do |limits|
%td= instance_configuration_disabled_cell_html(limits[:ci_needs_size_limit])
%tr
- %td= s_('AdminSettings|Maximum number of runners registered per group')
+ %td= plan_limit_setting_description(:ci_registered_group_runners)
- ci_cd_limits.each_value do |limits|
%td= instance_configuration_disabled_cell_html(limits[:ci_registered_group_runners])
%tr
- %td= s_('AdminSettings|Maximum number of runners registered per project')
+ %td= plan_limit_setting_description(:ci_registered_project_runners)
- ci_cd_limits.each_value do |limits|
%td= instance_configuration_disabled_cell_html(limits[:ci_registered_project_runners])
diff --git a/app/views/ide/_show.html.haml b/app/views/ide/_show.html.haml
index 5a6e93c3573..eb6d5668807 100644
--- a/app/views/ide/_show.html.haml
+++ b/app/views/ide/_show.html.haml
@@ -7,4 +7,6 @@
- content_for :prefetch_asset_tags do
- webpack_preload_asset_tag('monaco')
-= render partial: 'shared/ide_root', locals: { data: ide_data(project: @project, branch: @branch, path: @path, merge_request: @merge_request, fork_info: @fork_info), loading_text: _('Loading the GitLab IDE...') }
+- data = ide_data(project: @project, fork_info: @fork_info, params: params)
+
+= render partial: 'shared/ide_root', locals: { data: data, loading_text: _('Loading the GitLab IDE...') }
diff --git a/app/views/import/_githubish_status.html.haml b/app/views/import/_githubish_status.html.haml
index 4d2186a1352..5eae48fd237 100644
--- a/app/views/import/_githubish_status.html.haml
+++ b/app/views/import/_githubish_status.html.haml
@@ -5,8 +5,10 @@
- paginatable = local_assigns.fetch(:paginatable, false)
- default_namespace_path = (local_assigns[:default_namespace] || current_user.namespace).full_path
- cancel_path = local_assigns.fetch(:cancel_path, nil)
+- details_path = local_assigns.fetch(:details_path, nil)
- provider_title = Gitlab::ImportSources.title(local_assigns.fetch(:provider))
- optional_stages = local_assigns.fetch(:optional_stages, [])
+- status_import_github_group_path = local_assigns.fetch(:status_import_github_group_path, '')
- header_title _("New project"), new_project_path
- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
@@ -18,7 +20,9 @@
jobs_path: url_for([:realtime_changes, :import, provider, { format: :json }]),
default_target_namespace: default_namespace_path,
import_path: url_for([:import, provider, { format: :json }]),
+ status_import_github_group_path: status_import_github_group_path,
cancel_path: cancel_path,
+ details_path: details_path,
filterable: filterable.to_s,
paginatable: paginatable.to_s,
optional_stages: optional_stages.to_json }.merge(extra_data) }
diff --git a/app/views/import/github/details.html.haml b/app/views/import/github/details.html.haml
new file mode 100644
index 00000000000..d5d36a9b581
--- /dev/null
+++ b/app/views/import/github/details.html.haml
@@ -0,0 +1,4 @@
+- add_to_breadcrumbs _('Create a new project'), new_project_path
+- page_title s_('Import|GitHub import details')
+
+.js-import-details{ data: { failures_path: failures_import_github_path } }
diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml
index 4a9f8be35c3..b07374e5b5f 100644
--- a/app/views/import/github/status.html.haml
+++ b/app/views/import/github/status.html.haml
@@ -11,4 +11,6 @@
provider: 'github', paginatable: paginatable,
default_namespace: @namespace,
cancel_path: cancel_import_github_path,
+ details_path: details_import_github_path,
+ status_import_github_group_path: status_import_github_group_path(format: :json),
optional_stages: Gitlab::GithubImport::Settings.stages_array
diff --git a/app/views/import/phabricator/new.html.haml b/app/views/import/phabricator/new.html.haml
deleted file mode 100644
index d4fdd107043..00000000000
--- a/app/views/import/phabricator/new.html.haml
+++ /dev/null
@@ -1,26 +0,0 @@
-- page_title _('Phabricator Server Import')
-- header_title _("New project"), new_project_path
-- add_to_breadcrumbs s_('ProjectsNew|Import project'), new_project_path(anchor: 'import_project')
-
-%h1.page-title.gl-font-size-h-display.d-flex
- .gl-display-flex.gl-align-items-center.gl-justify-content-center
- = sprite_icon('issues', css_class: 'gl-mr-2')
- = _('Import tasks from Phabricator into issues')
-
-= render 'import/shared/errors'
-
-= form_tag import_phabricator_path, class: 'new_project', method: :post do
- = render 'import/shared/new_project_form'
-
- %h4.gl-mt-0= _('Enter in your Phabricator Server URL and personal access token below')
-
- .form-group.row
- = label_tag :phabricator_server_url, _('Phabricator Server URL'), class: 'col-form-label col-md-2'
- .col-md-4
- = text_field_tag :phabricator_server_url, params[:phabricator_server_url], class: 'form-control gl-form-input gl-mr-3', placeholder: 'https://your-phabricator-server', size: 40
- .form-group.row
- = label_tag :api_token, _('API Token'), class: 'col-form-label col-md-2'
- .col-md-4
- = password_field_tag :api_token, params[:api_token], class: 'form-control gl-form-input gl-mr-3', placeholder: _('Personal Access Token'), size: 40
- .form-actions
- = submit_tag _('Import tasks'), class: 'gl-button btn btn-confirm'
diff --git a/app/views/jira_connect/branches/new.html.haml b/app/views/jira_connect/branches/new.html.haml
index 482012b2848..bb27e89abb9 100644
--- a/app/views/jira_connect/branches/new.html.haml
+++ b/app/views/jira_connect/branches/new.html.haml
@@ -1,4 +1,3 @@
-- @hide_breadcrumbs = true
- @hide_top_links = true
- @content_class = 'limit-container-width'
- page_title _('Create branch')
diff --git a/app/views/jira_connect/users/show.html.haml b/app/views/jira_connect/users/show.html.haml
deleted file mode 100644
index 5db6cb44ff6..00000000000
--- a/app/views/jira_connect/users/show.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-.gl-text-center.gl-mx-auto.gl-pt-6
- %h3.gl-mb-4
- = _('You are signed in to GitLab as:')
-
- .gl-display-flex.gl-flex-direction-column.gl-align-items-center.gl-mb-4
- = link_to user_path(current_user), target: '_blank', rel: 'noopener noreferrer' do
- = user_avatar_without_link(user: current_user, size: 60, css_class: 'gl-mr-0! gl-mb-2', has_tooltip: false)
- = link_to current_user.to_reference, user_path(current_user), target: '_blank', rel: 'noopener noreferrer'
-
- %p.gl-mb-6
- = s_('JiraService|You can now close this window and%{br}return to the GitLab for Jira application.').html_safe % { br: '<br>'.html_safe }
-
- - if @jira_app_link
- %p
- = render Pajamas::ButtonComponent.new(href: @jira_app_link, variant: :confirm) do
- = s_('Integrations|Return to GitLab for Jira')
-
-
- %p= link_to _('Sign out'), destroy_user_session_path, method: :post
-
-- add_page_specific_style 'page_bundles/jira_connect_users'
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index dd441d0d155..d3a4c5c5ba8 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -1,6 +1,7 @@
- page_description brand_title unless page_description
- site_name = _('GitLab')
-%head{ prefix: "og: http://ogp.me/ns#" }
+- omit_og = sign_in_with_redirect?
+%head{ omit_og ? { } : { prefix: "og: http://ogp.me/ns#" } }
%meta{ charset: "utf-8" }
%title= page_title(site_name)
@@ -10,6 +11,7 @@
%meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge' }
= render 'layouts/startup_js'
+ = yield :startup_js
- if page_canonical_link
%link{ rel: 'canonical', href: page_canonical_link }
@@ -45,6 +47,7 @@
= render 'layouts/startup_css_activation'
= stylesheet_link_tag 'performance_bar' if performance_bar_enabled?
+ = render 'layouts/snowplow'
= Gon::Base.render_data(nonce: content_security_policy_nonce)
@@ -57,26 +60,29 @@
= yield :page_specific_javascripts
+ = webpack_bundle_tag 'super_sidebar' if show_super_sidebar?
+
= webpack_controller_bundle_tags
= yield :project_javascripts
- -# Open Graph - http://ogp.me/
- %meta{ property: 'og:type', content: "object" }
- %meta{ property: 'og:site_name', content: site_name }
- %meta{ property: 'og:title', content: page_title }
- %meta{ property: 'og:description', content: page_description }
- %meta{ property: 'og:image', content: page_image }
- %meta{ property: 'og:image:width', content: '64' }
- %meta{ property: 'og:image:height', content: '64' }
- %meta{ property: 'og:url', content: request.base_url + request.fullpath }
-
- -# Twitter Card - https://dev.twitter.com/cards/types/summary
- %meta{ property: 'twitter:card', content: "summary" }
- %meta{ property: 'twitter:title', content: page_title }
- %meta{ property: 'twitter:description', content: page_description }
- %meta{ property: 'twitter:image', content: page_image }
- = page_card_meta_tags
+ - unless omit_og
+ -# Open Graph - http://ogp.me/
+ %meta{ property: 'og:type', content: "object" }
+ %meta{ property: 'og:site_name', content: site_name }
+ %meta{ property: 'og:title', content: page_title }
+ %meta{ property: 'og:description', content: page_description }
+ %meta{ property: 'og:image', content: page_image }
+ %meta{ property: 'og:image:width', content: '64' }
+ %meta{ property: 'og:image:height', content: '64' }
+ %meta{ property: 'og:url', content: request.base_url + request.fullpath }
+
+ -# Twitter Card - https://dev.twitter.com/cards/types/summary
+ %meta{ property: 'twitter:card', content: "summary" }
+ %meta{ property: 'twitter:title', content: page_title }
+ %meta{ property: 'twitter:description', content: page_description }
+ %meta{ property: 'twitter:image', content: page_image }
+ = page_card_meta_tags
%meta{ name: "description", content: page_description }
@@ -98,6 +104,5 @@
= render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
= render 'layouts/matomo' if extra_config.has_key?('matomo_url') && extra_config.has_key?('matomo_site_id')
- = render 'layouts/snowplow'
-# This is needed by [GitLab JH](https://gitlab.com/gitlab-jh/gitlab/-/issues/184)
= render_if_exists "layouts/frontend_monitor"
diff --git a/app/views/layouts/_loading_hints.html.haml b/app/views/layouts/_loading_hints.html.haml
index 9026bec84c3..b20b95cade8 100644
--- a/app/views/layouts/_loading_hints.html.haml
+++ b/app/views/layouts/_loading_hints.html.haml
@@ -12,7 +12,8 @@
= preload_link_tag(path_to_stylesheet('application'), crossorigin: css_crossorigin)
= preload_link_tag(path_to_stylesheet("highlight/themes/#{user_color_scheme}"), crossorigin: css_crossorigin)
- if Gitlab::Tracking.enabled? && Gitlab::Tracking.collector_hostname
- %link{ rel: 'preconnect', href: "https://#{Gitlab::Tracking.collector_hostname}", crossorigin: '' }
+ - unless Rails.env.development?
+ %link{ rel: 'preconnect', href: "https://#{Gitlab::Tracking.collector_hostname}", crossorigin: '' }
-# Do not use preload_link_tag for fonts, to work around Firefox double-fetch bug.
-# See https://github.com/web-platform-tests/wpt/pull/36930
%link{ rel: 'preload', href: font_path('gitlab-sans/GitLabSans.woff2'), as: 'font', crossorigin: css_crossorigin }
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index d2ed70d6b48..aa80de7f789 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -2,15 +2,21 @@
- @left_sidebar = true
.layout-page.hide-when-top-nav-responsive-open{ class: page_with_sidebar_class }
- if show_super_sidebar?
- - sidebar_data = super_sidebar_context(current_user, group: @group, project: @project).to_json
- %aside.js-super-sidebar.nav-sidebar{ data: { root_path: root_path, sidebar: sidebar_data, toggle_new_nav_endpoint: profile_preferences_url } }
+ -# Render the parent group sidebar while creating a new subgroup/project, see GroupsController#new.
+ - group = @parent_group || @group
+
+ - sidebar_panel = super_sidebar_nav_panel(nav: nav, user: current_user, group: group, project: @project, current_ref: current_ref, ref_type: @ref_type, viewed_user: @user)
+ - sidebar_data = super_sidebar_context(current_user, group: group, project: @project, panel: sidebar_panel, panel_type: nav).to_json
+ %aside.js-super-sidebar.super-sidebar.super-sidebar-loading{ data: { root_path: root_path, sidebar: sidebar_data, toggle_new_nav_endpoint: profile_preferences_url, force_desktop_expanded_sidebar: @force_desktop_expanded_sidebar.to_s } }
- if display_whats_new?
#whats-new-app{ data: { version_digest: whats_new_version_digest } }
+ = render_if_exists "layouts/tanuki_bot_chat"
+
- elsif defined?(nav) && nav
= render "layouts/nav/sidebar/#{nav}"
- .content-wrapper.content-wrapper-margin{ class: "#{@content_wrapper_class}" }
+ .content-wrapper{ class: "#{@content_wrapper_class}" }
.mobile-overlay
= dispensable_render_if_exists 'layouts/header/verification_reminder'
.alert-wrapper.gl-force-block-formatting-context
@@ -30,10 +36,9 @@
= dispensable_render_if_exists "shared/namespace_user_cap_reached_alert"
= dispensable_render_if_exists "shared/new_user_signups_cap_reached_alert"
= yield :page_level_alert
- = yield :free_user_cap_alert
= yield :group_invite_members_banner
- - unless @hide_breadcrumbs
- = render "layouts/nav/breadcrumbs"
+ - unless @hide_top_bar
+ = render "layouts/nav/top_bar"
%div{ class: "#{container_class unless @no_container} #{@content_class}" }
%main.content{ id: "content-body", **page_itemtype }
= render "layouts/flash", extra_flash_class: 'limit-container-width'
@@ -44,4 +49,4 @@
-# This is needed by [GitLab JH](https://gitlab.com/gitlab-jh/jh-team/gitlab-cn/-/issues/81)
= render_if_exists "shared/footer/global_footer"
-= render "layouts/nav/top_nav_responsive", class: 'layout-page content-wrapper-margin'
+= render "layouts/nav/top_nav_responsive", class: 'layout-page' unless show_super_sidebar?
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
deleted file mode 100644
index daf2c582de2..00000000000
--- a/app/views/layouts/_search.html.haml
+++ /dev/null
@@ -1,42 +0,0 @@
-.search.search-form{ data: { track_label: "navbar_search", track_action: "activate_form_input", track_value: "" } }
- = form_tag search_path, method: :get, class: 'form-inline form-control' do |_f|
- .search-input-container
- .search-input-wrap
- .dropdown{ data: { url: search_autocomplete_path } }
- = search_field_tag 'search', nil, placeholder: _('Search GitLab'),
- class: 'search-input dropdown-menu-toggle no-outline js-search-dashboard-options',
- spellcheck: false,
- autocomplete: 'off',
- data: { issues_path: issues_dashboard_path,
- mr_path: merge_requests_dashboard_path,
- qa_selector: 'search_term_field' },
- aria: { label: _('Search GitLab') }
- %button.hidden.js-dropdown-search-toggle{ type: 'button', data: { toggle: 'dropdown' } }
- .dropdown-menu.dropdown-select{ data: { testid: 'dashboard-search-options' } }
- = dropdown_content do
- %ul
- %li.dropdown-menu-empty-item
- %a
- = _('Loading...')
- = dropdown_loading
- = sprite_icon('search', css_class: 'search-icon')
- = sprite_icon('close', css_class: 'clear-icon js-clear-input')
-
- = hidden_field_tag :group_id, search_context.for_group? ? search_context.group.id : '', class: 'js-search-group-options', data: search_context.group_metadata
- = hidden_field_tag :project_id, search_context.for_project? ? search_context.project.id : '', id: 'search_project_id', class: 'js-search-project-options', data: search_context.project_metadata
-
- - if search_context.for_project? || search_context.for_group?
- = hidden_field_tag :scope, search_context.scope
- = hidden_field_tag :search_code, search_context.code_search?
-
- - ref = search_context.ref if can?(current_user, :read_code, search_context.project)
- = hidden_field_tag :snippets, search_context.for_snippets?
- = hidden_field_tag :repository_ref, ref
- = hidden_field_tag :nav_source, 'navbar'
-
- -# workaround for non-JS feature specs, see spec/support/helpers/search_helpers.rb
- - if ENV['RAILS_ENV'] == 'test'
- %noscript= button_tag 'Search'
- .search-autocomplete-opts.hide{ :'data-autocomplete-path' => search_autocomplete_path,
- :'data-autocomplete-project-id' => search_context.project.try(:id),
- :'data-autocomplete-project-ref' => ref }
diff --git a/app/views/layouts/_snowplow.html.haml b/app/views/layouts/_snowplow.html.haml
index 5db7f22e36b..399a826d611 100644
--- a/app/views/layouts/_snowplow.html.haml
+++ b/app/views/layouts/_snowplow.html.haml
@@ -1,21 +1,17 @@
- return unless Gitlab::Tracking.enabled?
- namespace = @group || @project&.namespace || @namespace
-
+= webpack_bundle_tag 'tracker'
= javascript_tag do
:plain
- ;(function(p,l,o,w,i,n,g){if(!p[i]){p.GlobalSnowplowNamespace=p.GlobalSnowplowNamespace||[];
- p.GlobalSnowplowNamespace.push(i);p[i]=function(){(p[i].q=p[i].q||[]).push(arguments)
- };p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1;
- n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,"script","#{escaped_url(asset_url('snowplow/sp.js'))}","snowplow"));
-
window.snowplowOptions = #{Gitlab::Tracking.options(@group).to_json}
gl = window.gl || {};
gl.snowplowStandardContext = #{Gitlab::Tracking::StandardContext.new(
- namespace: namespace,
- project: @project,
- user: current_user,
+ namespace_id: namespace&.id,
+ plan_name: namespace&.actual_plan_name,
+ project_id: @project&.id,
+ user_id: current_user&.id,
new_nav: show_super_sidebar?
).to_context.to_json.to_json}
gl.snowplowPseudonymizedPageUrl = #{masked_page_url(group: namespace, project: @project).to_json};
diff --git a/app/views/layouts/component_preview.html.haml b/app/views/layouts/component_preview.html.haml
index a1b1304f994..8217ac13c52 100644
--- a/app/views/layouts/component_preview.html.haml
+++ b/app/views/layouts/component_preview.html.haml
@@ -1,12 +1,12 @@
%head
- - if params[:lookbook][:display][:theme] == 'light'
+ - if params[:lookbook][:display][:theme] == "light"
= stylesheet_link_tag "application"
= stylesheet_link_tag "application_utilities"
- else
= stylesheet_link_tag "application_dark"
= stylesheet_link_tag "application_utilities_dark"
%body
- .container.gl-mt-6
+ .gl-mt-6{ class: (params[:lookbook][:display][:layout] == "fluid" ? "container-fluid" : "container") }
- if params[:lookbook][:display][:bg_dark]
.bg-dark.rounded.shadow.p-4
= yield
diff --git a/app/views/layouts/dashboard.html.haml b/app/views/layouts/dashboard.html.haml
index 89f238eb6b3..39f4a755340 100644
--- a/app/views/layouts/dashboard.html.haml
+++ b/app/views/layouts/dashboard.html.haml
@@ -1,7 +1,6 @@
-- page_title _("Dashboard")
-- header_title _("Dashboard"), root_path unless header_title
+- header_title _("Your work"), root_path
- @left_sidebar = true
-- nav "your_work"
+- nav (@parent_group ? "group" : "your_work")
= render template: "layouts/application"
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 3532c6638ce..71771dd7cb6 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -1,3 +1,4 @@
+- add_page_specific_style 'page_bundles/login'
!!! 5
%html.devise-layout-html{ class: system_message_class }
= render "layouts/head", { startup_filename: 'signin' }
@@ -6,30 +7,37 @@
= render "layouts/init_client_detection_flags"
- if Feature.enabled?(:restyle_login_page, @project)
.page-wrap.borderless
- .login-page-broadcast
- = render "layouts/broadcast"
.container.navless-container
.content
= render "layouts/flash"
- .mt-3
- .col-sm-12.gl-text-center
- = brand_image
- %h1.mb-3.gl-font-size-h2
- = brand_title
- - if current_appearance&.description?
- = brand_text
- = render_if_exists 'layouts/devise_help_text'
- .mb-3
- .gl-w-half.gl-xs-w-full.gl-ml-auto.gl-mr-auto.bar
- = yield
-
+ - if current_appearance&.description?
+ .row
+ .col-md.order-12.sm-bg-gray-10
+ .col-sm-12
+ %h1.mb-3.gl-font-size-h2
+ = brand_title
+ = brand_text
+ = render_if_exists 'layouts/devise_help_text'
+ .col-md.order-md-12
+ .col-sm-12.bar
+ .gl-text-center
+ = brand_image
+ = yield
+ - else
+ .mt-3
+ .col-sm-12.gl-text-center
+ = brand_image
+ %h1.mb-3.gl-font-size-h2
+ = brand_title
+ = render_if_exists 'layouts/devise_help_text'
+ .mb-3
+ .gl-w-half.gl-xs-w-full.gl-ml-auto.gl-mr-auto.bar
+ = yield
= render 'devise/shared/footer', footer_message: footer_message
- else
.page-wrap
= render "layouts/header/empty"
- .login-page-broadcast
- = render "layouts/broadcast"
.container.navless-container
.content
= render "layouts/flash"
diff --git a/app/views/layouts/devise_empty.html.haml b/app/views/layouts/devise_empty.html.haml
index cadba3f91e9..89aba85984f 100644
--- a/app/views/layouts/devise_empty.html.haml
+++ b/app/views/layouts/devise_empty.html.haml
@@ -1,3 +1,4 @@
+- add_page_specific_style 'page_bundles/login'
!!! 5
%html.devise-layout-html{ lang: "en", class: system_message_class }
= render "layouts/head"
diff --git a/app/views/layouts/explore.html.haml b/app/views/layouts/explore.html.haml
index c495bab4547..02c00a53316 100644
--- a/app/views/layouts/explore.html.haml
+++ b/app/views/layouts/explore.html.haml
@@ -1,11 +1,6 @@
-- page_title _("Explore")
+- header_title _("Explore"), explore_root_path
-- if current_user
- - @left_sidebar = true
- - nav "your_work"
-
-- unless current_user
- - @hide_breadcrumbs = true
- - header_title _("Explore GitLab"), explore_root_path
+- @left_sidebar = true
+- nav "explore"
= render template: "layouts/application"
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index 95934f43a51..1f742279756 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -16,6 +16,11 @@
:plain
window.uploads_path = "#{group_uploads_path(@group)}";
+- content_for :before_content do
+ = render 'groups/invite_members_modal', group: @group
+
+= dispensable_render_if_exists "shared/web_hooks/group_web_hook_disabled_alert"
= dispensable_render_if_exists "shared/free_user_cap_alert", source: @group
+= dispensable_render_if_exists "shared/unlimited_members_during_trial_alert", resource: @group
= render template: base_layout || "layouts/application"
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index af27026845e..1739dee1511 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -16,11 +16,7 @@
= s_('SetStatusModal|Edit status')
- else
= s_('SetStatusModal|Set status')
- - if current_user_menu?(:start_trial)
- %li
- %a.trial-link{ href: trials_link_url }
- = s_("CurrentUser|Start an Ultimate trial")
- = emoji_icon('rocket')
+ = dispensable_render_if_exists 'layouts/header/start_trial'
- if current_user_menu?(:settings)
%li
= link_to s_("CurrentUser|Edit profile"), profile_path, data: { qa_selector: 'edit_profile_link', track_action: "click_link", track_label: "user_edit_profile", track_property: "navigation_top" }
@@ -48,7 +44,7 @@
- if Feature.enabled?(:super_sidebar_nav, current_user)
%li.divider
- .js-new-nav-toggle{ data: { enabled: current_user.use_new_navigation.to_s, endpoint: profile_preferences_url} }
+ .js-new-nav-toggle{ data: { enabled: show_super_sidebar?.to_s, endpoint: profile_preferences_url} }
- if current_user_menu?(:sign_out)
%li.divider
diff --git a/app/views/layouts/header/_current_user_dropdown_item.html.haml b/app/views/layouts/header/_current_user_dropdown_item.html.haml
index 3fded43ee4f..fa0a6364a15 100644
--- a/app/views/layouts/header/_current_user_dropdown_item.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown_item.html.haml
@@ -1,7 +1,7 @@
.gl-font-weight-bold
= current_user.name
- if current_user.status&.busy?
- %span.gl-font-weight-normal.gl-text-gray-500= s_("UserProfile|(Busy)")
+ = render Pajamas::BadgeComponent.new(s_('UserProfile|Busy'), size: 'sm', variant: 'warning')
= current_user.to_reference
- if current_user.status
.user-status.d-flex.align-items-center.gl-mt-2.gl-mr-0.gl-font-sm.has-tooltip{ title: current_user.status.message_html, data: { html: 'true', placement: 'bottom' } }
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 6d000c3e9ad..7156a0e5931 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -8,7 +8,7 @@
.title-container.hide-when-top-nav-responsive-open.gl-transition-medium.gl-display-flex.gl-align-items-stretch.gl-pt-0.gl-mr-3
.title
%span.gl-sr-only GitLab
- = link_to root_path, title: _('Dashboard'), id: 'logo', class: 'has-tooltip', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation_top') do
+ = link_to root_path, title: _('Homepage'), id: 'logo', class: 'has-tooltip', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation_top') do
= brand_header_logo
.gl-display-flex.gl-align-items-center
- if Gitlab.com_and_canary?
@@ -31,10 +31,7 @@
%ul.nav.navbar-nav.gl-w-full.gl-align-items-center
%li.nav-item.header-search-new.gl-display-none.gl-lg-display-block.gl-w-full
- unless current_controller?(:search)
- - if Feature.enabled?(:new_header_search)
- = render 'layouts/header_search'
- - else
- = render 'layouts/search'
+ = render 'layouts/header_search'
%li.nav-item{ class: 'd-none d-sm-inline-block d-lg-none' }
= link_to search_menu_item.fetch(:href), title: search_menu_item.fetch(:title), aria: { label: search_menu_item.fetch(:title) },
data: { toggle: 'tooltip', placement: 'bottom', container: 'body',
@@ -106,7 +103,7 @@
= gl_badge_tag({ size: :sm, variant: :info }, { class: "js-todos-count gl-ml-n2 #{'hidden' if todos_pending_count == 0}", "aria-label": _("Todos count") }) do
= todos_count_format(todos_pending_count)
%li.nav-item.header-help.dropdown.d-none.d-md-block
- = link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown", track_action: 'click_question_mark_link', track_label: 'main_navigation', track_property: 'navigation_top', track_experiment: 'cross_stage_fdm' } do
+ = link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown", track_action: 'click_question_mark_link', track_label: 'main_navigation', track_property: 'navigation_top' } do
%span.gl-sr-only
= s_('Nav|Help')
= sprite_icon('question-o')
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index f50df72afbc..38b9a9a5383 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -2,7 +2,6 @@
- if current_user_menu?(:help)
%li
= render 'layouts/header/gitlab_version'
- = render_if_exists 'layouts/header/help_dropdown/cross_stage_fdm'
= render 'layouts/header/whats_new_dropdown_item'
%li
= link_to _("Help"), help_path, data: {track_action: 'click_link', track_label: 'help', track_property: 'navigation_top'}
diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml
index 372babea18e..50a2b45aa7e 100644
--- a/app/views/layouts/header/_new_dropdown.html.haml
+++ b/app/views/layouts/header/_new_dropdown.html.haml
@@ -26,8 +26,13 @@
= section.fetch(:title)
- section.fetch(:menu_items).each do |menu_item|
%li<
- = link_to menu_item.fetch(:href), class: menu_item.fetch(:css_class), data: menu_item.fetch(:data) do
- = menu_item.fetch(:title)
- - if menu_item.fetch(:emoji)
- -# We need to insert a space between the title and emoji
- = " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: 'gl-font-base gl-vertical-align-baseline')}".html_safe
+ - if menu_item.fetch(:partial).present?
+ = render partial: menu_item.fetch(:partial),
+ locals: { display_text: menu_item.fetch(:title),
+ icon: menu_item.fetch(:icon),
+ data: menu_item.fetch(:data) }
+ - else
+ = link_to menu_item.fetch(:title),
+ menu_item.fetch(:href),
+ class: menu_item.fetch(:css_class),
+ data: menu_item.fetch(:data)
diff --git a/app/views/layouts/help.html.haml b/app/views/layouts/help.html.haml
index a913bea0c93..68426f71879 100644
--- a/app/views/layouts/help.html.haml
+++ b/app/views/layouts/help.html.haml
@@ -1,5 +1,7 @@
- @breadcrumb_title = _("Help")
- page_title _("Help")
- header_title _("Help"), help_path
+- if show_super_sidebar?
+ - @force_desktop_expanded_sidebar = true
= render template: "layouts/application"
diff --git a/app/views/layouts/minimal.html.haml b/app/views/layouts/minimal.html.haml
index b5cb8f2af37..5531c0ab23a 100644
--- a/app/views/layouts/minimal.html.haml
+++ b/app/views/layouts/minimal.html.haml
@@ -6,12 +6,11 @@
%body{ data: body_data }
= header_message
= render 'peek/bar'
+ = render 'layouts/published_experiments'
= render "layouts/header/empty"
.layout-page
- .content-wrapper.content-wrapper-margin.gl-pt-6{ class: 'gl-md-pt-11!' }
- .alert-wrapper.gl-force-block-formatting-context
- = render "layouts/broadcast"
- .limit-container-width{ class: container_class }
+ .content-wrapper.gl-pt-6{ class: 'gl-md-pt-11!' }
+ %div{ class: container_class }
%main#content-body.content
= render "layouts/flash" unless @hide_flash
= yield
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
deleted file mode 100644
index 98d6af28cf5..00000000000
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ /dev/null
@@ -1,27 +0,0 @@
-- container = @no_breadcrumb_container ? 'container-fluid' : container_class
-- hide_top_links = @hide_top_links || false
-- unless @skip_current_level_breadcrumb
- - push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link)
-
-%nav.breadcrumbs{ class: [container, @content_class], 'aria-label': _('Breadcrumbs') }
- .breadcrumbs-container{ class: ("border-bottom-0" if @no_breadcrumb_border) }
- - if defined?(@left_sidebar)
- = button_tag class: 'toggle-mobile-nav', data: { qa_selector: 'toggle_mobile_nav_button' }, type: 'button' do
- %span.sr-only= _("Open sidebar")
- = sprite_icon('sidebar', size: 18)
- .breadcrumbs-links{ data: { testid: 'breadcrumb-links', qa_selector: 'breadcrumb_links_content' } }
- %ul.list-unstyled.breadcrumbs-list.js-breadcrumbs-list
- - unless hide_top_links
- = header_title
- - if @breadcrumbs_extra_links
- - @breadcrumbs_extra_links.each do |extra|
- = breadcrumb_list_item link_to(extra[:text], extra[:link])
- = render "layouts/nav/breadcrumbs/collapsed_inline_list", location: :after
- - unless @skip_current_level_breadcrumb
- %li{ data: { testid: 'breadcrumb-current-link', qa_selector: 'breadcrumb_current_link' } }
- = link_to @breadcrumb_title, breadcrumb_title_link
- -# haml-lint:disable InlineJavaScript
- %script{ type: 'application/ld+json' }
- :plain
- #{schema_breadcrumb_json}
- = yield :header_content
diff --git a/app/views/layouts/nav/_top_bar.html.haml b/app/views/layouts/nav/_top_bar.html.haml
new file mode 100644
index 00000000000..a0e03c9c0cf
--- /dev/null
+++ b/app/views/layouts/nav/_top_bar.html.haml
@@ -0,0 +1,14 @@
+- if show_super_sidebar?
+ - top_bar_class = 'top-bar-fixed container-fluid'
+ - top_bar_container_class = nil
+- else
+ - top_bar_class = [@no_top_bar_container ? 'container-fluid' : container_class, @content_class]
+ - top_bar_container_class = 'gl-border-b'
+
+%div{ class: top_bar_class }
+ .top-bar-container.gl-display-flex.gl-align-items-center{ :class => top_bar_container_class }
+ - if show_super_sidebar?
+ = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'js-super-sidebar-toggle-expand super-sidebar-toggle gl-ml-n3 gl-mr-2', title: _('Expand sidebar'), aria: { controls: 'super-sidebar', expanded: 'false', label: _('Navigation sidebar') } })
+ - elsif defined?(@left_sidebar)
+ = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'toggle-mobile-nav gl-ml-n3 gl-mr-2', data: { qa_selector: 'toggle_mobile_nav_button' }, aria: { label: _('Open sidebar') } })
+ = render "layouts/nav/breadcrumbs/breadcrumbs"
diff --git a/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml b/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml
new file mode 100644
index 00000000000..b5f067cf42f
--- /dev/null
+++ b/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml
@@ -0,0 +1,20 @@
+- hide_top_links = @hide_top_links || false
+- unless @skip_current_level_breadcrumb
+ - push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link)
+
+%nav.breadcrumbs{ 'aria-label': _('Breadcrumbs'), data: { testid: 'breadcrumb-links', qa_selector: 'breadcrumb_links_content' } }
+ %ul.list-unstyled.breadcrumbs-list.js-breadcrumbs-list
+ - unless hide_top_links
+ = header_title
+ - if @breadcrumbs_extra_links
+ - @breadcrumbs_extra_links.each do |extra|
+ = breadcrumb_list_item link_to(extra[:text], extra[:link])
+ = render "layouts/nav/breadcrumbs/collapsed_inline_list", location: :after
+ - unless @skip_current_level_breadcrumb
+ %li{ data: { testid: 'breadcrumb-current-link', qa_selector: 'breadcrumb_current_link' } }
+ = link_to @breadcrumb_title, breadcrumb_title_link
+ -# haml-lint:disable InlineJavaScript
+ %script{ type: 'application/ld+json' }
+ :plain
+ #{schema_breadcrumb_json}
+= yield :header_content
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 24b301fadce..bffc030dbd9 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -1,298 +1 @@
-%aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), 'aria-label': _('Admin navigation'), data: { qa_selector: 'admin_sidebar_content' } }
- .nav-sidebar-inner-scroll
- .context-header
- = 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_overview_submenu_content' } }
- = nav_link(controller: %w[dashboard admin admin/projects users groups admin/topics gitaly_servers cohorts], html_options: {class: 'home'}) do
- = link_to admin_root_path, class: 'has-sub-items' do
- .nav-icon-container
- = sprite_icon('overview')
- %span.nav-item-name
- = _('Overview')
- %ul.sidebar-sub-level-items
- = nav_link(controller: %w[dashboard admin admin/projects users groups gitaly_servers cohorts], html_options: { class: "fly-out-top-item" }) do
- = link_to admin_root_path do
- %strong.fly-out-top-item-name
- = _('Overview')
- %li.divider.fly-out-top-item
- = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
- = link_to admin_root_path, title: _('Overview') do
- %span
- = _('Dashboard')
- = nav_link(controller: [:admin, 'admin/projects']) do
- = link_to admin_projects_path, title: _('Projects') do
- %span
- = _('Projects')
- = nav_link(controller: %w[users cohorts]) do
- = link_to admin_users_path, title: _('Users'), data: { qa_selector: 'admin_overview_users_link' } do
- %span
- = _('Users')
- = nav_link(controller: :groups) do
- = link_to admin_groups_path, title: _('Groups'), data: { qa_selector: 'admin_overview_groups_link' } do
- %span
- = _('Groups')
- = nav_link(controller: [:admin, 'admin/topics']) do
- = link_to admin_topics_path, title: _('Topics') do
- %span
- = _('Topics')
- = nav_link(controller: :gitaly_servers) do
- = link_to admin_gitaly_servers_path, title: 'Gitaly Servers' do
- %span
- = _('Gitaly Servers')
-
- = nav_link(controller: %w[runners jobs]) do
- = link_to admin_runners_path, class: 'has-sub-items' do
- .nav-icon-container
- = sprite_icon('rocket')
- %span.nav-item-name
- = _('CI/CD')
- %ul.sidebar-sub-level-items
- = nav_link(controller: %w[runners jobs], html_options: { class: "fly-out-top-item" }) do
- = link_to admin_runners_path do
- %strong.fly-out-top-item-name
- = _('CI/CD')
- %li.divider.fly-out-top-item
- = nav_link(controller: :runners) do
- = link_to admin_runners_path, title: _('Runners') do
- %span
- = _('Runners')
- = nav_link(controller: :jobs) do
- = link_to admin_jobs_path, title: _('Jobs') do
- %span
- = _('Jobs')
-
- = nav_link(controller: admin_analytics_nav_links) do
- = link_to admin_dev_ops_reports_path, data: { qa_selector: 'admin_analytics_link' }, class: 'has-sub-items' do
- .nav-icon-container
- = sprite_icon('chart')
- %span.nav-item-name
- = _('Analytics')
-
- %ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_analytics_submenu_content' } }
- = nav_link(controller: admin_analytics_nav_links, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_dev_ops_reports_path do
- %strong.fly-out-top-item-name
- = _('Analytics')
- %li.divider.fly-out-top-item
- = nav_link(controller: :dev_ops_report) do
- = link_to admin_dev_ops_reports_path, title: _('DevOps Reports') do
- %span
- = _('DevOps Reports')
- = nav_link(controller: :usage_trends) do
- = link_to admin_usage_trends_path, title: _('Usage Trends') do
- %span
- = _('Usage Trends')
-
- = nav_link(controller: admin_monitoring_nav_links) do
- = link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_menu_link' }, class: 'has-sub-items' do
- .nav-icon-container
- = sprite_icon('monitor')
- %span.nav-item-name
- = _('Monitoring')
-
- %ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_monitoring_submenu_content' } }
- = nav_link(controller: admin_monitoring_nav_links, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_system_info_path do
- %strong.fly-out-top-item-name
- = _('Monitoring')
- %li.divider.fly-out-top-item
- = nav_link(controller: :system_info) do
- = link_to admin_system_info_path, title: _('System Info') do
- %span
- = _('System Info')
- = nav_link(controller: :background_migrations) do
- = link_to admin_background_migrations_path, title: _('Background Migrations') do
- %span
- = _('Background Migrations')
- = nav_link(controller: :background_jobs) do
- = link_to admin_background_jobs_path, title: _('Background Jobs') do
- %span
- = _('Background Jobs')
- = nav_link(controller: :health_check) do
- = link_to admin_health_check_path, title: _('Health Check') do
- %span
- = _('Health Check')
- - if Gitlab::CurrentSettings.current_application_settings.grafana_enabled?
- = nav_link do
- = link_to Gitlab::CurrentSettings.current_application_settings.grafana_url, target: '_blank', title: _('Metrics Dashboard'), rel: 'noopener noreferrer' do
- %span
- = _('Metrics Dashboard')
- = render_if_exists 'layouts/nav/ee/admin/new_monitoring_sidebar'
-
- = nav_link(controller: :broadcast_messages) do
- = link_to admin_broadcast_messages_path do
- .nav-icon-container
- = sprite_icon('messages')
- %span.nav-item-name
- = _('Messages')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :broadcast_messages, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_broadcast_messages_path do
- %strong.fly-out-top-item-name
- = _('Messages')
-
- = nav_link(controller: [:hooks, :hook_logs]) do
- = link_to admin_hooks_path do
- .nav-icon-container
- = sprite_icon('hook')
- %span.nav-item-name
- = _('System Hooks')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: [:hooks, :hook_logs], html_options: { class: "fly-out-top-item" }) do
- = link_to admin_hooks_path do
- %strong.fly-out-top-item-name
- = _('System Hooks')
-
- = nav_link(controller: :applications) do
- = link_to admin_applications_path do
- .nav-icon-container
- = sprite_icon('applications')
- %span.nav-item-name
- = _('Applications')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :applications, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_applications_path do
- %strong.fly-out-top-item-name
- = _('Applications')
-
- = nav_link(controller: :abuse_reports) do
- = link_to admin_abuse_reports_path do
- .nav-icon-container
- = sprite_icon('slight-frown')
- %span.nav-item-name
- = _('Abuse Reports')
- = gl_badge_tag number_with_delimiter(AbuseReport.count(:all)), variant: :info, size: :sm
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :abuse_reports, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_abuse_reports_path do
- %strong.fly-out-top-item-name
- = _('Abuse Reports')
- = gl_badge_tag number_with_delimiter(AbuseReport.count(:all)), variant: :info, size: :sm
-
- = render_if_exists 'layouts/nav/sidebar/licenses_link'
-
- - if instance_clusters_enabled?
- = nav_link(controller: :clusters) do
- = link_to admin_clusters_path do
- .nav-icon-container
- = sprite_icon('cloud-gear')
- %span.nav-item-name
- = _('Kubernetes')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :clusters, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_clusters_path do
- %strong.fly-out-top-item-name
- = _('Kubernetes')
-
- - if anti_spam_service_enabled?
- = nav_link(controller: :spam_logs) do
- = link_to admin_spam_logs_path do
- .nav-icon-container
- = sprite_icon('spam')
- %span.nav-item-name
- = _('Spam Logs')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :spam_logs, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_spam_logs_path do
- %strong.fly-out-top-item-name
- = _('Spam Logs')
-
- = render_if_exists 'layouts/nav/sidebar/push_rules_link'
-
- = render_if_exists 'layouts/nav/ee/admin/geo_sidebar'
-
- = nav_link(controller: :deploy_keys) do
- = link_to admin_deploy_keys_path do
- .nav-icon-container
- = sprite_icon('key')
- %span.nav-item-name
- = _('Deploy Keys')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :deploy_keys, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_deploy_keys_path do
- %strong.fly-out-top-item-name
- = _('Deploy Keys')
-
- = render_if_exists 'layouts/nav/sidebar/credentials_link'
-
- = nav_link(controller: :labels) do
- = link_to admin_labels_path do
- .nav-icon-container
- = sprite_icon('labels')
- %span.nav-item-name
- = _('Labels')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :labels, html_options: { class: "fly-out-top-item" }) do
- = link_to admin_labels_path do
- %strong.fly-out-top-item-name
- = _('Labels')
-
- = nav_link(controller: [:application_settings, :integrations, :appearances]) do
- = link_to general_admin_application_settings_path, class: 'has-sub-items' do
- .nav-icon-container
- = sprite_icon('settings')
- %span.nav-item-name{ data: { qa_selector: 'admin_settings_menu_link' } }
- = _('Settings')
-
- %ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_settings_submenu_content' } }
- -# This active_nav_link check is also used in `app/views/layouts/admin.html.haml`
- = nav_link(controller: [:application_settings, :integrations, :appearances], html_options: { class: "fly-out-top-item" }) do
- = link_to general_admin_application_settings_path do
- %strong.fly-out-top-item-name
- = _('Settings')
- %li.divider.fly-out-top-item
- = nav_link(path: 'application_settings#general') do
- = link_to general_admin_application_settings_path, title: _('General'), data: { qa_selector: 'admin_settings_general_link' } do
- %span
- = _('General')
-
- = render_if_exists 'layouts/nav/sidebar/advanced_search', data: { qa_selector: 'admin_settings_advanced_search_link' }
-
- - if instance_level_integrations?
- = nav_link(path: ['application_settings#integrations', 'integrations#edit']) do
- = link_to integrations_admin_application_settings_path, title: _('Integrations'), data: { qa_selector: 'admin_settings_integrations_link' } do
- %span
- = _('Integrations')
- = nav_link(path: 'application_settings#repository') do
- = link_to repository_admin_application_settings_path, title: _('Repository'), data: { qa_selector: 'admin_settings_repository_link' } do
- %span
- = _('Repository')
- - if Gitlab.ee? && License.feature_available?(:custom_file_templates)
- = nav_link(path: 'application_settings#templates') do
- = link_to templates_admin_application_settings_path, title: _('Templates'), data: { qa_selector: 'admin_settings_templates_link' } do
- %span
- = _('Templates')
- = nav_link(path: 'application_settings#ci_cd') do
- = link_to ci_cd_admin_application_settings_path, title: _('CI/CD') do
- %span
- = _('CI/CD')
- = nav_link(path: 'application_settings#reporting') do
- = link_to reporting_admin_application_settings_path, title: _('Reporting') do
- %span
- = _('Reporting')
- = nav_link(path: 'application_settings#metrics_and_profiling') do
- = link_to metrics_and_profiling_admin_application_settings_path, title: _('Metrics and profiling'), data: { qa_selector: 'admin_settings_metrics_and_profiling_link' } do
- %span
- = _('Metrics and profiling')
- = nav_link(path: ['application_settings#service_usage_data']) do
- = link_to service_usage_data_admin_application_settings_path, title: _('Service usage data') do
- %span
- = _('Service usage data')
- = nav_link(path: 'application_settings#network') do
- = link_to network_admin_application_settings_path, title: _('Network'), data: { qa_selector: 'admin_settings_network_link' } do
- %span
- = _('Network')
- = nav_link(controller: :appearances) do
- = link_to admin_application_settings_appearances_path do
- %span
- = _('Appearance')
- = nav_link(path: 'application_settings#preferences') do
- = link_to preferences_admin_application_settings_path, title: _('Preferences'), data: { qa_selector: 'admin_settings_preferences_link' } do
- %span
- = _('Preferences')
-
- = render 'shared/sidebar_toggle_button'
+= render partial: 'shared/nav/sidebar', object: Sidebars::Admin::Panel.new(Sidebars::Context.new(current_user: current_user, container: nil))
diff --git a/app/views/layouts/nav/sidebar/_explore.html.haml b/app/views/layouts/nav/sidebar/_explore.html.haml
new file mode 100644
index 00000000000..ccbcb434af1
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_explore.html.haml
@@ -0,0 +1 @@
+= render partial: 'shared/nav/sidebar', object: Sidebars::Explore::Panel.new(Sidebars::Context.new(current_user: current_user, container: nil))
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index c2b50bc0e52..fd0e47b543f 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -1 +1,2 @@
-= render partial: 'shared/nav/sidebar', object: Sidebars::Groups::Panel.new(group_sidebar_context(@group, current_user))
+- group = @parent_group || @group
+= render partial: 'shared/nav/sidebar', object: Sidebars::Groups::Panel.new(group_sidebar_context(group, current_user))
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 087eca3ba35..d53316442f8 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -1,169 +1 @@
-%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'), class: 'has-tooltip', data: { container: 'body', placement: 'right' } do
- = render Pajamas::AvatarComponent.new(current_user, size: 32, alt: current_user.name, class: 'gl-mr-3 js-sidebar-user-avatar', avatar_options: { data: { testid: 'sidebar-user-avatar' } })
- %span.sidebar-context-title= _('User Settings')
- %ul.sidebar-top-level-items
- = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
- = link_to profile_path do
- .nav-icon-container
- = sprite_icon('profile')
- %span.nav-item-name
- = _('Profile')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(path: 'profiles#show', html_options: { class: "fly-out-top-item" }) do
- = link_to profile_path do
- %strong.fly-out-top-item-name
- = _('Profile')
- = nav_link(controller: [:accounts, :two_factor_auths]) do
- = link_to profile_account_path, data: { qa_selector: 'profile_account_link' } do
- .nav-icon-container
- = sprite_icon('account')
- %span.nav-item-name
- = _('Account')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: [:accounts, :two_factor_auths], html_options: { class: "fly-out-top-item" }) do
- = link_to profile_account_path do
- %strong.fly-out-top-item-name
- = _('Account')
-
- = render_if_exists 'layouts/nav/sidebar/profile_billing_link'
- = nav_link(controller: 'oauth/applications') do
- = link_to applications_profile_path do
- .nav-icon-container
- = sprite_icon('applications')
- %span.nav-item-name
- = _('Applications')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: 'oauth/applications', html_options: { class: "fly-out-top-item" }) do
- = link_to applications_profile_path do
- %strong.fly-out-top-item-name
- = _('Applications')
- = nav_link(controller: :chat_names) do
- = link_to profile_chat_names_path do
- .nav-icon-container
- = sprite_icon('comment')
- %span.nav-item-name
- = _('Chat')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :chat_names, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_chat_names_path do
- %strong.fly-out-top-item-name
- = _('Chat')
- - unless Gitlab::CurrentSettings.personal_access_tokens_disabled?
- = nav_link(controller: :personal_access_tokens) do
- = link_to profile_personal_access_tokens_path do
- .nav-icon-container
- = sprite_icon('token')
- %span.nav-item-name
- = _('Access Tokens')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :personal_access_tokens, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_personal_access_tokens_path do
- %strong.fly-out-top-item-name
- = _('Access Tokens')
- = nav_link(controller: :emails) do
- = link_to profile_emails_path, data: { qa_selector: 'profile_emails_link' } do
- .nav-icon-container
- = sprite_icon('mail')
- %span.nav-item-name
- = _('Emails')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :emails, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_emails_path do
- %strong.fly-out-top-item-name
- = _('Emails')
- - if current_user.allow_password_authentication?
- = nav_link(controller: :passwords) do
- = link_to edit_profile_password_path , data: { qa_selector: 'profile_password_link' } do
- .nav-icon-container
- = sprite_icon('lock')
- %span.nav-item-name
- = _('Password')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :passwords, html_options: { class: "fly-out-top-item" }) do
- = link_to edit_profile_password_path do
- %strong.fly-out-top-item-name
- = _('Password')
- = nav_link(controller: :notifications) do
- = link_to profile_notifications_path do
- .nav-icon-container
- = sprite_icon('notifications')
- %span.nav-item-name
- = _('Notifications')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :notifications, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_notifications_path do
- %strong.fly-out-top-item-name
- = _('Notifications')
- = nav_link(controller: :keys) do
- = link_to profile_keys_path do
- .nav-icon-container
- = sprite_icon('key')
- %span.nav-item-name
- = _('SSH Keys')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :keys, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_keys_path do
- %strong.fly-out-top-item-name
- = _('SSH Keys')
- = nav_link(controller: :gpg_keys) do
- = link_to profile_gpg_keys_path do
- .nav-icon-container
- = sprite_icon('key')
- %span.nav-item-name
- = _('GPG Keys')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :gpg_keys, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_gpg_keys_path do
- %strong.fly-out-top-item-name
- = _('GPG Keys')
- = nav_link(controller: :preferences) do
- = link_to profile_preferences_path do
- .nav-icon-container
- = sprite_icon('preferences')
- %span.nav-item-name
- = _('Preferences')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :preferences, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_preferences_path do
- %strong.fly-out-top-item-name
- = _('Preferences')
- - if saved_replies_enabled?
- = nav_link(controller: :saved_replies) do
- = link_to profile_saved_replies_path do
- .nav-icon-container
- = sprite_icon('symlink')
- %span.nav-item-name
- = _('Saved Replies')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :saved_replies, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_saved_replies_path do
- %strong.fly-out-top-item-name
- = _('Saved Replies')
- = nav_link(controller: :active_sessions) do
- = link_to profile_active_sessions_path do
- .nav-icon-container
- = sprite_icon('monitor-lines')
- %span.nav-item-name
- = _('Active Sessions')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :active_sessions, html_options: { class: "fly-out-top-item" }) do
- = link_to profile_active_sessions_path do
- %strong.fly-out-top-item-name
- = _('Active Sessions')
- = nav_link(path: 'profiles#audit_log') do
- = link_to audit_log_profile_path do
- .nav-icon-container
- = sprite_icon('log')
- %span.nav-item-name
- = _('Authentication log')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(path: 'profiles#audit_log', html_options: { class: "fly-out-top-item" }) do
- = link_to audit_log_profile_path do
- %strong.fly-out-top-item-name
- = _('Authentication Log')
- = render_if_exists 'layouts/nav/sidebar/profile_usage_quotas_link'
-
- = render 'shared/sidebar_toggle_button'
+= render partial: 'shared/nav/sidebar', object: Sidebars::UserSettings::Panel.new(Sidebars::Context.new(current_user: current_user, container: current_user))
diff --git a/app/views/layouts/nav/sidebar/_search.html.haml b/app/views/layouts/nav/sidebar/_search.html.haml
new file mode 100644
index 00000000000..956079c351a
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_search.html.haml
@@ -0,0 +1 @@
+-# if this file is missing empty or not the old left menu throws error
diff --git a/app/views/layouts/nav/sidebar/_user_profile.html.haml b/app/views/layouts/nav/sidebar/_user_profile.html.haml
new file mode 100644
index 00000000000..b24334f48c4
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_user_profile.html.haml
@@ -0,0 +1 @@
+= render partial: 'shared/nav/sidebar', object: Sidebars::UserProfile::Panel.new(Sidebars::Context.new(current_user: current_user, container: @user))
diff --git a/app/views/layouts/nav/sidebar/_your_work.html.haml b/app/views/layouts/nav/sidebar/_your_work.html.haml
index 0eba5045ab1..0da66c2e14e 100644
--- a/app/views/layouts/nav/sidebar/_your_work.html.haml
+++ b/app/views/layouts/nav/sidebar/_your_work.html.haml
@@ -1 +1 @@
-= render partial: 'shared/nav/sidebar', object: Sidebars::YourWork::Panel.new(Sidebars::Context.new(current_user: current_user, container: nil))
+= render partial: 'shared/nav/sidebar', object: Sidebars::YourWork::Panel.new(your_work_sidebar_context(current_user))
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index 6ad6696b313..31d02324e68 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -18,7 +18,11 @@
:plain
window.uploads_path = "#{project_uploads_path(project)}";
+- content_for :before_content do
+ = render 'projects/invite_members_modal', project: @project
+
= dispensable_render_if_exists "shared/web_hooks/web_hook_disabled_alert"
= dispensable_render_if_exists "projects/free_user_cap_alert", project: @project
+= dispensable_render_if_exists 'shared/unlimited_members_during_trial_alert', resource: @project
= render template: "layouts/application"
diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml
index 44c4b14e90d..885fda10744 100644
--- a/app/views/layouts/search.html.haml
+++ b/app/views/layouts/search.html.haml
@@ -1,5 +1,7 @@
- page_title _("Search")
- header_title _("Search"), search_path
- add_page_specific_style 'page_bundles/search'
+- if show_super_sidebar?
+ - @force_desktop_expanded_sidebar = true
= render template: "layouts/application"
diff --git a/app/views/layouts/signup_onboarding.html.haml b/app/views/layouts/signup_onboarding.html.haml
index 4d0bb36d4b5..8cbea686d51 100644
--- a/app/views/layouts/signup_onboarding.html.haml
+++ b/app/views/layouts/signup_onboarding.html.haml
@@ -1,6 +1,7 @@
!!! 5
%html.devise-layout-html.navless{ class: system_message_class }
- add_page_specific_style 'page_bundles/signup'
+ - add_page_specific_style 'page_bundles/login'
= render "layouts/head"
%body.signup-page{ class: "#{user_application_theme} #{client_class_list}", data: { page: body_data_page, qa_selector: 'signup_page' } }
= render "layouts/header/logo_with_title"
diff --git a/app/views/layouts/simple_registration.html.haml b/app/views/layouts/simple_registration.html.haml
index dc7ec25c96e..a68941b031f 100644
--- a/app/views/layouts/simple_registration.html.haml
+++ b/app/views/layouts/simple_registration.html.haml
@@ -1,6 +1,7 @@
!!! 5
%html{ lang: "en" }
= render "layouts/head"
+ - add_page_specific_style 'page_bundles/login'
%body.login-page.application.navless{ class: user_application_theme, data: { page: body_data_page } }
= render "layouts/header/logo_with_title"
= render "layouts/broadcast"
diff --git a/app/views/layouts/snippets.html.haml b/app/views/layouts/snippets.html.haml
index 95a204a3319..ad566f262cf 100644
--- a/app/views/layouts/snippets.html.haml
+++ b/app/views/layouts/snippets.html.haml
@@ -1,9 +1,10 @@
- page_title _("Snippets")
-- header_title _("Snippets"), snippets_path
+- header_title _("Your work"), root_path
+- add_to_breadcrumbs _("Snippets"), dashboard_snippets_path
- snippets_upload_path = snippets_upload_path(@snippet, current_user)
+- @left_sidebar = true
- if current_user
- - @left_sidebar = true
- nav "your_work"
- content_for :page_specific_javascripts do
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index 032be73f70c..71c622d7a62 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -1,6 +1,6 @@
!!! 5
- add_page_specific_style 'page_bundles/terms'
-- @hide_breadcrumbs = true
+- @hide_top_bar = true
- body_classes = [user_application_theme]
%html{ lang: I18n.locale, class: page_class }
= render "layouts/head"
diff --git a/app/views/notify/_issuable_csv_export.html.haml b/app/views/notify/_issuable_csv_export.html.haml
index 3b1fe90eaee..f7c6168ecb6 100644
--- a/app/views/notify/_issuable_csv_export.html.haml
+++ b/app/views/notify/_issuable_csv_export.html.haml
@@ -1,6 +1,8 @@
+- type = type.to_s.humanize.downcase
+
%p{ style: 'font-size:18px; text-align:center; line-height:30px;' }
- project_link = link_to(@project.full_name, project_url(@project), style: "color:#3777b0; text-decoration:none; display:block;")
- = _('Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment.').html_safe % { count: pluralize(@written_count, type.to_s.titleize.downcase), project_link: project_link }
+ = _('Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment.').html_safe % { count: pluralize(@written_count, type.titleize.downcase), project_link: project_link }
- if @truncated
%p
- = _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{count} %{issuables} have been included. Consider re-exporting with a narrower selection of %{issuables}.') % { written_count: @written_count, count: @count, issuables: type.to_s.pluralize, size_limit: @size_limit }
+ = _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{count} %{issuables} have been included. Consider re-exporting with a narrower selection of %{issuables}.') % { written_count: @written_count, count: @count, issuables: type.pluralize, size_limit: @size_limit }
diff --git a/app/views/notify/_issuable_csv_export.text.erb b/app/views/notify/_issuable_csv_export.text.erb
new file mode 100644
index 00000000000..a6e908803f5
--- /dev/null
+++ b/app/views/notify/_issuable_csv_export.text.erb
@@ -0,0 +1,7 @@
+<% type = type.to_s.humanize.downcase %>
+
+<%= _('Your CSV export of %{exported_objects} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { exported_objects: pluralize(@written_count, type), project_name: @project.full_name, project_url: project_url(@project) } %>
+
+<% if @truncated %>
+ <%= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{total_count} %{object_type} have been included. Consider re-exporting with a narrower selection of %{object_type}.') % { written_count: @written_count, total_count: @count, size_limit: @size_limit, object_type: type.pluralize } %>
+<% end %>
diff --git a/app/views/notify/_note_email.text.erb b/app/views/notify/_note_email.text.erb
index 8853519fb8d..b23ba464c06 100644
--- a/app/views/notify/_note_email.text.erb
+++ b/app/views/notify/_note_email.text.erb
@@ -6,7 +6,7 @@
<%= sanitize_name(author.name) -%>
<% if discussion.nil? -%>
- <%= 'commented' -%>:
+ <%= 'commented' -%>
<% else -%>
<% if discussion.first_note == note -%>
<%= 'started a new discussion' -%>
@@ -16,9 +16,9 @@
<% if discussion.diff_discussion? -%>
<%= "on #{discussion.file_path}" -%>
<% end -%>
-<%= ':' -%>
-<%= " #{target_url}" -%>
<% end -%>
+<%= ':' -%>
+<%= " #{target_url}" -%>
<% if discussion&.diff_discussion? && discussion.on_text? -%>
diff --git a/app/views/notify/access_token_created_email.html.haml b/app/views/notify/access_token_created_email.html.haml
index 9eea8f44142..8216994f8fa 100644
--- a/app/views/notify/access_token_created_email.html.haml
+++ b/app/views/notify/access_token_created_email.html.haml
@@ -1,7 +1,7 @@
%p
= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
%p
- = html_escape(_('A new personal access token, named %{token_name}, has been created.')) % { token_name: @token_name }
+ = html_escape(_('A new personal access token, named %{code_start}%{token_name}%{code_end}, has been created.')) % { code_start: '<code>'.html_safe, token_name: @token_name, code_end: '</code>'.html_safe }
%p
- pat_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: @target_url }
= html_escape(_('You can check it in your %{pat_link_start}personal access tokens%{pat_link_end} settings.')) % { pat_link_start: pat_link_start, pat_link_end: '</a>'.html_safe }
diff --git a/app/views/notify/export_work_items_csv_email.html.haml b/app/views/notify/export_work_items_csv_email.html.haml
new file mode 100644
index 00000000000..db842262049
--- /dev/null
+++ b/app/views/notify/export_work_items_csv_email.html.haml
@@ -0,0 +1 @@
+= render 'issuable_csv_export', type: :work_item
diff --git a/app/views/notify/export_work_items_csv_email.text.erb b/app/views/notify/export_work_items_csv_email.text.erb
new file mode 100644
index 00000000000..ec4aaa38886
--- /dev/null
+++ b/app/views/notify/export_work_items_csv_email.text.erb
@@ -0,0 +1 @@
+<%= render 'issuable_csv_export', type: :work_item %>
diff --git a/app/views/notify/import_work_items_csv_email.html.haml b/app/views/notify/import_work_items_csv_email.html.haml
new file mode 100644
index 00000000000..d4326d6bdf9
--- /dev/null
+++ b/app/views/notify/import_work_items_csv_email.html.haml
@@ -0,0 +1,49 @@
+- info_style = 'font-size:16px; text-align:center; line-height:24px;'
+- error_style = 'font-size:13px; text-align:center; line-height:16px; color:#dd2b0e;'
+
+%p{ style: info_style }
+ - project_link = link_to(@project.full_name, project_url(@project), style: "color:#3777b0; text-decoration:none;")
+ = s_('Notify|Here are the results for your CSV import for %{project_link}.').html_safe % { project_link: project_link }
+
+- success_lines = @results[:success]
+%p{ style: info_style }
+ - if success_lines > 0
+ - work_items = n_('%d work item', '%d work items', success_lines) % success_lines
+ = s_('Notify|%{work_items} successfully imported.') % { work_items: work_items }
+ - else
+ = s_('Notify|No work items have been imported.')
+
+ - if @results[:parse_error]
+ %p{ style: info_style }
+ = s_('Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values.')
+
+- type_errors = @results[:type_errors]
+- if type_errors
+ %p{ style: info_style }
+ = s_('Notify|Some values in the "type" column could not be matched with supported work item types:')
+
+ - blank_lines = type_errors[:blank]
+ - missing_lines = type_errors[:missing]
+ - disallowed_lines = type_errors[:disallowed]
+
+ - if blank_lines.present?
+ %p{ style: error_style }
+ = s_('Notify|%{singular_or_plural_line} %{error_lines}: Work item type is empty.') % { singular_or_plural_line: n_('Line', 'Lines', blank_lines.size), error_lines: blank_lines.join(', ') }
+
+ - if missing_lines.present?
+ %p{ style: error_style }
+ = s_('Notify|%{singular_or_plural_line} %{error_lines}: Work item type cannot be found or is not supported.') % { singular_or_plural_line: n_('Line', 'Lines', missing_lines.size), error_lines: missing_lines.join(', ') }
+
+ - if disallowed_lines.present?
+ %p{ style: error_style }
+ = s_('Notify|%{singular_or_plural_line} %{error_lines}: Work item type is not available. Please check your license and permissions.') % { singular_or_plural_line: n_('Line', 'Lines', disallowed_lines.size), error_lines: disallowed_lines.join(', ') }
+
+- error_lines = @results[:error_lines]
+- if error_lines.present?
+ %p{ style: error_style }
+ = s_('Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check that these lines have the following fields: %{required_headers}.') % { singular_or_plural_line: n_('line', 'lines', error_lines.size), required_headers: WorkItems::ImportCsvService.required_headers.join(', '),
+ error_lines: error_lines.join(', ') }
+
+- if error_lines.present? || type_errors
+ %p{ style: info_style }
+ = s_('Notify|Please fix the lines with errors and try the CSV import again.')
diff --git a/app/views/notify/import_work_items_csv_email.text.erb b/app/views/notify/import_work_items_csv_email.text.erb
new file mode 100644
index 00000000000..059dbc95cbc
--- /dev/null
+++ b/app/views/notify/import_work_items_csv_email.text.erb
@@ -0,0 +1,48 @@
+<%= s_('Notify|Here are the results for your CSV import for %{project_name} (%{project_link}).') % { project_name: @project.full_name, project_link: project_url(@project) } %>
+
+<% success_lines = @results[:success] %>
+<% if success_lines > 0 %>
+ <% work_items = n_('%d work item', '%d work items', success_lines) % success_lines %>
+ <%= s_('Notify|%{work_items} successfully imported.') % { work_items: work_items } %>
+<% else %>
+ <%= s_('Notify|No work items have been imported.') %>
+
+ <% if @results[:parse_error] %>
+ <%= s_('Notify|Error parsing CSV file. Please make sure it has the correct format: a delimited text file that uses a comma to separate values.') %>
+ <% end %>
+<% end %>
+
+<% type_errors = @results[:type_errors] %>
+<%
+ if type_errors
+ blank_lines = type_errors[:blank]
+ missing_lines = type_errors[:missing]
+ disallowed_lines = type_errors[:disallowed]
+%>
+ <%= s_('Notify|Some values in the "type" column could not be matched with supported work item types:') %>
+
+ <% if blank_lines.present? %>
+ <%= s_('Notify|%{singular_or_plural_line} %{error_lines}: Work item type is empty.') % { singular_or_plural_line: n_('Line', 'Lines', blank_lines.size), error_lines: blank_lines.join(', ') } %>
+ <% end %>
+
+ <% if missing_lines.present? %>
+ <%= s_('Notify|%{singular_or_plural_line} %{error_lines}: Work item type cannot be found or is not supported.') % { singular_or_plural_line: n_('Line', 'Lines', missing_lines.size), error_lines: missing_lines.join(', ') } %>
+ <% end %>
+
+ <% if disallowed_lines.present? %>
+ <%= s_('Notify|%{singular_or_plural_line} %{error_lines}: Work item type is not available. Please check your license and permissions.') % { singular_or_plural_line: n_('Line', 'Lines', disallowed_lines.size), error_lines: disallowed_lines.join(', ') } %>
+ <% end %>
+<% end %>
+
+<%
+ error_lines = @results[:error_lines]
+ if error_lines.present?
+%>
+ <%= s_('Notify|Errors found on %{singular_or_plural_line}: %{error_lines}. Please check that these lines have the following fields: %{required_headers}.') % { singular_or_plural_line: n_('line', 'lines', error_lines.size), required_headers: WorkItems::ImportCsvService.required_headers.join(', '),
+ error_lines: error_lines.join(', ') } %>
+<% end %>
+
+<% if error_lines.present? || type_errors %>
+ <%= s_('Notify|Please fix the lines with errors and try the CSV import again.') %>
+<% end %>
+
diff --git a/app/views/notify/issues_csv_email.text.erb b/app/views/notify/issues_csv_email.text.erb
index cf2910c4014..5b6c151e4ce 100644
--- a/app/views/notify/issues_csv_email.text.erb
+++ b/app/views/notify/issues_csv_email.text.erb
@@ -1,5 +1 @@
-<%= _('Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { written_count: pluralize(@written_count, 'issue'), project_name: @project.full_name, project_url: project_url(@project) } %>
-
-<% if @truncated %>
- <%= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues.') % { written_count: @written_count, issues_count: @issues_count, size_limit: @size_limit } %>
-<% end %>
+<%= render 'issuable_csv_export', type: :issue %>
diff --git a/app/views/notify/merge_request_status_email.text.haml b/app/views/notify/merge_request_status_email.text.haml
index 61c9b130da8..7d10bc77126 100644
--- a/app/views/notify/merge_request_status_email.text.haml
+++ b/app/views/notify/merge_request_status_email.text.haml
@@ -1,4 +1,4 @@
-= sprintf(s_('Notify|Merge request %{merge_request} was %{mr_status}'), { merge_request: @merge_request.to_reference, mr_status: sanitize_name(@updated_by.name) })
+= sprintf(s_('Notify|Merge request %{merge_request} was %{mr_status} by %{updated_by}'), { merge_request: @merge_request.to_reference, mr_status: @mr_status, updated_by: sanitize_name(@updated_by.name) })
= sprintf(s_('Notify|Merge request URL: %{merge_request_url}'), { merge_request_url: project_merge_request_url(@merge_request.target_project, @merge_request) })
diff --git a/app/views/notify/merge_requests_csv_email.text.erb b/app/views/notify/merge_requests_csv_email.text.erb
index 78d11dde69f..c5dec164a4d 100644
--- a/app/views/notify/merge_requests_csv_email.text.erb
+++ b/app/views/notify/merge_requests_csv_email.text.erb
@@ -1,5 +1 @@
-<%= _('Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { written_count: pluralize(@written_count, 'merge request'), project_name: @project.full_name, project_url: project_url(@project) } %>
-
-<% if @truncated %>
- <%= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of %{size_limit}. %{written_count} of %{merge_requests_count} merge requests have been included. Consider re-exporting with a narrower selection of merge requests.') % { written_count: @written_count, merge_requests_count: @merge_requests_count, size_limit: @size_limit} %>
-<% end %>
+<%= render 'issuable_csv_export', type: :merge_request %>
diff --git a/app/views/notify/new_achievement_email.html.haml b/app/views/notify/new_achievement_email.html.haml
new file mode 100644
index 00000000000..f802684fb56
--- /dev/null
+++ b/app/views/notify/new_achievement_email.html.haml
@@ -0,0 +1,7 @@
+- namespace_link = link_to(@achievement.namespace.full_path, group_url(@achievement.namespace))
+- profile_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">' % { url: user_url(@user) }
+
+%p
+ = sprintf(s_("Achievements|%{namespace_link} awarded you the %{bold_start}%{achievement_name}%{bold_end} achievement!"), { namespace_link: namespace_link, achievement_name: @achievement.name, bold_start: '<b>', bold_end: '</b>' }).html_safe
+%p
+ = sprintf(s_("Achievements|View your achievements on your %{link_start}profile%{link_end}."), { link_start: profile_link_start, link_end: '</a>' }).html_safe
diff --git a/app/views/notify/new_achievement_email.text.erb b/app/views/notify/new_achievement_email.text.erb
new file mode 100644
index 00000000000..6d66c1130bf
--- /dev/null
+++ b/app/views/notify/new_achievement_email.text.erb
@@ -0,0 +1,4 @@
+<%= sprintf(s_("Achievements|%{namespace_full_path} awarded you the %{achievement_name} achievement!"),
+ { namespace_full_path: @achievement.namespace.full_path, achievement_name: @achievement.name }) %>
+
+<%= s_("Achievements|View your achievements on your profile.") %>
diff --git a/app/views/notify/new_review_email.text.erb b/app/views/notify/new_review_email.text.erb
index 7bf878aefd0..69cb33b05df 100644
--- a/app/views/notify/new_review_email.text.erb
+++ b/app/views/notify/new_review_email.text.erb
@@ -4,7 +4,6 @@
--
<% @notes.each_with_index do |note, index| %>
- <!-- Get preloaded note discussion-->
<% discussion = @discussions[note.discussion_id] if note.part_of_discussion?%>
<% target_url = project_merge_request_url(@project, @merge_request, anchor: "note_#{note.id}") %>
<%= render 'note_email', note: note, diff_limit: 3, target_url: target_url, discussion: discussion, author: @author %>
diff --git a/app/views/notify/pages_domain_auto_ssl_failed_email.html.haml b/app/views/notify/pages_domain_auto_ssl_failed_email.html.haml
index 1bc2cc15616..c0b334fba94 100644
--- a/app/views/notify/pages_domain_auto_ssl_failed_email.html.haml
+++ b/app/views/notify/pages_domain_auto_ssl_failed_email.html.haml
@@ -8,4 +8,4 @@
- docs_url = help_page_url('user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md', anchor: 'troubleshooting')
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_url }
- link_end = '</a>'.html_safe
- = _("Please follow the %{link_start}Let\'s Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate.").html_safe % { link_start: link_start, link_end: link_end }
+ = _("Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate.").html_safe % { link_start: link_start, link_end: link_end }
diff --git a/app/views/notify/pages_domain_auto_ssl_failed_email.text.haml b/app/views/notify/pages_domain_auto_ssl_failed_email.text.haml
index 6f20d11c966..feb88d2df39 100644
--- a/app/views/notify/pages_domain_auto_ssl_failed_email.text.haml
+++ b/app/views/notify/pages_domain_auto_ssl_failed_email.text.haml
@@ -4,4 +4,4 @@
#{_('Domain')}: #{project_pages_domain_url(@project, @domain)}
- docs_url = help_page_url('user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md', anchor: 'troubleshooting')
-= _("Please follow the Let\'s Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}.").html_safe % { docs_url: docs_url }
+= _("Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}.").html_safe % { docs_url: docs_url }
diff --git a/app/views/notify/reassigned_issue_email.text.erb b/app/views/notify/reassigned_issue_email.text.erb
index dc0d8fc80b0..f37c8ffa515 100644
--- a/app/views/notify/reassigned_issue_email.text.erb
+++ b/app/views/notify/reassigned_issue_email.text.erb
@@ -2,5 +2,5 @@ Reassigned Issue <%= @issue.iid %>
<%= url_for([@issue.project, @issue, { only_path: false }]) %>
-Assignee changed <%= "from #{sanitize_name(@previous_assignees.map(&:name).to_sentence)}" if @previous_assignees.any? -%>
+Assignee changed<%= " from #{sanitize_name(@previous_assignees.map(&:name).to_sentence)}" if @previous_assignees.any? -%>
to <%= "#{@issue.assignees.any? ? @issue.assignee_list : 'Unassigned'}" %>
diff --git a/app/views/notify/service_desk_custom_email_verification_email.text.erb b/app/views/notify/service_desk_custom_email_verification_email.text.erb
new file mode 100644
index 00000000000..c3d49a67263
--- /dev/null
+++ b/app/views/notify/service_desk_custom_email_verification_email.text.erb
@@ -0,0 +1,4 @@
+This email is auto-generated. It verifies the ownership of the entered Service Desk custom email address and
+correct functionality of email forwarding.
+
+Verification token: <%= @verification_token %>
diff --git a/app/views/notify/service_desk_verification_result_email.html.haml b/app/views/notify/service_desk_verification_result_email.html.haml
new file mode 100644
index 00000000000..c072744c43c
--- /dev/null
+++ b/app/views/notify/service_desk_verification_result_email.html.haml
@@ -0,0 +1,58 @@
+- project_link = @service_desk_setting.project.web_url
+- project_link_start = '<a href="%{project_link}" target="_blank" rel="noopener noreferrer" class="highlight">'.html_safe % { project_link: project_link }
+- project_name = @service_desk_setting.project.human_name
+- project_link_end = '</a>'.html_safe
+- settings_link = edit_project_url(@service_desk_setting.project, anchor: 'js-service-desk')
+- settings_link_start = '<a href="%{settings_link}" target="_blank" rel="noopener noreferrer" class="highlight">'.html_safe % { settings_link: settings_link }
+- settings_link_end = '</a>'.html_safe
+- strong_open = '<strong>'.html_safe
+- strong_close = '</strong>'.html_safe
+- email_address = @service_desk_setting.custom_email
+- verify_email_address = @service_desk_setting.custom_email_address_for_verification
+- code_open = '<code>'.html_safe
+- code_end = '</code>'.html_safe
+
+%tr
+ %td.text-content
+ - if @verification.finished?
+ %h1{ :style => "margin-top:0;" }
+ = s_("Notify|Email successfully verified")
+ %p
+ = html_escape(s_('Notify|Your email address %{strong_open}%{email_address}%{strong_close} for the Service Desk of %{project_link_start}%{project_name}%{project_link_end} was verified successfully.')) % { email_address: email_address, project_link_start: project_link_start, project_name: project_name, project_link_end: project_link_end, strong_open: strong_open, strong_close: strong_close }
+ %p
+ = html_escape(s_('Notify|To enable the custom email address, go to your %{settings_link_start}project\'s Service Desk settings page%{settings_link_end}.')) % { settings_link_start: settings_link_start, settings_link_end: settings_link_end }
+ - else
+ %h1{ :style => "margin-top:0;" }
+ = s_("Notify|Email could not be verified")
+ %p
+ = html_escape(s_('Notify|We could not verify your email address %{strong_open}%{email_address}%{strong_close} for the Service Desk of %{project_link_start}%{project_name}%{project_link_end}.')) % { email_address: email_address, project_link_start: project_link_start, project_name: project_name, project_link_end: project_link_end, strong_open: strong_open, strong_close: strong_close }
+ - if @verification.smtp_host_issue?
+ %p
+ %b
+ = s_('Notify|SMTP host issue:')
+ = s_('Notify|We were not able to make a connection to the specified host or there was an SSL issue.')
+ - if @verification.invalid_credentials?
+ %p
+ %b
+ = s_('Notify|Invalid credentials:')
+ = s_('Notify|The given credentials (username and password) were rejected by the SMTP server.')
+ - if @verification.mail_not_received_within_timeframe?
+ %p
+ %b
+ = s_('Notify|Verification email not received within timeframe:')
+ = html_escape(s_('Notify|We did not receive the verification email we sent out to %{strong_open}%{email_address}%{strong_close} in time.')) % { email_address: verify_email_address, strong_open: strong_open, strong_close: strong_close }
+ %p
+ = s_('Notify|We wait for 30 minutes for messages to appear in your instance\'s Service Desk inbox.')
+ = s_('Notify|Please check that your service provider supports email subaddressing and that you have set up email forwarding correctly.')
+ - if @verification.incorrect_from?
+ %p
+ %b
+ = html_escape(s_('Notify|Incorrect %{code_open}From%{code_end} header:')) % { code_open: code_open, code_end: code_end }
+ = html_escape(s_('Notify|Check your forwarding settings and make sure the original email sender remains in the %{code_open}From%{code_end} header.')) % { code_open: code_open, code_end: code_end }
+ - if @verification.incorrect_token?
+ %p
+ %b
+ = s_('Notify|Incorrect verification token:')
+ = s_('Notify|We could not verify that we received the email we sent to your email inbox.')
+ %p
+ = html_escape(s_('Notify|To restart the verification process, go to your %{settings_link_start}project\'s Service Desk settings page%{settings_link_end}.')) % { settings_link_start: settings_link_start, settings_link_end: settings_link_end }
diff --git a/app/views/notify/service_desk_verification_result_email.text.erb b/app/views/notify/service_desk_verification_result_email.text.erb
new file mode 100644
index 00000000000..65b0cba5616
--- /dev/null
+++ b/app/views/notify/service_desk_verification_result_email.text.erb
@@ -0,0 +1,38 @@
+<% project_name = @service_desk_setting.project.human_name %>
+<% email_address = @service_desk_setting.custom_email %>
+<% verify_email_address = @service_desk_setting.custom_email_address_for_verification %>
+
+<% if @verification.finished? %>
+ <%= s_("Notify|Email successfully verified") %>
+
+ <%= s_('Notify|Your email address %{strong_open}%{email_address}%{strong_close} for the Service Desk of %{project_link_start}%{project_name}%{project_link_end} was verified successfully.') % { email_address: email_address, project_link_start: '', project_name: project_name, project_link_end: '', strong_open: '', strong_close: '' } %>
+
+ <%= s_('Notify|To enable the custom email address, go to your %{settings_link_start}project\'s Service Desk settings page%{settings_link_end}.') % { settings_link_start: '', settings_link_end: '' } %>
+<% else %>
+ <%= s_("Notify|Email could not be verified") %>
+
+ <%= s_('Notify|We could not verify your email address %{strong_open}%{email_address}%{strong_close} for the Service Desk of %{project_link_start}%{project_name}%{project_link_end}.') % { email_address: email_address, project_link_start: '', project_name: project_name, project_link_end: '', strong_open: '', strong_close: '' } %>
+
+ <% if @verification.smtp_host_issue? %>
+ <%= s_('Notify|SMTP host issue:') %>
+ <%= s_('Notify|We were not able to make a connection to the specified host or there was an SSL issue.') %>
+ <% elsif @verification.invalid_credentials? %>
+ <%= s_('Notify|Invalid credentials:') %>
+ <%= s_('Notify|The given credentials (username and password) were rejected by the SMTP server.') %>
+ <% elsif @verification.mail_not_received_within_timeframe? %>
+ <%= s_('Notify|Verification email not received within timeframe:') %>
+ <%= s_('Notify|We did not receive the verification email we sent out to %{strong_open}%{email_address}%{strong_close} in time.') % { email_address: verify_email_address, strong_open: '', strong_close: '' } %>
+
+ <%= s_('Notify|We wait for 30 minutes for messages to appear in your instance\'s Service Desk inbox.') %>
+
+ <%= s_('Notify|Please check that your service provider supports email subaddressing and that you have set up email forwarding correctly.') %>
+ <% elsif @verification.incorrect_from? %>
+ <%= s_('Notify|Incorrect %{code_open}From%{code_end} header:') % { code_open: '', code_end: '' } %>
+ <%= s_('Notify|Check your forwarding settings and make sure the original email sender remains in the %{code_open}From%{code_end} header.') % { code_open: '', code_end: '' } %>
+ <% elsif @verification.incorrect_token? %>
+ <%= s_('Notify|Incorrect verification token:') %>
+ <%= s_('Notify|We could not verify that we received the email we sent to your email inbox.') %>
+ <% end %>
+
+ <%= s_('Notify|To restart the verification process, go to your %{settings_link_start}project\'s Service Desk settings page%{settings_link_end}.') % { settings_link_start: '', settings_link_end: '' } %>
+<% end %>
diff --git a/app/views/notify/service_desk_verification_triggered_email.html.haml b/app/views/notify/service_desk_verification_triggered_email.html.haml
new file mode 100644
index 00000000000..f2174af9615
--- /dev/null
+++ b/app/views/notify/service_desk_verification_triggered_email.html.haml
@@ -0,0 +1,18 @@
+- user_name = '@' + @triggerer.username
+- project_link = @service_desk_setting.project.web_url
+- project_link_start = '<a href="%{project_link}" target="_blank" rel="noopener noreferrer" class="highlight">'.html_safe % { project_link: project_link}
+- project_name = @service_desk_setting.project.human_name
+- project_link_end = '</a>'.html_safe
+- strong_open = '<strong>'.html_safe
+- strong_close = '</strong>'.html_safe
+- email_address = @service_desk_setting.custom_email
+- smtp_host = @smtp_address
+
+%tr
+ %td.text-content
+ %p
+ = html_escape(s_('Notify|%{strong_open}%{user_name}%{strong_close} updated the custom email address credentials for the Service Desk of %{project_link_start}%{project_name}%{project_link_end} and triggered the verification process.')) % { user_name: user_name, project_link_start: project_link_start, project_name: project_name, project_link_end: project_link_end, strong_open: strong_open, strong_close: strong_close }
+ %p
+ = html_escape(s_('Notify|The provided custom email address is %{strong_open}%{email_address}%{strong_close} and uses the SMTP host %{strong_open}%{smtp_host}%{strong_close}.')) % { email_address: email_address, smtp_host: smtp_host, strong_open: strong_open, strong_close: strong_close }
+ %p
+ = s_('Notify|If this was a mistake you can change these settings or deactivate the custom email address in the project settings.')
diff --git a/app/views/notify/service_desk_verification_triggered_email.text.erb b/app/views/notify/service_desk_verification_triggered_email.text.erb
new file mode 100644
index 00000000000..98c79e2d2f1
--- /dev/null
+++ b/app/views/notify/service_desk_verification_triggered_email.text.erb
@@ -0,0 +1,10 @@
+<% user_name = '@' + @triggerer.username %>
+<% project_name = @service_desk_setting.project.human_name %>
+<% email_address = @service_desk_setting.custom_email %>
+<% smtp_host = @smtp_address %>
+
+<%= s_('Notify|%{strong_open}%{user_name}%{strong_close} updated the custom email address credentials for the Service Desk of %{project_link_start}%{project_name}%{project_link_end} and triggered the verification process.') % { user_name: user_name, project_link_start: '', project_name: project_name, project_link_end: '', strong_open: '', strong_close: '' } %>
+
+<%= s_('Notify|The provided custom email address is %{strong_open}%{email_address}%{strong_close} and uses the SMTP host %{strong_open}%{smtp_host}%{strong_close}.') % { email_address: email_address, smtp_host: smtp_host, strong_open: '', strong_close: '' } %>
+
+<%= s_('Notify|If this was a mistake you can change these settings or deactivate the custom email address in the project settings.') %>
diff --git a/app/views/notify/two_factor_otp_attempt_failed_email.html.haml b/app/views/notify/two_factor_otp_attempt_failed_email.html.haml
index 83f028af500..968d84f700d 100644
--- a/app/views/notify/two_factor_otp_attempt_failed_email.html.haml
+++ b/app/views/notify/two_factor_otp_attempt_failed_email.html.haml
@@ -9,7 +9,7 @@
%tr
%td{ style: "#{default_font}vertical-align:middle;color:#ffffff;text-align:center;" }
%span
- = _("We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code") % { host: Gitlab.config.gitlab.host }
+ = _("GitLab detected an attempt to sign in to your %{host} account using an incorrect verification code") % { host: Gitlab.config.gitlab.host }
%tr.spacer
%td{ style: spacer_style }
&nbsp;
@@ -43,7 +43,7 @@
%tr{ style: 'width:100%;' }
%td{ style: "#{default_style}text-align:center;" }
- password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_url('user/profile/user_passwords', anchor: 'change-your-password') }
- = _('If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email.')
+ = _('If you recently tried to sign in, but mistakenly entered an incorrect verification code, you can ignore this email.')
- if password_authentication_enabled_for_web?
%p
diff --git a/app/views/notify/two_factor_otp_attempt_failed_email.text.haml b/app/views/notify/two_factor_otp_attempt_failed_email.text.haml
index 8718ab034ff..9760dd3d985 100644
--- a/app/views/notify/two_factor_otp_attempt_failed_email.text.haml
+++ b/app/views/notify/two_factor_otp_attempt_failed_email.text.haml
@@ -1,7 +1,7 @@
= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
-= _('We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}') % { host: Gitlab.config.gitlab.host, ip: @ip, time: @time }
+= _('GitLab detected an attempt to sign in to your %{host} account using an incorrect verification code from the following IP address: %{ip}, at %{time}') % { host: Gitlab.config.gitlab.host, ip: @ip, time: @time }
-= _('If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email.')
+= _('If you recently tried to sign in, but mistakenly entered an incorrect verification code, you can ignore this email.')
= _('If you did not recently try to sign in, you should immediately change your password: %{password_link}.') % { password_link: help_page_url('user/profile/user_passwords', anchor: 'change-your-password') }
= _('Make sure you choose a strong, unique password.')
diff --git a/app/views/notify/unknown_sign_in_email.html.haml b/app/views/notify/unknown_sign_in_email.html.haml
index f8a0ae1352c..e252af78060 100644
--- a/app/views/notify/unknown_sign_in_email.html.haml
+++ b/app/views/notify/unknown_sign_in_email.html.haml
@@ -24,6 +24,11 @@
= Gitlab.config.gitlab.host
%tr
%td{ style: "#{default_style}border-top:1px solid #ededed;" }
+ = _('User')
+ %td{ style: "#{default_style}color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
+ #{sanitize_name(@user.name)} (#{@user.username})
+ %tr
+ %td{ style: "#{default_style}border-top:1px solid #ededed;" }
= _('IP Address')
%td{ style: "#{default_style}color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
%span.muted{ style: "color:#333333;text-decoration:none;" }
diff --git a/app/views/notify/unknown_sign_in_email.text.haml b/app/views/notify/unknown_sign_in_email.text.haml
index f3e318f0d15..fbe35c502da 100644
--- a/app/views/notify/unknown_sign_in_email.text.haml
+++ b/app/views/notify/unknown_sign_in_email.text.haml
@@ -1,4 +1,4 @@
-= _('Hi %{username}!') % { username: sanitize_name(@user.name) }
+= _('Hi %{user_name} (%{user_username})!') % { user_name: sanitize_name(@user.name), user_username: @user.username }
= _('A sign-in to your account has been made from the following IP address: %{ip}') % { ip: @ip }
diff --git a/app/views/peek/_bar.html.haml b/app/views/peek/_bar.html.haml
index 8914bfab336..cc58ad248e8 100644
--- a/app/views/peek/_bar.html.haml
+++ b/app/views/peek/_bar.html.haml
@@ -3,5 +3,6 @@
#js-peek{ data: { env: Peek.env,
request_id: peek_request_id,
stats_url: ENV.fetch('GITLAB_PERFORMANCE_BAR_STATS_URL', ''),
- peek_url: "#{peek_routes_path}/results" },
+ peek_url: "#{peek_routes_path}/results",
+ request_method: request.method, },
class: Peek.env }
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index bc0d615bb64..0505a205333 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -1,5 +1,5 @@
- page_title _('Account')
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
- if current_user.ldap_user?
= render Pajamas::AlertComponent.new(alert_options: { class: 'gl-my-5' },
diff --git a/app/views/profiles/active_sessions/index.html.haml b/app/views/profiles/active_sessions/index.html.haml
index e9e6ca3ecce..54736153223 100644
--- a/app/views/profiles/active_sessions/index.html.haml
+++ b/app/views/profiles/active_sessions/index.html.haml
@@ -1,5 +1,5 @@
- page_title _('Active Sessions')
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
diff --git a/app/views/profiles/audit_log.html.haml b/app/views/profiles/audit_log.html.haml
index 9997c8c4b4c..44cfbc1f74f 100644
--- a/app/views/profiles/audit_log.html.haml
+++ b/app/views/profiles/audit_log.html.haml
@@ -1,5 +1,5 @@
- page_title _('Authentication log')
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
diff --git a/app/views/profiles/chat_names/_chat_name.html.haml b/app/views/profiles/chat_names/_chat_name.html.haml
index ce2fc2098c5..afc3894c23b 100644
--- a/app/views/profiles/chat_names/_chat_name.html.haml
+++ b/app/views/profiles/chat_names/_chat_name.html.haml
@@ -1,21 +1,5 @@
-- integration = chat_name.integration
-- project = integration&.project
%tr
%td
- %strong
- - if project.present? && can?(current_user, :read_project, project)
- = link_to project.full_name, project_path(project)
- - else
- .light= _('Not applicable.')
- %td
- %strong
- - if integration.present? && can?(current_user, :admin_project, project)
- = link_to integration.title, edit_project_settings_integration_path(project, integration)
- - elsif integration.present?
- = integration.title
- - else
- .light= _('Not applicable.')
- %td
= chat_name.team_domain
%td
= chat_name.chat_name
diff --git a/app/views/profiles/chat_names/index.html.haml b/app/views/profiles/chat_names/index.html.haml
index 41bd81d0250..264ee040d7d 100644
--- a/app/views/profiles/chat_names/index.html.haml
+++ b/app/views/profiles/chat_names/index.html.haml
@@ -1,7 +1,8 @@
- page_title _('Chat')
-- @content_class = "limit-container-width" unless fluid_layout
+- @hide_search_settings = true
+- @force_desktop_expanded_sidebar = true
-.row.gl-mt-3.js-search-settings-section
+.row.gl-mt-5.js-search-settings-section
.col-lg-4.profile-settings-sidebar
%h4.gl-mt-0
= page_title
@@ -14,11 +15,9 @@
- if @chat_names.present?
.table-responsive
- %table.table.chat-names
+ %table.table
%thead
%tr
- %th= _('Project')
- %th= _('Service')
%th= _('Team domain')
%th= _('Nickname')
%th= _('Last used')
diff --git a/app/views/profiles/chat_names/new.html.haml b/app/views/profiles/chat_names/new.html.haml
index 303b8b10027..bc30ccc5821 100644
--- a/app/views/profiles/chat_names/new.html.haml
+++ b/app/views/profiles/chat_names/new.html.haml
@@ -1,14 +1,28 @@
-%h1.page-title.gl-font-size-h-display
- = _("Authorization required")
-%main{ :role => "main" }
- %p.h4
- = html_escape(_("Authorize %{user} to use your account?")) % { user: tag.strong(@chat_name_params[:chat_name]) }
+- @hide_search_settings = true
- %hr
- .actions
- = form_tag profile_chat_names_path, method: :post do
- = hidden_field_tag :token, @chat_name_token.token
- = submit_tag _("Authorize"), class: "gl-button btn btn-confirm wide float-left"
- = form_tag deny_profile_chat_names_path, method: :delete do
- = hidden_field_tag :token, @chat_name_token.token
- = submit_tag _("Deny"), class: "gl-button btn btn-danger gl-ml-3"
+%main{ role: 'main' }
+ .gl-max-w-80.gl-mx-auto.gl-mt-6
+ = render Pajamas::CardComponent.new do |c|
+ - c.header do
+ %h4.gl-m-0= sprintf(s_('Integrations|Authorize %{integration_name} (%{user}) to use your account?'), { user: @chat_name_params[:chat_name], integration_name: @integration_name })
+ - c.body do
+ %p
+ = sprintf(s_('Integrations|An application called %{integration_name} is requesting access to your GitLab account. This application was created by GitLab Inc.'), { integration_name: @integration_name })
+ %p
+ = _('This application will be able to:')
+ %ul
+ %li= s_('SlackIntegration|Create and read issue data and comments.')
+ %li= s_('SlackIntegration|Perform deployments.')
+ %li= s_('SlackIntegration|Run ChatOps jobs.')
+ %p.gl-mb-0
+ = s_("SlackIntegration|You don't have to reauthorize this application if the permission scope changes in future releases.")
+ - c.footer do
+ .gl-display-flex
+ = form_tag profile_chat_names_path, method: :post do
+ = hidden_field_tag :token, @chat_name_token.token
+ = render Pajamas::ButtonComponent.new(type: :submit, variant: :danger) do
+ = _('Authorize')
+ = form_tag deny_profile_chat_names_path, method: :delete do
+ = hidden_field_tag :token, @chat_name_token.token
+ = render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-ml-3' }) do
+ = _('Deny')
diff --git a/app/views/profiles/comment_templates/index.html.haml b/app/views/profiles/comment_templates/index.html.haml
new file mode 100644
index 00000000000..dd5b43aa802
--- /dev/null
+++ b/app/views/profiles/comment_templates/index.html.haml
@@ -0,0 +1,10 @@
+- page_title _('Comment Templates')
+
+#js-comment-templates-root.row.gl-mt-5{ data: { base_path: profile_comment_templates_path } }
+ .col-lg-4
+ %h4.gl-mt-0
+ = page_title
+ %p
+ = _('Comment templates can be used when creating comments inside issues, merge requests, and epics.')
+ .col-lg-8
+ = gl_loading_icon(size: 'lg')
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index f4513d15a30..c16f3c3b12b 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -1,5 +1,5 @@
- page_title _('Emails')
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
@@ -56,7 +56,7 @@
%li= s_('Profiles|Public email')
- if email.email == current_user.notification_email_or_default
%li= s_('Profiles|Notification email')
- .gl-display-flex.gl-justify-content-end.gl-align-items-flex-end.gl-flex-grow-1.gl-flex-wrap-wrap-reverse.gl-gap-3
+ .gl-display-flex.gl-justify-content-end.gl-align-items-flex-end.gl-flex-grow-1.gl-flex-wrap-reverse.gl-gap-3
- unless email.confirmed?
- confirm_title = "#{email.confirmation_sent_at ? _('Resend confirmation email') : _('Send confirmation email')}"
= link_to confirm_title, resend_confirmation_instructions_profile_email_path(email), method: :put, class: 'gl-button btn btn-sm btn-default'
diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml
index ec48a611377..d52b16814c0 100644
--- a/app/views/profiles/gpg_keys/_key.html.haml
+++ b/app/views/profiles/gpg_keys/_key.html.haml
@@ -18,7 +18,7 @@
%code= subkey.fingerprint
.float-right
%span.key-created-at
- = s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago: time_ago_with_tooltip(key.created_at) }
+ = html_escape(s_('Profiles|Created %{time_ago}')) % { time_ago: time_ago_with_tooltip(key.created_at) }
= link_to profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: "gl-button btn btn-icon btn-danger gl-ml-3" do
%span.sr-only= _('Remove')
= sprite_icon('remove')
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 539a0cd1f0e..b21a4da16b9 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -1,6 +1,6 @@
- page_title _('GPG Keys')
- add_page_specific_style 'page_bundles/profile'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
diff --git a/app/views/profiles/keys/_key.html.haml b/app/views/profiles/keys/_key.html.haml
index 825fb98782a..288007ec806 100644
--- a/app/views/profiles/keys/_key.html.haml
+++ b/app/views/profiles/keys/_key.html.haml
@@ -35,7 +35,7 @@
= ssh_key_usage_types.invert[key.usage_type]
.gl-display-flex.gl-float-right
- if key.can_delete?
- - if key.signing? && !is_admin && Feature.enabled?(:revoke_ssh_signatures)
+ - if key.signing? && !is_admin
= render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-confirm-modal-button', data: ssh_key_revoke_modal_data(key, revoke_profile_key_path(key)) }) do
= _('Revoke')
.gl-pl-3
diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml
index 69e92b9e508..e7c0cf813b5 100644
--- a/app/views/profiles/keys/index.html.haml
+++ b/app/views/profiles/keys/index.html.haml
@@ -1,6 +1,6 @@
- page_title _('SSH Keys')
- add_page_specific_style 'page_bundles/profile'
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
diff --git a/app/views/profiles/keys/show.html.haml b/app/views/profiles/keys/show.html.haml
index 09c16b0c038..f5fed281e20 100644
--- a/app/views/profiles/keys/show.html.haml
+++ b/app/views/profiles/keys/show.html.haml
@@ -1,5 +1,4 @@
- add_to_breadcrumbs _('SSH Keys'), profile_keys_path
- breadcrumb_title @key.title
- page_title @key.title, _('SSH Keys')
-- @content_class = "limit-container-width" unless fluid_layout
= render "key_details"
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index efc1e23d9b4..a632c450eda 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -1,6 +1,6 @@
- add_page_specific_style 'page_bundles/notifications'
- page_title _('Notifications')
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%div
- if @user.errors.any?
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index 99c89dcebb4..4fdf80c1eb1 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -1,6 +1,6 @@
- breadcrumb_title _('Edit Password')
- page_title _('Password')
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml
index 82df6b1b2c7..57c0badd033 100644
--- a/app/views/profiles/personal_access_tokens/index.html.haml
+++ b/app/views/profiles/personal_access_tokens/index.html.haml
@@ -2,7 +2,7 @@
- page_title s_('AccessTokens|Personal Access Tokens')
- type = _('personal access token')
- type_plural = _('personal access tokens')
-- @content_class = 'limit-container-width' unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index b10d05efc4f..7f8858411ca 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -1,11 +1,11 @@
- page_title _('Preferences')
- add_page_specific_style 'page_bundles/profiles/preferences'
-- @content_class = "limit-container-width" unless fluid_layout
- user_theme_id = Gitlab::Themes.for_user(@user).id
- user_color_schema_id = Gitlab::ColorSchemes.for_user(@user).id
- user_fields = { theme: user_theme_id, gitpod_enabled: @user.gitpod_enabled, sourcegraph_enabled: @user.sourcegraph_enabled }.to_json
- @themes = Gitlab::Themes::available_themes.to_json
- data_attributes = { themes: @themes, integration_views: integration_views.to_json, user_fields: user_fields, body_classes: Gitlab::Themes.body_classes, profile_preferences_path: profile_preferences_path }
+- @force_desktop_expanded_sidebar = true
- Gitlab::Themes.each do |theme|
= stylesheet_link_tag "themes/#{theme.css_filename}" if theme.css_filename
@@ -17,6 +17,9 @@
= s_('Preferences|Color theme')
%p
= s_('Preferences|Customize the color of GitLab.')
+ - if show_super_sidebar?
+ %p
+ = s_('Preferences|Note: You have the new navigation enabled, so only Dark Mode theme significantly changes GitLab\'s appearance.')
.col-lg-8.application-theme
.row
- Gitlab::Themes.each do |theme|
@@ -34,7 +37,7 @@
%h4.gl-mt-0
= s_('Preferences|Syntax highlighting theme')
%p
- = s_('Preferences|This setting allows you to customize the appearance of the syntax.')
+ = s_('Preferences|Customize the appearance of the syntax.')
= succeed '.' do
= link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'syntax-highlighting-theme'), target: '_blank', rel: 'noopener noreferrer'
.col-lg-8.syntax-theme
@@ -66,7 +69,7 @@
%h4.gl-mt-0
= s_('Preferences|Behavior')
%p
- = s_('Preferences|This setting allows you to customize the behavior of the system layout and default views.')
+ = s_('Preferences|Customize the behavior of the system layout and default views.')
= succeed '.' do
= link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'behavior'), target: '_blank', rel: 'noopener noreferrer'
.col-lg-8
@@ -76,7 +79,7 @@
= f.select :layout, layout_choices, {}, class: 'gl-form-select custom-select'
.form-text.text-muted
= s_('Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout.').html_safe % { percentage: '100%' }
- .js-listbox-input{ data: { label: s_('Preferences|Dashboard'), description: s_('Preferences|Choose what content you want to see by default on your dashboard.'), name: 'user[dashboard]', items: dashboard_choices.to_json, value: current_user.dashboard } }
+ .js-listbox-input{ data: { label: s_('Preferences|Homepage'), description: s_('Preferences|Choose what content you want to see by default on your homepage.'), name: 'user[dashboard]', items: dashboard_choices.to_json, value: current_user.dashboard } }
= render_if_exists 'profiles/preferences/group_overview_selector', f: f # EE-specific
@@ -137,21 +140,6 @@
= f.select :first_day_of_week, first_day_of_week_choices_with_default, {}, class: 'gl-form-select custom-select'
.col-sm-12
%hr
- - if Feature.enabled?(:vscode_web_ide, current_user)
- .row.js-preferences-form.js-search-settings-section
- .col-lg-4.profile-settings-sidebar#web-ide
- %h4.gl-mt-0
- = s_('Preferences|Web IDE')
- %p
- = s_('Preferences|The Web IDE Beta is the default Web IDE experience.')
- = link_to _('Learn more'), help_page_path('user/project/web_ide_beta/index.md'), target: '_blank', rel: 'noopener noreferrer'
- .col-lg-8
- .form-group
- = f.gitlab_ui_checkbox_component :use_legacy_web_ide,
- s_('Preferences|Opt out of the Web IDE Beta'),
- help_text: s_('Preferences|The Web IDE remains available alongside the Beta.')
- .col-sm-12
- %hr
.row.js-preferences-form.js-search-settings-section
.col-lg-4.profile-settings-sidebar#time-preferences
%h4.gl-mt-0
@@ -165,8 +153,21 @@
= f.gitlab_ui_checkbox_component :time_display_relative,
s_('Preferences|Use relative times'),
help_text: s_('Preferences|For example: 30 minutes ago.')
- - if Feature.enabled?(:user_time_settings)
+ - if Feature.enabled?(:disable_follow_users, @user)
+ .row.js-preferences-form.js-search-settings-section
+ .col-sm-12
+ %hr
+ .col-lg-4.profile-settings-sidebar#enabled_following
+ %h4.gl-mt-0
+ = s_('Preferences|Enable follow users feature')
+ %p
+ = s_('Preferences|Turns on or off the ability to follow or be followed by other users.')
+ = succeed '.' do
+ = link_to _('Learn more'), help_page_path('user/profile/index', anchor: 'follow-users'), target: '_blank', rel: 'noopener noreferrer'
+ .col-lg-8
.form-group
- = f.gitlab_ui_checkbox_component :time_format_in_24h, s_('Preferences|Display time in 24-hour format')
+ = f.gitlab_ui_checkbox_component :enabled_following,
+ s_('Preferences|Enable follow users')
+
#js-profile-preferences-app{ data: data_attributes }
diff --git a/app/views/profiles/saved_replies/index.html.haml b/app/views/profiles/saved_replies/index.html.haml
deleted file mode 100644
index 2ae7a092249..00000000000
--- a/app/views/profiles/saved_replies/index.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- page_title _('Saved Replies')
-
-#js-saved-replies-root.row.gl-mt-5{ data: { base_path: profile_saved_replies_path } }
- .col-lg-4
- %h4.gl-mt-0
- = page_title
- %p
- = _('Saved replies can be used when creating comments inside issues, merge requests, and epics.')
- .col-lg-8
- = gl_loading_icon(size: 'lg')
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 5ffffb80d97..930f4f5c397 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -1,8 +1,8 @@
- breadcrumb_title s_("Profiles|Edit Profile")
- page_title s_("Profiles|Edit Profile")
- add_page_specific_style 'page_bundles/profile'
-- @content_class = "limit-container-width" unless fluid_layout
- gravatar_link = link_to Gitlab.config.gravatar.host, 'https://' + Gitlab.config.gravatar.host
+- @force_desktop_expanded_sidebar = true
= gitlab_ui_form_for @user, url: profile_path, method: :put, html: { multipart: true, class: 'edit-user js-edit-user gl-mt-3 js-quick-submit gl-show-field-errors js-password-prompt-form', remote: true }, authenticity_token: true do |f|
.row.js-search-settings-section
@@ -53,7 +53,9 @@
= status_form.hidden_field :emoji, data: { js_name: 'emoji' }
= status_form.hidden_field :message, data: { js_name: 'message' }
= status_form.hidden_field :availability, data: { js_name: 'availability' }
- = status_form.hidden_field :clear_status_after, value: @user.status&.clear_status_at&.to_s(:iso8601), data: { js_name: 'clearStatusAfter' }
+ = status_form.hidden_field :clear_status_after,
+ value: user_clear_status_at(@user),
+ data: { js_name: 'clearStatusAfter' }
.col-lg-12
%hr
.row.user-time-preferences.js-search-settings-section
@@ -106,9 +108,18 @@
.form-group.gl-form-group
- external_accounts_help_url = help_page_path('user/profile/index', anchor: 'add-external-accounts-to-your-user-profile-page')
- external_accounts_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: external_accounts_help_url }
- - external_accounts_docs_link = s_('Profiles|Your Discord user ID. Should be between %{min} and %{max} digits long. %{external_accounts_link_start}Learn more.%{external_accounts_link_end}').html_safe % { min: '17', max: '20', external_accounts_link_start: external_accounts_link_start, external_accounts_link_end: '</a>'.html_safe }
+ - external_accounts_docs_link = s_('Profiles|Your Discord user ID. %{external_accounts_link_start}Learn more.%{external_accounts_link_end}').html_safe % { external_accounts_link_start: external_accounts_link_start, external_accounts_link_end: '</a>'.html_safe }
+ - min_discord_length = 17
+ - max_discord_length = 20
= f.label :discord
- = f.text_field :discord, class: 'gl-form-input form-control gl-md-form-input-lg', placeholder: s_("Profiles|User ID")
+ = f.text_field :discord,
+ class: 'gl-form-input form-control gl-md-form-input-lg js-validate-length',
+ placeholder: s_("Profiles|User ID"),
+ data: { min_length: min_discord_length,
+ min_length_message: s_('Profiles|Discord ID is too short (minimum is %{min_length} characters).') % { min_length: min_discord_length },
+ max_length: max_discord_length,
+ max_length_message: s_('Profiles|Discord ID is too long (maximum is %{max_length} characters).') % { max_length: max_discord_length },
+ allow_empty: true}
%small.form-text.text-gl-muted
= external_accounts_docs_link
@@ -147,8 +158,13 @@
%legend.col-form-label.col-form-label
= s_("Profiles|Private contributions")
= f.gitlab_ui_checkbox_component :include_private_contributions,
- s_('Profiles|Include private contributions on my profile'),
+ s_('Profiles|Include private contributions on your profile'),
help_text: s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information.")
+ %fieldset.form-group.gl-form-group
+ %legend.col-form-label.col-form-label
+ = s_("Profiles|Achievements")
+ = f.gitlab_ui_checkbox_component :achievements_enabled,
+ s_('Profiles|Display achievements on your profile')
.row.js-hide-when-nothing-matches-search
.col-lg-12
%hr
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 3add3af3c65..9cc7f6bdd49 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -1,31 +1,18 @@
- breadcrumb_title _('Two-Factor Authentication')
- page_title _('Two-Factor Authentication'), _('Account')
- add_to_breadcrumbs _('Account'), profile_account_path
-- @content_class = "limit-container-width" unless fluid_layout
-- webauthn_enabled = Feature.enabled?(:webauthn)
.js-two-factor-auth{ 'data-two-factor-skippable' => "#{two_factor_skippable?}", 'data-two_factor_skip_url' => skip_profile_two_factor_auth_path }
.row.gl-mt-3
.col-lg-4
%h4.gl-mt-0
- = _('Register Two-Factor Authenticator')
+ = _('Register a one-time password authenticator')
%p
= _('Use a one-time password authenticator on your mobile device or computer to enable two-factor authentication (2FA).')
.col-lg-8
- if current_user.two_factor_otp_enabled?
%p
= _("You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication.")
- %p
- = _('If you lose your recovery codes you can generate new ones, invalidating all previous codes.')
- - if @error
- = render Pajamas::AlertComponent.new(title: @error[:message],
- variant: :danger,
- alert_options: { class: 'gl-mb-3' },
- dismissible: false) do |c|
- = c.body do
- = link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
- .js-manage-two-factor-form{ data: { webauthn_enabled: webauthn_enabled, current_password_required: current_password_required?.to_s, profile_two_factor_auth_path: profile_two_factor_auth_path, profile_two_factor_auth_method: 'delete', codes_profile_two_factor_auth_path: codes_profile_two_factor_auth_path, codes_profile_two_factor_auth_method: 'post' } }
-
- else
%p
- register_2fa_token = _('We recommend using cloud-based authenticator applications that can restore access if you lose your hardware device.')
@@ -36,8 +23,8 @@
.gl-p-2.gl-mb-3{ style: 'background: #fff' }
= raw @qr_code
.col-md-8
- .gl-card
- .gl-card-body
+ = render Pajamas::CardComponent.new do |c|
+ - c.body do
%p.gl-mt-0.gl-mb-3.gl-font-weight-bold
= _("Can't scan the code?")
%p.gl-mt-0.gl-mb-3
@@ -58,15 +45,15 @@
= c.body do
= link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
- .form-group
- = label_tag :pin_code, _('Pin code'), class: "label-bold"
- = text_field_tag :pin_code, nil, class: "form-control gl-form-input", required: true, data: { qa_selector: 'pin_code_field' }
- if current_password_required?
.form-group
= label_tag :current_password, _('Current password'), class: 'label-bold'
= 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.')
+ .form-group
+ = label_tag :pin_code, _('Enter verification code'), class: "label-bold"
+ = text_field_tag :pin_code, nil, autocomplete: 'off', inputmode: 'numeric', class: "form-control gl-form-input", required: true, data: { qa_selector: 'pin_code_field' }
.gl-mt-3
= submit_tag _('Register with two-factor app'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'register_2fa_app_button' }
@@ -75,37 +62,27 @@
.row.gl-mt-3
.col-lg-4
%h4.gl-mt-0
- - if webauthn_enabled
- = _('Register WebAuthn Device')
- - else
- = _('Register Universal Two-Factor (U2F) Device')
+ = _('Register a WebAuthn device')
%p
- = _('Set up a hardware device as a second factor to sign in.')
+ = _('Set up a hardware device to enable two-factor authentication (2FA).')
%p
- - if webauthn_enabled
- = _("Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even from an unsupported browser.")
+ - if Feature.enabled?(:webauthn_without_totp)
+ = _("Not all browsers support WebAuthn. You must save your recovery codes after you first register a two-factor authenticator to be able to sign in, even from an unsupported browser.")
- else
- = _("Not all browsers support U2F devices. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in - even when you're using an unsupported browser.")
+ = _("Not all browsers support WebAuthn. Therefore, we require that you set up a two-factor authentication app first. That way you'll always be able to sign in, even from an unsupported browser.")
.col-lg-8
- - registration = webauthn_enabled ? @webauthn_registration : @u2f_registration
- - if registration.errors.present?
- = form_errors(registration)
- - if webauthn_enabled
- = render "authentication/register", target_path: create_webauthn_profile_two_factor_auth_path
- - else
- = render "authentication/register", target_path: create_u2f_profile_two_factor_auth_path
+ - if @webauthn_registration.errors.present?
+ = form_errors(@webauthn_registration)
+ = render "authentication/register", target_path: create_webauthn_profile_two_factor_auth_path
%hr
%h5
- - if webauthn_enabled
- = _('WebAuthn Devices (%{length})') % { length: @registrations.length }
- - else
- = _('U2F Devices (%{length})') % { length: @registrations.length }
+ = _('WebAuthn Devices (%{length})') % { length: @registrations.length }
- if @registrations.present?
.table-responsive
- %table.table.table-bordered.u2f-registrations
+ %table.table
%colgroup
%col{ width: "50%" }
%col{ width: "30%" }
@@ -134,7 +111,28 @@
- else
.settings-message.text-center
- - if webauthn_enabled
- = _("You don't have any WebAuthn devices registered yet.")
- - else
- = _("You don't have any U2F devices registered yet.")
+ = _("You don't have any WebAuthn devices registered yet.")
+
+ %hr
+
+ .row.gl-mt-3
+ .col-lg-4
+ %h4.gl-mt-0
+ = _('Disable two-factor authentication')
+ %p
+ = _('Use this section to disable your one-time password authenticator and WebAuthn devices. You can also generate new recovery codes.')
+ .col-lg-8
+ - if current_user.two_factor_enabled?
+ %p
+ = _('If you lose your recovery codes you can generate new ones, invalidating all previous codes.')
+ - if @error
+ = render Pajamas::AlertComponent.new(title: @error[:message],
+ variant: :danger,
+ alert_options: { class: 'gl-mb-3' },
+ dismissible: false) do |c|
+ = c.body do
+ = link_to _('Try the troubleshooting steps here.'), help_page_path('user/profile/account/two_factor_authentication.md', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
+ .js-manage-two-factor-form{ data: { current_password_required: current_password_required?.to_s, profile_two_factor_auth_path: profile_two_factor_auth_path, profile_two_factor_auth_method: 'delete', codes_profile_two_factor_auth_path: codes_profile_two_factor_auth_path, codes_profile_two_factor_auth_method: 'post' } }
+ - else
+ %p
+ = _("Register a one-time password authenticator or a WebAuthn device first.")
diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml
index 9962e03995b..19943aa68a3 100644
--- a/app/views/projects/_commit_button.html.haml
+++ b/app/views/projects/_commit_button.html.haml
@@ -1,4 +1,4 @@
-.form-actions.gl-display-flex
+.gl-display-flex.gl-mt-7
- submit_button_options = { type: :submit, variant: :confirm, button_options: { id: 'commit-changes', class: 'js-commit-button', data: { qa_selector: 'commit_button' } } }
= render Pajamas::ButtonComponent.new(**submit_button_options) do
= _('Commit changes')
diff --git a/app/views/projects/_deletion_failed.html.haml b/app/views/projects/_deletion_failed.html.haml
index 489d303c5b9..29551505a7e 100644
--- a/app/views/projects/_deletion_failed.html.haml
+++ b/app/views/projects/_deletion_failed.html.haml
@@ -4,6 +4,6 @@
= render Pajamas::AlertComponent.new(variant: :warning,
dismissible: false,
alert_options: { class: 'project-deletion-failed-message' }) do |c|
- = c.body do
+ - c.with_body do
This project was scheduled for deletion, but failed with the following message:
= project.delete_error
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index e2d1a50ae5e..5c7f83fc579 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -1,4 +1,3 @@
-- @no_breadcrumb_border = true
- show_auto_devops_callout = show_auto_devops_callout?(@project)
- is_project_overview = local_assigns.fetch(:is_project_overview, false)
- ref = local_assigns.fetch(:ref) { current_ref }
@@ -7,18 +6,17 @@
- if readme_path = @project.repository.readme_path
- add_page_startup_api_call project_blob_path(@project, tree_join(@ref, readme_path), viewer: "rich", format: "json")
-#tree-holder.tree-holder.clearfix.js-per-page{ data: { blame_per_page: Projects::BlameService::PER_PAGE } }
- .info-well.gl-display-none.gl-sm-display-flex.project-last-commit.gl-flex-direction-column
+#tree-holder.tree-holder.clearfix.js-per-page{ data: { blame_per_page: Gitlab::Git::BlamePagination::PAGINATION_PER_PAGE } }
+ .info-well.gl-display-none.gl-sm-display-flex.project-last-commit.gl-flex-direction-column.gl-mt-5
#js-last-commit.gl-m-auto
= gl_loading_icon(size: 'md')
- #js-code-owners
+ #js-code-owners{ data: { branch: @ref, can_view_branch_rules: can_view_branch_rules?, branch_rules_path: branch_rules_path } }
.nav-block.gl-display-flex.gl-xs-flex-direction-column.gl-align-items-stretch
= render 'projects/tree/tree_header', tree: @tree, is_project_overview: is_project_overview
- - if project.forked? && Feature.enabled?(:fork_divergence_counts, @project.fork_source)
-
- #js-fork-info{ data: vue_fork_divergence_data(project, ref), project_id: @project.id }
+ - if project.forked?
+ #js-fork-info{ data: vue_fork_divergence_data(project, ref) }
- if is_project_overview
.project-buttons.gl-mb-5.js-show-on-project-root{ data: { qa_selector: 'project_buttons' } }
diff --git a/app/views/projects/_flash_messages.html.haml b/app/views/projects/_flash_messages.html.haml
index 2d9f7e49ddc..dc0c9547901 100644
--- a/app/views/projects/_flash_messages.html.haml
+++ b/app/views/projects/_flash_messages.html.haml
@@ -10,5 +10,5 @@
- if show_auto_devops_callout?(@project)
= render 'shared/auto_devops_callout'
= render_if_exists 'projects/above_size_limit_warning', project: project
- = render_if_exists 'shared/shared_runners_minutes_limit', project: project, classes: [container_class, ("limit-container-width" unless fluid_layout)]
+ = render_if_exists 'shared/shared_runners_minutes_limit', project: project
= render_if_exists 'projects/terraform_banner', project: project
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index b9aeed188fa..9cb5ec39de2 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,9 +1,8 @@
- empty_repo = @project.empty_repo?
- show_auto_devops_callout = show_auto_devops_callout?(@project)
- emails_disabled = @project.emails_disabled?
-- cache_enabled = Feature.enabled?(:cache_home_panel, @project, type: :development)
-.project-home-panel.js-show-on-project-root.gl-my-5{ class: [("empty-project" if empty_repo)] }
+.project-home-panel.js-show-on-project-root.gl-mt-4.gl-mb-5{ class: [("empty-project" if empty_repo)] }
.gl-display-flex.gl-justify-content-space-between.gl-flex-wrap.gl-sm-flex-direction-column.gl-mb-3.gl-gap-5
.home-panel-title-row.gl-display-flex.gl-align-items-center
%div{ class: 'avatar-container rect-avatar s64 home-panel-avatar gl-flex-shrink-0 gl-w-11 gl-h-11 gl-mr-3! float-none' }
@@ -25,28 +24,26 @@
%span.gl-ml-3.gl-mb-3
= render 'shared/members/access_request_links', source: @project
- = cache_if(cache_enabled, [@project, @project.star_count, @project.forks_count, :buttons, current_user, @notification_setting], expires_in: 1.day) do
- .project-repo-buttons.gl-display-flex.gl-justify-content-md-end.gl-align-items-center.gl-flex-wrap.gl-gap-3
- - if current_user
- - if current_user.admin?
- = link_to [:admin, @project], class: 'btn btn-default gl-button btn-icon', title: _('View project in admin area'),
- data: {toggle: 'tooltip', placement: 'top', container: 'body'} do
- = sprite_icon('admin')
- - if @notification_setting
- .js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), project_id: @project.id, no_flip: 'true' } }
+ .project-repo-buttons.gl-display-flex.gl-justify-content-md-end.gl-align-items-center.gl-flex-wrap.gl-gap-3
+ - if current_user
+ - if current_user.admin?
+ = link_to [:admin, @project], class: 'btn btn-default gl-button btn-icon', title: _('View project in admin area'),
+ data: {toggle: 'tooltip', placement: 'top', container: 'body'} do
+ = sprite_icon('admin')
+ - if @notification_setting
+ .js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), project_id: @project.id, no_flip: 'true' } }
- = render 'projects/buttons/star'
- = render 'projects/buttons/fork'
+ = render 'projects/buttons/star'
+ = render 'projects/buttons/fork'
- if can?(current_user, :read_code, @project)
- = cache_if(cache_enabled, [@project, :read_code], expires_in: 1.minute) do
- %nav.project-stats
- - 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)
+ %nav.project-stats
+ - 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)
.gl-my-3
- = render "shared/projects/topics", project: @project, cache_enabled: cache_enabled
+ = render "shared/projects/topics", project: @project
.home-panel-home-desc.mt-1
- if @project.description.present?
.home-panel-description.text-break
@@ -55,15 +52,6 @@
%button.btn.gl-button.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more")
- - if @project.forked? && Feature.disabled?(:fork_divergence_counts, @project.fork_source)
- %p
- - source = visible_fork_source(@project)
- - if source
- #{ s_('ForkedFromProjectPath|Forked from') }
- = link_to source.full_name, project_path(source), data: { qa_selector: 'forked_from_link' }
- - else
- = s_('ForkedFromProjectPath|Forked from an inaccessible project.')
-
= render_if_exists "projects/home_mirror"
- if @project.badges.present?
diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml
index 412c91544a6..947a1007fd5 100644
--- a/app/views/projects/_import_project_pane.html.haml
+++ b/app/views/projects/_import_project_pane.html.haml
@@ -11,7 +11,7 @@
= render Pajamas::AlertComponent.new(variant: :tip,
alert_options: { class: 'gl-my-3' },
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
- docs_link_url = help_page_path('user/group/import/index') + '#migrate-groups-by-direct-transfer-recommended'
- docs_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
= html_escape(_("Importing GitLab projects? Migrating GitLab projects when migrating groups by direct transfer is in Beta. %{link_start}Learn more.%{link_end}")) % { link_start: docs_link, link_end: '</a>'.html_safe }
@@ -21,11 +21,6 @@
= render Pajamas::ButtonComponent.new(href: '#', icon: 'tanuki', button_options: { class: 'btn_import_gitlab_project js-import-project-btn', data: { href: new_import_gitlab_project_path, platform: 'gitlab_export', **tracking_attrs_data(track_label, 'click_button', 'gitlab_export') } }) do
= _('GitLab export')
- - if gitlab_import_enabled?
- %div
- = render Pajamas::ButtonComponent.new(href: status_import_gitlab_path(namespace_id: namespace_id), icon: 'tanuki', button_options: { class: "import_gitlab js-import-project-btn #{'js-how-to-import-link' unless gitlab_import_configured?}", data: { modal_title: _("Import projects from GitLab.com"), modal_message: import_from_gitlab_message, platform: 'gitlab_com', **tracking_attrs_data(track_label, 'click_button', 'gitlab_com') } }) do
- GitLab.com
-
- if github_import_enabled?
%div
= render Pajamas::ButtonComponent.new(href: new_import_github_path(namespace_id: namespace_id), icon: 'github', button_options: { class: 'js-import-github js-import-project-btn', data: { platform: 'github', **tracking_attrs_data(track_label, 'click_button', 'github') } }) do
@@ -63,11 +58,6 @@
= render Pajamas::ButtonComponent.new(href: new_import_manifest_path(namespace_id: namespace_id), icon: 'doc-text', button_options: { class: 'import_manifest js-import-project-btn', data: { platform: 'manifest_file', **tracking_attrs_data(track_label, 'click_button', 'manifest_file') } }) do
= _('Manifest file')
- - if phabricator_import_enabled?
- %div
- = render Pajamas::ButtonComponent.new(href: new_import_phabricator_path(namespace_id: namespace_id), icon: 'issues', button_options: { class: 'import_phabricator js-import-project-btn', data: { platform: 'phabricator', track_label: "#{track_label}", track_action: "click_button", track_property: "phabricator" } }) do
- = _('Phabricator tasks')
-
= render_if_exists "projects/gitee_import_button", namespace_id: namespace_id, track_label: track_label
diff --git a/app/views/projects/_invite_members_empty_project.html.haml b/app/views/projects/_invite_members_empty_project.html.haml
index 5bc53339bf0..18d06c7d0bb 100644
--- a/app/views/projects/_invite_members_empty_project.html.haml
+++ b/app/views/projects/_invite_members_empty_project.html.haml
@@ -6,8 +6,4 @@
.js-invite-members-trigger{ data: { variant: 'confirm',
classes: 'gl-mb-8 gl-xs-w-full',
display_text: s_('InviteMember|Invite members'),
- trigger_source: 'project-empty-page',
- event: 'click_button',
- label: 'invite_members_empty_project' } }
-
-= render 'projects/invite_members_modal', project: @project
+ trigger_source: 'project-empty-page' } }
diff --git a/app/views/projects/_invite_members_modal.html.haml b/app/views/projects/_invite_members_modal.html.haml
index 53f74a0f270..a1b0bdd6c56 100644
--- a/app/views/projects/_invite_members_modal.html.haml
+++ b/app/views/projects/_invite_members_modal.html.haml
@@ -2,5 +2,5 @@
.js-invite-members-modal{ data: { is_project: 'true',
access_levels: ProjectMember.permissible_access_level_roles(current_user, project).to_json,
- reload_page_on_submit: local_assigns.fetch(:reload_page_on_submit, false).to_s,
+ reload_page_on_submit: current_path?('project_members#index').to_s,
help_link: help_page_url('user/permissions') }.merge(common_invite_modal_dataset(project)).merge(users_filter_data(project.group)) }
diff --git a/app/views/projects/_invite_members_side_nav_link.html.haml b/app/views/projects/_invite_members_side_nav_link.html.haml
deleted file mode 100644
index b96a7608ce2..00000000000
--- a/app/views/projects/_invite_members_side_nav_link.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-.js-invite-members-trigger{ data: { trigger_source: 'project-side-nav',
- icon: 'users',
- display_text: title,
- trigger_element: 'side-nav',
- qa_selector: 'invite_members_sidebar_button' } }
-
-= render partial: 'shared/nav/sidebar_submenu', locals: { sidebar_menu: sidebar_menu }
-= render 'projects/invite_members_modal', project: project
diff --git a/app/views/projects/_invite_members_top_nav_link.html.haml b/app/views/projects/_invite_members_top_nav_link.html.haml
new file mode 100644
index 00000000000..35a8d4d9944
--- /dev/null
+++ b/app/views/projects/_invite_members_top_nav_link.html.haml
@@ -0,0 +1,5 @@
+- data = local_assigns.fetch(:data)
+- data[:display_text] = local_assigns.fetch(:display_text)
+- data[:icon] = local_assigns.fetch(:icon)
+
+.js-invite-members-trigger{ data: data }
diff --git a/app/views/projects/_last_push.html.haml b/app/views/projects/_last_push.html.haml
index 5b493772f0a..89c91887d19 100644
--- a/app/views/projects/_last_push.html.haml
+++ b/app/views/projects/_last_push.html.haml
@@ -3,7 +3,7 @@
= render Pajamas::AlertComponent.new(variant: :success,
alert_options: { class: 'gl-mt-3' },
close_button_options: { class: 'js-close-banner' }) do |c|
- = c.body do
+ - c.with_body do
%span= s_("LastPushEvent|You pushed to")
%strong.gl-display-inline-flex.gl-max-w-50p{ data: { toggle: 'tooltip' }, title: event.ref_name }
= link_to event.ref_name, project_commits_path(event.project, event.ref_name), class: 'ref-name gl-text-truncate'
@@ -15,6 +15,6 @@
#{time_ago_with_tooltip(event.created_at)}
- if create_mr_button_from_event?(event)
- = c.actions do
+ - c.with_actions do
= render Pajamas::ButtonComponent.new(variant: :confirm, href: create_mr_path_from_push_event(event), button_options: { data: { qa_selector: 'create_merge_request_button' }}) do
= _('Create merge request')
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 53a1abdff33..70a2476c8e5 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -46,7 +46,7 @@
= render Pajamas::AlertComponent.new(alert_options: { class: "gl-mb-4 gl-display-none js-user-readme-repo" },
dismissible: false,
variant: :success) do |c|
- = c.body do
+ - c.with_body do
- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/profile/index', anchor: 'add-details-to-your-profile-with-a-readme') }
= html_escape(_('%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}')) % { project_path: "<strong>#{current_user.username} / #{current_user.username}</strong>".html_safe, help_link_start: help_link_start, help_link_end: '</a>'.html_safe }
@@ -81,21 +81,21 @@
= render Pajamas::CheckboxTagComponent.new(name: 'project[initialize_with_readme]',
checked: true,
checkbox_options: { data: { qa_selector: 'initialize_with_readme_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_readme' } }) do |c|
- = c.label do
+ - c.with_label do
= s_('ProjectsNew|Initialize repository with a README')
- = c.help_text do
+ - c.with_help_text do
= s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
.form-group
= render Pajamas::CheckboxTagComponent.new(name: 'project[initialize_with_sast]',
checkbox_options: { data: { qa_selector: 'initialize_with_sast_checkbox', track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' } }) do |c|
- = c.label do
+ - c.with_label do
= s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
- = c.help_text do
+ - c.with_help_text do
= 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' }
-# this partial is from JiHu, see details in https://jihulab.com/gitlab-cn/gitlab/-/merge_requests/675
= render_if_exists 'shared/other_project_options', f: f, visibility_level: visibility_level, track_label: track_label
= f.submit _('Create project'), class: "js-create-project-button", data: { qa_selector: 'project_create_button', track_label: "#{track_label}", track_action: "click_button", track_property: "create_project", track_value: "" }, pajamas_button: true
-= 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: "" }
+= link_to _('Cancel'), @parent_group || dashboard_groups_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/_remove.html.haml b/app/views/projects/_remove.html.haml
index ed238dab4ff..dec3199ffe1 100644
--- a/app/views/projects/_remove.html.haml
+++ b/app/views/projects/_remove.html.haml
@@ -7,7 +7,6 @@
%h4.danger-title= _('Delete project')
%p
%strong= _('Deleting the project will delete its repository and all related resources, including issues and merge requests.')
- = link_to _('Learn more.'), help_page_path('user/project/settings/index', anchor: 'remove-a-fork-relationship'), target: '_blank', rel: 'noopener noreferrer'
%p
%strong= _('Deleted projects cannot be restored!')
#js-project-delete-button{ data: { form_path: project_path(project), confirm_phrase: delete_confirm_phrase(project), is_fork: project.forked?.to_s, issues_count: number_with_delimiter(issues_count), merge_requests_count: number_with_delimiter(merge_requests_count), forks_count: number_with_delimiter(forks_count), stars_count: number_with_delimiter(project.star_count) } }
diff --git a/app/views/projects/_remove_fork.html.haml b/app/views/projects/_remove_fork.html.haml
index bfc1e77118a..260c2b2272e 100644
--- a/app/views/projects/_remove_fork.html.haml
+++ b/app/views/projects/_remove_fork.html.haml
@@ -7,6 +7,5 @@
= form_for @project, url: remove_fork_project_path(@project), method: :delete, html: { id: remove_form_id } do |f|
%p
- %strong= _('Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks.')
- = link_to _('Learn more.'), help_page_path('user/project/settings/index', anchor: 'remove-a-fork-relationship'), target: '_blank', rel: 'noopener noreferrer'
+ %strong= _('After it is removed, the fork relationship can only be restored by using the API. This project will no longer be able to receive or send merge requests to the upstream project or other forks.')
.js-confirm-danger{ data: remove_fork_project_confirm_json(@project, remove_form_id) }
diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml
index 349cd88437f..7654677d8a8 100644
--- a/app/views/projects/_service_desk_settings.html.haml
+++ b/app/views/projects/_service_desk_settings.html.haml
@@ -12,7 +12,7 @@
enabled: "#{@project.service_desk_enabled}",
incoming_email: (@project.service_desk_incoming_address if @project.service_desk_enabled),
custom_email: (@project.service_desk_custom_address if @project.service_desk_enabled),
- custom_email_enabled: "#{Gitlab::ServiceDeskEmail.enabled?}",
+ custom_email_enabled: "#{Gitlab::Email::ServiceDeskEmail.enabled?}",
selected_template: "#{@project.service_desk_setting&.issue_template_key}",
selected_file_template_project_id: "#{@project.service_desk_setting&.file_template_project_id}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
diff --git a/app/views/projects/_terraform_banner.html.haml b/app/views/projects/_terraform_banner.html.haml
index 881e4ccd9df..24711fc39d8 100644
--- a/app/views/projects/_terraform_banner.html.haml
+++ b/app/views/projects/_terraform_banner.html.haml
@@ -1,5 +1,3 @@
-- @content_class = "container-limited limit-container-width" unless fluid_layout
-
- if show_terraform_banner?(project)
.container-fluid{ class: @content_class }
.js-terraform-notification{ data: { terraform_image_path: image_path('illustrations/third-party-logos/ci_cd-template-logos/terraform.svg') } }
diff --git a/app/views/projects/airflow/dags/index.html.haml b/app/views/projects/airflow/dags/index.html.haml
deleted file mode 100644
index d631d084db1..00000000000
--- a/app/views/projects/airflow/dags/index.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-- breadcrumb_title s_('Airflow|Airflow DAGs')
-- page_title s_('Airflow|Airflow DAGs')
-
-.page-title-holder
- %h1.page-title.gl-font-size-h-display= s_('Airflow|Airflow DAGs')
-
-#js-show-airflow-dags{ data: {
- dags: @dags.to_json,
- pagination: @pagination.to_json
- }
-}
diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml
index 3359ea5f63b..ccda06c7e4c 100644
--- a/app/views/projects/artifacts/browse.html.haml
+++ b/app/views/projects/artifacts/browse.html.haml
@@ -12,7 +12,7 @@
.nav-block
%ul.breadcrumb.repo-breadcrumb
%li.breadcrumb-item
- = link_to 'Artifacts', browse_project_job_artifacts_path(@project, @build)
+ = link_to _('Artifacts'), browse_project_job_artifacts_path(@project, @build)
- path_breadcrumbs do |title, path|
%li.breadcrumb-item
= link_to truncate(title, length: 40), browse_project_job_artifacts_path(@project, @build, path)
diff --git a/app/views/projects/aws/configuration/index.html.haml b/app/views/projects/aws/configuration/index.html.haml
new file mode 100644
index 00000000000..27d8652c625
--- /dev/null
+++ b/app/views/projects/aws/configuration/index.html.haml
@@ -0,0 +1,7 @@
+- add_to_breadcrumbs _('AWS'), project_aws_path(@project)
+- breadcrumb_title s_('CloudSeed|Configuration')
+- page_title s_('CloudSeed|Configuration')
+
+- @content_class = "limit-container-width" unless fluid_layout
+
+#js-aws-configuration{ data: @js_data }
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index 74b85a93c8e..e2cad2fb3d7 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -1,6 +1,17 @@
- page_title _("Blame"), @blob.path, @ref
- add_page_specific_style 'page_bundles/tree'
-- dataset = { testid: 'blob-content-holder', qa_selector: 'blame_file_content', per_page: @blame_per_page }
+- blame_streaming_url = blame_pages_streaming_url(@id, @project)
+
+- if @blame_mode.streaming? && @blame_pagination.total_extra_pages > 0
+ - content_for :startup_js do
+ = javascript_tag do
+ :plain
+ window.blamePageStream = (() => {
+ const url = new URL("#{blame_streaming_url}");
+ url.searchParams.set('page', 2);
+ return fetch(url).then(response => response.body);
+ })();
+- dataset = { testid: 'blob-content-holder', qa_selector: 'blame_file_content', per_page: @blame_pagination.per_page, total_extra_pages: @blame_pagination.total_extra_pages - 1, pages_url: blame_streaming_url }
#blob-content-holder.tree-holder.js-per-page{ data: dataset }
= render "projects/blob/breadcrumb", blob: @blob, blame: true
@@ -26,11 +37,20 @@
.blame-table-wrapper
= render partial: 'page'
- - if @blame_pagination && @blame_pagination.total_pages > 1
+ - if @blame_mode.streaming?
+ #blame-stream-container.blame-stream-container
+
+ - if @blame_mode.pagination? && @blame_pagination.total_pages > 1
.gl-display-flex.gl-justify-content-center.gl-flex-direction-column.gl-align-items-center.gl-p-3.gl-bg-gray-50.gl-border-t-solid.gl-border-t-1.gl-border-gray-100
- = _('For faster browsing, not all history is shown.')
- = render Pajamas::ButtonComponent.new(href: namespace_project_blame_path(namespace_id: @project.namespace, project_id: @project, id: @id, no_pagination: true), size: :small, button_options: { class: 'gl-mt-3' }) do |c|
- = _('View entire blame')
+ = render Pajamas::ButtonComponent.new(href: entire_blame_path(@id, @project), size: :small, button_options: { class: 'gl-mt-3' }) do |c|
+ = _('Show full blame')
+
+ - if @blame_mode.streaming?
+ #blame-stream-loading.blame-stream-loading
+ .gradient
+ = gl_loading_icon(size: 'sm')
+ %span.gl-mx-2
+ = _('Loading full blame...')
- - if @blame_pagination
- = paginate(@blame_pagination, theme: "gitlab")
+ - if @blame_mode.pagination?
+ = paginate(@blame_pagination.paginator, theme: "gitlab")
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index 17d5ef69b76..453a60a62f4 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -10,19 +10,19 @@
%ul.blob-commit-info
= render 'projects/commits/commit', commit: @last_commit, project: @project, ref: @ref
- #js-code-owners{ data: { blob_path: blob.path, project_path: @project.full_path, branch: @ref } }
+ #js-code-owners{ data: { blob_path: blob.path, project_path: @project.full_path, branch: @ref, can_view_branch_rules: can_view_branch_rules?, branch_rules_path: branch_rules_path } }
= render "projects/blob/auxiliary_viewer", blob: blob
-#blob-content-holder.blob-content-holder.js-per-page{ data: { blame_per_page: Projects::BlameService::PER_PAGE } }
+- if project.forked?
+ #js-fork-info{ data: vue_fork_divergence_data(project, ref) }
+
+#blob-content-holder.blob-content-holder.js-per-page{ data: { blame_per_page: Gitlab::Git::BlamePagination::PAGINATION_PER_PAGE } }
- if @code_navigation_path
#js-code-navigation{ data: { code_navigation_path: @code_navigation_path, blob_path: blob.path, definition_path_prefix: project_blob_path(@project, @ref) } }
- if !expanded
-# Data info will be removed once we migrate this to use GraphQL
-# Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/330406
- #js-view-blob-app{ data: { blob_path: blob.path,
- project_path: @project.full_path,
- target_branch: project.empty_repo? ? ref : @ref,
- original_branch: @ref } }
+ #js-view-blob-app{ data: vue_blob_app_data(project, blob, ref) }
= gl_loading_icon(size: 'md')
- else
%article.file-holder
diff --git a/app/views/projects/blob/_breadcrumb.html.haml b/app/views/projects/blob/_breadcrumb.html.haml
index 7c2caf34fd1..79b13dc861a 100644
--- a/app/views/projects/blob/_breadcrumb.html.haml
+++ b/app/views/projects/blob/_breadcrumb.html.haml
@@ -2,7 +2,7 @@
.nav-block
.tree-ref-container
.tree-ref-holder
- = render 'shared/ref_switcher', destination: 'blob'
+ #js-tree-ref-switcher{ data: { project_id: @project.id, project_root_path: project_path(@project), ref: current_ref, ref_type: @ref_type.to_s } }
%ul.breadcrumb.repo-breadcrumb
%li.breadcrumb-item
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 87a6b54d697..621cd251bdf 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -2,8 +2,8 @@
- file_name = params[:id].split("/").last ||= ""
- is_markdown = Gitlab::MarkupHelper.gitlab_markdown?(file_name)
-.file-holder-bottom-radius.file-holder.file.gl-mb-3
- .js-file-title.file-title.gl-display-flex.gl-align-items-center.clearfix{ data: { current_action: action } }
+.file-holder.file.gl-mb-3
+ .js-file-title.file-title.gl-display-flex.gl-align-items-center.gl-rounded-top-base{ data: { current_action: action } }
.editor-ref.block-truncated.has-tooltip{ title: ref }
= sprite_icon('branch', size: 12)
= ref
@@ -16,7 +16,7 @@
- if current_action?(:new) || current_action?(:create)
%span.float-left.gl-mr-3
\/
- = text_field_tag 'file_name', params[:file_name], placeholder: "File name", data: { qa_selector: 'file_name_field' },
+ = text_field_tag 'file_name', params[:file_name], placeholder: "Filename", data: { qa_selector: 'file_name_field' },
required: true, class: 'form-control gl-form-input new-file-name js-file-path-name-input', value: params[:file_name] || (should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : '')
= render 'template_selectors'
- if should_suggest_gitlab_ci_yml?
@@ -26,15 +26,18 @@
dismiss_key: @project.id,
human_access: human_access } }
- .file-buttons.gl-display-flex.gl-align-items-center.gl-justify-content-end
- - if is_markdown
- - unless Feature.enabled?(:source_editor_toolbar, current_user)
- = render 'shared/blob/markdown_buttons', show_fullscreen_button: false, supports_file_upload: false
- %span.soft-wrap-toggle
- = render Pajamas::ButtonComponent.new(icon: 'soft-unwrap', button_options: { class: 'no-wrap' }) do
- = _("No wrap")
- = render Pajamas::ButtonComponent.new(icon: 'soft-wrap', button_options: { class: 'soft-wrap' }) do
- = _("Soft wrap")
+ - unless Feature.enabled?(:source_editor_toolbar, current_user)
+ .file-buttons.gl-display-flex.gl-align-items-center.gl-justify-content-end
+ - if is_markdown
+ .md-header.gl-display-flex.gl-px-2.gl-rounded-base.gl-mx-2.gl-mt-2
+ .gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-justify-content-space-between
+ .md-header-toolbar.gl-display-flex.gl-py-2.gl-flex-wrap{ class: "gl-m-0!" }
+ = render 'shared/blob/markdown_buttons', supports_file_upload: false
+ %span.soft-wrap-toggle
+ = render Pajamas::ButtonComponent.new(icon: 'soft-unwrap', button_options: { class: 'no-wrap' }) do
+ = _("No wrap")
+ = render Pajamas::ButtonComponent.new(icon: 'soft-wrap', button_options: { class: 'soft-wrap' }) do
+ = _("Soft wrap")
.file-editor.code
- if Feature.enabled?(:source_editor_toolbar, current_user)
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index 528999f5c89..195dc03632a 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -3,18 +3,20 @@
- content_for :prefetch_asset_tags do
- webpack_preload_asset_tag('monaco')
- add_page_specific_style 'page_bundles/editor'
-
- if @conflict
= render Pajamas::AlertComponent.new(alert_options: { class: 'gl-mb-5 gl-mt-5' },
variant: :danger,
dismissible: false) do |c|
- - blob_url = project_blob_path(@project, @id)
- - external_link_icon = content_tag 'span', { aria: { label: _('Opens new window') }} do
- - sprite_icon('external-link', css_class: 'gl-icon').html_safe
- - blob_link_start = '<a href="%{url}" class="gl-link" target="_blank" rel="noopener noreferrer">'.html_safe % { url: blob_url }
- = c.body do
- = _('Someone edited the file the same time you did. Please check out %{link_start}the file %{icon}%{link_end} and make sure your changes will not unintentionally remove theirs.').html_safe % { link_start: blob_link_start, link_end: '</a>'.html_safe , icon: external_link_icon }
-
+ - c.with_body do
+ - blob_link_start = '<a href="%{url}" class="gl-link" target="_blank" rel="noopener noreferrer">'.html_safe
+ - link_end = '</a>'.html_safe
+ - external_link_icon = content_tag 'span', { aria: { label: _('Opens new window') }} do
+ - sprite_icon('external-link', css_class: 'gl-icon').html_safe
+ - if @different_project
+ = _("Error: Can't edit this file. The fork and upstream project have diverged. %{link_start}Edit the file on the fork %{icon}%{link_end}, and create a merge request.").html_safe % {link_start: blob_link_start % { url: project_blob_path(@project_to_commit_into, @id) } , link_end: link_end, icon: external_link_icon }
+ - else
+ - blob_url = project_blob_path(@project, @id)
+ = _('Someone edited the file the same time you did. Please check out %{link_start}the file %{icon}%{link_end} and make sure your changes will not unintentionally remove theirs.').html_safe % { link_start: blob_link_start % { url: blob_url }, link_end: link_end , icon: external_link_icon }
%h1.page-title.gl-font-size-h-display.blob-edit-page-title
Edit file
diff --git a/app/views/projects/blob/viewers/_csv.html.haml b/app/views/projects/blob/viewers/_csv.html.haml
index 3a58bc9902c..3538ba1dd0d 100644
--- a/app/views/projects/blob/viewers/_csv.html.haml
+++ b/app/views/projects/blob/viewers/_csv.html.haml
@@ -1 +1 @@
-.file-content#js-csv-viewer{ data: { data: viewer.blob.data } }
+.file-content#js-csv-viewer{ data: { data: blob_raw_path } }
diff --git a/app/views/projects/branch_defaults/_branch_names_fields.html.haml b/app/views/projects/branch_defaults/_branch_names_fields.html.haml
index 393b19e6c5a..4e4a72c154f 100644
--- a/app/views/projects/branch_defaults/_branch_names_fields.html.haml
+++ b/app/views/projects/branch_defaults/_branch_names_fields.html.haml
@@ -10,5 +10,6 @@
%p.form-text.text-muted
= s_('ProjectSettings|Leave empty to use default template.')
= sprintf(s_('ProjectSettings|Maximum %{maxLength} characters.'), { maxLength: Issue::MAX_BRANCH_TEMPLATE })
- - branch_name_help_link = help_page_path('user/project/merge_requests/creating_merge_requests.md', anchor: 'from-an-issue')
+ - branch_name_help_link = help_page_path('user/project/repository/branches/index.md', anchor: 'name-your-branch')
= link_to _('What variables can I use?'), branch_name_help_link, target: "_blank"
+ = render_if_exists 'projects/branch_defaults/branch_names_help'
diff --git a/app/views/projects/branch_rules/_show.html.haml b/app/views/projects/branch_rules/_show.html.haml
index 27525b441ab..605715e2899 100644
--- a/app/views/projects/branch_rules/_show.html.haml
+++ b/app/views/projects/branch_rules/_show.html.haml
@@ -1,12 +1,16 @@
- expanded = expanded_by_default?
+- show_code_owners = @project.licensed_feature_available?(:code_owner_approval_required)
+- show_status_checks = @project.licensed_feature_available?(:external_status_checks)
+- show_approvers = @project.licensed_feature_available?(:merge_request_approvers)
-%section.settings.no-animate#branch-rules{ class: ('expanded' if expanded) }
+%section.settings.no-animate#branch-rules{ class: ('expanded' if expanded), data: { qa_selector: 'branch_rules_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Branch rules')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
= expanded ? _('Collapse') : _('Expand')
%p
= _('Define rules for who can push, merge, and the required approvals for each branch.')
+ = link_to(_('Leave feedback.'), 'https://gitlab.com/gitlab-org/gitlab/-/issues/388149', target: '_blank', rel: 'noopener noreferrer')
.settings-content.gl-pr-0
- #js-branch-rules{ data: { project_path: @project.full_path, branch_rules_path: project_settings_repository_branch_rules_path(@project) } }
+ #js-branch-rules{ data: { project_path: @project.full_path, branch_rules_path: project_settings_repository_branch_rules_path(@project), show_code_owners: show_code_owners.to_s, show_status_checks: show_status_checks.to_s, show_approvers: show_approvers.to_s } }
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 51c218f40b9..dbc1fe24d96 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -1,50 +1,51 @@
- merged = local_assigns.fetch(:merged, false)
- commit = @repository.commit(branch.dereferenced_target)
- merge_project = merge_request_source_project_for_project(@project)
-%li{ class: "branch-item gl-display-flex! gl-align-items-center! js-branch-item js-branch-#{branch.name}", data: { name: branch.name, qa_selector: 'branch_container', qa_name: branch.name } }
- .branch-info
- .gl-display-flex.gl-align-items-center
- = sprite_icon('branch', size: 12, css_class: 'gl-flex-shrink-0')
- = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name gl-ml-3', data: { qa_selector: 'branch_link' } do
- = branch.name
- = clipboard_button(text: branch.name, title: _("Copy branch name"))
- - if branch.name == @repository.root_ref
- = gl_badge_tag s_('DefaultBranchLabel|default'), { variant: :info, size: :sm }, { class: 'gl-ml-2', data: { qa_selector: 'badge_content' } }
- - elsif merged
- = gl_badge_tag s_('Branches|merged'), { variant: :info, size: :sm }, { class: 'gl-ml-2', title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref }, data: { toggle: 'tooltip', container: 'body', qa_selector: 'badge_content' } }
- - if protected_branch?(@project, branch)
- = gl_badge_tag s_('Branches|protected'), { variant: :success, size: :sm }, { class: 'gl-ml-2', data: { qa_selector: 'badge_content' } }
-
- = render_if_exists 'projects/branches/diverged_from_upstream', branch: branch
-
- .block-truncated
- - if commit
- = render 'projects/branches/commit', commit: commit, project: @project
- - else
- = s_('Branches|Can’t find HEAD commit for this branch')
-
- - if branch.name != @repository.root_ref
- .js-branch-divergence-graph
-
- .controls.d-none.d-md-block<
- - if commit_status
- = render 'ci/status/icon', size: 24, status: commit_status, option_css_classes: 'gl-display-inline-flex gl-vertical-align-middle gl-mr-5'
- - elsif show_commit_status
- .gl-display-inline-flex.gl-vertical-align-middle.gl-mr-5
- %svg.s24
-
- - if merge_project && create_mr_button?(from: branch.name, source_project: @project)
- = render Pajamas::ButtonComponent.new(href: create_mr_path(from: branch.name, source_project: @project)) do
- = _('Merge request')
+%li{ class: "branch-item gl-py-3! js-branch-item js-branch-#{branch.name}", data: { name: branch.name, qa_selector: 'branch_container', qa_name: branch.name } }
+ .branch-item-content.gl-display-flex.gl-align-items-center.gl-px-3.gl-py-2
+ .branch-info
+ .gl-display-flex.gl-align-items-center
+ = sprite_icon('branch', size: 12, css_class: 'gl-flex-shrink-0')
+ = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name gl-ml-3', data: { qa_selector: 'branch_link' } do
+ = branch.name
+ = clipboard_button(text: branch.name, title: _("Copy branch name"))
+ - if branch.name == @repository.root_ref
+ = gl_badge_tag s_('DefaultBranchLabel|default'), { variant: :info, size: :sm }, { class: 'gl-ml-2', data: { qa_selector: 'badge_content' } }
+ - elsif merged
+ = gl_badge_tag s_('Branches|merged'), { variant: :info, size: :sm }, { class: 'gl-ml-2', title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref }, data: { toggle: 'tooltip', container: 'body', qa_selector: 'badge_content' } }
+ - if protected_branch?(@project, branch)
+ = gl_badge_tag s_('Branches|protected'), { variant: :success, size: :sm }, { class: 'gl-ml-2', data: { qa_selector: 'badge_content' } }
+
+ = render_if_exists 'projects/branches/diverged_from_upstream', branch: branch
+
+ .block-truncated
+ - if commit
+ = render 'projects/branches/commit', commit: commit, project: @project
+ - else
+ = s_('Branches|Can’t find HEAD commit for this branch')
- if branch.name != @repository.root_ref
- = link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name),
- class: "gl-button btn btn-default js-onboarding-compare-branches #{'gl-ml-3' unless merge_project}",
- method: :post,
- title: s_('Branches|Compare') do
- = s_('Branches|Compare')
-
- = render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name], class: 'gl-vertical-align-top'
-
- - if can?(current_user, :push_code, @project)
- = render 'projects/branches/delete_branch_modal_button', project: @project, branch: branch, merged: merged
+ .js-branch-divergence-graph
+
+ .controls.d-none.d-md-block<
+ - if commit_status
+ = render 'ci/status/icon', size: 24, status: commit_status, option_css_classes: 'gl-display-inline-flex gl-vertical-align-middle gl-mr-5'
+ - elsif show_commit_status
+ .gl-display-inline-flex.gl-vertical-align-middle.gl-mr-5
+ %svg.s24
+
+ - if merge_project && create_mr_button?(from: branch.name, source_project: @project)
+ = render Pajamas::ButtonComponent.new(href: create_mr_path(from: branch.name, source_project: @project)) do
+ = _('Merge request')
+
+ - if branch.name != @repository.root_ref
+ = link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name),
+ class: "gl-button btn btn-default js-onboarding-compare-branches #{'gl-ml-3' unless merge_project}",
+ method: :post,
+ title: s_('Branches|Compare') do
+ = s_('Branches|Compare')
+
+ = render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name], class: 'gl-vertical-align-top'
+
+ - if can?(current_user, :push_code, @project)
+ = render 'projects/branches/delete_branch_modal_button', project: @project, branch: branch, merged: merged
diff --git a/app/views/projects/branches/_branch_rules_info.haml b/app/views/projects/branches/_branch_rules_info.haml
new file mode 100644
index 00000000000..451d0f9928c
--- /dev/null
+++ b/app/views/projects/branches/_branch_rules_info.haml
@@ -0,0 +1,12 @@
+- return unless show_branch_rules_info?
+= render Pajamas::AlertComponent.new(variant: :info,
+ title: s_("Branches|See all branch-related settings together with branch rules"),
+ alert_options: { class: 'js-branch-rules-info-callout gl-mb-6 gl-mt-4', data: { feature_id: Users::CalloutsHelper::BRANCH_RULES_INFO_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' } }) do |c|
+ - c.with_body do
+ = s_("Branches|You can now find an overview of settings for protected branches, merge request approvals, status checks, and security approvals conveniently in one spot.")
+
+ - c.with_actions do
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: project_settings_repository_path(@project, anchor: 'js-branch-rules'), button_options: { class: 'deferred-link gl-alert-action' }) do
+ = s_("Branches|View branch rules")
+ = render Pajamas::ButtonComponent.new(button_options: { class: 'js-close'}) do
+ = _('Dismiss')
diff --git a/app/views/projects/branches/_commit.html.haml b/app/views/projects/branches/_commit.html.haml
index e33e9509e3a..cfa0cf6d07b 100644
--- a/app/views/projects/branches/_commit.html.haml
+++ b/app/views/projects/branches/_commit.html.haml
@@ -6,4 +6,4 @@
%span.str-truncated
= link_to_markdown commit.title, project_commit_path(project, commit.id), class: "commit-row-message cgray"
&middot;
- #{time_ago_with_tooltip(commit.committed_date)}
+ %span.gl-text-secondary= time_ago_with_tooltip(commit.committed_date)
diff --git a/app/views/projects/branches/_panel.html.haml b/app/views/projects/branches/_panel.html.haml
index a1f93d21647..a632e29d34f 100644
--- a/app/views/projects/branches/_panel.html.haml
+++ b/app/views/projects/branches/_panel.html.haml
@@ -7,13 +7,14 @@
- return unless branches.any?
-= render Pajamas::CardComponent.new(card_options: {class: 'gl-mb-5'}, body_options: {class: 'gl-py-0'}, footer_options: {class: 'gl-text-center'}) do |c|
- - c.header do
- = panel_title
- - c.body do
- %ul.content-list.all-branches{ data: { qa_selector: 'all_branches_container' } }
+= render Pajamas::CardComponent.new(card_options: {class: 'gl-mt-5 gl-bg-gray-10'}, header_options: {class: 'gl-px-5 gl-py-4 gl-bg-white'}, body_options: {class: 'gl-px-3 gl-py-0'}, footer_options: {class: 'gl-bg-white'}) do |c|
+ - c.with_header do
+ %h3.card-title.h5.gl-line-height-24.gl-m-0
+ = panel_title
+ - c.with_body do
+ %ul.content-list.branches-list.all-branches{ data: { qa_selector: 'all_branches_container' } }
- branches.first(overview_max_branches).each do |branch|
= render "projects/branches/branch", branch: branch, merged: project.repository.merged_to_root_ref?(branch), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
- if branches.size > overview_max_branches
- - c.footer do
+ - c.with_footer do
= link_to show_more_text, project_branches_filtered_path(project, state: state), id: "state-#{state}", data: { state: state }
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index f43d19e2542..64adf97b1b5 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -1,13 +1,15 @@
- add_page_specific_style 'page_bundles/branches'
- page_title _('Branches')
- add_to_breadcrumbs(_('Repository'), project_tree_path(@project))
+- is_branch_rules_available = (can? current_user, :maintainer_access, @project) && Feature.enabled?(:branch_rules, @project)
+- can_push_code = (can? current_user, :push_code, @project)
-# Possible values for variables passed down from the projects/branches_controller.rb
-#
-# @mode - overview|active|stale|all (default:overview)
-# @sort - name_asc|updated_asc|updated_desc
-.top-area.gl-border-0
+.top-area
= 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') }
@@ -22,16 +24,23 @@
sorted_by: @sort }
}
- - if can? current_user, :push_code, @project
+ - if is_branch_rules_available
+ = link_to project_settings_repository_path(@project, anchor: 'js-branch-rules'), class: 'gl-button btn btn-default' do
+ = s_('Branches|View branch rules')
+
+ - if can_push_code
+ = link_to new_project_branch_path(@project), class: 'gl-button btn btn-confirm' do
+ = s_('Branches|New branch')
.js-delete-merged-branches{ data: {
default_branch: @project.repository.root_ref,
form_path: project_merged_branches_path(@project) }
}
- = link_to new_project_branch_path(@project), class: 'gl-button btn btn-confirm' do
- = s_('Branches|New branch')
= render_if_exists 'projects/commits/mirror_status'
+- if is_branch_rules_available
+ = render 'branch_rules_info'
+
.js-branch-list{ data: { diverging_counts_endpoint: diverging_commit_counts_namespace_project_branches_path(@project.namespace, @project, format: :json), default_branch: @project.default_branch } }
- if @gitaly_unavailable
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 91efd5ef048..9fd9943fd26 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -3,26 +3,21 @@
- if @error
= render Pajamas::AlertComponent.new(variant: :danger) do |c|
- = c.body do
+ - c.with_body do
= @error
%h1.page-title.gl-font-size-h-display
= _('New Branch')
-%hr
= form_tag namespace_project_branches_path, method: :post, id: "new-branch-form", class: "js-create-branch-form js-requires-input" do
- .form-group.row
- = label_tag :branch_name, _('Branch name'), class: 'col-form-label col-sm-2'
- .col-sm-10
- = text_field_tag :branch_name, params[:branch_name], required: true, autofocus: true, class: 'form-control js-branch-name monospace'
- .form-text.text-muted.text-danger.js-branch-name-error
- .form-group.row
- = label_tag :ref, _('Create from'), class: 'col-form-label col-sm-2'
- .col-sm-auto.create-from
- .js-new-branch-ref-selector{ data: { project_id: @project.id, default_branch_name: default_ref, hidden_input_name: 'ref' } }
- .form-text.text-muted
- = _('Existing branch name, tag, or commit SHA')
- .form-actions
- = render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { type: 'submit', class: 'gl-mr-3' }) do
- = _('Create branch')
- = link_to _('Cancel'), project_branches_path(@project), class: 'gl-button btn btn-default btn-cancel'
-
+ .form-group.gl-max-w-80
+ = label_tag :branch_name, _('Branch name')
+ = text_field_tag :branch_name, params[:branch_name], required: true, autofocus: true, class: 'form-control js-branch-name monospace'
+ .form-text.text-muted.text-danger.js-branch-name-error{ 'aria-live': 'assertive' }
+ .form-group.gl-max-w-80
+ = label_tag :ref, _('Create from')
+ .js-new-branch-ref-selector{ data: { project_id: @project.id, default_branch_name: default_ref, hidden_input_name: 'ref' } }
+ .form-text.text-muted
+ = _('Existing branch name, tag, or commit SHA')
+ = render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { type: 'submit', class: 'gl-mr-3' }) do
+ = _('Create branch')
+ = link_to _('Cancel'), project_branches_path(@project), class: 'gl-button btn btn-default btn-cancel'
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index a8a911adb7d..ab026d9c6ac 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -13,7 +13,7 @@
%label.label-bold
= _('Clone with SSH')
.input-group.btn-group
- = text_field_tag :ssh_project_clone, project.ssh_url_to_repo, class: "js-select-on-focus form-control", readonly: true, aria: { label: _('Repository clone URL') }, data: { qa_selector: 'ssh_clone_url_content' }
+ = text_field_tag :ssh_project_clone, ssh_clone_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true, aria: { label: _('Repository clone URL') }, data: { qa_selector: 'ssh_clone_url_content' }
.input-group-append
= clipboard_button(target: '#ssh_project_clone', title: _("Copy URL"), class: "input-group-text gl-button btn btn-icon btn-default")
= render_if_exists 'projects/buttons/geo'
@@ -22,7 +22,7 @@
%label.label-bold
= _('Clone with %{http_label}') % { http_label: gitlab_config.protocol.upcase }
.input-group.btn-group
- = text_field_tag :http_project_clone, project.http_url_to_repo, class: "js-select-on-focus form-control", readonly: true, aria: { label: _('Repository clone URL') }, data: { qa_selector: 'http_clone_url_content' }
+ = text_field_tag :http_project_clone, http_clone_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true, aria: { label: _('Repository clone URL') }, data: { qa_selector: 'http_clone_url_content' }
.input-group-append
= clipboard_button(target: '#http_project_clone', title: _("Copy URL"), class: "input-group-text gl-button btn btn-icon btn-default")
= render_if_exists 'projects/buttons/geo'
@@ -32,12 +32,12 @@
%label.label-bold{ class: 'gl-px-4!' }
= _('Open in your IDE')
- if ssh_enabled?
- - escaped_ssh_url_to_repo = CGI.escape(project.ssh_url_to_repo)
+ - escaped_ssh_url_to_repo = CGI.escape(ssh_clone_url_to_repo(project))
%a.dropdown-item.open-with-link{ href: 'vscode://vscode.git/clone?url=' + escaped_ssh_url_to_repo }
.gl-dropdown-item-text-wrapper
= _('Visual Studio Code (SSH)')
- if http_enabled?
- - escaped_http_url_to_repo = CGI.escape(project.http_url_to_repo)
+ - escaped_http_url_to_repo = CGI.escape(http_clone_url_to_repo(project))
%a.dropdown-item.open-with-link{ href: 'vscode://vscode.git/clone?url=' + escaped_http_url_to_repo }
.gl-dropdown-item-text-wrapper
= _('Visual Studio Code (HTTPS)')
diff --git a/app/views/projects/commit/_pipelines_list.haml b/app/views/projects/commit/_pipelines_list.haml
index 16df743475d..f7ae462e8f9 100644
--- a/app/views/projects/commit/_pipelines_list.haml
+++ b/app/views/projects/commit/_pipelines_list.haml
@@ -3,7 +3,8 @@
#commit-pipeline-table-view{ data: { disable_initialization: disable_initialization,
endpoint: endpoint,
- "empty-state-svg-path" => image_path('illustrations/pipelines_empty.svg'),
+ full_path: @project.full_path,
+ "empty-state-svg-path" => image_path('illustrations/empty-state/empty-pipeline-md.svg'),
"error-state-svg-path" => image_path('illustrations/pipelines_failed.svg'),
"project-id": @project.id,
"artifacts-endpoint" => downloadable_artifacts_project_pipeline_path(@project, artifacts_endpoint_placeholder, format: :json),
diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml
index 88631f14e56..9cca928e794 100644
--- a/app/views/projects/commit/_signature_badge.html.haml
+++ b/app/views/projects/commit/_signature_badge.html.haml
@@ -29,5 +29,5 @@
= link_to(_('Learn about signing commits'), help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gl-link gl-display-block gl-mt-3')
-%a.signature-badge.gl-display-flex{ role: 'button', tabindex: 0, data: { toggle: 'popover', html: 'true', placement: 'top', title: title, content: content } }
+%a.signature-badge.gl-display-inline-block{ role: 'button', tabindex: 0, data: { toggle: 'popover', html: 'true', placement: 'top', title: title, content: content } }
= gl_badge_tag label, variant: variant
diff --git a/app/views/projects/commit/diff_files.html.haml b/app/views/projects/commit/diff_files.html.haml
index 0c52c1a15a4..7287d10a109 100644
--- a/app/views/projects/commit/diff_files.html.haml
+++ b/app/views/projects/commit/diff_files.html.haml
@@ -1 +1,5 @@
-= render partial: 'projects/diffs/file', collection: diffs.diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, diff_page_context: 'is-commit' }
+- diff_files = conditionally_paginate_diff_files(diffs, paginate: true, page: params[:page], per: Projects::CommitController::COMMIT_DIFFS_PER_PAGE)
+
+= render partial: 'projects/diffs/file', collection: diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, diff_page_context: 'is-commit' }
+
+= paginate(diff_files, theme: "gitlab", params: { action: :show })
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index feaac255d8c..0868475c49f 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -3,13 +3,11 @@
- add_to_breadcrumbs _('Commits'), project_commits_path(@project)
- breadcrumb_title @commit.short_id
- container_class = !fluid_layout && diff_view == :inline ? 'container-limited' : ''
-- limited_container_width = fluid_layout ? '' : 'limit-container-width'
-- @content_class = limited_container_width
- page_title "#{@commit.title} (#{@commit.short_id})", _('Commits')
- page_description @commit.description
- add_page_specific_style 'page_bundles/pipelines'
-.container-fluid{ class: [limited_container_width, container_class] }
+.container-fluid{ class: [container_class] }
= render "commit_box"
= render "ci_menu"
= render "projects/diffs/diffs",
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index b5481f19352..6209ef48f96 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -15,6 +15,7 @@
- ref = local_assigns.fetch(:ref) { merge_request&.source_branch }
- commit = commit.present(current_user: current_user)
- commit_status = commit.detailed_status_for(ref)
+- tags = commit.tags_for_display
- collapsible = local_assigns.fetch(:collapsible, true)
- link_data_attrs = local_assigns.fetch(:link_data_attrs, {})
- link = commit_path(project, commit, merge_request: merge_request)
@@ -55,6 +56,13 @@
= preserve(markdown_field(commit, :description))
.commit-actions.flex-row
+ - if tags.present?
+ = gl_badge_tag(variant: :neutral, icon: 'tag', class: 'gl-font-monospace') do
+ - if tags.size > 1
+ = link_to _('%{count} tags') % { count: tags.size } , project_commit_path(project, commit.id)
+ - else
+ = link_to tags.first, project_commits_path(project, tags.first, ref_type: 'tags'), class: 'gl-text-truncate gl-max-w-15'
+
- if request.xhr?
= render partial: 'projects/commit/signature', object: commit.signature
- else
diff --git a/app/views/projects/commits/_commit_list.html.haml b/app/views/projects/commits/_commit_list.html.haml
index 23b25b5dcbd..22f4594c1d5 100644
--- a/app/views/projects/commits/_commit_list.html.haml
+++ b/app/views/projects/commits/_commit_list.html.haml
@@ -3,9 +3,9 @@
- commits = Commit.decorate(commits, @project)
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5'}, body_options: { class: 'gl-py-0'}) do |c|
- - c.header do
+ - c.with_header do
Commits (#{@total_commit_count})
- - c.body do
+ - c.with_body do
- if hidden > 0
%ul.content-list
- commits.each do |commit|
diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml
index b79f17ae7b3..9cbabaee774 100644
--- a/app/views/projects/commits/_commits.html.haml
+++ b/app/views/projects/commits/_commits.html.haml
@@ -8,8 +8,9 @@
- hidden = @hidden_commit_count
- commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, daily_commits|
- %li.commit-header.js-commit-header{ data: { day: day } }
- %span.day= l(day, format: '%d %b, %Y')
+ %li.js-commit-header.gl-mt-7.gl-pb-2.gl-border-b{ data: { day: day } }
+ %span.day.font-weight-bold= l(day, format: '%d %b, %Y')
+ %span -
%span.commits-count= n_("%d commit", "%d commits", daily_commits.size) % daily_commits.size
%li.commits-row{ data: { day: day } }
@@ -20,7 +21,7 @@
= render partial: 'projects/commits/commit', collection: daily_commits, locals: { project: project, ref: ref, merge_request: merge_request }
- if context_commits.present?
- %li.commit-header.js-commit-header
+ %li.js-commit-header.gl-mt-7.gl-pb-2.gl-border-b
%span.font-weight-bold= n_("%d previously merged commit", "%d previously merged commits", context_commits.count) % context_commits.count
- if can_update_merge_request
= render Pajamas::ButtonComponent.new(button_options: { class: 'gl-ml-3 add-review-item-modal-trigger', data: { context_commits_empty: 'false' } }) do
@@ -37,7 +38,7 @@
%li
= render Pajamas::AlertComponent.new(variant: :warning,
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= n_('%s additional commit has been omitted to prevent performance issues.', '%s additional commits have been omitted to prevent performance issues.', hidden) % number_with_delimiter(hidden)
- if can_update_merge_request && context_commits&.empty? && !(defined?(@next_page) && @next_page)
diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml
index 689862eae8a..4c5a9acdf83 100644
--- a/app/views/projects/commits/show.html.haml
+++ b/app/views/projects/commits/show.html.haml
@@ -6,7 +6,7 @@
= auto_discovery_link_tag(:atom, project_commits_path(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits")
.js-project-commits-show{ 'data-commits-limit' => @limit }
- .tree-holder
+ .tree-holder.gl-mt-5
.nav-block
.tree-ref-container
.tree-ref-holder.gl-max-w-26
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index b3590eea631..58da76a3231 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -1,5 +1,5 @@
-- breadcrumb_title _("Compare Revisions")
-- page_title _("Compare")
+- breadcrumb_title _("Compare revisions")
+- page_title _("Compare revisions")
%h1.page-title.gl-font-size-h-display
= _("Compare Git revisions")
diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml
index 1bdf3d1e6e3..9185afc0771 100644
--- a/app/views/projects/compare/show.html.haml
+++ b/app/views/projects/compare/show.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs _("Compare Revisions"), project_compare_index_path(@project)
+- add_to_breadcrumbs _("Compare revisions"), project_compare_index_path(@project)
- page_title "#{params[:from]}...#{params[:to]}"
.sub-header-block.gl-border-b-0.gl-mb-0
@@ -18,7 +18,7 @@
paginate_diffs_per_page: Projects::CompareController::COMMIT_DIFFS_PER_PAGE
- else
= render Pajamas::CardComponent.new(card_options: { class: "gl-bg-gray-50 gl-mb-5 gl-border-none gl-text-center" }) do |c|
- - c.body do
+ - c.with_body do
%h4
= s_("CompareBranches|There isn't anything to compare.")
%p.gl-mb-4.gl-line-height-24
diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml
index ba79f0ee3cb..1e8b1255f0c 100644
--- a/app/views/projects/cycle_analytics/show.html.haml
+++ b/app/views/projects/cycle_analytics/show.html.haml
@@ -1,6 +1,5 @@
- page_title _("Value Stream Analytics")
- data_attributes = @request_params.valid? ? @request_params.to_data_attributes : {}
-- data_attributes.merge!(cycle_analytics_initial_data(@project, @group))
- add_page_specific_style 'page_bundles/cycle_analytics'
#js-cycle-analytics{ data: data_attributes }
diff --git a/app/views/projects/diffs/_content.html.haml b/app/views/projects/diffs/_content.html.haml
index 780bb3404cc..0a87ae145ac 100644
--- a/app/views/projects/diffs/_content.html.haml
+++ b/app/views/projects/diffs/_content.html.haml
@@ -1,7 +1,7 @@
- diff_file = local_assigns.fetch(:diff_file, nil)
- file_hash = hexdigest(diff_file.file_path)
-.diff-content
+.diff-content.gl-rounded-bottom-base
- if diff_file.has_renderable?
.hidden{ id: "#raw-diff-#{file_hash}", data: { file_hash: file_hash, diff_toggle_entity: 'rawViewer' } }
= render 'projects/diffs/viewer', viewer: diff_file.viewer
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 8ff6d348d95..982ecbbae51 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -2,22 +2,20 @@
- show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true)
- can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project)
- diff_page_context = local_assigns.fetch(:diff_page_context, nil)
-- load_diff_files_async = Feature.enabled?(:async_commit_diff_files, @project) && diff_page_context == "is-commit"
-- paginate_diffs = local_assigns.fetch(:paginate_diffs, false) && !load_diff_files_async
+- load_diff_files_async = diff_page_context == "is-commit"
+- paginate_diffs = local_assigns.fetch(:paginate_diffs, false)
- paginate_diffs_per_page = local_assigns.fetch(:paginate_diffs_per_page, nil)
- page = local_assigns.fetch(:page, nil)
- diff_files = conditionally_paginate_diff_files(diffs, paginate: paginate_diffs, page: page, per: paginate_diffs_per_page)
-.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed
+.js-diff-files-changed.gl-py-3
.files-changed-inner
- .inline-parallel-buttons.gl-display-none.gl-md-display-flex
+ .inline-parallel-buttons.gl-display-none.gl-md-display-flex.gl-relative
- if !diffs_expanded? && diff_files.any?(&:collapsed?)
= link_to _('Expand all'), url_for(safe_params.merge(expanded: 1, format: nil)), class: 'gl-button btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
= commit_diff_whitespace_link(diffs.project, @commit, class: 'd-none d-sm-inline-block')
- - elsif current_controller?('projects/merge_requests/diffs')
- = diff_merge_request_whitespace_link(diffs.project, @merge_request, class: 'd-none d-sm-inline-block')
- elsif current_controller?(:compare)
= diff_compare_whitespace_link(diffs.project, params[:from], params[:to], class: 'd-none d-sm-inline-block')
- elsif current_controller?(:wikis)
@@ -32,7 +30,7 @@
.files{ data: { can_create_note: can_create_note } }
- if load_diff_files_async
- - url = url_for(safe_params.merge(action: 'diff_files'))
+ - url = url_for(safe_params.merge(action: 'diff_files', page: page))
.js-diffs-batch{ data: { diff_files_path: url } }
= gl_loading_icon(size: "md", css_class: "gl-mt-4")
- else
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index e87005434e4..02a69f25985 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -1,12 +1,19 @@
- breadcrumb_title _("General Settings")
- page_title _("General")
- add_page_specific_style 'page_bundles/projects_edit'
-- @content_class = "limit-container-width" unless fluid_layout
- expanded = expanded_by_default?
- reduce_visibility_form_id = 'reduce-visibility-form'
+- @force_desktop_expanded_sidebar = true
= render_if_exists 'shared/ultimate_feature_removal_banner', project: @project
+- if Feature.enabled?(:show_pages_in_deployments_menu, current_user, type: :experiment)
+ = render Pajamas::AlertComponent.new(variant: :info,
+ title: _('GitLab Pages has moved'),
+ alert_options: { class: 'gl-my-5', data: { feature_id: Users::CalloutsHelper::PAGES_MOVED_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' } }) do |c|
+ - c.with_body do
+ = _('To go to GitLab Pages, on the left sidebar, select %{pages_link}.').html_safe % {pages_link: link_to('Deployments > Pages', project_pages_path(@project)).html_safe}
+
%section.settings.general-settings.no-animate.expanded#js-general-settings
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Naming, topics, avatar')
@@ -27,16 +34,15 @@
%input{ name: 'update_section', type: 'hidden', value: 'js-shared-permissions' }
%template.js-project-permissions-form-data{ type: "application/json" }= project_permissions_panel_data(@project).to_json.html_safe
.js-project-permissions-form{ data: visibility_confirm_modal_data(@project, reduce_visibility_form_id) }
-
- if show_merge_request_settings_callout?(@project)
%section.settings.expanded
= render Pajamas::AlertComponent.new(variant: :info,
title: _('Merge requests and approvals settings have moved.'),
alert_options: { class: 'js-merge-request-settings-callout gl-my-5', data: { feature_id: Users::CalloutsHelper::MERGE_REQUEST_SETTINGS_MOVED_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' } }) do |c|
- = c.body do
+ - c.with_body do
= _('On the left sidebar, select %{merge_requests_link} to view them.').html_safe % { merge_requests_link: link_to('Settings > Merge requests', project_settings_merge_requests_path(@project)).html_safe }
-= render_if_exists 'projects/settings/analytics_dashboards', expanded: expanded
+= render_if_exists 'projects/settings/analytics', expanded: expanded
%section.settings.no-animate{ class: ('expanded' if expanded), data: { qa_selector: 'badges_settings_content' } }
.settings-header
@@ -56,6 +62,8 @@
= render 'projects/service_desk_settings'
+= render_if_exists 'product_analytics/project_settings', expanded: expanded
+
%section.settings.advanced-settings.no-animate#js-project-advanced-settings{ class: ('expanded' if expanded), data: { qa_selector: 'advanced_settings_content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Advanced')
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index 43159a759f4..a51d1080d96 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -1,4 +1,3 @@
-- @content_class = "limit-container-width" unless fluid_layout
- default_branch_name = @project.default_branch_or_main
- escaped_default_branch_name = default_branch_name.shellescape
- @skip_current_level_breadcrumb = true
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index e4b8750b96c..7ddaf868a35 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -8,4 +8,5 @@
"help-page-path" => help_page_path("ci/environments/index.md"),
"project-path" => @project.full_path,
"project-id" => @project.id,
- "default-branch-name" => @project.default_branch_or_main } }
+ "default-branch-name" => @project.default_branch_or_main,
+ "kas-tunnel-url" => ::Gitlab::Kas.tunnel_url } }
diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml
index de7f976717b..11c36b5ea6d 100644
--- a/app/views/projects/environments/new.html.haml
+++ b/app/views/projects/environments/new.html.haml
@@ -1,5 +1,6 @@
-- breadcrumb_title _("Environments")
-- page_title _("New Environment")
+- add_to_breadcrumbs s_("Environments|Environments"), project_environments_path(@project)
+- breadcrumb_title s_("Environments|New")
+- page_title s_("Environments|New Environment")
- add_page_specific_style 'page_bundles/environments'
#js-new-environment{ data: { project_environments_path: project_environments_path(@project) } }
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 53b2af88511..e97cae911d9 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -20,7 +20,9 @@
%p
= html_escape(_("Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
.text-center
- = link_to _("Read more"), help_page_path("ci/environments/index.md"), class: "gl-button btn btn-confirm"
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: help_page_path("ci/environments/index.md")) do
+ = _('Read more')
+
- else
.table-holder.gl-overflow-visible
.ci-table.environments{ role: 'grid' }
diff --git a/app/views/projects/feature_flags/edit.html.haml b/app/views/projects/feature_flags/edit.html.haml
index 121dcd31a13..28a8f8729dd 100644
--- a/app/views/projects/feature_flags/edit.html.haml
+++ b/app/views/projects/feature_flags/edit.html.haml
@@ -1,7 +1,7 @@
- @gfm_form = true
-- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|Feature flags'), project_feature_flags_path(@project)
- breadcrumb_title @feature_flag.name
-- page_title s_('FeatureFlags|Edit Feature Flag'), @feature_flag.name
+- page_title s_('FeatureFlags|Edit Feature flag'), @feature_flag.name
#js-edit-feature-flag{ data: edit_feature_flag_data }
diff --git a/app/views/projects/feature_flags/index.html.haml b/app/views/projects/feature_flags/index.html.haml
index 53fe30422ca..e473a6f3cfd 100644
--- a/app/views/projects/feature_flags/index.html.haml
+++ b/app/views/projects/feature_flags/index.html.haml
@@ -1,4 +1,4 @@
-- page_title s_('FeatureFlags|Feature Flags')
+- page_title s_('FeatureFlags|Feature flags')
#feature-flags-vue{ data: { endpoint: project_feature_flags_path(@project, format: :json),
"project-id" => @project.id,
@@ -6,7 +6,7 @@
"error-state-svg-path" => image_path('illustrations/feature_flag.svg'),
"feature-flags-help-page-path" => help_page_path("operations/feature_flags"),
"feature-flags-client-libraries-help-page-path" => help_page_path("operations/feature_flags", anchor: "choose-a-client-library"),
- "feature-flags-client-example-help-page-path" => help_page_path("operations/feature_flags", anchor: "golang-application-example"),
+ "feature-flags-client-example-help-page-path" => help_page_path("operations/feature_flags", anchor: "go-application-example"),
"feature-flags-limit-exceeded" => @project.actual_limits.exceeded?(:project_feature_flags, @project.operations_feature_flags.count),
"feature-flags-limit" => @project.actual_limits.project_feature_flags,
"unleash-api-url" => (unleash_api_url(@project) if can?(current_user, :admin_feature_flag, @project)),
diff --git a/app/views/projects/feature_flags/new.html.haml b/app/views/projects/feature_flags/new.html.haml
index c91487ad198..3a32a249d1e 100644
--- a/app/views/projects/feature_flags/new.html.haml
+++ b/app/views/projects/feature_flags/new.html.haml
@@ -1,7 +1,7 @@
- @breadcrumb_link = new_project_feature_flag_path(@project)
-- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|Feature flags'), project_feature_flags_path(@project)
- breadcrumb_title s_('FeatureFlags|New')
-- page_title s_('FeatureFlags|New Feature Flag')
+- page_title s_('FeatureFlags|New feature flag')
#js-new-feature-flag{ data: { endpoint: project_feature_flags_path(@project, format: :json),
feature_flags_path: project_feature_flags_path(@project),
diff --git a/app/views/projects/feature_flags_user_lists/edit.html.haml b/app/views/projects/feature_flags_user_lists/edit.html.haml
index 1ff488ff0f0..417b6354ec0 100644
--- a/app/views/projects/feature_flags_user_lists/edit.html.haml
+++ b/app/views/projects/feature_flags_user_lists/edit.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|Feature flags'), project_feature_flags_path(@project)
- add_to_breadcrumbs s_('FeatureFlags|User Lists'), project_feature_flags_user_lists_path(@project)
- breadcrumb_title s_('FeatureFlags|Edit User List')
- page_title s_('FeatureFlags|Edit User List')
diff --git a/app/views/projects/feature_flags_user_lists/index.html.haml b/app/views/projects/feature_flags_user_lists/index.html.haml
index f0e3c36992a..c0e98b27d29 100644
--- a/app/views/projects/feature_flags_user_lists/index.html.haml
+++ b/app/views/projects/feature_flags_user_lists/index.html.haml
@@ -1,6 +1,6 @@
-- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|Feature flags'), project_feature_flags_path(@project)
- breadcrumb_title s_('FeatureFlags|User Lists')
-- page_title s_('FeatureFlags|Feature Flag User Lists')
+- page_title s_('FeatureFlags|Feature flag User Lists')
#js-user-lists{ data: { project_id: @project.id,
feature_flags_help_page_path: help_page_path("operations/feature_flags"),
diff --git a/app/views/projects/feature_flags_user_lists/new.html.haml b/app/views/projects/feature_flags_user_lists/new.html.haml
index f2e1ea38d9c..cea55c0ca2a 100644
--- a/app/views/projects/feature_flags_user_lists/new.html.haml
+++ b/app/views/projects/feature_flags_user_lists/new.html.haml
@@ -1,5 +1,5 @@
- @breadcrumb_link = new_project_feature_flags_user_list_path(@project)
-- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|Feature flags'), project_feature_flags_path(@project)
- add_to_breadcrumbs s_('FeatureFlags|User Lists'), project_feature_flags_user_lists_path(@project)
- breadcrumb_title s_('FeatureFlags|New User List')
- page_title s_('FeatureFlags|New User List')
diff --git a/app/views/projects/feature_flags_user_lists/show.html.haml b/app/views/projects/feature_flags_user_lists/show.html.haml
index 2c88f3da66b..5c4e93e7707 100644
--- a/app/views/projects/feature_flags_user_lists/show.html.haml
+++ b/app/views/projects/feature_flags_user_lists/show.html.haml
@@ -1,7 +1,7 @@
-- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|Feature flags'), project_feature_flags_path(@project)
- add_to_breadcrumbs s_('FeatureFlags|User Lists'), project_feature_flags_user_lists_path(@project)
- breadcrumb_title s_('FeatureFlags|List details')
-- page_title s_('FeatureFlags|Feature Flag User List Details')
+- page_title s_('FeatureFlags|Feature flag user list details')
#js-edit-user-list{ data: { project_id: @project.id,
user_list_iid: @user_list.iid,
diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml
index 1d4e907dd61..afb49c48146 100644
--- a/app/views/projects/find_file/show.html.haml
+++ b/app/views/projects/find_file/show.html.haml
@@ -17,8 +17,8 @@
%table.table.files-slider{ class: "table_#{@hex_path} tree-table" }
%tbody
.col-12.empty-state.hidden
- .svg-250.svg-content
- = image_tag('illustrations/profile-page/personal-projects.svg', alt: 'No files svg', lazy: true)
+ .svg-150.svg-content
+ = image_tag('illustrations/empty-state/empty-search-md.svg', alt: 'No files svg', lazy: true)
.text-center
%h4
= _('There are no matching files')
diff --git a/app/views/projects/forks/error.html.haml b/app/views/projects/forks/error.html.haml
index 022a96b15a7..cff5899b960 100644
--- a/app/views/projects/forks/error.html.haml
+++ b/app/views/projects/forks/error.html.haml
@@ -4,7 +4,7 @@
variant: :danger,
alert_options: { class: 'gl-mt-5' },
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
%p
= _("You tried to fork %{link_to_the_project} but it failed for the following reason:").html_safe % { link_to_the_project: link_to_project(@project) }
@@ -17,5 +17,5 @@
- else
= error
- = c.actions do
+ - c.with_actions do
= link_to _('Try to fork again'), new_project_fork_path(@project), title: _("Fork"), class: "btn gl-alert-action btn-info btn-md gl-button"
diff --git a/app/views/projects/google_cloud/configuration/index.html.haml b/app/views/projects/google_cloud/configuration/index.html.haml
index dab49d5032a..07aaf9b2513 100644
--- a/app/views/projects/google_cloud/configuration/index.html.haml
+++ b/app/views/projects/google_cloud/configuration/index.html.haml
@@ -2,6 +2,4 @@
- breadcrumb_title s_('CloudSeed|Configuration')
- page_title s_('CloudSeed|Configuration')
-- @content_class = "limit-container-width" unless fluid_layout
-
#js-google-cloud-configuration{ data: @js_data }
diff --git a/app/views/projects/google_cloud/databases/cloudsql_form.html.haml b/app/views/projects/google_cloud/databases/cloudsql_form.html.haml
index 05838717b49..ea0a53010ef 100644
--- a/app/views/projects/google_cloud/databases/cloudsql_form.html.haml
+++ b/app/views/projects/google_cloud/databases/cloudsql_form.html.haml
@@ -3,7 +3,5 @@
- breadcrumb_title @title
- page_title @title
-- @content_class = "limit-container-width" unless fluid_layout
-
= form_tag project_google_cloud_databases_path(@project), method: 'post' do
#js-google-cloud-databases-cloudsql-form{ data: @js_data }
diff --git a/app/views/projects/google_cloud/databases/index.html.haml b/app/views/projects/google_cloud/databases/index.html.haml
index 0528ac3d1f5..0d54c1618e4 100644
--- a/app/views/projects/google_cloud/databases/index.html.haml
+++ b/app/views/projects/google_cloud/databases/index.html.haml
@@ -2,6 +2,4 @@
- breadcrumb_title s_('CloudSeed|Databases')
- page_title s_('CloudSeed|Databases')
-- @content_class = "limit-container-width" unless fluid_layout
-
#js-google-cloud-databases{ data: @js_data }
diff --git a/app/views/projects/google_cloud/deployments/index.html.haml b/app/views/projects/google_cloud/deployments/index.html.haml
index 22a365671bc..96f73fc3dd1 100644
--- a/app/views/projects/google_cloud/deployments/index.html.haml
+++ b/app/views/projects/google_cloud/deployments/index.html.haml
@@ -2,6 +2,4 @@
- breadcrumb_title s_('CloudSeed|Deployments')
- page_title s_('CloudSeed|Deployments')
-- @content_class = "limit-container-width" unless fluid_layout
-
#js-google-cloud-deployments{ data: @js_data }
diff --git a/app/views/projects/google_cloud/gcp_regions/index.html.haml b/app/views/projects/google_cloud/gcp_regions/index.html.haml
index 4cc218ff548..378ec592a74 100644
--- a/app/views/projects/google_cloud/gcp_regions/index.html.haml
+++ b/app/views/projects/google_cloud/gcp_regions/index.html.haml
@@ -2,7 +2,5 @@
- breadcrumb_title s_('CloudSeed|Regions')
- page_title s_('CloudSeed|Regions')
-- @content_class = "limit-container-width" unless fluid_layout
-
= form_tag project_google_cloud_gcp_regions_path(@project), method: 'post' do
#js-google-cloud-gcp-regions{ data: @js_data }
diff --git a/app/views/projects/google_cloud/service_accounts/index.html.haml b/app/views/projects/google_cloud/service_accounts/index.html.haml
index 8f70818abd9..0e114350193 100644
--- a/app/views/projects/google_cloud/service_accounts/index.html.haml
+++ b/app/views/projects/google_cloud/service_accounts/index.html.haml
@@ -2,7 +2,5 @@
- breadcrumb_title s_('CloudSeed|Service Account')
- page_title s_('CloudSeed|Service Account')
-- @content_class = "limit-container-width" unless fluid_layout
-
= form_tag project_google_cloud_service_accounts_path(@project), method: 'post' do
#js-google-cloud-service-accounts{ data: @js_data }
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index 754de2db8f3..9d6f67bd190 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -1,4 +1,4 @@
-- page_title _('Contributors')
+- page_title _('Contributor statistics')
- graph_path = project_graph_path(@project, current_ref, ref_type: @ref_type, format: :json)
- commits_path = project_commits_path(@project, current_ref, ref_type: @ref_type)
diff --git a/app/views/projects/harbor/repositories/index.html.haml b/app/views/projects/harbor/repositories/index.html.haml
index e6f0e3e950c..b6f6fb64451 100644
--- a/app/views/projects/harbor/repositories/index.html.haml
+++ b/app/views/projects/harbor/repositories/index.html.haml
@@ -1,5 +1,4 @@
- page_title _("Harbor Registry")
-- @content_class = "limit-container-width" unless fluid_layout
#js-harbor-registry-list-project{ data: { endpoint: project_harbor_repositories_path(@project),
"no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
diff --git a/app/views/projects/hook_logs/show.html.haml b/app/views/projects/hook_logs/show.html.haml
index d610ef21400..0f4dc4b5e32 100644
--- a/app/views/projects/hook_logs/show.html.haml
+++ b/app/views/projects/hook_logs/show.html.haml
@@ -1,4 +1,3 @@
-- @content_class = 'limit-container-width' unless fluid_layout
- add_to_breadcrumbs _('Webhook Settings'), namespace_project_hooks_path
- page_title _('Webhook Logs')
diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml
index 3e63faaf448..b553249c4b8 100644
--- a/app/views/projects/hooks/edit.html.haml
+++ b/app/views/projects/hooks/edit.html.haml
@@ -1,4 +1,3 @@
-- @content_class = 'limit-container-width' unless fluid_layout
- add_to_breadcrumbs _('Webhook Settings'), project_hooks_path(@project)
- page_title _('Webhook')
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index 15cb7869dc5..4d71161c96e 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -1,6 +1,6 @@
-- @content_class = 'limit-container-width' unless fluid_layout
- breadcrumb_title _('Webhook Settings')
- page_title _('Webhooks')
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4
diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml
index efb364bd013..af337082141 100644
--- a/app/views/projects/imports/new.html.haml
+++ b/app/views/projects/imports/new.html.haml
@@ -9,7 +9,7 @@
dismissible: false,
variant: :danger,
alert_options: { class: 'gl-mb-5' }) do |c|
- = c.body do
+ - c.with_body do
= @project.import_state.last_error
= gitlab_ui_form_for @project, url: project_import_path(@project), method: :post, html: { class: 'js-project-import' } do |f|
diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml
index 9fe541c5912..7f509aee07c 100644
--- a/app/views/projects/imports/show.html.haml
+++ b/app/views/projects/imports/show.html.haml
@@ -1,5 +1,4 @@
- page_title import_in_progress_title
-- @content_class = "limit-container-width" unless fluid_layout
.save-project-loader
.center
diff --git a/app/views/projects/issues/_design_management.html.haml b/app/views/projects/issues/_design_management.html.haml
index c5ce0549816..de8725df871 100644
--- a/app/views/projects/issues/_design_management.html.haml
+++ b/app/views/projects/issues/_design_management.html.haml
@@ -1,4 +1,4 @@
-- return if @issue.incident?
+- return if @issue.work_item_type&.incident?
- requirements_link_url = help_page_path('user/project/issues/design_management', anchor: 'requirements')
- requirements_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: requirements_link_url }
@@ -12,7 +12,8 @@
issue_iid: @issue.iid,
issue_path: project_issue_path(@project, @issue),
register_path: new_user_registration_path(redirect_to_referer: 'yes'),
- sign_in_path: new_session_path(:user, redirect_to_referer: 'yes') } }
+ sign_in_path: new_session_path(:user, redirect_to_referer: 'yes'),
+ new_comment_template_path: profile_comment_templates_path } }
- else
.gl-border-solid.gl-border-1.gl-border-gray-100.gl-rounded-base.gl-mt-5.gl-p-3.gl-text-center
= enable_lfs_message
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index c86f9c79912..c6e5102889a 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -12,4 +12,5 @@
show_timeline_view_toggle: show_timeline_view_toggle?(@issue).to_s,
current_user_data: UserSerializer.new.represent(current_user, {only_path: true}, CurrentUserEntity).to_json,
can_add_timeline_events: "#{can?(current_user, :admin_incident_management_timeline_event, @issue)}",
- report_abuse_path: add_category_abuse_reports_path } }
+ report_abuse_path: add_category_abuse_reports_path,
+ new_comment_template_path: profile_comment_templates_path } }
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 18975bc3db6..fc6ef2ea153 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -50,10 +50,10 @@
%ul.controls
- if issue.closed? && issue.moved?
%li.issuable-status
- = _('CLOSED (MOVED)')
+ = render Pajamas::BadgeComponent.new(_('Closed (moved)'), size: 'sm', variant: 'info')
- elsif issue.closed?
%li.issuable-status
- = _('CLOSED')
+ = render Pajamas::BadgeComponent.new(_('Closed'), size: 'sm', variant: 'info')
- if issue.assignees.any?
%li.gl-display-flex
= render 'shared/issuable/assignees', project: @project, issuable: issue
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index f9798d25b06..90d99d51d29 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -11,18 +11,18 @@
.create-mr-dropdown-wrap.d-inline-block.full-width-mobile.js-create-mr{ data: { project_path: @project.full_path, project_id: @project.id, can_create_path: can_create_path, create_mr_path: create_mr_path(from: @issue.to_branch_name, source_project: @project, to: @project.default_branch, mr_params: { issue_iid: @issue.iid }), create_branch_path: create_branch_path, refs_path: refs_path, is_confidential: can_create_confidential_merge_request?.to_s } }
.btn-group.unavailable
- %button.gl-button.btn{ type: 'button', disabled: 'disabled' }
+ = render Pajamas::ButtonComponent.new(button_options: { disabled: 'disabled' }) do
= gl_loading_icon(inline: true, css_class: 'js-create-mr-spinner gl-button-icon gl-display-none')
%span.text
- Checking branch availability…
+ = _('Checking branch availability…')
+
.btn-group.available.hidden
- %button.gl-button.btn.js-create-merge-request.btn-confirm{ type: 'button', data: { action: data_action } }
- = gl_loading_icon(css_class: 'js-create-mr-spinner js-spinner gl-mr-2 gl-display-none')
+ = render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { class: 'js-create-merge-request', data: { action: data_action } }) do
+ = gl_loading_icon(inline: true , css_class: 'js-create-mr-spinner js-spinner gl-display-none')
= value
- %button.gl-button.btn.btn-confirm.btn-icon.dropdown-toggle.create-merge-request-dropdown-toggle.js-dropdown-toggle{ type: 'button', data: { dropdown: { trigger: '#create-merge-request-dropdown' }, display: 'static' } }
- = sprite_icon('chevron-down')
+ = render Pajamas::ButtonComponent.new(variant: :confirm, icon: 'chevron-down', button_options: { class: 'js-dropdown-toggle dropdown-toggle create-merge-request-dropdown-toggle', data: { 'dropdown-trigger': '#create-merge-request-dropdown', display: 'static' } })
.droplab-dropdown
%ul#create-merge-request-dropdown.create-merge-request-dropdown-menu.dropdown-menu.dropdown-menu-right.gl-show-field-errors{ class: ("create-confidential-merge-request-dropdown-menu" if can_create_confidential_merge_request?), data: { dropdown: true } }
@@ -57,7 +57,7 @@
%span.js-ref-message.form-text
.form-group
- %button.btn.gl-button.btn-confirm.js-create-target{ type: 'button', data: { action: 'create-mr' } }
+ = render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { class: 'js-create-target', data: { action: 'create-mr' } }) do
= create_mr_text
- if can_create_confidential_merge_request?
diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml
index 466eca2fdb0..3d6a266dc4d 100644
--- a/app/views/projects/issues/_related_branches.html.haml
+++ b/app/views/projects/issues/_related_branches.html.haml
@@ -1,12 +1,24 @@
- if @related_branches.any?
- %h2.gl-font-lg
- = pluralize(@related_branches.size, 'Related Branch')
- %ul.related-merge-requests.gl-pl-0.gl-mb-3
- - @related_branches.each do |branch|
- %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]
- %span.related-branch-info
- %strong
- = link_to branch[:name], branch[:link], class: "ref-name"
+ - if @related_branches.any?
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-bg-gray-10 gl-mt-5 gl-mb-0' }, header_options: { class: 'gl-bg-white gl-pl-5 gl-pr-4 gl-py-4' } , body_options: { class: 'gl-py-3 gl-px-4' }) do |c|
+ - c.with_header do
+ %h3.card-title.h5.gl-my-0.gl-display-flex.gl-align-items-center.gl-flex-grow-1.gl-relative.gl-line-height-24
+ = link_to "", "#related-branches", class: "gl-link anchor position-absolute gl-text-decoration-none", "aria-hidden": true
+ = _('Related branches')
+ .gl-display-inline-flex.gl-mx-3.gl-text-gray-500
+ .gl-display-inline-flex.gl-align-items-center
+ = sprite_icon('branch', css_class: "gl-mr-2 gl-text-gray-500 gl-icon")
+ = @related_branches.size
+ - c.with_body do
+ %ul.related-merge-requests.content-list.gl-p-3!
+ - @related_branches.each do |branch|
+ %li.list-item{ class: "gl-py-0! gl-border-0!" }
+ .item-body.gl-display-flex.align-items-center.gl-px-3.gl-pr-2.gl-mx-n2
+ .item-contents.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-flex-grow-1.gl-min-h-7
+ .item-title.gl-display-flex.mb-xl-0.gl-min-w-0
+ - if branch[:pipeline_status].present?
+ %span.related-branch-ci-status
+ = render 'ci/status/icon', status: branch[:pipeline_status]
+ %span.related-branch-info
+ %strong
+ = link_to branch[:name], branch[:link], class: "ref-name"
diff --git a/app/views/projects/issues/_related_issues.html.haml b/app/views/projects/issues/_related_issues.html.haml
index 80f2b8b189c..2409c61fbf2 100644
--- a/app/views/projects/issues/_related_issues.html.haml
+++ b/app/views/projects/issues/_related_issues.html.haml
@@ -5,4 +5,5 @@
has_issue_weights_feature: @project.licensed_feature_available?(:issue_weights).to_s,
help_path: help_page_path('user/project/issues/related_issues'),
show_categorized_issues: @project.licensed_feature_available?(:blocked_issues).to_s,
- has_iterations_feature: @project.licensed_feature_available?(:iterations).to_s } }
+ has_iterations_feature: @project.licensed_feature_available?(:iterations).to_s,
+ report_abuse_path: add_category_abuse_reports_path } }
diff --git a/app/views/projects/issues/_work_item_links.html.haml b/app/views/projects/issues/_work_item_links.html.haml
index 3deceacec8d..981021c97e6 100644
--- a/app/views/projects/issues/_work_item_links.html.haml
+++ b/app/views/projects/issues/_work_item_links.html.haml
@@ -1,5 +1,5 @@
-.js-work-item-links-root{ data: { issuable_id: @issue.id, iid: @issue.iid,
- project_path: @project.full_path,
+.js-work-item-links-root{ data: { issuable_id: @issue.id,
+ full_path: @project.full_path,
wi: work_items_index_data(@project),
register_path: new_user_registration_path(redirect_to_referer: 'yes'),
sign_in_path: new_session_path(:user, redirect_to_referer: 'yes') } }
diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml
index 617579cdd6f..d344ae6a4e6 100644
--- a/app/views/projects/issues/new.html.haml
+++ b/app/views/projects/issues/new.html.haml
@@ -2,7 +2,7 @@
- breadcrumb_title _("New")
- page_title _("New Issue")
-.top-area.gl-lg-flex-direction-row.gl-border-bottom-0
+.page-title-holder
%h1.page-title.gl-font-size-h-display= _("New Issue")
= render "form"
diff --git a/app/views/projects/issues/service_desk/_alert_moved_from_service_desk.html.haml b/app/views/projects/issues/service_desk/_alert_moved_from_service_desk.html.haml
index cc8d5bdaeec..b087a1d0151 100644
--- a/app/views/projects/issues/service_desk/_alert_moved_from_service_desk.html.haml
+++ b/app/views/projects/issues/service_desk/_alert_moved_from_service_desk.html.haml
@@ -4,5 +4,5 @@
= render Pajamas::AlertComponent.new(variant: :warning,
alert_options: { class: 'hide js-alert-moved-from-service-desk-warning gl-mt-5' }) do |c|
- = c.body do
+ - c.with_body do
= s_('This project does not have %{service_desk_link_start}Service Desk%{service_desk_link_end} enabled, so the user who created the issue will no longer receive email notifications about new activity.').html_safe % { service_desk_link_start: service_desk_link_start, service_desk_link_end: '</a>'.html_safe }
diff --git a/app/views/projects/issues/service_desk/_nav_btns.html.haml b/app/views/projects/issues/service_desk/_nav_btns.html.haml
index 8d16c3d978f..a0a290f340a 100644
--- a/app/views/projects/issues/service_desk/_nav_btns.html.haml
+++ b/app/views/projects/issues/service_desk/_nav_btns.html.haml
@@ -1,20 +1,34 @@
- show_feed_buttons = local_assigns.fetch(:show_feed_buttons, true)
- show_import_button = local_assigns.fetch(:show_import_button, true) && can?(current_user, :import_issues, @project)
- show_export_button = local_assigns.fetch(:show_export_button, true)
-- issuable_type = 'issues'
+- issuable_type = 'issue'
- 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.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), 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"
+ = button_tag _("Bulk edit"), class: "gl-button btn btn-default gl-mr-3 js-bulk-update-toggle"
- if show_new_issue_link?(@project)
= link_to _("New issue"), new_project_issue_path(@project,
issue: { milestone_id: finder.milestones.first.try(:id) }),
- class: "gl-button btn btn-confirm",
+ class: "gl-button btn btn-confirm gl-mr-3",
id: "new_issue_link"
+
+.dropdown.gl-dropdown
+ = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret has-tooltip gl-display-none! gl-md-display-inline-flex!", data: { toggle: 'dropdown', title: _('Actions') } do
+ = sprite_icon "ellipsis_v", size: 16, css_class: "dropdown-icon gl-icon"
+ %span.gl-sr-only
+ = _('Actions')
+ = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md btn-block gl-button gl-dropdown-toggle gl-md-display-none!", data: { 'toggle' => 'dropdown' } do
+ %span.gl-dropdown-button-text= _('Actions')
+ = sprite_icon "chevron-down", size: 16, css_class: "dropdown-icon gl-icon"
+ .dropdown-menu.dropdown-menu-right
+ .gl-dropdown-inner
+ .gl-dropdown-contents
+ %ul
+ .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, 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) } }
+ %li.gl-dropdown-divider
+ %hr.dropdown-divider
+ %li.gl-dropdown-item
+ - if show_feed_buttons
+ = render 'shared/issuable/feed_buttons'
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index a8edf87b696..7e8bf4ae57f 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -8,4 +8,3 @@
- add_page_specific_style 'page_bundles/work_items'
= render 'projects/issuable/show', issuable: @issue, api_awards_path: award_emoji_issue_api_path(@issue)
-= render 'projects/invite_members_modal', project: @project
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index f95689c0b1d..ce7006001c7 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -9,18 +9,20 @@
#js-promote-label-modal
= render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label
- .labels-container.gl-mt-5
- - if can_admin_label && search.blank?
- %p.text-muted
- = _('Labels can be applied to issues and merge requests. Star a label to make it a priority label.')
+ - if can_admin_label && search.blank?
+ %p.text-muted.gl-mt-5
+ = _('Labels can be applied to issues and merge requests. Star a label to make it a priority label.')
+ .labels-container
-# Only show it in the first page
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
- .prioritized-labels.gl-mb-7{ class: [('hide' if hide), ('is-not-draggable' unless can_admin_label)] }
- %h4.gl-mt-3= _('Prioritized Labels')
- %p.text-muted
- = _('Drag to reorder prioritized labels and change their relative priority.')
- .manage-labels-list.js-prioritized-labels{ data: { url: set_priorities_project_labels_path(@project), sortable: can_admin_label } }
+ .prioritized-labels.gl-rounded-base.gl-border.gl-bg-gray-10.gl-mt-4{ class: [('hide' if hide), ('is-not-draggable' unless can_admin_label)] }
+ .gl-px-5.gl-py-4.gl-bg-white.gl-rounded-base.gl-border-b{ class: 'gl-rounded-bottom-left-none! gl-rounded-bottom-right-none!' }
+ %h3.card-title.h5.gl-m-0.gl-relative.gl-line-height-24
+ = _('Prioritized labels')
+ .gl-font-sm.gl-font-weight-semibold.gl-text-gray-500
+ = _('Drag to reorder prioritized labels and change their relative priority.')
+ .js-prioritized-labels.gl-px-3.gl-rounded-base.manage-labels-list{ data: { url: set_priorities_project_labels_path(@project), sortable: can_admin_label } }
#js-priority-labels-empty-state.priority-labels-empty-state{ class: "#{'hidden' unless @prioritized_labels.empty? && search.blank?}" }
= render 'shared/empty_states/priority_labels'
- if @prioritized_labels.any?
@@ -30,16 +32,18 @@
= _('No prioritized labels with such name or description')
- if @labels.any?
- .other-labels
- %h4{ class: ('hide' if hide) }= _('Other Labels')
- .manage-labels-list.js-other-labels
+ .other-labels.gl-rounded-base.gl-border.gl-bg-gray-10.gl-mt-4
+ .gl-px-5.gl-py-4.gl-bg-white.gl-rounded-base.gl-border-b{ class: 'gl-rounded-bottom-left-none! gl-rounded-bottom-right-none!' }
+ %h3.card-title.h5.gl-m-0.gl-relative.gl-line-height-24{ class: ('hide' if hide) }= _('Other labels')
+ .js-other-labels.gl-px-3.gl-rounded-base.manage-labels-list
= render partial: 'shared/label', collection: @labels, as: :label, locals: { subject: @project }
= paginate @labels, theme: 'gitlab'
+
- elsif search.present?
.other-labels
- if @available_labels.any?
%h4
- = _('Other Labels')
+ = _('Other labels')
.nothing-here-block
= _('No other labels with such name or description')
- else
@@ -53,5 +57,5 @@
= render 'shared/empty_states/labels'
%template#js-badge-item-template
- %li.js-priority-badge.inline.gl-ml-3
- .label-badge.gl-bg-blue-50= _('Prioritized label')
+ %li.js-priority-badge.inline.gl-mr-3
+ .label-badge.gl-bg-blue-50= _('Prioritized')
diff --git a/app/views/projects/mattermosts/_team_selection.html.haml b/app/views/projects/mattermosts/_team_selection.html.haml
index 98221125443..397f96d6846 100644
--- a/app/views/projects/mattermosts/_team_selection.html.haml
+++ b/app/views/projects/mattermosts/_team_selection.html.haml
@@ -2,7 +2,7 @@
This service will be installed on the Mattermost instance at
%strong= link_to Gitlab.config.mattermost.host, Gitlab.config.mattermost.host
%hr
-= form_for(:mattermost, method: :post, url: project_mattermost_path(@project), html: { class: 'js-requires-input' }) do |f|
+= gitlab_ui_form_for(:mattermost, method: :post, url: project_mattermost_path(@project), html: { class: 'js-requires-input' }) do |f|
%h4 Team
%p
= @teams.one? ? 'The team' : 'Select the team'
@@ -42,5 +42,6 @@
%hr
.clearfix
.float-right
- = link_to _('Cancel'), edit_project_settings_integration_path(@project, @integration), class: 'gl-button btn btn-lg'
- = f.submit 'Install', class: 'gl-button btn btn-confirm btn-lg'
+ = render Pajamas::ButtonComponent.new(href: edit_project_settings_integration_path(@project, @integration)) do
+ = _('Cancel')
+ = f.submit s_('MattermostService|Install'), pajamas_button: true
diff --git a/app/views/projects/mattermosts/new.html.haml b/app/views/projects/mattermosts/new.html.haml
index 8254198bd41..c73c256c1c3 100644
--- a/app/views/projects/mattermosts/new.html.haml
+++ b/app/views/projects/mattermosts/new.html.haml
@@ -2,11 +2,10 @@
- add_to_breadcrumbs @integration.title, scoped_edit_integration_path(@integration, project: @project, group: @group)
- breadcrumb_title _('New')
- page_title @integration.title, _('Integrations')
-- @content_class = 'limit-container-width' unless fluid_layout
- if @teams_error_message
= render Pajamas::AlertComponent.new(variant: :danger) do |c|
- = c.body do
+ - c.with_body do
= @teams_error_message
%h3
diff --git a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
index 92b0a5a0b90..9bfa0e7a309 100644
--- a/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
+++ b/app/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml
@@ -1,7 +1,8 @@
- display_issuable_type = issuable_display_type(@merge_request)
.btn-group.gl-md-ml-3.gl-display-flex.dropdown.gl-dropdown.gl-md-w-auto.gl-w-full
- = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret has-tooltip gl-display-none! gl-md-display-inline-flex!", data: { toggle: 'dropdown', title: _('Merge request actions'), testid: 'merge-request-actions', 'aria-label': _('Merge request actions') } do
+ %span.js-sidebar-header-popover
+ = button_tag type: 'button', id: "new-actions-header-dropdown", class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret gl-display-none! gl-md-display-inline-flex!", title: _('Merge request actions'), 'aria-label': _('Merge request actions'), data: { toggle: 'dropdown', testid: 'merge-request-actions' } do
= sprite_icon "ellipsis_v", size: 16, css_class: "dropdown-icon gl-icon"
= button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md btn-block gl-button gl-dropdown-toggle gl-md-display-none!", data: { 'toggle' => 'dropdown' } do
%span.gl-dropdown-button-text= _('Merge request actions')
diff --git a/app/views/projects/merge_requests/_code_dropdown.html.haml b/app/views/projects/merge_requests/_code_dropdown.html.haml
index 2ef89a7bf04..4cab6fac388 100644
--- a/app/views/projects/merge_requests/_code_dropdown.html.haml
+++ b/app/views/projects/merge_requests/_code_dropdown.html.haml
@@ -32,7 +32,7 @@
%li.gl-dropdown-item
= link_to merge_request_path(@merge_request, format: :patch), class: 'dropdown-item', download: '', data: { qa_selector: 'download_email_patches_menu_item' } do
.gl-dropdown-item-text-wrapper
- = _('Email patches')
+ = _('Patches')
%li.gl-dropdown-item
= link_to merge_request_path(@merge_request, format: :diff), class: 'dropdown-item', download: '', data: { qa_selector: 'download_plain_diff_menu_item' } do
.gl-dropdown-item-text-wrapper
diff --git a/app/views/projects/merge_requests/_description.html.haml b/app/views/projects/merge_requests/_description.html.haml
index 1dd4cc6495c..5590f9e6184 100644
--- a/app/views/projects/merge_requests/_description.html.haml
+++ b/app/views/projects/merge_requests/_description.html.haml
@@ -1,6 +1,6 @@
%div
- if @merge_request.description.present?
- .description{ class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : '' , data: { qa_selector: 'description_content' } }
+ .description{ class: ['gl-mt-4!', can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''], data: { qa_selector: 'description_content' } }
.md
= markdown_field(@merge_request, :description)
%textarea.hidden.js-task-list-field{ data: { value: @merge_request.description } }
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index b96d869e9d7..9142893d400 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -4,7 +4,7 @@
= render Pajamas::CheckboxTagComponent.new(name: dom_id(merge_request, "selected"),
value: nil,
checkbox_options: { 'data-id' => merge_request.id }) do |c|
- = c.label do
+ - c.with_label do
%span.gl-sr-only
= merge_request.title
@@ -15,43 +15,42 @@
= hidden_merge_request_icon(merge_request)
= link_to merge_request.title, merge_request_path(merge_request), class: 'js-prefetch-document'
- if merge_request.tasks?
- %span.task-status.d-none.d-sm-inline-block
+ %span.task-status.d-none.d-sm-inline-block.gl-font-sm
&nbsp;
= merge_request.task_status
.issuable-info
%span.issuable-reference
#{issuable_reference(merge_request)}
- %span.issuable-authored.d-none.d-sm-inline-block
+ %span.issuable-authored.d-none.d-sm-inline-block.gl-text-gray-500!
&middot;
- #{s_('IssueList|created %{timeAgoString} by %{user}').html_safe % { timeAgoString: time_ago_with_tooltip(merge_request.created_at, placement: 'bottom'), user: link_to_member(@project, merge_request.author, avatar: false) }}
+ #{s_('IssueList|created %{timeAgoString} by %{user}').html_safe % { timeAgoString: time_ago_with_tooltip(merge_request.created_at, placement: 'bottom'), user: link_to_member(@project, merge_request.author, avatar: false, extra_class: 'gl-text-gray-500!') }}
= render_if_exists 'shared/issuable/gitlab_team_member_badge', author: merge_request.author
- if merge_request.milestone
- %span.issuable-milestone.d-none.d-sm-inline-block
+ %span.issuable-milestone.d-none.d-sm-inline-block.gl-text-truncate.gl-max-w-26.gl-vertical-align-bottom
&nbsp;
- = link_to project_merge_requests_path(merge_request.project, milestone_title: merge_request.milestone.title), data: { html: 'true', toggle: 'tooltip', title: milestone_tooltip_due_date(merge_request.milestone) } do
- = sprite_icon('clock', css_class: 'gl-vertical-align-text-bottom')
+ = link_to project_merge_requests_path(merge_request.project, milestone_title: merge_request.milestone.title), class: 'gl-text-gray-500!', data: { html: 'true', toggle: 'tooltip', title: milestone_tooltip_due_date(merge_request.milestone) } do
+ = sprite_icon('clock', size: 12, css_class: 'gl-vertical-align-text-bottom')
= merge_request.milestone.title
- if merge_request.target_project.default_branch != merge_request.target_branch
- %span.project-ref-path.has-tooltip{ title: _('Target branch') }
+ %span.project-ref-path.has-tooltip.d-inline-block.gl-text-truncate.gl-max-w-26.gl-vertical-align-bottom{ title: _('Target branch: %{target_branch}') % {target_branch: merge_request.target_branch} }
&nbsp;
- = link_to project_ref_path(merge_request.project, merge_request.target_branch), class: 'ref-name' do
+ = link_to project_ref_path(merge_request.project, merge_request.target_branch), class: 'ref-name gl-text-gray-500!' do
= sprite_icon('branch', size: 12, css_class: 'fork-sprite')
= merge_request.target_branch
- if merge_request.labels.any?
- &nbsp;
- - presented_labels_sorted_by_title(merge_request.labels, merge_request.project).each do |label|
- = link_to_label(label, type: :merge_request, small: true)
+ .gl-mt-1{ role: 'group', 'aria-label': _('Labels') }
+ - presented_labels_sorted_by_title(merge_request.labels, merge_request.project).each do |label|
+ = link_to_label(label, type: :merge_request, small: true)
.issuable-meta
%ul.controls.d-flex.align-items-end
- if merge_request.merged?
- %li.issuable-status.d-none.d-sm-inline-block
- = _('MERGED')
+ %li.d-none.d-sm-flex
+ = render Pajamas::BadgeComponent.new(_('Merged'), size: 'sm', variant: 'info')
- elsif merge_request.closed?
- %li.issuable-status.d-none.d-sm-inline-block
- = sprite_icon('cancel', css_class: 'gl-vertical-align-text-bottom')
- = _('CLOSED')
+ %li.d-none.d-sm-flex
+ = render Pajamas::BadgeComponent.new(_('Closed'), size: 'sm', variant: 'danger')
= render 'shared/merge_request_pipeline_status', merge_request: merge_request
- if merge_request.open? && merge_request.broken?
%li.issuable-pipeline-broken.d-none.d-sm-flex
@@ -67,6 +66,7 @@
= render 'shared/issuable_meta_data', issuable: merge_request
- .float-right.issuable-updated-at.d-none.d-sm-inline-block
- %span
- = _('updated %{time_ago}').html_safe % { time_ago: time_ago_with_tooltip(merge_request.updated_at, placement: 'bottom', html_class: 'merge_request_updated_ago') }
+ - if merge_request.updated_at != merge_request.created_at
+ .float-right.issuable-updated-at.d-none.d-sm-inline-block.gl-text-gray-500
+ %span
+ = _('updated %{time_ago}').html_safe % { time_ago: time_ago_with_tooltip(merge_request.updated_at, placement: 'bottom', html_class: 'merge_request_updated_ago') }
diff --git a/app/views/projects/merge_requests/_mr_box.html.haml b/app/views/projects/merge_requests/_mr_box.html.haml
index 901a2ebfd1e..6f662b81dd7 100644
--- a/app/views/projects/merge_requests/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/_mr_box.html.haml
@@ -1,3 +1,3 @@
-.detail-page-description.py-2.gl-display-flex.gl-align-items-center.gl-flex-wrap{ class: "#{'is-merge-request' if moved_mr_sidebar_enabled? && !fluid_layout}" }
+.detail-page-description.gl-pt-2.gl-pb-4.gl-display-flex.gl-align-items-center.gl-flex-wrap{ class: "#{'is-merge-request' if moved_mr_sidebar_enabled? && !fluid_layout}" }
= render 'shared/issuable/status_box', issuable: @merge_request
= merge_request_header(@project, @merge_request)
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 9d25603994a..15339becb74 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -1,4 +1,3 @@
-- @no_breadcrumb_border = true
- can_update_merge_request = can?(current_user, :update_merge_request, @merge_request)
- can_reopen_merge_request = can?(current_user, :reopen_merge_request, @merge_request)
- are_close_and_open_buttons_hidden = merge_request_button_hidden?(@merge_request, true) && merge_request_button_hidden?(@merge_request, false)
@@ -10,10 +9,10 @@
= render Pajamas::AlertComponent.new(alert_options: { class: 'gl-mb-5' },
variant: :danger,
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= _('The source project of this merge request has been removed.')
- .detail-page-header.border-bottom-0.pt-0.pb-0.gl-display-block{ class: "gl-md-display-flex! #{'is-merge-request' if moved_mr_sidebar_enabled? && !fluid_layout}" }
+ .detail-page-header.border-bottom-0.gl-display-block.gl-pt-5{ class: "gl-md-display-flex! #{'is-merge-request' if moved_mr_sidebar_enabled? && !fluid_layout}" }
.detail-page-header-body
.issuable-meta.gl-display-flex
#js-issuable-header-warnings{ data: { hidden: @merge_request.hidden?.to_s } }
@@ -27,7 +26,8 @@
.detail-page-header-actions.gl-align-self-start.is-merge-request.js-issuable-actions.gl-display-flex
- if can_update_merge_request
- = link_to _('Edit'), edit_project_merge_request_path(@project, @merge_request), class: "gl-display-none gl-md-display-block btn gl-button btn-default js-issuable-edit", data: { qa_selector: "edit_button" }
+ = render Pajamas::ButtonComponent.new(href: edit_project_merge_request_path(@project, @merge_request), button_options: {class: "gl-display-none gl-md-display-block js-issuable-edit", data: { qa_selector: "edit_button" }}) do
+ = _('Edit')
- if @merge_request.source_project
= render 'projects/merge_requests/code_dropdown'
diff --git a/app/views/projects/merge_requests/_nav_btns.html.haml b/app/views/projects/merge_requests/_nav_btns.html.haml
index 1efea6a1d37..80085cc6a34 100644
--- a/app/views/projects/merge_requests/_nav_btns.html.haml
+++ b/app/views/projects/merge_requests/_nav_btns.html.haml
@@ -1,12 +1,27 @@
-- issuable_type = 'merge-requests'
+- issuable_type = 'merge_request'
- notification_email = @current_user.present? ? @current_user.notification_email_or_default : nil
-= render 'shared/issuable/feed_buttons', show_calendar_button: false
-.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
= render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-mr-3 js-bulk-update-toggle' }) do
- = _("Edit merge requests")
+ = _("Bulk edit")
- if merge_project
= render Pajamas::ButtonComponent.new(href: new_merge_request_path, variant: :confirm) do
= _("New merge request")
+
+.dropdown.gl-dropdown
+ = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret has-tooltip gl-display-none! gl-md-display-inline-flex!", data: { toggle: 'dropdown', title: _('Actions') } do
+ = sprite_icon "ellipsis_v", size: 16, css_class: "dropdown-icon gl-icon"
+ %span.gl-sr-only
+ = _('Actions')
+ = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md btn-block gl-button gl-dropdown-toggle gl-md-display-none!", data: { 'toggle' => 'dropdown' } do
+ %span.gl-dropdown-button-text= _('Actions')
+ = sprite_icon "chevron-down", size: 16, css_class: "dropdown-icon gl-icon"
+ .dropdown-menu.dropdown-menu-right
+ .gl-dropdown-inner
+ .gl-dropdown-contents
+ %ul
+ .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) } }
+ %li.gl-dropdown-divider
+ %hr.dropdown-divider
+ %li.gl-dropdown-item
+ = render 'shared/issuable/feed_buttons', show_calendar_button: false
diff --git a/app/views/projects/merge_requests/_page.html.haml b/app/views/projects/merge_requests/_page.html.haml
index 880bffc43ab..3e56148f777 100644
--- a/app/views/projects/merge_requests/_page.html.haml
+++ b/app/views/projects/merge_requests/_page.html.haml
@@ -16,7 +16,7 @@
- add_page_specific_style 'page_bundles/ci_status'
- add_page_startup_api_call @endpoint_metadata_url
-- if mr_action == 'diffs'
+- if mr_action == 'diffs' && (!@file_by_file_default || !single_file_file_by_file?)
- add_page_startup_api_call @endpoint_diff_batch_url
.merge-request{ data: { mr_action: mr_action, url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version, diffs_batch_cache_key: @diffs_batch_cache_key } }
@@ -36,7 +36,7 @@
= render "projects/merge_requests/tabs/tab", name: "commits", class: "commits-tab", qa_selector: "commits_tab" do
= tab_link_for @merge_request, :commits do
= _("Commits")
- = gl_badge_tag @commits_count, { size: :sm }
+ = gl_badge_tag tab_count_display(@merge_request, @commits_count), { size: :sm }, { class: 'js-commits-count' }
- if @project.builds_enabled?
= render "projects/merge_requests/tabs/tab", name: "pipelines", class: "pipelines-tab" do
= tab_link_for @merge_request, :pipelines do
@@ -45,7 +45,7 @@
= render "projects/merge_requests/tabs/tab", name: "diffs", class: "diffs-tab js-diffs-tab", id: "diffs-tab", qa_selector: "diffs_tab" do
= tab_link_for @merge_request, :diffs do
= _("Changes")
- = gl_badge_tag @diffs_count, { size: :sm }
+ = gl_badge_tag tab_count_display(@merge_request, @diffs_count), { size: :sm }
.d-flex.flex-wrap.align-items-center.justify-content-lg-end
#js-vue-discussion-counter{ data: { blocks_merge: @project.only_allow_merge_if_all_discussions_are_resolved?.to_s } }
- if moved_mr_sidebar_enabled?
@@ -81,7 +81,8 @@
help_page_path: suggest_changes_help_path,
current_user_data: @current_user_data,
is_locked: @merge_request.discussion_locked.to_s,
- report_abuse_path: add_category_abuse_reports_path } }
+ report_abuse_path: add_category_abuse_reports_path,
+ new_comment_template_path: profile_comment_templates_path } }
- if moved_mr_sidebar_enabled?
= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, reviewers: @merge_request.reviewers, source_branch: @merge_request.source_branch
@@ -90,7 +91,7 @@
= render "projects/merge_requests/tabs/pane", name: "pipelines", id: "pipelines", class: "pipelines" do
- if @project.builds_enabled?
= render 'projects/commit/pipelines_list', disable_initialization: true, endpoint: pipelines_project_merge_request_path(@project, @merge_request)
- - params = request.query_parameters.merge(diff_head: true)
+ - params = request.query_parameters.merge(ck: @diffs_batch_cache_key, diff_head: true)
= render "projects/merge_requests/tabs/pane", name: "diffs", id: "js-diffs-app", class: "diffs", data: diffs_tab_pane_data(@project, @merge_request, params)
.mr-loading-status
@@ -105,10 +106,9 @@
- if @merge_request.can_be_cherry_picked?
= render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit
-#js-review-bar
+#js-review-bar{ data: { new_comment_template_path: profile_comment_templates_path } }
- if current_user && Feature.enabled?(:mr_experience_survey, current_user)
#js-mr-experience-survey{ data: { account_age: current_user.account_age_in_days } }
-= render 'projects/invite_members_modal', project: @project
= render 'shared/web_ide_path'
diff --git a/app/views/projects/merge_requests/_widget.html.haml b/app/views/projects/merge_requests/_widget.html.haml
index 4f6983c6fe3..576fed58609 100644
--- a/app/views/projects/merge_requests/_widget.html.haml
+++ b/app/views/projects/merge_requests/_widget.html.haml
@@ -11,12 +11,12 @@
window.gl.mrWidgetData.ci_troubleshooting_docs_path = '#{help_page_path('ci/troubleshooting.md')}';
window.gl.mrWidgetData.mr_troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/reviews/index.md', anchor: 'troubleshooting')}';
window.gl.mrWidgetData.pipeline_must_succeed_docs_path = '#{help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds.md', anchor: 'require-a-successful-pipeline-for-merge')}';
- window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests')}';
+ window.gl.mrWidgetData.code_coverage_check_help_page_path = '#{help_page_path('ci/testing/code_coverage.md', anchor: 'coverage-check-approval-rule')}';
window.gl.mrWidgetData.security_configuration_path = '#{project_security_configuration_path(@project)}';
- window.gl.mrWidgetData.license_compliance_docs_path = '#{help_page_path('user/compliance/license_compliance/index.md', anchor: 'policies')}';
+ window.gl.mrWidgetData.license_compliance_docs_path = '#{help_page_path('user/compliance/license_compliance/index.md')}';
window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/approvals/rules.md', anchor: 'eligible-approvers')}';
window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/approvals/index.md")}';
- window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/pipelines_empty.svg')}';
+ window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/empty-state/empty-pipeline-md.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 = '#{@merge_request.project.licensed_feature_available?(:sast_fp_reduction).to_s}';
diff --git a/app/views/projects/merge_requests/conflicts/show.html.haml b/app/views/projects/merge_requests/conflicts/show.html.haml
index a882196ffa2..3facca4d4f7 100644
--- a/app/views/projects/merge_requests/conflicts/show.html.haml
+++ b/app/views/projects/merge_requests/conflicts/show.html.haml
@@ -1,3 +1,6 @@
+- add_to_breadcrumbs _("Merge requests"), project_merge_requests_path(@project)
+- add_to_breadcrumbs @merge_request.to_reference, project_merge_request_path(@project, @merge_request)
+- breadcrumb_title _("Merge conflicts")
- page_title _("Merge Conflicts"), "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge requests")
- add_page_specific_style 'page_bundles/merge_conflicts'
diff --git a/app/views/projects/merge_requests/creations/_new_submit.html.haml b/app/views/projects/merge_requests/creations/_new_submit.html.haml
index 1246c45a529..35e8b30e6e9 100644
--- a/app/views/projects/merge_requests/creations/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_submit.html.haml
@@ -10,12 +10,24 @@
- if params[:nav_source].present?
= hidden_field_tag(:nav_source, params[:nav_source])
-.mr-compare.merge-request.js-merge-request-new-submit{ 'data-mr-submit-action': "#{j params[:tab].presence || 'new'}" }
+.mr-compare.merge-request.js-merge-request-new-submit.gl-mt-5{ 'data-mr-submit-action': "#{j params[:tab].presence || 'new'}" }
- if @commits.empty?
- .commits-empty
- %h4
- = _("There are no commits yet.")
- = custom_icon ('illustration_no_commits')
+ .merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
+ .merge-request-tabs-container.gl-display-flex.gl-justify-content-space-between
+ .scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
+ .fade-left= sprite_icon('chevron-lg-left', size: 12)
+ .fade-right= sprite_icon('chevron-lg-right', size: 12)
+ %ul.merge-request-tabs.nav.nav-tabs.nav-links.no-top.no-bottom.gl-display-flex.gl-flex-nowrap.gl-m-0.gl-p-0.js-tabs-affix
+ %li.commits-tab.new-tab
+ = link_to url_for(safe_params), data: {target: 'div#commits', action: 'new', toggle: 'tabvue'} do
+ = _("Commits")
+ = gl_badge_tag @total_commit_count, { size: :sm }, { class: 'gl-tab-counter-badge' }
+
+ #diff-notes-app.tab-content
+ #new.commits.tab-pane.active
+ .commits-empty.gl-text-left.gl-my-5.gl-text-gray-500
+ %p
+ = _("There are no commits yet.")
- else
.merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
.merge-request-tabs-container.gl-display-flex.gl-justify-content-space-between
diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml
index 4596fcd280d..4ea33cbbd99 100644
--- a/app/views/projects/merge_requests/invalid.html.haml
+++ b/app/views/projects/merge_requests/invalid.html.haml
@@ -11,7 +11,7 @@
= render Pajamas::AlertComponent.new(variant: :danger,
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
- if @merge_request.for_fork? && !@merge_request.source_project
= err_fork_project_removed
- elsif !@merge_request.source_branch_exists?
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index cdb8a63bca9..be6f9ac83dc 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -1,32 +1,32 @@
-= gitlab_ui_form_for [@project, @milestone],
- html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
+= gitlab_ui_form_for [@project, @milestone], html: { class: 'milestone-form common-note-form js-quick-submit js-requires-input' } do |f|
= form_errors(@milestone)
+
+ - if @conflict
+ = render 'shared/model_version_conflict', model_name: _('milestone'), link_path: project_milestone_path(@project, @milestone)
+
- if @redirect_path.present?
= f.hidden_field(:redirect_path, name: :redirect_path, id: :redirect_path, value: @redirect_path)
- .form-group.row
- .col-form-label.col-sm-2
- = f.label :title, _('Title')
- .col-sm-10
- = f.text_field :title, maxlength: 255, class: 'form-control gl-form-input', data: { qa_selector: 'milestone_title_field' }, required: true, autofocus: true
+ .form-group
+ = f.label :title, _('Title')
+ = f.text_field :title, maxlength: 255, class: 'form-control gl-form-input', data: { qa_selector: 'milestone_title_field' }, required: true, autofocus: true
= render 'shared/milestones/form_dates', f: f
- .form-group.row.milestone-description
- .col-form-label.col-sm-2
- = f.label :description, _('Description')
- .col-sm-10
- = render layout: 'shared/md_preview', locals: { url: preview_markdown_path(@project) } do
- = render 'shared/zen', f: f, attr: :description,
- classes: 'note-textarea',
- qa_selector: 'milestone_description_field',
- supports_autocomplete: true,
- placeholder: _('Write milestone description...')
- = render 'shared/notes/hints'
- .clearfix
- .error-alert
+ .form-group
+ = f.label :description, _('Description')
+ = render layout: 'shared/md_preview', locals: { url: preview_markdown_path(@project) } do
+ = render 'shared/zen', f: f, attr: :description,
+ classes: 'note-textarea',
+ qa_selector: 'milestone_description_field',
+ supports_autocomplete: true,
+ placeholder: _('Write milestone description...')
+ = render 'shared/notes/hints'
+ .clearfix
+ .error-alert
+
+ = f.hidden_field :lock_version
- .form-actions
- - if @milestone.new_record?
- = f.submit _('Create milestone'), data: { qa_selector: 'create_milestone_button' }, pajamas_button: true
- = link_to _('Cancel'), project_milestones_path(@project), class: 'gl-button btn btn-default btn-cancel'
- - else
- = f.submit _('Save changes'), pajamas_button: true
- = link_to _('Cancel'), project_milestone_path(@project, @milestone), class: 'gl-button btn btn-default btn-cancel'
+ - if @milestone.new_record?
+ = f.submit _('Create milestone'), data: { qa_selector: 'create_milestone_button' }, class: 'gl-mr-2', pajamas_button: true
+ = link_to _('Cancel'), project_milestones_path(@project), class: 'gl-button btn btn-default btn-cancel'
+ - else
+ = f.submit _('Save changes'), class: 'gl-mr-2', pajamas_button: true
+ = link_to _('Cancel'), project_milestone_path(@project, @milestone), class: 'gl-button btn btn-default btn-cancel'
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 95ef856daba..36500e157b4 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -16,7 +16,7 @@
= render Pajamas::AlertComponent.new(dismissible: false,
alert_options: { class: 'gl-mt-3 gl-mb-5',
data: { testid: 'no-issues-alert' }}) do |c|
- = c.body do
+ - c.with_body do
= _('Assign some issues to this milestone.')
- else
= render 'shared/milestones/milestone_complete_alert', milestone: @milestone do
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 4cfe463fa38..110bc8d82f8 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -33,7 +33,7 @@
= f.submit _('Mirror repository'), class: 'js-mirror-submit', name: :update_remote_mirror, pajamas_button: true, data: { qa_selector: 'mirror_repository_button' }
- else
= render Pajamas::AlertComponent.new(dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= _('Mirror settings are only available to GitLab administrators.')
= render 'projects/mirrors/mirror_repos_list'
diff --git a/app/views/projects/mirrors/_mirror_repos_list.html.haml b/app/views/projects/mirrors/_mirror_repos_list.html.haml
index 46833b5986b..185d86245c5 100644
--- a/app/views/projects/mirrors/_mirror_repos_list.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_list.html.haml
@@ -3,14 +3,14 @@
.panel.panel-default
.table-responsive
- if !@project.mirror? && @project.remote_mirrors.count == 0
- .gl-card.gl-mt-5
- .gl-card-header
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mt-5' }) do |c|
+ - c.with_header do
%strong
= _('Mirrored repositories') + ' (0)'
- .gl-card-body
+ - c.with_body do
= _('There are currently no mirrored repositories.')
- else
- %table.table.push-pull-table
+ %table.table.gl-table.gl-mt-5
%thead
%tr
%th
diff --git a/app/views/projects/ml/candidates/show.html.haml b/app/views/projects/ml/candidates/show.html.haml
index 77262243efb..5d5059551d3 100644
--- a/app/views/projects/ml/candidates/show.html.haml
+++ b/app/views/projects/ml/candidates/show.html.haml
@@ -2,5 +2,7 @@
- add_to_breadcrumbs _("Experiments"), project_ml_experiments_path(@project)
- add_to_breadcrumbs experiment.name, project_ml_experiment_path(@project, experiment.iid)
- breadcrumb_title "Candidate #{@candidate.iid}"
+- add_page_specific_style 'page_bundles/ml_experiment_tracking'
+- presenter = ::Ml::CandidateDetailsPresenter.new(@candidate)
-#js-show-ml-candidate{ data: { view_model: show_candidate_view_model(@candidate) } }
+#js-show-ml-candidate{ data: { view_model: presenter.present } }
diff --git a/app/views/projects/ml/experiments/_experiment.html.haml b/app/views/projects/ml/experiments/_experiment.html.haml
deleted file mode 100644
index 42823f47469..00000000000
--- a/app/views/projects/ml/experiments/_experiment.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-%li.ml-experiment-row.py-3
- = link_to project_ml_experiment_path(@project, experiment.iid), class: "title" do
- = experiment.name
diff --git a/app/views/projects/ml/experiments/_experiment_list.html.haml b/app/views/projects/ml/experiments/_experiment_list.html.haml
deleted file mode 100644
index a25e814b2b5..00000000000
--- a/app/views/projects/ml/experiments/_experiment_list.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-- if experiments.blank?
- .nothing-here-block= s_('MlExperimentsEmptyState|No Experiments to Show')
-- else
- .ml-experiments-list-holder
- %ul.content-list
- = render partial: 'experiment', collection: experiments, as: :experiment
- = paginate_collection @experiments
diff --git a/app/views/projects/ml/experiments/_incubation_banner.html.haml b/app/views/projects/ml/experiments/_incubation_banner.html.haml
deleted file mode 100644
index e34f3fd2d2f..00000000000
--- a/app/views/projects/ml/experiments/_incubation_banner.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-= render Pajamas::AlertComponent.new(variant: :warning,
- title: _('Machine Learning Experiment Tracking is in Incubating Phase'),
- alert_options: { class: 'gl-my-3' }) do |c|
- = c.body do
- = _('GitLab incubates features to explore new use cases. These features are updated regularly, and support is limited')
- = link_to _('Learn more.'), 'https://about.gitlab.com/handbook/engineering/incubation/', target: "_blank"
- = c.actions do
- = link_to _('Feedback and Updates'), 'https://gitlab.com/groups/gitlab-org/-/epics/8560', target: "_blank"
diff --git a/app/views/projects/ml/experiments/index.html.haml b/app/views/projects/ml/experiments/index.html.haml
index dd064239e36..612481dbf41 100644
--- a/app/views/projects/ml/experiments/index.html.haml
+++ b/app/views/projects/ml/experiments/index.html.haml
@@ -3,5 +3,6 @@
#js-project-ml-experiments-index{ data: {
experiments: experiments_as_data(@project, @experiments),
- page_info: formatted_page_info(@page_info)
+ page_info: formatted_page_info(@page_info),
+ empty_state_svg_path: image_path('illustrations/empty-state/empty-dag-md.svg'),
} }
diff --git a/app/views/projects/ml/experiments/show.html.haml b/app/views/projects/ml/experiments/show.html.haml
index 4433d1fafe9..d4a05b613c9 100644
--- a/app/views/projects/ml/experiments/show.html.haml
+++ b/app/views/projects/ml/experiments/show.html.haml
@@ -1,17 +1,19 @@
- add_to_breadcrumbs _("Experiments"), project_ml_experiments_path(@project)
- breadcrumb_title @experiment.name
- page_title @experiment.name
+- add_page_specific_style 'page_bundles/ml_experiment_tracking'
+
+- experiment = experiment_as_data(@experiment)
- items = candidates_table_items(@candidates)
- metrics = unique_logged_names(@candidates, &:latest_metrics)
- params = unique_logged_names(@candidates, &:params)
- page_info = formatted_page_info(@page_info)
-.page-title-holder.d-flex.align-items-center
- %h1.page-title.gl-font-size-h-display= @experiment.name
-
#js-show-ml-experiment{ data: {
+ experiment: experiment,
candidates: items,
metrics: metrics,
params: params,
- page_info: page_info
+ page_info: page_info,
+ empty_state_svg_path: image_path('illustrations/empty-state/empty-dag-md.svg'),
} }
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 56581fe7b18..59a21cecd39 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -1,14 +1,24 @@
-- @hide_breadcrumbs = true
+- @hide_top_bar = true
- @hide_top_links = true
- page_title _('New Project')
- header_title _("Projects"), dashboard_projects_path
- add_page_specific_style 'page_bundles/new_namespace'
-.project-edit-container.gl-mt-5
+.project-edit-container
.project-edit-errors
= render 'projects/errors'
- .js-new-project-creation{ data: { is_ci_cd_available: (ci_cd_projects_available? if Gitlab.ee?).to_s, has_errors: @project.errors.any?.to_s, new_project_guidelines: brand_new_project_guidelines, push_to_create_project_command: push_to_create_project_command, working_with_projects_help_path: help_page_path("user/project/working_with_projects") } }
+ .js-new-project-creation{ data: {
+ is_ci_cd_available: remote_mirror_setting_enabled?.to_s,
+ has_errors: @project.errors.any?.to_s,
+ new_project_guidelines: brand_new_project_guidelines,
+ push_to_create_project_command: push_to_create_project_command,
+ working_with_projects_help_path: help_page_path("user/project/working_with_projects"),
+ root_path: root_path,
+ parent_group_url: @project.parent && group_url(@project.parent),
+ parent_group_name: @project.parent&.name,
+ projects_url: dashboard_projects_url,
+ can_import_projects: params[:namespace_id].presence ? current_user.can?(:import_projects, @namespace).to_s : 'true' } }
.row{ 'v-cloak': true }
#blank-project-pane.tab-pane.active
@@ -17,7 +27,7 @@
#create-from-template-pane.tab-pane
= render Pajamas::CardComponent.new(card_options: { class: 'gl-my-5' }) do |c|
- = c.body do
+ - c.with_body do
%div
- contributing_templates_url = 'https://gitlab.com/gitlab-org/project-templates/contributing'
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: contributing_templates_url }
diff --git a/app/views/projects/packages/infrastructure_registry/index.html.haml b/app/views/projects/packages/infrastructure_registry/index.html.haml
index 5a118997ff9..9577f6383e9 100644
--- a/app/views/projects/packages/infrastructure_registry/index.html.haml
+++ b/app/views/projects/packages/infrastructure_registry/index.html.haml
@@ -1,5 +1,4 @@
- page_title _("Infrastructure Registry")
-- @content_class = "limit-container-width" unless fluid_layout
.row
.col-12
diff --git a/app/views/projects/packages/infrastructure_registry/show.html.haml b/app/views/projects/packages/infrastructure_registry/show.html.haml
index e7c77478170..8624fdacda7 100644
--- a/app/views/projects/packages/infrastructure_registry/show.html.haml
+++ b/app/views/projects/packages/infrastructure_registry/show.html.haml
@@ -1,8 +1,7 @@
-- add_to_breadcrumbs _("Infrastructure Registry"), project_infrastructure_registry_index_path(@project)
+- add_to_breadcrumbs _("Terraform Module Registry"), project_infrastructure_registry_index_path(@project)
- add_to_breadcrumbs @package.name, project_infrastructure_registry_index_path(@project)
- breadcrumb_title @package.version
-- page_title _("Infrastructure Registry")
-- @content_class = "limit-container-width" unless fluid_layout
+- page_title _("Terraform Module Registry")
.row
.col-12
diff --git a/app/views/projects/packages/packages/index.html.haml b/app/views/projects/packages/packages/index.html.haml
index 4ab16f25dd2..48aaf0884c8 100644
--- a/app/views/projects/packages/packages/index.html.haml
+++ b/app/views/projects/packages/packages/index.html.haml
@@ -1,5 +1,4 @@
- page_title _("Package Registry")
-- @content_class = "limit-container-width" unless fluid_layout
.row
.col-12
@@ -10,4 +9,5 @@
empty_list_illustration: image_path('illustrations/no-packages.svg'),
npm_instance_url: package_registry_instance_url(:npm),
project_list_url: project_packages_path(@project),
+ settings_path: show_package_registry_settings(@project) ? project_settings_packages_and_registries_path(@project) : '',
group_list_url: '' } }
diff --git a/app/views/projects/pages/_access.html.haml b/app/views/projects/pages/_access.html.haml
index 28f04d78861..50e48187be3 100644
--- a/app/views/projects/pages/_access.html.haml
+++ b/app/views/projects/pages/_access.html.haml
@@ -1,20 +1,18 @@
- if @project.pages_deployed?
+ - pages_url = @project.pages_url(with_unique_domain: true)
+
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5', data: { qa_selector: 'access_page_container' } }, footer_options: { class: 'gl-alert-warning' }) do |c|
- - c.header do
+ - c.with_header do
= s_('GitLabPages|Access pages')
- - c.body do
- %p
- %strong
- = s_('GitLabPages|Your pages are served under:')
-
+ - c.with_body do
%p
- = external_link(@project.pages_url, @project.pages_url)
+ = external_link(pages_url, pages_url)
- @project.pages_domains.each do |domain|
%p
= external_link(domain.url, domain.url)
- unless @project.public_pages?
- - c.footer do
+ - c.with_footer do
- help_page = help_page_path('user/project/pages/pages_access_control')
- link_start = '<a href="%{url}" target="_blank" class="gl-alert-link" rel="noopener noreferrer">'.html_safe % { url: help_page }
- link_end = '</a>'.html_safe
diff --git a/app/views/projects/pages/_destroy.haml b/app/views/projects/pages/_destroy.haml
index ff30c9ce1ea..3d95fa8a655 100644
--- a/app/views/projects/pages/_destroy.haml
+++ b/app/views/projects/pages/_destroy.haml
@@ -1,16 +1,13 @@
- if @project.pages_deployed?
- if can?(current_user, :remove_pages, @project)
- = render Pajamas::CardComponent.new(card_options: { class: 'border-danger' }, header_options: {class: 'bg-danger text-white'}) do |c|
- - c.with_header do
+ .gl-bg-red-50.gl-inset-border-l-3-red-600.gl-py-5.gl-px-6
+ %h4.gl-font-lg.gl-mt-0= s_('GitLabPages|Remove pages')
+ %p= s_('GitLabPages|Removing pages will prevent them from being exposed to the outside world.')
+ = render Pajamas::ButtonComponent.new(href: project_pages_path(@project),
+ variant: :danger,
+ method: :delete,
+ button_options: {data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger'}, "aria-label": s_('GitLabPages|Remove pages')}) do
= s_('GitLabPages|Remove pages')
- - c.with_body do
- = s_('GitLabPages|Removing pages will prevent them from being exposed to the outside world.')
- - c.with_footer do
- = render Pajamas::ButtonComponent.new(href: project_pages_path(@project),
- variant: :danger,
- method: :delete,
- button_options: {data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger'}, "aria-label": s_('GitLabPages|Remove pages')}) do
- = s_('GitLabPages|Remove pages')
- else
.nothing-here-block
= s_('GitLabPages|Only project maintainers can remove pages')
diff --git a/app/views/projects/pages/_header.html.haml b/app/views/projects/pages/_header.html.haml
index cf51796e878..c34034ccafc 100644
--- a/app/views/projects/pages/_header.html.haml
+++ b/app/views/projects/pages/_header.html.haml
@@ -1,10 +1,7 @@
-- can_add_new_domain = can_create_pages_custom_domains?(current_user, @project)
+- @content_class = 'limit-container-width'
-%h1.page-title.gl-font-size-h-display.with-button
+%h4.page-title
= s_('GitLabPages|Pages')
- - if can_add_new_domain
- = render Pajamas::ButtonComponent.new(variant: :confirm, button_options: { class: 'float-right'}, href: new_project_pages_domain_path(@project)) do
- = s_('GitLabPages|New Domain')
%p
- docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer'>".html_safe
- docs_link_end = '</a>'.html_safe
diff --git a/app/views/projects/pages/_list.html.haml b/app/views/projects/pages/_list.html.haml
index 32e67fdadb8..57371aa49f6 100644
--- a/app/views/projects/pages/_list.html.haml
+++ b/app/views/projects/pages/_list.html.haml
@@ -1,39 +1,47 @@
+- can_add_new_domain = can_create_pages_custom_domains?(current_user, @project)
- verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled?
-- if can?(current_user, :update_pages, @project) && @domains.any?
- = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5'}) do |c|
- - c.header do
+- if can?(current_user, :update_pages, @project)
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5'}, header_options: { class: 'gl-display-flex gl-align-items-center gl-justify-content-space-between' }) do |c|
+ - c.with_header do
Domains (#{@domains.size})
- - c.body do
- %ul.list-group.list-group-flush
- - @domains.each do |domain|
- %li.list-group-item.gl-display-flex.gl-justify-content-space-between.gl-align-items-center.gl-p-0
- .gl-display-flex.gl-align-items-center
- - if verification_enabled
- - tooltip, status = domain.unverified? ? [s_('GitLabPages|Unverified'), 'failed'] : [s_('GitLabPages|Verified'), 'success']
- .domain-status.ci-status-icon.has-tooltip{ class: "gl-mr-5 ci-status-icon-#{status}", title: tooltip }
- = sprite_icon("status_#{status}")
- .domain-name
- = external_link(domain.url, domain.url)
- - if domain.certificate
- %div
- = gl_badge_tag(s_('GitLabPages|Certificate: %{subject}') % { subject: domain.pages_domain.subject })
- - if domain.expired?
- = gl_badge_tag s_('GitLabPages|Expired'), variant: :danger
- %div
- = link_to s_('GitLabPages|Edit'), project_pages_domain_path(@project, domain), class: "btn gl-button btn-sm btn-grouped btn-confirm btn-inverted"
- = link_to s_('GitLabPages|Remove'), project_pages_domain_path(@project, domain), data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger'}, "aria-label": s_("GitLabPages|Remove domain"), method: :delete, class: "btn gl-button btn-danger btn-sm btn-grouped"
- - if domain.needs_verification?
- %li.list-group-item.bs-callout-warning
- - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
- - details_link_end = '</a>'.html_safe
- = s_('GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}.').html_safe % { domain: domain.domain,
- link_start: details_link_start,
- link_end: details_link_end }
- - if domain.show_auto_ssl_failed_warning?
- %li.list-group-item.bs-callout-warning
- - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
- - details_link_end = '</a>'.html_safe
- = s_("GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}.").html_safe % { domain: domain.domain,
- link_start: details_link_start,
- link_end: details_link_end }
+ - if can_add_new_domain
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: new_project_pages_domain_path(@project)) do
+ = s_('GitLabPages|New Domain')
+ - c.with_body do
+ - if @domains.any?
+ %ul.list-group.list-group-flush
+ - @domains.each do |domain|
+ %li.list-group-item.gl-display-flex.gl-justify-content-space-between.gl-align-items-center.gl-p-0
+ .gl-display-flex.gl-align-items-center
+ - if verification_enabled
+ - tooltip, status = domain.unverified? ? [s_('GitLabPages|Unverified'), 'failed'] : [s_('GitLabPages|Verified'), 'success']
+ .domain-status.ci-status-icon.has-tooltip{ class: "gl-mr-5 ci-status-icon-#{status}", title: tooltip }
+ = sprite_icon("status_#{status}")
+ .domain-name
+ = external_link(domain.url, domain.url)
+ - if domain.certificate
+ %div
+ = gl_badge_tag(s_('GitLabPages|Certificate: %{subject}') % { subject: domain.pages_domain.subject })
+ - if domain.expired?
+ = gl_badge_tag s_('GitLabPages|Expired'), variant: :danger
+ %div
+ = link_to s_('GitLabPages|Edit'), project_pages_domain_path(@project, domain), class: "btn gl-button btn-sm btn-grouped btn-confirm btn-inverted"
+ = link_to s_('GitLabPages|Remove'), project_pages_domain_path(@project, domain), data: { confirm: s_('GitLabPages|Are you sure?'), 'confirm-btn-variant': 'danger'}, "aria-label": s_("GitLabPages|Remove domain"), method: :delete, class: "btn gl-button btn-danger btn-sm btn-grouped"
+ - if domain.needs_verification?
+ %li.list-group-item.bs-callout-warning
+ - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
+ - details_link_end = '</a>'.html_safe
+ = s_('GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}.').html_safe % { domain: domain.domain,
+ link_start: details_link_start,
+ link_end: details_link_end }
+ - if domain.show_auto_ssl_failed_warning?
+ %li.list-group-item.bs-callout-warning
+ - details_link_start = "<a href='#{project_pages_domain_path(@project, domain)}'>".html_safe
+ - details_link_end = '</a>'.html_safe
+ = s_("GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}.").html_safe % { domain: domain.domain,
+ link_start: details_link_start,
+ link_end: details_link_end }
+ - else
+ .gl-text-center
+ = s_("You currently have no custom domains.")
diff --git a/app/views/projects/pages/_no_domains.html.haml b/app/views/projects/pages/_no_domains.html.haml
index eee7d062d00..97c3ad11f1a 100644
--- a/app/views/projects/pages/_no_domains.html.haml
+++ b/app/views/projects/pages/_no_domains.html.haml
@@ -1,6 +1,11 @@
+- can_add_new_domain = can_create_pages_custom_domains?(current_user, @project)
+
- if can?(current_user, :update_pages, @project)
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5'}, body_options: { class: 'gl-text-center nothing-here-block' }) do |c|
- - c.header do
+ - c.with_header do
= s_('GitLabPages|Domains')
- - c.body do
+ - if can_add_new_domain
+ = render Pajamas::ButtonComponent.new(variant: :confirm, href: new_project_pages_domain_path(@project)) do
+ = s_('GitLabPages|New Domain')
+ - c.with_body do
= s_("GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it.")
diff --git a/app/views/projects/pages/_pages_settings.html.haml b/app/views/projects/pages/_pages_settings.html.haml
index 0010564081e..4c8ec21db39 100644
--- a/app/views/projects/pages/_pages_settings.html.haml
+++ b/app/views/projects/pages/_pages_settings.html.haml
@@ -17,5 +17,14 @@
%p.gl-pl-6
= s_("GitLabPages|When enabled, all attempts to visit your website through HTTP are automatically redirected to HTTPS using a response with status code 301. Requires a valid certificate for all domains. %{docs_link_start}Learn more.%{link_end}").html_safe % { docs_link_start: docs_link_start, link_end: link_end }
+ - if Feature.enabled?(:pages_unique_domain, @project)
+ .form-group
+ = f.fields_for :project_setting do |settings|
+ = settings.gitlab_ui_checkbox_component :pages_unique_domain_enabled,
+ s_('GitLabPages|Use unique domain'),
+ label_options: { class: 'label-bold' }
+ %p.gl-pl-6
+ = s_("GitLabPages|When enabled, a unique domain is generated to access pages.").html_safe
+
.gl-mt-3
- = f.submit s_('GitLabPages|Save changes'), class: 'btn btn-confirm gl-button'
+ = f.submit s_('GitLabPages|Save changes'), pajamas_button: true
diff --git a/app/views/projects/pages/_use.html.haml b/app/views/projects/pages/_use.html.haml
index dccf61c6ec5..4c39c1be060 100644
--- a/app/views/projects/pages/_use.html.haml
+++ b/app/views/projects/pages/_use.html.haml
@@ -1,8 +1,8 @@
- unless @project.pages_deployed?
= render Pajamas::CardComponent.new(card_options: { class: 'gl-border-blue-500' }, header_options: { class: 'gl-bg-blue-500 gl-text-white' }) do |c|
- - c.header do
+ - c.with_header do
= s_('GitLabPages|Configure pages')
- - c.body do
+ - c.with_body do
- docs_link_start = "<a href='#{help_page_path('user/project/pages/index')}' target='_blank' rel='noopener noreferrer' data-track-action='click_link' data-track-label='pages_docs_link'>".html_safe
- samples_link_start = "<a href='https://gitlab.com/pages' target='_blank' rel='noopener noreferrer' data-track-action='click_link' data-track-label='pages_samples_link'>".html_safe
- link_end = '</a>'.html_safe
diff --git a/app/views/projects/pages_domains/_certificate.html.haml b/app/views/projects/pages_domains/_certificate.html.haml
index 4ba3e084dc4..f80fd495695 100644
--- a/app/views/projects/pages_domains/_certificate.html.haml
+++ b/app/views/projects/pages_domains/_certificate.html.haml
@@ -30,10 +30,10 @@
- if has_user_defined_certificate
.row
.col-sm-10.offset-sm-2
- .card
- .card-header
+ = render Pajamas::CardComponent.new(body_options: { class: 'gl-display-flex gl-align-items-center gl-justify-content-space-between gl-p-5' }) do |c|
+ - c.with_header do
= _('Certificate')
- .d-flex.justify-content-between.align-items-center.p-3
+ - c.with_body do
%span
= domain_presenter.pages_domain.subject || _('missing')
= link_to _('Remove'),
diff --git a/app/views/projects/pages_domains/_dns.html.haml b/app/views/projects/pages_domains/_dns.html.haml
index 2c6b808eb1c..3e6a92d8bc0 100644
--- a/app/views/projects/pages_domains/_dns.html.haml
+++ b/app/views/projects/pages_domains/_dns.html.haml
@@ -13,7 +13,6 @@
%p.form-text.text-muted
= _("To access this domain create a new DNS record")
- if verification_enabled
- - verification_record = "#{domain_presenter.verification_domain} TXT #{domain_presenter.keyed_verification_code}"
.form-group.border-section
.row
.col-sm-2
@@ -24,7 +23,7 @@
= gl_badge_tag text, variant: status
= link_to sprite_icon("redo"), verify_project_pages_domain_path(@project, domain_presenter), method: :post, class: "gl-ml-2 gl-button btn btn-sm btn-default has-tooltip", title: _("Retry verification")
.input-group
- = text_field_tag :domain_verification, verification_record, class: "monospace js-select-on-focus form-control", readonly: true
+ = text_field_tag :domain_verification, domain_presenter.verification_record, class: "monospace js-select-on-focus form-control", readonly: true
.input-group-append
= clipboard_button(target: '#domain_verification', class: 'btn-default d-none d-sm-block')
%p.form-text.text-muted
diff --git a/app/views/projects/pages_domains/_form.html.haml b/app/views/projects/pages_domains/_form.html.haml
index 9d9603b0947..bca955dcdae 100644
--- a/app/views/projects/pages_domains/_form.html.haml
+++ b/app/views/projects/pages_domains/_form.html.haml
@@ -1,6 +1,6 @@
- if domain_presenter.errors.any?
= render Pajamas::AlertComponent.new(variant: :danger, dismissible: false) do |c|
- = c.body do
+ - c.with_body do
- domain_presenter.errors.full_messages.each do |msg|
= msg
diff --git a/app/views/projects/pages_domains/show.html.haml b/app/views/projects/pages_domains/show.html.haml
index 5de5188ae6a..89e64d607a6 100644
--- a/app/views/projects/pages_domains/show.html.haml
+++ b/app/views/projects/pages_domains/show.html.haml
@@ -7,7 +7,7 @@
- if verification_enabled && domain_presenter.unverified?
= content_for :flash_message do
= render Pajamas::AlertComponent.new(variant: :warning, dismissible: false) do |c|
- = c.body do
+ - c.with_body do
.container-fluid.container-limited
= _("This domain is not verified. You will need to verify ownership before access is enabled.")
diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
index 0de31f59033..37b2b3ecfde 100644
--- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
+++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml
@@ -37,7 +37,7 @@
- if can?(current_user, :play_pipeline_schedule, pipeline_schedule)
= link_to play_pipeline_schedule_path(pipeline_schedule), method: :post, title: _('Play'), class: 'btn gl-button btn-default btn-icon' do
= sprite_icon('play')
- - if can?(current_user, :take_ownership_pipeline_schedule, pipeline_schedule)
+ - if can?(current_user, :admin_pipeline_schedule, pipeline_schedule) && pipeline_schedule.owner != current_user
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-take-ownership-button has-tooltip', title: s_('PipelineSchedule|Take ownership to edit'), data: { url: take_ownership_pipeline_schedule_path(pipeline_schedule) } }) do
= s_('PipelineSchedules|Take ownership')
- if can?(current_user, :update_pipeline_schedule, pipeline_schedule)
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 8f7f0a15e69..3ff370dfaa4 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -11,17 +11,17 @@
= preserve(markdown(commit.description, pipeline: :single_line))
.info-well
- .well-segment.pipeline-info{ class: "gl-align-items-baseline!" }
- .icon-container
- = sprite_icon('clock', css_class: 'gl-top-0!')
- - jobs = n_('%d job', '%d jobs', @pipeline.total_size) % @pipeline.total_size
- - if @pipeline.duration
- = s_('Pipelines|%{jobs} %{ref_text} in %{duration}').html_safe % { jobs: jobs, ref_text: @pipeline.ref_text, duration: time_interval_in_words(@pipeline.duration) }
- - else
- = jobs
+ .well-segment.pipeline-info{ class: "gl-align-items-baseline! gl-flex-direction-column" }
+ %div
+ .icon-container
+ = sprite_icon('clock', css_class: 'gl-top-0!')
+ = n_('%d job', '%d jobs', @pipeline.total_size) % @pipeline.total_size
= @pipeline.ref_text
- - if @pipeline.queued_duration
- = s_("Pipelines|(queued for %{queued_duration})") % { queued_duration: time_interval_in_words(@pipeline.queued_duration)}
+ - if @pipeline.finished_at
+ - duration = time_interval_in_words(@pipeline.duration)
+ - queued_duration = time_interval_in_words(@pipeline.queued_duration)
+ %span.gl-pl-7{ 'data-testid': 'pipeline-stats-text' }
+ = render_if_exists 'projects/pipelines/pipeline_stats_text', duration: duration, pipeline: @pipeline, queued_duration: queued_duration
- if has_pipeline_badges?(@pipeline)
.well-segment
diff --git a/app/views/projects/pipelines/_pipeline_stats_text.html.haml b/app/views/projects/pipelines/_pipeline_stats_text.html.haml
new file mode 100644
index 00000000000..8adf94e61c4
--- /dev/null
+++ b/app/views/projects/pipelines/_pipeline_stats_text.html.haml
@@ -0,0 +1 @@
+= s_("in %{duration} and was queued for %{queued_duration}").html_safe % { duration: duration, queued_duration: queued_duration }
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index d2b2a58fcf8..210f9c35c79 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -1,4 +1,5 @@
-- breadcrumb_title _('Pipelines')
+- breadcrumb_title s_('Pipeline|Run pipeline')
+- add_to_breadcrumbs s_('Pipeline|Pipelines'), project_pipelines_path(@project)
- page_title s_('Pipeline|Run pipeline')
%h1.page-title.gl-font-size-h-display
@@ -7,8 +8,9 @@
#js-new-pipeline{ data: { project_id: @project.id,
pipelines_path: project_pipelines_path(@project),
- config_variables_path: config_variables_namespace_project_pipelines_path(@project.namespace, @project),
default_branch: @project.default_branch,
+ pipelines_editor_path: project_ci_pipeline_editor_path(@project),
+ can_view_pipeline_editor: can_view_pipeline_editor?(@project),
ref_param: params[:ref] || @project.default_branch,
var_param: params[:var].to_json,
file_param: params[:file_var].to_json,
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index 9b0a81a2f60..a7d670f8475 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -17,11 +17,17 @@
= render "projects/pipelines/info", commit: @pipeline.commit
- if pipeline_has_errors
- .bs-callout.bs-callout-danger
- %h4= _('Unable to create pipeline')
- %ul
- - @pipeline.yaml_errors.split("\n").each do |error|
- %li= error
+ = render Pajamas::AlertComponent.new(title: s_('Pipelines|Unable to create pipeline'),
+ variant: :danger,
+ dismissible: false,
+ alert_options: { class: 'gl-mb-5' }) do |c|
+ - c.with_body do
+ %ul
+ - @pipeline.yaml_errors.split("\n").each do |error|
+ %li= error
+ - if can_view_pipeline_editor?(@project)
+ = render Pajamas::ButtonComponent.new(href: project_ci_pipeline_editor_path(@project), variant: :confirm) do
+ = s_("Pipelines|Go to the pipeline editor")
- else
#js-pipeline-tabs{ data: js_pipeline_tabs_data(@project, @pipeline, @current_user) }
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 4ac0e28d386..a0a90fbe204 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -25,7 +25,6 @@
classes: 'gl-md-w-auto gl-w-full gl-md-ml-3 gl-md-mt-0 gl-mt-3',
trigger_source: 'project-members-page',
display_text: _('Invite members') } }
- = render 'projects/invite_members_modal', project: @project, reload_page_on_submit: true
- else
- if project_can_be_shared?
%h4
diff --git a/app/views/projects/protected_tags/_create_protected_tag.html.haml b/app/views/projects/protected_tags/_create_protected_tag.html.haml
index d19a6401fc8..ef3974b04b5 100644
--- a/app/views/projects/protected_tags/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/_create_protected_tag.html.haml
@@ -1,9 +1,9 @@
- content_for :create_access_levels do
.create_access_levels-container
= dropdown_tag('Select',
- options: { toggle_class: 'js-allowed-to-create wide',
+ options: { toggle_class: 'js-allowed-to-create js-multiselect wide',
dropdown_class: 'dropdown-menu-selectable capitalize-header',
- dropdown_qa_selector: 'access_levels_content',
+ dropdown_qa_selector: 'access_levels_content', dropdown_testid: 'allowed-to-create-dropdown',
data: { field_name: 'protected_tag[create_access_levels_attributes][0][access_level]', input_id: 'create_access_levels_attributes', qa_selector: 'access_levels_dropdown' }})
= render 'projects/protected_tags/shared/create_protected_tag'
diff --git a/app/views/projects/protected_tags/_protected_tag.html.haml b/app/views/projects/protected_tags/_protected_tag.html.haml
index e0912bf39c0..68e4a5e97a3 100644
--- a/app/views/projects/protected_tags/_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/_protected_tag.html.haml
@@ -1,4 +1,4 @@
= render layout: 'projects/protected_tags/shared/protected_tag', locals: { protected_tag: protected_tag } do
- %td
- = render 'projects/protected_tags/protected_tag_create_access_levels', protected_tag: protected_tag, create_access_level: protected_tag.create_access_levels.for_role.first
+ %td.create_access_levels-container
+ = render 'projects/protected_tags/protected_tag_create_access_levels', protected_tag: protected_tag, create_access_level: protected_tag.create_access_levels.for_role
= render_if_exists 'projects/protected_tags/protected_tag_extra_create_access_levels', protected_tag: protected_tag
diff --git a/app/views/projects/protected_tags/_protected_tag_create_access_levels.haml b/app/views/projects/protected_tags/_protected_tag_create_access_levels.haml
index 1d4e9565156..30b9e3e9005 100644
--- a/app/views/projects/protected_tags/_protected_tag_create_access_levels.haml
+++ b/app/views/projects/protected_tags/_protected_tag_create_access_levels.haml
@@ -1,8 +1,8 @@
- protected_tag = local_assigns.fetch(:protected_tag)
- create_access_level = local_assigns.fetch(:create_access_level)
-- dropdown_label = create_access_level&.humanize || 'Select'
+- dropdown_label = create_access_level.first&.humanize || 'Select'
-= hidden_field_tag "allowed_to_create_#{protected_tag.id}", create_access_level&.access_level
+= hidden_field_tag "allowed_to_create_#{protected_tag.id}", create_access_level.first&.access_level
= dropdown_tag(dropdown_label,
- options: { toggle_class: 'js-allowed-to-create', dropdown_class: 'dropdown-menu-selectable capitalize-header js-allowed-to-create-container',
- data: { field_name: "allowed_to_create_#{protected_tag.id}", access_level_id: create_access_level&.id }})
+ options: { toggle_class: 'js-allowed-to-create js-multiselect', dropdown_class: 'dropdown-menu-selectable capitalize-header js-allowed-to-create-container',
+ data: { field_name: "allowed_to_create_#{protected_tag.id}", preselected_items: access_levels_data(create_access_level) }})
diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
index 1db1da5e428..d67c3dc19d7 100644
--- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
@@ -1,9 +1,9 @@
= gitlab_ui_form_for [@project, @protected_tag], html: { class: 'new-protected-tag js-new-protected-tag' } do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-tags-settings' }
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }) do |c|
- - c.header do
+ - c.with_header do
= _('Protect a tag')
- - c.body do
+ - c.with_body do
= form_errors(@protected_tag)
.form-group.row
= f.label :name, _('Tag:'), class: 'col-md-2 text-left text-md-right'
@@ -19,5 +19,5 @@
.create_access_levels-container
= yield :create_access_levels
- - c.footer do
+ - c.with_footer do
= f.submit _('Protect'), pajamas_button: true, disabled: true, data: { qa_selector: 'protect_tag_button' }
diff --git a/app/views/projects/readme_templates/default.md.tt b/app/views/projects/readme_templates/default.md.tt
index cd0b2db1d31..ad1d6cce08d 100644
--- a/app/views/projects/readme_templates/default.md.tt
+++ b/app/views/projects/readme_templates/default.md.tt
@@ -17,8 +17,8 @@ Already a pro? Just edit this README.md and make it your own. Want to make it ea
```
cd existing_repo
git remote add origin <%= project.http_url_to_repo %>
-git branch -M <%= project.default_branch_or_main %>
-git push -uf origin <%= project.default_branch_or_main %>
+git branch -M <%= params[:default_branch] %>
+git push -uf origin <%= params[:default_branch] %>
```
## Integrate with your tools
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index 910aab6da72..e1ec510d271 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -1,5 +1,4 @@
- page_title _("Container Registry")
-- @content_class = "limit-container-width" unless fluid_layout
- add_page_startup_graphql_call('container_registry/get_container_repositories', { fullPath: @project.full_path, first: 10, name: nil, isGroupPage: false, sort: nil})
%section
@@ -19,6 +18,7 @@
"gid_prefix": container_repository_gid_prefix,
"is_admin": current_user&.admin.to_s,
"show_cleanup_policy_link": show_cleanup_policy_link(@project).to_s,
+ "show_container_registry_settings": show_container_registry_settings(@project).to_s,
"cleanup_policies_settings_path": project_settings_packages_and_registries_path(@project),
connection_error: (!!@connection_error).to_s,
invalid_path_error: (!!@invalid_path_error).to_s,
diff --git a/app/views/projects/releases/new.html.haml b/app/views/projects/releases/new.html.haml
index 4348035a324..908cbd00f47 100644
--- a/app/views/projects/releases/new.html.haml
+++ b/app/views/projects/releases/new.html.haml
@@ -1,3 +1,5 @@
-- page_title s_('Releases|New Release')
+- add_to_breadcrumbs s_("Releases|Releases"), project_releases_path(@project)
+- page_title s_('Releases|New')
+- add_page_specific_style 'page_bundles/releases'
#js-new-release-page{ data: data_for_new_release_page }
diff --git a/app/views/projects/runners/_project_runners.html.haml b/app/views/projects/runners/_project_runners.html.haml
index 543a564568b..1d4e45c71b5 100644
--- a/app/views/projects/runners/_project_runners.html.haml
+++ b/app/views/projects/runners/_project_runners.html.haml
@@ -2,18 +2,26 @@
= s_('Runners|Project runners')
.bs-callout.help-callout
- - if can?(current_user, :register_project_runners, @project)
- = s_('Runners|These runners are assigned to this project.')
- %hr
- = render partial: 'ci/runner/how_to_setup_runner',
- locals: { registration_token: @project.runners_token,
- type: _('project'),
- reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path,
- project_path: @project.path_with_namespace,
- group_path: '' }
+ %p= s_('Runners|These runners are assigned to this project.')
+ - if Feature.enabled?(:create_runner_workflow_for_namespace, @project.namespace)
+ - if can?(current_user, :create_runner, @project)
+ = render Pajamas::ButtonComponent.new(href: new_project_runner_path(@project), variant: :confirm) do
+ = s_('Runners|New project runner')
+ #js-project-runner-registration-dropdown{ data: { registration_token: @project.runners_token, project_id: @project.id } }
+ - else
+ = _('Please contact an admin to create runners.')
+ = link_to _('Learn more.'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer'
- else
- = _('Please contact an admin to register runners.')
- = link_to _('Learn more.'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer'
+ - if can?(current_user, :register_project_runners, @project)
+ = render partial: 'ci/runner/how_to_setup_runner',
+ locals: { registration_token: @project.runners_token,
+ type: _('project'),
+ reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path,
+ project_path: @project.path_with_namespace,
+ group_path: '' }
+ - else
+ = _('Please contact an admin to register runners.')
+ = link_to _('Learn more.'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer'
%hr
diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
index ce56b160187..58955663bfa 100644
--- a/app/views/projects/runners/edit.html.haml
+++ b/app/views/projects/runners/edit.html.haml
@@ -1,10 +1,11 @@
+- runner_name = runner_short_name(@runner)
- breadcrumb_title _('Edit')
-- page_title _('Edit'), "##{@runner.id} (#{@runner.short_sha})"
+- page_title _('Edit'), runner_name
- add_to_breadcrumbs _('CI/CD Settings'), project_settings_ci_cd_path(@project)
-- add_to_breadcrumbs "#{@runner.short_sha}", project_runner_path(@project, @runner)
+- add_to_breadcrumbs runner_name, project_runner_path(@project, @runner)
%h1.page-title.gl-font-size-h-display
- = s_('Runners|Runner #%{runner_id}' % { runner_id: @runner.id })
+ = s_('Runners|Runner #%{runner_id}') % { runner_id: @runner.id }
= render 'shared/runners/runner_type_badge', runner: @runner
= render 'shared/runners/runner_type_alert', runner: @runner
diff --git a/app/views/projects/runners/new.html.haml b/app/views/projects/runners/new.html.haml
new file mode 100644
index 00000000000..4aeed910452
--- /dev/null
+++ b/app/views/projects/runners/new.html.haml
@@ -0,0 +1,5 @@
+- add_to_breadcrumbs _('CI/CD Settings'), project_settings_ci_cd_path(@project)
+- breadcrumb_title s_('Runners|New runner')
+- page_title s_('Runners|Create a project runner')
+
+#js-project-new-runner{ data: { project_id: @project.to_global_id } }
diff --git a/app/views/projects/runners/register.html.haml b/app/views/projects/runners/register.html.haml
new file mode 100644
index 00000000000..a8ce08f051f
--- /dev/null
+++ b/app/views/projects/runners/register.html.haml
@@ -0,0 +1,6 @@
+- runner_name = runner_short_name(@runner)
+- add_to_breadcrumbs _('CI/CD Settings'), project_settings_ci_cd_path(@project)
+- breadcrumb_title s_('Runners|Register runner')
+- page_title s_('Runners|Register'), runner_name
+
+#js-project-register-runner{ data: { runner_id: @runner.id, runners_path: project_runners_path(@project) } }
diff --git a/app/views/projects/runners/show.html.haml b/app/views/projects/runners/show.html.haml
index cb7984729c8..60f403b1015 100644
--- a/app/views/projects/runners/show.html.haml
+++ b/app/views/projects/runners/show.html.haml
@@ -1,3 +1,6 @@
+- runner_name = runner_short_name(@runner)
+- breadcrumb_title runner_name
+- page_title runner_name
- add_to_breadcrumbs _('CI/CD Settings'), project_settings_ci_cd_path(@project)
= render 'shared/runners/runner_details', runner: @runner
diff --git a/app/views/projects/security/configuration/show.html.haml b/app/views/projects/security/configuration/show.html.haml
index 4b82f74d035..63e175f96e5 100644
--- a/app/views/projects/security/configuration/show.html.haml
+++ b/app/views/projects/security/configuration/show.html.haml
@@ -1,6 +1,5 @@
-- breadcrumb_title _("Security Configuration")
-- page_title _("Security Configuration")
-- @content_class = "limit-container-width" unless fluid_layout
+- breadcrumb_title _("Security configuration")
+- page_title _("Security configuration")
#js-security-configuration{ data: { **@configuration.to_html_data_attribute,
vulnerability_training_docs_path: vulnerability_training_docs_path,
diff --git a/app/views/projects/settings/_general.html.haml b/app/views/projects/settings/_general.html.haml
index 5f1dee39e25..847f9ad3e2a 100644
--- a/app/views/projects/settings/_general.html.haml
+++ b/app/views/projects/settings/_general.html.haml
@@ -16,7 +16,6 @@
.row
.form-group.col-md-9
- = f.label :topics, _('Topics'), class: 'label-bold'
.js-topics-selector{ data: { hidden_input_id: hidden_topics_field_id } }
= f.hidden_field :topics, value: @project.topic_list.join(', '), id: hidden_topics_field_id
@@ -31,8 +30,7 @@
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
.form-group.gl-mt-3.gl-mb-3
- .avatar-container.rect-avatar.s90
- = project_icon(@project, alt: _('Project avatar'), class: 'avatar project-avatar s90')
+ = render Pajamas::AvatarComponent.new(@project, size: 96, alt: '', class: 'gl-float-left gl-mr-5')
= f.label :avatar, _('Project avatar'), class: 'label-bold d-block'
= render 'shared/choose_avatar_button', f: f
- if @project.avatar?
diff --git a/app/views/projects/settings/access_tokens/index.html.haml b/app/views/projects/settings/access_tokens/index.html.haml
index f6c5c4e2950..26c08fcdfe4 100644
--- a/app/views/projects/settings/access_tokens/index.html.haml
+++ b/app/views/projects/settings/access_tokens/index.html.haml
@@ -2,7 +2,7 @@
- page_title _('Project Access Tokens')
- type = _('project access token')
- type_plural = _('project access tokens')
-- @content_class = 'limit-container-width' unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4
diff --git a/app/views/projects/settings/branch_rules/index.html.haml b/app/views/projects/settings/branch_rules/index.html.haml
index 80a41bb579b..efebc4223d9 100644
--- a/app/views/projects/settings/branch_rules/index.html.haml
+++ b/app/views/projects/settings/branch_rules/index.html.haml
@@ -1,6 +1,9 @@
- add_to_breadcrumbs _('Repository Settings'), project_settings_repository_path(@project)
+- add_to_breadcrumbs _('Branch rules'), project_settings_repository_path(@project, anchor: 'branch-rules')
+- breadcrumb_title _('Details')
+- @breadcrumb_link = '#'
- page_title s_('BranchRules|Branch rules details')
-%h3.gl-mb-5= s_('BranchRules|Branch rules details')
+%h3.gl-mb-5= page_title
-#js-branch-rules{ data: { project_path: @project.full_path, protected_branches_path: project_settings_repository_path(@project, anchor: 'js-protected-branches-settings'), approval_rules_path: project_settings_merge_requests_path(@project, anchor: 'js-merge-request-approval-settings'), status_checks_path: project_settings_merge_requests_path(@project, anchor: 'js-merge-request-settings'), branches_path: project_branches_path(@project) } }
+#js-branch-rules{ data: branch_rules_data(@project) }
diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
index 86238a41f0b..46cfcf20535 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -20,15 +20,15 @@
%fieldset.builds-feature.js-auto-devops-settings
.form-group
= f.fields_for :auto_devops_attributes, @auto_devops do |form|
- .card.gl-mb-3
- .card-body
+ = render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-3' }, footer_options: { class: auto_devops_enabled || 'hidden' }) do |c|
+ - c.with_body do
- autodevops_help_link = link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer'
- auto_devops_badge = auto_devops_enabled ? (gl_badge_tag badge_for_auto_devops_scope(@project), { variant: :info }, { class: 'js-instance-default-badge gl-ml-3 gl-mt-n1'}) : ''
= form.gitlab_ui_checkbox_component :enabled,
(s_('CICD|Default to Auto DevOps pipeline') + auto_devops_badge).html_safe,
checkbox_options: { class: 'js-toggle-extra-settings', checked: auto_devops_enabled, data: { qa_selector: 'enable_autodevops_checkbox' } },
help_text: (s_('CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found.') + ' ' + autodevops_help_link).html_safe
- .card-footer.js-extra-settings{ class: auto_devops_enabled || 'hidden' }
+ - c.with_footer do
- if @project.all_clusters.empty?
%p.settings-message.text-center
= s_('CICD|Add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable.').html_safe % { kubernetes_cluster_link_start: kubernetes_cluster_link_start, link_end: link_end }
diff --git a/app/views/projects/settings/ci_cd/_badge.html.haml b/app/views/projects/settings/ci_cd/_badge.html.haml
index 99eef38827b..e9766b36c79 100644
--- a/app/views/projects/settings/ci_cd/_badge.html.haml
+++ b/app/views/projects/settings/ci_cd/_badge.html.haml
@@ -3,14 +3,14 @@
%h4
= badge.title.capitalize
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, header_options: { class: 'gl-display-flex gl-align-items-center' }) do |c|
- - c.header do
+ - c.with_header do
.gl-flex-grow-1
%b
= badge.title.capitalize
&middot;
= badge.to_html
- = render 'shared/ref_switcher', destination: 'badges', align_right: true
- - c.body do
+ .js-ref-switcher-badge{ id: "js-project-ci-cd-ref-switcher-#{badge.title.parameterize(separator: '-') }", data: { project_id: @project.id, ref: @ref } }
+ - c.with_body do
.row
.col-md-2.gl-text-center
Markdown
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index 68dc7f2be8d..6f64d3f3f76 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -18,7 +18,7 @@
_("Auto-cancel redundant pipelines"),
checked_value: 'enabled',
unchecked_value: 'disabled',
- help_text: (_('New pipelines cause older pending or running pipelines on the same branch to be cancelled.') + ' ' + help_link_auto_canceling).html_safe
+ help_text: (_('Pipelines for new changes cause older pending or running pipelines on the same branch to be cancelled.') + ' ' + help_link_auto_canceling).html_safe
.form-group
= f.fields_for :ci_cd_settings_attributes, @project.ci_cd_settings do |form|
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index b27f5a0e5ed..c7bb6a7f5da 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -1,6 +1,6 @@
-- @content_class = "limit-container-width" unless fluid_layout
- page_title _("CI/CD Settings")
- page_title _("CI/CD")
+- @force_desktop_expanded_sidebar = true
- expanded = expanded_by_default?
- general_expanded = @project.errors.empty? ? expanded : true
@@ -58,7 +58,7 @@
%p
= _("A job artifact is an archive of files and directories saved by a job when it finishes.")
.settings-content
- #js-artifacts-settings-app{ data: { full_path: @project.full_path, help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'keep-artifacts-from-most-recent-successful-jobs') } }
+ #js-artifacts-settings-app{ data: { full_path: @project.full_path, help_page_path: help_page_path('ci/jobs/job_artifacts', anchor: 'keep-artifacts-from-most-recent-successful-jobs') } }
%section.settings.no-animate#js-cicd-variables-settings{ class: ('expanded' if expanded), data: { qa_selector: 'variables_settings_content' } }
.settings-header
diff --git a/app/views/projects/settings/integrations/_form.html.haml b/app/views/projects/settings/integrations/_form.html.haml
index 9d74f99bb19..39dfd410727 100644
--- a/app/views/projects/settings/integrations/_form.html.haml
+++ b/app/views/projects/settings/integrations/_form.html.haml
@@ -8,9 +8,12 @@
= render Pajamas::AlertComponent.new(title: s_('ExternalIssueIntegration|Another issue tracker is already in use'),
variant: :warning,
dismissible: false) do |c|
- = c.body do
+ - c.with_body do
= s_('ExternalIssueIntegration|Only one issue tracker integration can be active at a time. Please disable the active tracker first and try again.')
+- if integration.to_param === 'slack'
+ = render 'shared/integrations/slack_notifications_deprecation_alert'
+
%h2.gl-mb-4
= integration.title
- if integration.operating?
diff --git a/app/views/projects/settings/integrations/edit.html.haml b/app/views/projects/settings/integrations/edit.html.haml
index 46276e6c6c9..84d3ac2ded9 100644
--- a/app/views/projects/settings/integrations/edit.html.haml
+++ b/app/views/projects/settings/integrations/edit.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title @integration.title
- add_to_breadcrumbs _('Integration Settings'), project_settings_integrations_path(@project)
- page_title @integration.title, _('Integrations')
-- @content_class = 'limit-container-width' unless fluid_layout
= render 'form', integration: @integration
diff --git a/app/views/projects/settings/integrations/index.html.haml b/app/views/projects/settings/integrations/index.html.haml
index 2077d244b24..59cdda5bb92 100644
--- a/app/views/projects/settings/integrations/index.html.haml
+++ b/app/views/projects/settings/integrations/index.html.haml
@@ -1,6 +1,8 @@
-- @content_class = "limit-container-width" unless fluid_layout
- breadcrumb_title _('Integration Settings')
- page_title _('Integrations')
+- @force_desktop_expanded_sidebar = true
+
+= render 'shared/integrations/slack_notifications_deprecation_alert'
%section.js-search-settings-section
%h3= _('Integrations')
diff --git a/app/views/projects/settings/members/show.html.haml b/app/views/projects/settings/members/show.html.haml
index 5fca734222b..5c9389c9c1c 100644
--- a/app/views/projects/settings/members/show.html.haml
+++ b/app/views/projects/settings/members/show.html.haml
@@ -1,5 +1,3 @@
-- @content_class = "limit-container-width" unless fluid_layout
-
- page_title _("Members")
= render "projects/project_members/index"
diff --git a/app/views/projects/settings/merge_requests/show.html.haml b/app/views/projects/settings/merge_requests/show.html.haml
index 7dfd304e07b..ef528d17fc9 100644
--- a/app/views/projects/settings/merge_requests/show.html.haml
+++ b/app/views/projects/settings/merge_requests/show.html.haml
@@ -1,6 +1,6 @@
- breadcrumb_title _('Merge requests')
- page_title _('Merge requests')
-- @content_class = 'limit-container-width' unless fluid_layout
+- @force_desktop_expanded_sidebar = true
%section.rspec-merge-request-settings.settings.merge-requests-feature.no-animate#js-merge-request-settings.expanded{ class: [('hidden' if @project.project_feature.send(:merge_requests_access_level) == 0)], data: { qa_selector: 'merge_request_settings_content' } }
.settings-header
diff --git a/app/views/projects/settings/operations/show.html.haml b/app/views/projects/settings/operations/show.html.haml
index 90e0ccce8b4..d44ebf1eb83 100644
--- a/app/views/projects/settings/operations/show.html.haml
+++ b/app/views/projects/settings/operations/show.html.haml
@@ -1,10 +1,15 @@
-- @content_class = 'limit-container-width' unless fluid_layout
- page_title _('Monitor Settings')
- breadcrumb_title _('Monitor Settings')
+- @force_desktop_expanded_sidebar = true
+
+- if Feature.disabled?(:remove_monitor_metrics)
+ = render 'projects/settings/operations/metrics_dashboard'
-= render 'projects/settings/operations/metrics_dashboard'
= render 'projects/settings/operations/error_tracking'
= render 'projects/settings/operations/alert_management'
= render 'projects/settings/operations/incidents'
-= render 'projects/settings/operations/grafana_integration'
+
+- if Feature.disabled?(:remove_monitor_metrics)
+ = render 'projects/settings/operations/grafana_integration'
+
= render_if_exists 'projects/settings/operations/status_page'
diff --git a/app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml b/app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml
index d27d268d65e..ad9ba0b506c 100644
--- a/app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml
+++ b/app/views/projects/settings/packages_and_registries/cleanup_tags.html.haml
@@ -1,6 +1,5 @@
- add_to_breadcrumbs _('Packages and registries settings'), project_settings_packages_and_registries_path(@project)
-- breadcrumb_title s_('ContainerRegistry|Clean up image tags')
-- page_title s_('ContainerRegistry|Clean up image tags'), _('Packages and registries settings')
-- @content_class = 'limit-container-width' unless fluid_layout
+- breadcrumb_title s_('ContainerRegistry|Cleanup policies')
+- page_title s_('ContainerRegistry|Cleanup policies'), _('Packages and registries settings')
#js-registry-settings-cleanup-image-tags{ data: cleanup_settings_data }
diff --git a/app/views/projects/settings/packages_and_registries/show.html.haml b/app/views/projects/settings/packages_and_registries/show.html.haml
index c81b38f44dd..6f38a3ace92 100644
--- a/app/views/projects/settings/packages_and_registries/show.html.haml
+++ b/app/views/projects/settings/packages_and_registries/show.html.haml
@@ -1,5 +1,5 @@
- breadcrumb_title _('Packages and registries settings')
- page_title _('Packages and registries settings')
-- @content_class = 'limit-container-width' unless fluid_layout
+- @force_desktop_expanded_sidebar = true
#js-registry-settings{ data: settings_data }
diff --git a/app/views/projects/settings/repository/show.html.haml b/app/views/projects/settings/repository/show.html.haml
index de171a25e8d..12404180362 100644
--- a/app/views/projects/settings/repository/show.html.haml
+++ b/app/views/projects/settings/repository/show.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _("Repository Settings")
- page_title _("Repository")
-- @content_class = "limit-container-width" unless fluid_layout
- deploy_token_description = s_('DeployTokens|Deploy tokens allow access to packages, your repository, and registry images.')
+- @force_desktop_expanded_sidebar = true
= render "projects/branch_defaults/show"
- if Feature.enabled?(:branch_rules, @project)
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 5fa70c3af32..8a35db357ee 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -1,5 +1,4 @@
- current_route_path = request.fullpath.match(%r{-/tree/[^/]+/(.+$)}).to_a[1]
-- @content_class = "limit-container-width" unless fluid_layout
- @skip_current_level_breadcrumb = true
- add_page_specific_style 'page_bundles/project'
- add_page_specific_style 'page_bundles/tree'
@@ -8,7 +7,9 @@
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
= render_if_exists 'shared/ultimate_feature_removal_banner', project: @project
+= render_if_exists 'shared/promotions/promote_mobile_devops', project: @project
= render partial: 'flash_messages', locals: { project: @project }
+
= render 'clusters_deprecation_alert'
= render "projects/last_push"
diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml
index d9bf064ad24..6e1ebdeedf0 100644
--- a/app/views/projects/snippets/edit.html.haml
+++ b/app/views/projects/snippets/edit.html.haml
@@ -1,7 +1,6 @@
- add_to_breadcrumbs _("Snippets"), project_snippets_path(@project)
- breadcrumb_title @snippet.to_reference
- page_title _("Edit"), "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
-- @content_class = "limit-container-width" unless fluid_layout
%h1.page-title.gl-font-size-h-display
= _("Edit Snippet")
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index f53b2051835..7c936c849d0 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -4,7 +4,7 @@
- if @snippets.exists?
- if current_user
.top-area
- - include_private = @project.team.member?(current_user) || current_user.admin?
+ - include_private = @project.member?(current_user) || current_user.admin?
= render partial: 'snippets/snippets_scope_menu', locals: { subject: @project, include_private: include_private, counts: @snippet_counts }
- if new_project_snippet_link.present?
diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml
index 5086b5eaa3d..fd74ffef425 100644
--- a/app/views/projects/snippets/new.html.haml
+++ b/app/views/projects/snippets/new.html.haml
@@ -1,9 +1,7 @@
- add_to_breadcrumbs _("Snippets"), project_snippets_path(@project)
- breadcrumb_title _("New")
- page_title _("New Snippet")
-- @content_class = "limit-container-width" unless fluid_layout
%h1.page-title.gl-font-size-h-display
= _("New Snippet")
-%hr
= render "shared/snippets/form", url: project_snippets_path(@project, @snippet)
diff --git a/app/views/projects/starrers/_starrer.html.haml b/app/views/projects/starrers/_starrer.html.haml
index c1cd2488142..16ae003255c 100644
--- a/app/views/projects/starrers/_starrer.html.haml
+++ b/app/views/projects/starrers/_starrer.html.haml
@@ -1,8 +1,8 @@
- starrer = local_assigns.fetch(:starrer)
.col-lg-3.col-md-4.col-sm-12
- .card
- .card-body.gl-display-flex
+ = render Pajamas::CardComponent.new(body_options: { class: 'gl-display-flex' }) do |c|
+ - c.with_body do
= render Pajamas::AvatarComponent.new(starrer.user, size: 48, alt: "", class: 'gl-mr-3')
.user-info
diff --git a/app/views/projects/tags/_edit_release_button.html.haml b/app/views/projects/tags/_edit_release_button.html.haml
index 1c2626e5612..9a6c18df2ca 100644
--- a/app/views/projects/tags/_edit_release_button.html.haml
+++ b/app/views/projects/tags/_edit_release_button.html.haml
@@ -5,5 +5,5 @@
- if release
- release_btn_text = s_('TagsPage|Edit release')
- release_btn_path = edit_project_release_path(project, release)
-= link_to release_btn_path, class: css_classes, title: release_btn_text, data: { container: "body" } do
- = sprite_icon('pencil', css_class: 'gl-icon')
+= link_to release_btn_path, class: css_classes do
+ = release_btn_text
diff --git a/app/views/projects/tags/_release_link.html.haml b/app/views/projects/tags/_release_link.html.haml
index 6c79b13f438..9284204af77 100644
--- a/app/views/projects/tags/_release_link.html.haml
+++ b/app/views/projects/tags/_release_link.html.haml
@@ -1,5 +1,5 @@
- if can?(current_user, :read_release, release)
- .gl-text-secondary
- = sprite_icon("rocket", size: 12)
- = _("Release")
+ %span
+ = sprite_icon("rocket", size: 12, css_class: "gl-text-secondary")
+ = _("Release:")
= link_to release.name, project_release_path(project, release), class: "gl-text-blue-600!"
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index fcad8509a7d..cc49ff9e293 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -2,9 +2,9 @@
- release = @releases.find { |release| release.tag == tag.name }
- commit_status = @tag_pipeline_statuses[tag.name] unless @tag_pipeline_statuses.nil?
-%li.flex-row.js-tag-list{ class: "gl-white-space-normal! gl-align-items-flex-start!" }
+%li.gl-justify-content-space-between{ class: "gl-md-display-flex! gl-align-items-flex-start!", data: { testid: 'tag-row' } }
.row-main-content
- = sprite_icon('tag')
+ = sprite_icon('tag', css_class: "gl-text-secondary")
= link_to tag.name, project_tag_path(@project, tag.name), class: 'item-title ref-name'
- if protected_tag?(@project, tag)
@@ -21,12 +21,13 @@
= render 'release_link', project: @project, release: release
- if tag.message.present?
- %pre.wrap
+ %pre.wrap.gl-mt-3.gl-max-w-80
= strip_signature(tag.message)
- .row-fixed-content.controls.flex-row
+ .row-fixed-content.flex-row
- if tag.has_signature?
- = render partial: 'projects/commit/signature', object: tag.signature
+ .gl-mr-3
+ = render partial: 'projects/commit/signature', object: tag.signature
- if commit_status
= render 'ci/status/icon', size: 24, status: commit_status, option_css_classes: 'gl-display-inline-flex gl-vertical-align-middle gl-mr-5'
@@ -34,8 +35,11 @@
.gl-display-inline-flex.gl-vertical-align-middle.gl-mr-5
%svg.s24
- = render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
-
- if can?(current_user, :admin_tag, @project)
= render 'edit_release_button', tag: tag, project: @project, release: release, option_css_classes: 'gl-mr-3!'
+
+ .gl-mr-3
+ = render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
+
+ - if can?(current_user, :admin_tag, @project)
= render 'projects/buttons/remove_tag', project: @project, tag: tag
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index 2f8291d255f..1df323e7451 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -1,9 +1,10 @@
-- page_title s_('TagsPage|New Tag')
+- add_to_breadcrumbs s_('TagsPage|Tags'), project_tags_path(@project)
+- page_title s_('TagsPage|New')
- default_ref = params[:ref] || @project.default_branch
- if @error
= render Pajamas::AlertComponent.new(variant: :danger, dismissible: true) do |c|
- = c.body do
+ - c.with_body do
= @error
%h1.page-title.gl-font-size-h-display
@@ -37,4 +38,3 @@
= s_('TagsPage|Create tag')
= render Pajamas::ButtonComponent.new(href: project_tags_path(@project)) do
= s_('TagsPage|Cancel')
-
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index a9c3309e38c..3124f47c832 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -57,13 +57,5 @@
%pre.wrap{ data: { qa_selector: 'tag_message_content' } }
= strip_signature(@tag.message)
-- if can?(current_user, :read_release, @release)
- .gl-mb-3.gl-mt-3
- - if @release&.description.present?
- .description.md{ data: { qa_selector: 'tag_release_notes_content' } }
- = markdown_field(@release, :description)
- - else
- = s_('TagsPage|This tag has no release notes.')
-
- if can?(current_user, :admin_tag, @project)
.js-delete-tag-modal
diff --git a/app/views/projects/terraform/index.html.haml b/app/views/projects/terraform/index.html.haml
index 21a4fe5eae6..2182778469a 100644
--- a/app/views/projects/terraform/index.html.haml
+++ b/app/views/projects/terraform/index.html.haml
@@ -1,6 +1,6 @@
- add_page_specific_style 'page_bundles/ci_status'
-- breadcrumb_title _('Terraform')
-- page_title _('Terraform')
+- breadcrumb_title s_('Terraform|Terraform states')
+- page_title s_('Terraform|Terraform states')
#js-terraform-list{ data: js_terraform_list_data(current_user, @project) }
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index d494d9cc36d..c834a0bc818 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -1,7 +1,7 @@
- is_project_overview = local_assigns.fetch(:is_project_overview, false)
.tree-ref-container.gl-display-flex.gl-flex-wrap.gl-gap-2.mb-2.mb-md-0
- .tree-ref-holder.gl-max-w-26
+ .tree-ref-holder.gl-max-w-26{ data: { qa_selector: 'ref_dropdown_container' } }
#js-tree-ref-switcher{ data: { project_id: @project.id, ref_type: @ref_type.to_s, project_root_path: project_path(@project) } }
#js-repo-breadcrumb{ data: breadcrumb_data_attributes }
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 6d1ab80bdc5..fbbf1c04613 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -4,7 +4,6 @@
- add_page_startup_graphql_call('repository/permissions', { projectPath: @project.full_path })
- add_page_startup_graphql_call('repository/files', { nextPageCursor: "", pageSize: 100, projectPath: @project.full_path, ref: current_ref, path: current_route_path || "/"})
- breadcrumb_title _("Repository")
-- @content_class = "limit-container-width" unless fluid_layout
- page_title @path.presence || _("Files"), @ref
= content_for :meta_tags do
diff --git a/app/views/projects/triggers/_index.html.haml b/app/views/projects/triggers/_index.html.haml
index de127d15351..b68aad24b50 100644
--- a/app/views/projects/triggers/_index.html.haml
+++ b/app/views/projects/triggers/_index.html.haml
@@ -1,13 +1,13 @@
.row.gl-mt-3.gl-mb-3
.col-lg-12
= render Pajamas::CardComponent.new do |c|
- - c.header do
+ - c.with_header do
= _("Manage your project's triggers")
- - c.body do
+ - c.with_body do
= render 'projects/triggers/form', btn_text: _('Add trigger')
.gl-mb-5
#js-ci-pipeline-triggers-list.triggers-list{ data: { triggers: @triggers_json } }
- - c.footer do
+ - c.with_footer do
%p
= _("These examples show how to trigger this project's pipeline for a branch or tag.")
diff --git a/app/views/projects/usage_quotas/index.html.haml b/app/views/projects/usage_quotas/index.html.haml
index 5e2217d3c9f..aad96151678 100644
--- a/app/views/projects/usage_quotas/index.html.haml
+++ b/app/views/projects/usage_quotas/index.html.haml
@@ -1,11 +1,13 @@
- page_title s_("UsageQuota|Usage")
+- add_page_specific_style 'page_bundles/projects_usage_quotas'
+- @force_desktop_expanded_sidebar = true
= render_if_exists 'shared/ultimate_feature_removal_banner', project: @project
= render Pajamas::AlertComponent.new(title: _('Repository usage recalculation started'),
variant: :info,
alert_options: { class: 'js-recalculation-started-alert gl-mt-4 gl-mb-5 gl-display-none' }) do |c|
- = c.body do
+ - c.with_body do
= _('To view usage, refresh this page in a few minutes.')
%h1.page-title.gl-font-size-h-display
@@ -17,10 +19,12 @@
%a{ href: help_page_path('user/usage_quotas.md'), target: '_blank', rel: 'noopener noreferrer' }
= s_('UsageQuota|Learn more about usage quotas') + '.'
-= gl_tabs_nav do
+= gl_tabs_nav({ id: 'js-project-usage-quotas-tabs' }) do
= gl_tab_link_to '#storage-quota-tab', item_active: true do
= s_('UsageQuota|Storage')
+ = render_if_exists 'projects/usage_quotas/transfer_tab_link'
.tab-content
.tab-pane.active#storage-quota-tab
#js-project-storage-count-app{ data: { project_path: @project.full_path } }
+ = render_if_exists 'projects/usage_quotas/transfer_tab_content'
diff --git a/app/views/projects/work_items/index.html.haml b/app/views/projects/work_items/index.html.haml
index 69597aab7ef..01b27eed267 100644
--- a/app/views/projects/work_items/index.html.haml
+++ b/app/views/projects/work_items/index.html.haml
@@ -1,7 +1,7 @@
-- page_title s_('WorkItem|Work Items')
+- page_title "##{request.params['work_items_path']}"
+- add_to_breadcrumbs _("Issues"), project_issues_path(@project)
- add_page_specific_style 'page_bundles/work_items'
- @gfm_form = true
- @noteable_type = 'WorkItem'
#js-work-items{ data: work_items_index_data(@project) }
-= render 'projects/invite_members_modal', project: @project
diff --git a/app/views/protected_branches/shared/_branches_list.html.haml b/app/views/protected_branches/shared/_branches_list.html.haml
index 8235411d240..ed2d420ffcd 100644
--- a/app/views/protected_branches/shared/_branches_list.html.haml
+++ b/app/views/protected_branches/shared/_branches_list.html.haml
@@ -26,7 +26,7 @@
%th
= s_("ProtectedBranch|Allowed to force push")
%span.has-tooltip{ data: { container: 'body' }, title: s_('ProtectedBranch|Allow all users with push access to force push.'), 'aria-hidden': 'true' }
- = sprite_icon('question', size: 16, css_class: 'gl-text-gray-500')
+ = sprite_icon('question-o', size: 16, css_class: 'gl-text-blue-500')
= render_if_exists 'protected_branches/ee/code_owner_approval_table_head', protected_branch_entity: protected_branch_entity
diff --git a/app/views/protected_branches/shared/_create_protected_branch.html.haml b/app/views/protected_branches/shared/_create_protected_branch.html.haml
index 109d92af8a7..9bc224b2e78 100644
--- a/app/views/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/protected_branches/shared/_create_protected_branch.html.haml
@@ -40,3 +40,5 @@
= render_if_exists 'protected_branches/ee/code_owner_approval_form', f: f, protected_branch_entity: protected_branch_entity
- c.footer do
= f.submit s_('ProtectedBranch|Protect'), disabled: true, data: { qa_selector: 'protect_button' }, pajamas_button: true
+
+ .js-alert-protected-branch-created-container.gl-mb-5
diff --git a/app/views/protected_branches/shared/_update_protected_branch.html.haml b/app/views/protected_branches/shared/_update_protected_branch.html.haml
index 0244f9e2158..ad61f557bb8 100644
--- a/app/views/protected_branches/shared/_update_protected_branch.html.haml
+++ b/app/views/protected_branches/shared/_update_protected_branch.html.haml
@@ -1,37 +1,21 @@
- merge_access_levels = protected_branch.merge_access_levels.for_role
- push_access_levels = protected_branch.push_access_levels.for_role
-- user_merge_access_levels = protected_branch.merge_access_levels.for_user
-- user_push_access_levels = protected_branch.push_access_levels.for_user
-
-- group_merge_access_levels = protected_branch.merge_access_levels.for_group
-- group_push_access_levels = protected_branch.push_access_levels.for_group
-
%td.merge_access_levels-container
= hidden_field_tag "allowed_to_merge_#{protected_branch.id}", merge_access_levels.first&.access_level
= dropdown_tag((merge_access_levels.first&.humanize || 'Select') ,
options: { toggle_class: 'js-allowed-to-merge', dropdown_class: 'dropdown-menu-selectable js-allowed-to-merge-container capitalize-header',
data: { field_name: "allowed_to_merge_#{protected_branch.id}", preselected_items: access_levels_data(merge_access_levels) }})
- - if user_merge_access_levels.any?
- %p.small
- = _('The following %{user} can also merge into this branch: %{branch}') % { user: 'user'.pluralize(user_merge_access_levels.size), branch: user_merge_access_levels.map(&:humanize).to_sentence }
-
- - if group_merge_access_levels.any?
- %p.small
- = _('Members of %{group} can also merge into this branch: %{branch}') % { group: (group_merge_access_levels.size > 1 ? 'these groups' : 'this group'), branch: group_merge_access_levels.map(&:humanize).to_sentence }
+ = render_if_exists 'protected_branches/shared/user_merge_access_levels', protected_branch: protected_branch
+ = render_if_exists 'protected_branches/shared/group_merge_access_levels', protected_branch: protected_branch
%td.push_access_levels-container
= hidden_field_tag "allowed_to_push_#{protected_branch.id}", push_access_levels.first&.access_level
= dropdown_tag((push_access_levels.first&.humanize || 'Select') ,
options: { toggle_class: "js-allowed-to-push js-multiselect", dropdown_class: 'dropdown-menu-selectable js-allowed-to-push-container capitalize-header',
data: { field_name: "allowed_to_push_#{protected_branch.id}", preselected_items: access_levels_data(push_access_levels) }})
- - if user_push_access_levels.any?
- %p.small
- = _('The following %{user} can also push to this branch: %{branch}') % { user: 'user'.pluralize(user_push_access_levels.size), branch: user_push_access_levels.map(&:humanize).to_sentence }
-
- - if group_push_access_levels.any?
- %p.small
- = _('Members of %{group} can also push to this branch: %{branch}') % { group: (group_push_access_levels.size > 1 ? 'these groups' : 'this group'), branch: group_push_access_levels.map(&:humanize).to_sentence }
+ = render_if_exists 'protected_branches/shared/user_push_access_levels', protected_branch: protected_branch
+ = render_if_exists 'protected_branches/shared/group_push_access_levels', protected_branch: protected_branch
%td
= render Pajamas::ToggleComponent.new(classes: 'js-force-push-toggle',
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
index f4e9a597fe2..6c8ab5654a0 100644
--- a/app/views/registrations/welcome/show.html.haml
+++ b/app/views/registrations/welcome/show.html.haml
@@ -1,6 +1,7 @@
- @html_class = "subscriptions-layout-html"
- page_title _('Your profile')
- add_page_specific_style 'page_bundles/signup'
+- add_page_specific_style 'page_bundles/login'
- gitlab_experience_text = _('To personalize your GitLab experience, we\'d like to know a bit more about you')
- content_for :page_specific_javascripts do
= render "layouts/google_tag_manager_head"
@@ -17,7 +18,7 @@
- else
%p.gl-text-center= html_escape(_('%{gitlab_experience_text}. Don\'t worry, this information isn\'t shared outside of your self-managed GitLab instance.')) % { gitlab_experience_text: gitlab_experience_text }
= gitlab_ui_form_for(current_user,
- url: users_sign_up_welcome_path(glm_tracking_params),
+ url: users_sign_up_welcome_path(welcome_update_params),
html: { class: 'gl-w-full! gl-p-5 js-users-signup-welcome',
'aria-live' => 'assertive',
data: { testid: 'welcome-form' } }) do |f|
@@ -28,7 +29,7 @@
.row
.form-group.col-sm-12
= f.label :role, _('Role'), class: 'label-bold'
- = f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { include_blank: _('Select a role') }, class: 'form-control js-user-role-dropdown', autofocus: true, required: true, data: { qa_selector: 'role_dropdown' }
+ = f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { include_blank: _('Select a role') }, class: 'form-control js-user-role-dropdown', required: true, data: { qa_selector: 'role_dropdown' }
= render_if_exists "registrations/welcome/jobs_to_be_done", f: f
= render_if_exists "registrations/welcome/setup_for_company", f: f
= render_if_exists "registrations/welcome/joining_project"
@@ -38,4 +39,5 @@
- if partial_exists? "registrations/welcome/button"
= render "registrations/welcome/button"
- else
- = f.submit _('Get started!'), class: 'btn-confirm gl-button btn btn-block gl-mb-0 gl-p-3', data: { qa_selector: 'get_started_button' }
+ = render Pajamas::ButtonComponent.new(block: true, type: :submit, variant: :confirm, button_options: { class: 'gl-mb-0', data: { qa_selector: 'get_started_button' }}) do
+ = _('Get started!')
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index fee943042f9..99558f61b25 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,9 +1,5 @@
-- search_bar_classes = 'search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4'
-
= render_if_exists 'shared/promotions/promote_advanced_search'
-.results.gl-md-display-flex.gl-mt-0
- #js-search-sidebar{ class: search_bar_classes, data: { navigation_json: search_navigation_json } }
- .gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden
- = render partial: 'search/results_status' unless @search_objects.to_a.empty?
- = render partial: 'search/results_list'
+.gl-w-full.gl-flex-grow-1.gl-overflow-x-hidden
+ = render partial: 'search/results_status' unless @search_objects.to_a.empty?
+ = render partial: 'search/results_list'
diff --git a/app/views/search/_results_list.html.haml b/app/views/search/_results_list.html.haml
index 7a57b5cc0fc..fcbf0ba4452 100644
--- a/app/views/search/_results_list.html.haml
+++ b/app/views/search/_results_list.html.haml
@@ -2,19 +2,22 @@
= render partial: "search/results/timeout"
- elsif @search_results.respond_to?(:failed?) && @search_results.failed?
= render partial: "search/results/error"
-- elsif @search_objects.to_a.empty?
+- elsif @search_objects.blank?
= render partial: "search/results/empty"
- else
- - if @scope == 'commits'
- %ul.content-list.commit-list
- = render partial: "search/results/commit", collection: @search_objects
- - else
- .search-results.js-search-results
- - if @scope == 'projects'
- .term
- = render 'shared/projects/list', projects: @search_objects, pipeline_status: false
- - else
- = render_if_exists partial: "search/results/#{@scope.singularize}", collection: @search_objects
+ - statusBarClass = !show_super_sidebar? ? 'gl-md-pl-5' : ''
- - if @scope != 'projects'
- = paginate_collection(@search_objects)
+ .section{ class: statusBarClass }
+ - if @scope == 'commits'
+ %ul.content-list.commit-list
+ = render partial: "search/results/commit", collection: @search_objects
+ - else
+ .search-results.js-search-results
+ - if @scope == 'projects'
+ .term
+ = render 'shared/projects/list', projects: @search_objects, pipeline_status: false
+ - else
+ = render_if_exists partial: "search/results/#{@scope.singularize}", collection: @search_objects
+
+ - if @scope != 'projects'
+ = paginate_collection(@search_objects)
diff --git a/app/views/search/_results_status.html.haml b/app/views/search/_results_status.html.haml
index 27405631360..6fc07d35296 100644
--- a/app/views/search/_results_status.html.haml
+++ b/app/views/search/_results_status.html.haml
@@ -1,25 +1,28 @@
- return unless @search_service_presenter.show_results_status?
+- statusBarClass = !show_super_sidebar? ? 'gl-md-pl-5' : ''
-.search-results-status
- .gl-display-flex.gl-flex-direction-column
- .gl-p-5.gl-display-flex
- .gl-md-display-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1.gl-white-space-nowrap.gl-max-w-full
- - unless @search_service_presenter.without_count?
- = search_entries_info(@search_objects, @scope, @search_term)
- - unless @search_service_presenter.show_snippets?
- - if @project
- - link_to_project = link_to(@project.full_name, @project, class: 'ml-md-1 gl-text-truncate search-wrap-f-md-down')
- - if @scope == 'blobs'
- = _("in")
- .mx-md-1
- #js-blob-ref-switcher{ data: { "project-id" => @project.id, "ref" => repository_ref(@project), "field-name": "repository_ref" } }
- = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project }
- - else
- = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project }
- - elsif @group
- - link_to_group = link_to(@group.name, @group, class: 'ml-md-1')
- = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
- - if @search_service_presenter.show_sort_dropdown?
- .gl-md-display-flex.gl-flex-direction-column
- #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json } }
- %hr.gl-mb-5.gl-mt-0.gl-border-gray-100.gl-w-full
+.section{ class: statusBarClass }
+ .search-results-status
+ .gl-display-flex.gl-flex-direction-column
+ .gl-p-5.gl-display-flex
+ .gl-md-display-flex.gl-text-left.gl-align-items-center.gl-flex-grow-1.gl-white-space-nowrap.gl-max-w-full
+ - unless @search_service_presenter.without_count?
+ .gl-text-truncate
+ = search_entries_info(@search_objects, @scope, @search_term)
+ - unless @search_service_presenter.show_snippets?
+ - if @project
+ - link_to_project = link_to(@project.full_name, @project, class: 'ml-md-1 gl-text-truncate search-wrap-f-md-down')
+ - if @scope == 'blobs'
+ = _("in")
+ .mx-md-1
+ #js-blob-ref-switcher{ data: { "project-id" => @project.id, "ref" => repository_ref(@project), "field-name": "repository_ref" } }
+ = s_('SearchCodeResults|of %{link_to_project}').html_safe % { link_to_project: link_to_project }
+ - else
+ = _("in project %{link_to_project}").html_safe % { link_to_project: link_to_project }
+ - elsif @group
+ - link_to_group = link_to(@group.name, @group, class: 'ml-md-1')
+ = _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
+ - if @search_service_presenter.show_sort_dropdown?
+ .gl-md-display-flex.gl-flex-direction-column
+ #js-search-sort{ data: { "search-sort-options" => search_sort_options.to_json } }
+ %hr.gl-mb-5.gl-mt-0.gl-border-gray-100.gl-w-full
diff --git a/app/views/search/results/_blob.html.haml b/app/views/search/results/_blob.html.haml
index 3681f823ef5..115bb6cc9fa 100644
--- a/app/views/search/results/_blob.html.haml
+++ b/app/views/search/results/_blob.html.haml
@@ -1,6 +1,8 @@
- project = blob.project
- return unless project
-- blob_link = project_blob_path(project, tree_join(repository_ref(project), blob.path))
-- blame_link = project_blame_path(project, tree_join(repository_ref(project), blob.path))
+- project_repository_ref = repository_ref(project) || ''
+- blob_path = blob.path || ''
+- blob_link = project_blob_path(project, tree_join(project_repository_ref, blob_path))
+- blame_link = project_blame_path(project, tree_join(project_repository_ref, blob_path))
-= render partial: 'search/results/blob_data', locals: { blob: blob, project: project, path: blob.path, blob_link: blob_link, blame_link: blame_link }
+= render partial: 'search/results/blob_data', locals: { blob: blob, project: project, path: blob_path, blob_link: blob_link, blame_link: blame_link }
diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml
index 04103794e60..934f59ea586 100644
--- a/app/views/search/show.html.haml
+++ b/app/views/search/show.html.haml
@@ -1,12 +1,14 @@
- @hide_top_links = true
+- breadcrumb_title _('Search')
- page_title @search_term
-- @hide_breadcrumbs = true
+- nav 'search'
- if params[:group_id].present?
= hidden_field_tag :group_id, params[:group_id]
- if params[:project_id].present?
= hidden_field_tag :project_id, params[:project_id]
- group_attributes = @group&.attributes&.slice('id', 'name')&.merge(full_name: @group&.full_name)
- project_attributes = @project&.attributes&.slice('id', 'namespace_id', 'name')&.merge(name_with_namespace: @project&.name_with_namespace)
+- search_bar_classes = 'search-sidebar gl-display-flex gl-flex-direction-column gl-mr-4'
- if @search_results && !(@search_results.respond_to?(:failed?) && @search_results.failed?)
- if @search_service_presenter.without_count?
@@ -19,7 +21,8 @@
%h1.page-title.gl-font-size-h-display.gl-mr-5= _('Search')
= render_if_exists 'search/form_elasticsearch', attrs: { class: 'mb-2 mb-sm-0 align-self-center' }
-.gl-mt-3
- #js-search-topbar{ data: { "group-initial-json": group_attributes.to_json, "project-initial-json": project_attributes.to_json, "elasticsearch-enabled": @search_service_presenter.advanced_search_enabled?.to_s, "default-branch-name": @project&.default_branch } }
-- if @search_term
- = render 'search/results'
+#js-search-topbar{ data: { "group-initial-json": group_attributes.to_json, "project-initial-json": project_attributes.to_json, "elasticsearch-enabled": @search_service_presenter.advanced_search_enabled?.to_s, "default-branch-name": @project&.default_branch } }
+.results.gl-md-display-flex.gl-mt-0
+ #js-search-sidebar{ class: search_bar_classes, data: { navigation_json: search_navigation_json } }
+ - if @search_term
+ = render 'search/results'
diff --git a/app/views/shared/_auto_devops_callout.html.haml b/app/views/shared/_auto_devops_callout.html.haml
index 93f919f01d9..c468b3a2001 100644
--- a/app/views/shared/_auto_devops_callout.html.haml
+++ b/app/views/shared/_auto_devops_callout.html.haml
@@ -1,4 +1,4 @@
-- container = @no_breadcrumb_container ? 'container-fluid' : container_class
+- container = @no_top_bar_container ? 'container-fluid' : container_class
%div{ class: [container, @content_class, 'gl-pt-5!'] }
= render Pajamas::BannerComponent.new(button_text: s_('AutoDevOps|Enable in settings'),
diff --git a/app/views/shared/_broadcast_message.html.haml b/app/views/shared/_broadcast_message.html.haml
index 4d286713cef..a2fed883739 100644
--- a/app/views/shared/_broadcast_message.html.haml
+++ b/app/views/shared/_broadcast_message.html.haml
@@ -9,6 +9,8 @@
= sprite_icon(icon_name)
.gl-broadcast-message-text.js-broadcast-message-preview
- if message.message.present?
+ %h2.gl-sr-only
+ = s_("Admin message")
= render_broadcast_message(message)
- else
= yield
@@ -24,6 +26,8 @@
.broadcast-message.broadcast-notification-message.mt-2{ role: "alert", class: notification_class, data: { qa_selector: 'broadcast_notification_container' } }
= sprite_icon(icon_name, css_class: 'vertical-align-text-top')
- if message.message.present?
+ %h2.gl-sr-only
+ = s_("Admin message")
= render_broadcast_message(message)
- else
= yield
diff --git a/app/views/shared/_captcha_check.html.haml b/app/views/shared/_captcha_check.html.haml
index a10ae655ea6..b3b2ae0d969 100644
--- a/app/views/shared/_captcha_check.html.haml
+++ b/app/views/shared/_captcha_check.html.haml
@@ -10,7 +10,7 @@
%p
= _("We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed.") % { humanized_resource_name: humanized_resource_name }
-= form_for resource_name, method: method, html: { class: 'recaptcha-form js-recaptcha-form' } do |f|
+= gitlab_ui_form_for resource_name, method: method, html: { class: 'recaptcha-form js-recaptcha-form' } do |f|
.recaptcha
-# Create a hidden field for each param of the resource
- params[resource_name].each do |field, value|
@@ -34,4 +34,4 @@
= yield
.row-content-block.footer-block
- = f.submit _("Create %{humanized_resource_name}") % { humanized_resource_name: humanized_resource_name }, class: 'gl-button btn btn-confirm'
+ = f.submit _("Create %{humanized_resource_name}") % { humanized_resource_name: humanized_resource_name }, pajamas_button: true
diff --git a/app/views/shared/_commit_message_container.html.haml b/app/views/shared/_commit_message_container.html.haml
index 904854c3fb7..2b55d35cf1f 100644
--- a/app/views/shared/_commit_message_container.html.haml
+++ b/app/views/shared/_commit_message_container.html.haml
@@ -1,19 +1,18 @@
-.form-group.row.commit_message-group
+.form-group.commit_message-group.gl-mt-5
- nonce = SecureRandom.hex
- descriptions = local_assigns.slice(:message_with_description, :message_without_description)
- = label_tag "commit_message-#{nonce}", class: 'col-form-label col-sm-2' do
+ = label_tag "commit_message-#{nonce}" do
#{ _('Commit message') }
- .col-sm-10
- .commit-message-container
- .max-width-marker
- = text_area_tag 'commit_message',
- (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder]),
- class: 'form-control gl-form-input js-commit-message',
- placeholder: local_assigns[:placeholder],
- data: descriptions,
- 'data-qa-selector': 'commit_message_field',
- required: true, rows: (local_assigns[:rows] || 3),
- id: "commit_message-#{nonce}"
+ .commit-message-container
+ .max-width-marker
+ = text_area_tag 'commit_message',
+ (params[:commit_message] || local_assigns[:text] || local_assigns[:placeholder]),
+ class: 'form-control gl-form-input js-commit-message',
+ placeholder: local_assigns[:placeholder],
+ data: descriptions,
+ 'data-qa-selector': 'commit_message_field',
+ required: true, rows: (local_assigns[:rows] || 3),
+ id: "commit_message-#{nonce}"
- if local_assigns[:hint]
%p.hint
= _('Try to keep the first line under 52 characters and the others under 72.')
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index a749d1037a1..9dfbad20726 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -2,14 +2,8 @@
- offset = defined?(first_line_number) ? first_line_number : 1
- highlight = defined?(highlight_line) && highlight_line ? highlight_line - offset : nil
-- file_line_blame = Feature.enabled?(:file_line_blame)
-
-- if file_line_blame
- - line_class = "js-line-links"
- - blame_path = project_blame_path(@project, tree_join(@ref, blob.path))
-- else
- - line_class = nil
- - blame_path = nil
+- line_class = "js-line-links"
+- blame_path = project_blame_path(@project, tree_join(@ref, blob.path))
- highlighted_blob = blob.present.highlight
diff --git a/app/views/shared/_file_picker_button.html.haml b/app/views/shared/_file_picker_button.html.haml
index 8d76e9c1b7d..beb564f7c7c 100644
--- a/app/views/shared/_file_picker_button.html.haml
+++ b/app/views/shared/_file_picker_button.html.haml
@@ -1,9 +1,10 @@
- classes = local_assigns.fetch(:classes, '')
+- mime_types = local_assigns.fetch(:mime_types, '')
%span.js-filepicker
= render Pajamas::ButtonComponent.new(button_options: { class: "js-filepicker-button #{classes}" }) do
= _("Choose file…")
- %span.file_name.js-filepicker-filename= _("No file chosen.")
- = f.file_field field, class: "js-filepicker-input hidden"
+ %span.file_name.gl-ml-3.js-filepicker-filename= _("No file chosen.")
+ = f.file_field field, class: "js-filepicker-input hidden", accept: mime_types
- if help_text.present?
.form-text.text-muted= help_text
diff --git a/app/views/shared/_issues.html.haml b/app/views/shared/_issues.html.haml
deleted file mode 100644
index 360a3f3eb89..00000000000
--- a/app/views/shared/_issues.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-= render 'shared/alerts/positioning_disabled' if @sort == 'relative_position'
-
-- if @issues.to_a.any?
- %ul.content-list.issues-list.issuable-list{ class: issue_manual_ordering_class }
- = render partial: 'projects/issues/issue', collection: @issues
- = paginate @issues, theme: "gitlab"
-- else
- = render 'shared/empty_states/issues'
diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml
index 8a626f1620b..1aac7af443f 100644
--- a/app/views/shared/_label.html.haml
+++ b/app/views/shared/_label.html.haml
@@ -6,56 +6,59 @@
- toggle_subscription_path = toggle_subscription_label_path(label, @project) if current_user
- tooltip_title = label_status_tooltip(label, status) if status
-%li.label-list-item{ id: label_css_id, class: "gl-p-5 gl-border-b", data: { id: label.id } }
- = render "shared/label_row", label: label, force_priority: force_priority
- %ul.label-actions-list
- - if can?(current_user, :admin_label, @project)
- %li.gl-display-inline-block.js-toggle-priority.gl-ml-3{ data: { url: remove_priority_project_label_path(@project, label),
- dom_id: dom_id(label), type: label.type } }
- = render Pajamas::ButtonComponent.new(category: :tertiary,
- icon: 'star',
- button_options: { class: 'remove-priority has-tooltip', 'title': _('Remove priority'), 'aria_label': _('Deprioritize label'), data: { placement: 'bottom' } })
- = render Pajamas::ButtonComponent.new(category: :tertiary,
- icon: 'star-o',
- button_options: { class: 'add-priority has-tooltip', title: _('Prioritize'), aria_label: _('Prioritize label'), data: { placement: 'bottom' } })
- - if can?(current_user, :admin_label, label)
- %li.gl-display-inline-block
- = render Pajamas::ButtonComponent.new(href: label.edit_path, category: :tertiary, icon: 'pencil', button_options: { class: 'edit has-tooltip', 'title': _('Edit'), 'aria_label': _('Edit'), data: { placement: 'bottom' } })
- - if can?(current_user, :admin_label, label)
- %li.gl-display-inline-block
- .dropdown
+%li.label-list-item.gl-list-style-none.gl-py-3{ id: label_css_id, data: { id: label.id } }
+ .label-content.gl-px-3.gl-py-2.gl-rounded-base{ class: "#{ 'gl-py-3' if force_priority }" }
+ = render "shared/label_row", label: label, force_priority: force_priority
+ %ul.label-actions-list
+ - if can?(current_user, :admin_label, @project)
+ %li.gl-display-inline-block.js-toggle-priority.gl-ml-3{ data: { url: remove_priority_project_label_path(@project, label),
+ dom_id: dom_id(label), type: label.type } }
= render Pajamas::ButtonComponent.new(category: :tertiary,
- icon: 'ellipsis_v',
- button_options: { class: 'js-label-options-dropdown', 'aria_label': _('Label actions dropdown'), data: { toggle: 'dropdown' } })
- .dropdown-menu.dropdown-open-left
- %ul
- - if label.project_label? && label.project.group && can?(current_user, :admin_label, label.project.group)
- %li
- = render Pajamas::ButtonComponent.new(category: :tertiary,
- button_options: { class: 'js-promote-project-label-button', data: { url: promote_project_label_path(label.project, label), label_title: label.title, label_color: label.color, label_text_color: label.text_color, group_name: label.project.group.name } }) do
- = _('Promote to group label')
- %li
- %span
- = render Pajamas::ButtonComponent.new(category: :tertiary,
- button_options: { class: 'text-danger js-delete-label-modal-button', data: { label_name: label.name, subject_name: label.subject_name, destroy_path: label.destroy_path } }) do
- = _('Delete')
- - if current_user
- %li.gl-display-inline-block.label-subscription.js-label-subscription.gl-ml-3
- - if label.can_subscribe_to_label_in_different_levels?
- = render Pajamas::ButtonComponent.new(button_options: { class: "js-unsubscribe-button #{'hidden' if status.unsubscribed?}", data: { url: toggle_subscription_path, toggle: 'tooltip', container: 'body' }, title: tooltip_title }) do
- = _('Unsubscribe')
- .dropdown.dropdown-group-label{ class: ('hidden' unless status.unsubscribed?) }
- = render Pajamas::ButtonComponent.new(button_options: { class: 'gl-w-full', data: { toggle: 'dropdown' } }) do
- = _('Subscribe')
- = sprite_icon('chevron-down')
- .dropdown-menu.dropdown-open-left
+ size: :small,
+ icon: 'star',
+ button_options: { class: 'remove-priority has-tooltip', 'title': _('Remove priority'), 'aria_label': _('Deprioritize label'), data: { placement: 'bottom' } })
+ = render Pajamas::ButtonComponent.new(category: :tertiary,
+ size: :small,
+ icon: 'star-o',
+ button_options: { class: 'add-priority has-tooltip', title: _('Prioritize'), aria_label: _('Prioritize label'), data: { placement: 'bottom' } })
+ - if current_user
+ %li.gl-display-inline-block.label-subscription.js-label-subscription.gl-ml-3.gl-mt-1
+ - if label.can_subscribe_to_label_in_different_levels?
+ = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: "js-unsubscribe-button gl-w-full #{'hidden' if status.unsubscribed?}", data: { url: toggle_subscription_path, toggle: 'tooltip', container: 'body' }, title: tooltip_title }) do
+ = _('Unsubscribe')
+ .dropdown.dropdown-group-label{ class: ('hidden' unless status.unsubscribed?) }
+ = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: "gl-w-full", data: { toggle: 'dropdown' } }) do
+ = _('Subscribe')
+ = sprite_icon('chevron-down')
+ .dropdown-menu.dropdown-menu-right
+ %ul
+ %li
+ = render Pajamas::ButtonComponent.new(category: :tertiary, button_options: { class: "js-subscribe-button #{'hidden' unless status.unsubscribed?}", data: { status: status, url: toggle_subscription_project_label_path(@project, label) } }) do
+ = _('Subscribe at project level')
+ %li
+ = render Pajamas::ButtonComponent.new(category: :tertiary, button_options: { class: "js-subscribe-button js-group-level #{'hidden' unless status.unsubscribed?}", data: { status: status, url: toggle_subscription_group_label_path(label.group, label) } }) do
+ = _('Subscribe at group level')
+ - else
+ = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-subscribe-button gl-w-full', data: { status: status, url: toggle_subscription_path, toggle: 'tooltip', container: 'body' }, title: tooltip_title }) do
+ = label_subscription_toggle_button_text(label, @project)
+ - if can?(current_user, :admin_label, label)
+ %li.gl-display-inline-block
+ .dropdown
+ = render Pajamas::ButtonComponent.new(category: :tertiary,
+ size: :small,
+ icon: 'ellipsis_v',
+ button_options: { class: 'js-label-options-dropdown gl-ml-3', 'aria_label': _('Label actions dropdown'), title: _('Label actions dropdown'), data: { toggle: 'dropdown' } })
+ .dropdown-menu.dropdown-menu-right
%ul
%li
- = render Pajamas::ButtonComponent.new(category: :tertiary, button_options: { class: "js-subscribe-button #{'hidden' unless status.unsubscribed?}", data: { status: status, url: toggle_subscription_project_label_path(@project, label) } }) do
- = _('Subscribe at project level')
+ = render Pajamas::ButtonComponent.new(category: :tertiary, href: label.edit_path, variant: :link) do
+ = _('Edit')
+ - if label.project_label? && label.project.group && can?(current_user, :admin_label, label.project.group)
+ %li
+ = render Pajamas::ButtonComponent.new(category: :tertiary, variant: :link,
+ button_options: { class: 'js-promote-project-label-button', data: { url: promote_project_label_path(label.project, label), label_title: label.title, label_color: label.color, label_text_color: label.text_color, group_name: label.project.group.name } }) do
+ = _('Promote to group label')
%li
- = render Pajamas::ButtonComponent.new(category: :tertiary, button_options: { class: "js-subscribe-button js-group-level #{'hidden' unless status.unsubscribed?}", data: { status: status, url: toggle_subscription_group_label_path(label.group, label) } }) do
- = _('Subscribe at group level')
- - else
- = render Pajamas::ButtonComponent.new(button_options: { class: 'js-subscribe-button gl-w-full', data: { status: status, url: toggle_subscription_path, toggle: 'tooltip', container: 'body' }, title: tooltip_title }) do
- = label_subscription_toggle_button_text(label, @project)
+ = render Pajamas::ButtonComponent.new(category: :tertiary, variant: :link,
+ button_options: { class: 'text-danger js-delete-label-modal-button', data: { label_name: label.name, subject_name: label.subject_name, destroy_path: label.destroy_path } }) do
+ = _('Delete')
diff --git a/app/views/shared/_label_full_path.html.haml b/app/views/shared/_label_full_path.html.haml
index fd67bbbbd10..b9e5e979ce5 100644
--- a/app/views/shared/_label_full_path.html.haml
+++ b/app/views/shared/_label_full_path.html.haml
@@ -1,4 +1,8 @@
- full_path = label.subject_full_name
-.label-badge.gl-bg-gray-50.gl-max-w-full.gl-text-truncate{ title: full_path }
+.gl-font-sm.gl-font-weight-semibold.gl-text-secondary
+ - if label.project_label?
+ = sprite_icon('project', size: 12, css_class: 'gl-text-gray-600')
+ - else
+ = sprite_icon('group', size: 12, css_class: 'gl-text-gray-600')
= full_path
diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml
index c351ea29c7c..19489981d94 100644
--- a/app/views/shared/_label_row.html.haml
+++ b/app/views/shared/_label_row.html.haml
@@ -3,28 +3,25 @@
- show_label_issues_link = subject_or_group_defined && show_label_issuables_link?(label, :issues)
- show_label_merge_requests_link = subject_or_group_defined && show_label_issuables_link?(label, :merge_requests)
-.label-name.gl-flex-shrink-0.gl-mt-2.gl-mr-5
+.label-name.gl-flex-shrink-0.gl-mr-5
= render_label(label, tooltip: false)
-.label-description.gl-overflow-hidden.gl-w-full
- .gl-display-flex.gl-align-items-stretch.gl-flex-wrap.gl-mt-2
- .gl-flex-basis-half.gl-flex-grow-1.gl-overflow-hidden.gl-mr-5
+ - if show_labels_full_path?(@project, @group)
+ .gl-mt-2
+ = render 'shared/label_full_path', label: label
+.label-description.gl-w-full
+ .gl-display-flex.gl-align-items-stretch.gl-flex-wrap
+ .gl-flex-basis-half.gl-flex-grow-1.gl-mr-5
- if label.description.present?
- = markdown_field(label, :description)
- - elsif show_labels_full_path?(@project, @group)
- = render 'shared/label_full_path', label: label
+ .gl-my-1
+ = markdown_field(label, :description)
%ul.label-links.gl-m-0.gl-p-0.gl-white-space-nowrap
+ - if force_priority
+ %li.js-priority-badge.inline.gl-mr-3.gl-mt-1
+ .label-badge.gl-bg-blue-50= _('Prioritized')
- if show_label_issues_link
- %li.inline
- = link_to_label(label, css_class: 'gl-text-blue-600!') { _('Issues') }
+ %li.inline.gl-my-1
+ = link_to_label(label, css_class: 'gl-mr-5') { _('Issues') }
- if show_label_merge_requests_link
- &middot;
- %li.inline
- = link_to_label(label, type: :merge_request, css_class: 'gl-text-blue-600!') { _('Merge requests') }
+ %li.inline.gl-my-1
+ = link_to_label(label, type: :merge_request) { _('Merge requests') }
= render_if_exists 'shared/label_row_epics_link', label: label
- - if force_priority
- &middot;
- %li.js-priority-badge.inline.gl-ml-3
- .label-badge.gl-bg-blue-50= _('Prioritized label')
- - if label.description.present? && show_labels_full_path?(@project, @group)
- .gl-mt-3
- = render 'shared/label_full_path', label: label
diff --git a/app/views/shared/_md_preview.html.haml b/app/views/shared/_md_preview.html.haml
index 2fff70cdc74..dd3a31f5a59 100644
--- a/app/views/shared/_md_preview.html.haml
+++ b/app/views/shared/_md_preview.html.haml
@@ -8,21 +8,18 @@
= _('Only project members can comment.')
.md-area.position-relative
- .md-header
- = gl_tabs_nav({ class: 'clearfix nav-links'}) do
- %li.md-header-tab.active
- %button.js-md-write-button{ class: 'gl-py-3!' }
- = _("Write")
- %li.md-header-tab
- %button.js-md-preview-button{ class: 'gl-py-3!' }
- = _("Preview")
-
- %li.md-header-toolbar.active.gl-py-2
- = render 'shared/blob/markdown_buttons', show_fullscreen_button: true
+ .md-header.gl-bg-gray-50.gl-px-2.gl-rounded-base.gl-mx-2.gl-mt-2
+ .gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-justify-content-space-between
+ .md-header-toolbar.gl-display-flex.gl-py-2.gl-flex-wrap
+ = render 'shared/blob/markdown_buttons'
+ .switch-preview.gl-py-2.gl-display-flex.gl-align-items-center.gl-ml-auto
+ = render Pajamas::ButtonComponent.new(category: :tertiary, size: :small, button_options: { class: 'js-md-preview-button', value: 'preview' }) do
+ = _('Preview')
+ = render Pajamas::ButtonComponent.new(icon: 'maximize', category: :tertiary, size: :small, button_options: { 'tabindex': -1, 'aria-label': _("Go full screen"), class: 'has-tooltip js-zen-enter gl-ml-2', data: { container: 'body' } })
.md-write-holder
= yield
- .md.md-preview-holder.js-md-preview.hide{ data: { url: url } }
+ .md.md-preview-holder.gl-px-5.js-md-preview.hide{ data: { url: url } }
.referenced-commands.hide
- if referenced_users
diff --git a/app/views/shared/_mobile_clone_panel.html.haml b/app/views/shared/_mobile_clone_panel.html.haml
index 8b7ef838d2b..aa3043b8fd6 100644
--- a/app/views/shared/_mobile_clone_panel.html.haml
+++ b/app/views/shared/_mobile_clone_panel.html.haml
@@ -9,8 +9,8 @@
%ul.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown{ data: { dropdown: true } }
- if ssh_enabled?
%li
- = dropdown_item_with_description(ssh_copy_label, project.ssh_url_to_repo, href: project.ssh_url_to_repo, data: { clone_type: 'ssh' }, default: true)
+ = dropdown_item_with_description(ssh_copy_label, ssh_clone_url_to_repo(project), href: ssh_clone_url_to_repo(project), data: { clone_type: 'ssh' }, default: true)
- if http_enabled?
%li
- = dropdown_item_with_description(http_copy_label, project.http_url_to_repo, href: project.http_url_to_repo, data: { clone_type: 'http' })
+ = dropdown_item_with_description(http_copy_label, http_clone_url_to_repo(project), href: http_clone_url_to_repo(project), data: { clone_type: 'http' })
= render_if_exists 'shared/mobile_kerberos_clone'
diff --git a/app/views/shared/_model_version_conflict.html.haml b/app/views/shared/_model_version_conflict.html.haml
new file mode 100644
index 00000000000..134dcf8db7f
--- /dev/null
+++ b/app/views/shared/_model_version_conflict.html.haml
@@ -0,0 +1,6 @@
+= render Pajamas::AlertComponent.new(variant: :danger,
+ dismissible: false,
+ alert_options: { class: 'gl-mb-5' }) do |c|
+ = c.body do
+ - link_to_model = link_to(model_name, link_path, target: '_blank', rel: 'noopener noreferrer')
+ = _("Someone edited this %{model_name} at the same time you did. Please check out the %{link_to_model} and make sure your changes will not unintentionally remove theirs.").html_safe % { model_name: model_name, link_to_model: link_to_model }
diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml
index 14ea96f9669..bdc7156242d 100644
--- a/app/views/shared/_new_commit_form.html.haml
+++ b/app/views/shared/_new_commit_form.html.haml
@@ -8,13 +8,12 @@
= hidden_field_tag 'branch_name', ref, class: 'js-branch-name'
- else
- if can?(current_user, :push_code, @project)
- .form-group.row.branch
- = label_tag 'branch_name', _('Target Branch'), class: 'col-form-label col-sm-2'
- .col-sm-10
- = text_field_tag 'branch_name', branch_name, required: true, class: "form-control gl-form-input js-branch-name ref-name"
+ .form-group.branch
+ = label_tag 'branch_name', _('Target Branch')
+ = text_field_tag 'branch_name', branch_name, required: true, class: "form-control gl-form-input js-branch-name ref-name"
- .js-create-merge-request-container
- = render 'shared/new_merge_request_checkbox'
+ .js-create-merge-request-container
+ = render 'shared/new_merge_request_checkbox'
- elsif project.can_current_user_push_to_branch?(branch_name)
= hidden_field_tag 'branch_name', branch_name
- else
diff --git a/app/views/shared/_ref_switcher.html.haml b/app/views/shared/_ref_switcher.html.haml
deleted file mode 100644
index fa718a9c907..00000000000
--- a/app/views/shared/_ref_switcher.html.haml
+++ /dev/null
@@ -1,22 +0,0 @@
-- return unless @project
-
-- ref = local_assigns.fetch(:ref, @ref)
-- form_path = local_assigns.fetch(:form_path, switch_project_refs_path(@project))
-- dropdown_toggle_text = ref || @project.default_branch
-- field_name = local_assigns.fetch(:field_name, 'ref')
-
-= form_tag form_path, method: :get, class: "project-refs-form" do
- - if defined?(destination)
- = hidden_field_tag :destination, destination
- - if defined?(path)
- = hidden_field_tag :path, path
- - @options && @options.each do |key, value|
- = hidden_field_tag key, value, id: nil
- .dropdown
- = dropdown_toggle dropdown_toggle_text, { toggle: "dropdown", selected: dropdown_toggle_text, ref: ref, ref_type: @ref_type, refs_url: refs_project_path(@project, sort: 'updated_desc'), field_name: field_name, submit_form_on_click: true, visit: true, qa_selector: "branches_dropdown", testid: "branches-select" }, { toggle_class: "js-project-refs-dropdown" }
- .dropdown-menu.dropdown-menu-selectable.git-revision-dropdown.dropdown-menu-paging{ class: ("dropdown-menu-right" if local_assigns[:align_right]), data: { qa_selector: "branches_dropdown_content" } }
- .dropdown-page-one
- = dropdown_title _("Switch branch/tag")
- = dropdown_filter _("Search branches and tags")
- = dropdown_content
- = dropdown_loading
diff --git a/app/views/shared/_remote_mirror_update_button.html.haml b/app/views/shared/_remote_mirror_update_button.html.haml
index 770d335a88b..bc80ebe3950 100644
--- a/app/views/shared/_remote_mirror_update_button.html.haml
+++ b/app/views/shared/_remote_mirror_update_button.html.haml
@@ -1,6 +1,6 @@
- if remote_mirror.update_in_progress?
= render Pajamas::ButtonComponent.new(icon: 'retry',
- button_options: { class: 'disabled', title: _('Updating'), data: { toggle: 'tooltip', container: 'body', qa_selector: 'updating_button' } },
+ button_options: { class: 'disabled', title: _('Updating'), data: { toggle: 'tooltip', container: 'body' } },
icon_classes: 'spin')
- elsif remote_mirror.enabled?
= link_to update_now_project_mirror_path(@project, sync_remote: true), method: :post, class: "btn btn-icon gl-button rspec-update-now-button", data: { toggle: 'tooltip', container: 'body', qa_selector: 'update_now_button' }, title: _('Update now') do
diff --git a/app/views/shared/_zen.html.haml b/app/views/shared/_zen.html.haml
index 5a4efe7fe7f..05bee9e4d42 100644
--- a/app/views/shared/_zen.html.haml
+++ b/app/views/shared/_zen.html.haml
@@ -4,6 +4,7 @@
- supports_quick_actions = local_assigns.fetch(:supports_quick_actions, false)
- qa_selector = local_assigns.fetch(:qa_selector, '')
- autofocus = local_assigns.fetch(:autofocus, false)
+
.zen-backdrop
- classes << ' js-gfm-input js-autosize markdown-area'
- if defined?(f) && f
diff --git a/app/views/shared/blob/_markdown_buttons.html.haml b/app/views/shared/blob/_markdown_buttons.html.haml
index db53d78dadb..a3d3c1c8231 100644
--- a/app/views/shared/blob/_markdown_buttons.html.haml
+++ b/app/views/shared/blob/_markdown_buttons.html.haml
@@ -1,42 +1,44 @@
- modifier_key = client_js_flags[:isMac] ? '⌘' : s_('KeyboardKey|Ctrl+')
- supports_file_upload = local_assigns.fetch(:supports_file_upload, true)
-.md-header-toolbar.active
- = markdown_toolbar_button({ icon: "bold",
- data: { "md-tag" => "**", "md-shortcuts": '["mod+b"]' },
- title: sprintf(s_("MarkdownEditor|Add bold text (%{modifier_key}B)") % { modifier_key: modifier_key }) })
+= markdown_toolbar_button({ icon: "bold",
+ css_class: 'gl-mr-3',
+ data: { "md-tag" => "**", "md-shortcuts": '["mod+b"]' },
+ title: sprintf(s_("MarkdownEditor|Add bold text (%{modifier_key}B)") % { modifier_key: modifier_key }) })
- = markdown_toolbar_button({ icon: "italic",
- data: { "md-tag" => "_", "md-shortcuts": '["mod+i"]' },
- title: sprintf(s_("MarkdownEditor|Add italic text (%{modifier_key}I)") % { modifier_key: modifier_key }) })
+= markdown_toolbar_button({ icon: "italic",
+ css_class: 'gl-mr-3',
+ data: { "md-tag" => "_", "md-shortcuts": '["mod+i"]' },
+ title: sprintf(s_("MarkdownEditor|Add italic text (%{modifier_key}I)") % { modifier_key: modifier_key }) })
- = markdown_toolbar_button({ icon: "strikethrough",
- data: { "md-tag" => "~~", "md-shortcuts": '["mod+shift+x"]' },
- title: sprintf(s_("MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)") % { modifier_key: modifier_key }) })
+= markdown_toolbar_button({ icon: "strikethrough",
+ css_class: 'gl-mr-3',
+ data: { "md-tag" => "~~", "md-shortcuts": '["mod+shift+x"]' },
+ title: sprintf(s_("MarkdownEditor|Add strikethrough text (%{modifier_key}⇧X)") % { modifier_key: modifier_key }) })
- = markdown_toolbar_button({ icon: "quote", data: { "md-tag" => "> ", "md-prepend" => true }, title: _("Insert a quote") })
- = markdown_toolbar_button({ icon: "code", data: { "md-tag" => "`", "md-block" => "```" }, title: _("Insert code") })
+= markdown_toolbar_button({ icon: "quote", css_class: 'gl-mr-3', data: { "md-tag" => "> ", "md-prepend" => true }, title: _("Insert a quote") })
+= markdown_toolbar_button({ icon: "code", css_class: 'gl-mr-3', data: { "md-tag" => "`", "md-block" => "```" }, title: _("Insert code") })
- = markdown_toolbar_button({ icon: "link",
- data: { "md-tag" => "[{text}](url)", "md-select" => "url", "md-shortcuts": '["mod+k"]' },
- title: sprintf(s_("MarkdownEditor|Add a link (%{modifier_key}K)") % { modifier_key: modifier_key }) })
+= markdown_toolbar_button({ icon: "link",
+ css_class: 'gl-mr-3',
+ data: { "md-tag" => "[{text}](url)", "md-select" => "url", "md-shortcuts": '["mod+k"]' },
+ title: sprintf(s_("MarkdownEditor|Add a link (%{modifier_key}K)") % { modifier_key: modifier_key }) })
- = markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "- ", "md-prepend" => true }, title: _("Add a bullet list") })
- = markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: _("Add a numbered list") })
- = markdown_toolbar_button({ icon: "list-task", data: { "md-tag" => "- [ ] ", "md-prepend" => true }, title: _("Add a checklist") })
- = markdown_toolbar_button({ icon: "list-indent",
- data: { "md-command" => 'indentLines', "md-shortcuts": '["mod+]"]' },
- css_class: 'gl-display-none',
- title: sprintf(s_("MarkdownEditor|Indent line (%{modifier_key}])") % { modifier_key: modifier_key }) })
- = markdown_toolbar_button({ icon: "list-outdent",
- data: { "md-command" => 'outdentLines', "md-shortcuts": '["mod+["]' },
- css_class: 'gl-display-none',
- title: sprintf(s_("MarkdownEditor|Outdent line (%{modifier_key}[)") % { modifier_key: modifier_key }) })
- = markdown_toolbar_button({ icon: "details-block",
- data: { "md-tag" => "<details><summary>Click to expand</summary>\n{text}\n</details>", "md-prepend" => true, "md-select" => "Click to expand" },
- title: _("Add a collapsible section") })
- = markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| | |\n| | |", "md-prepend" => true }, title: _("Add a table") })
- - if supports_file_upload
- = render Pajamas::ButtonComponent.new(icon: 'paperclip', category: :tertiary, button_options: { 'aria-label': _("Attach a file or image"), class: 'has-tooltip js-attach-file-button', data: { testid: 'button-attach-file', container: 'body' } })
- - if show_fullscreen_button
- = render Pajamas::ButtonComponent.new(icon: 'maximize', category: :tertiary, button_options: { 'tabindex': -1, 'aria-label': _("Go full screen"), class: 'has-tooltip js-zen-enter', data: { container: 'body' } })
+= markdown_toolbar_button({ icon: "list-bulleted", css_class: 'gl-mr-3', data: { "md-tag" => "- ", "md-prepend" => true }, title: _("Add a bullet list") })
+= markdown_toolbar_button({ icon: "list-numbered", css_class: 'gl-mr-3', data: { "md-tag" => "1. ", "md-prepend" => true }, title: _("Add a numbered list") })
+= markdown_toolbar_button({ icon: "list-task", css_class: 'gl-mr-3', data: { "md-tag" => "- [ ] ", "md-prepend" => true }, title: _("Add a checklist") })
+= markdown_toolbar_button({ icon: "list-indent",
+ css_class: 'gl-display-none gl-mr-3',
+ data: { "md-command" => 'indentLines', "md-shortcuts": '["mod+]"]' },
+ title: sprintf(s_("MarkdownEditor|Indent line (%{modifier_key}])") % { modifier_key: modifier_key }) })
+= markdown_toolbar_button({ icon: "list-outdent",
+ css_class: 'gl-display-none gl-mr-3',
+ data: { "md-command" => 'outdentLines', "md-shortcuts": '["mod+["]' },
+ title: sprintf(s_("MarkdownEditor|Outdent line (%{modifier_key}[)") % { modifier_key: modifier_key }) })
+= markdown_toolbar_button({ icon: "details-block",
+ css_class: 'gl-mr-3',
+ data: { "md-tag" => "<details><summary>Click to expand</summary>\n{text}\n</details>", "md-prepend" => true, "md-select" => "Click to expand" },
+ title: _("Add a collapsible section") })
+= markdown_toolbar_button({ icon: "table", css_class: 'gl-mr-3', data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| | |\n| | |", "md-prepend" => true }, title: _("Add a table") })
+- if supports_file_upload
+ = render Pajamas::ButtonComponent.new(icon: 'paperclip', category: :tertiary, size: :small, button_options: { 'aria-label': _("Attach a file or image"), class: 'has-tooltip js-attach-file-button gl-mr-3', data: { testid: 'button-attach-file', container: 'body' } })
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index c3835386d5a..e5aa4c58da1 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -1,5 +1,5 @@
- board = local_assigns.fetch(:board, nil)
-- @no_breadcrumb_container = true
+- @no_top_bar_container = true
- @no_container = true
- @content_wrapper_class = "#{@content_wrapper_class} gl-relative gl-pb-0"
- @content_class = "issue-boards-content js-focus-mode-board"
diff --git a/app/views/shared/deploy_keys/_form.html.haml b/app/views/shared/deploy_keys/_form.html.haml
index 93f31629ca7..584d0758c76 100644
--- a/app/views/shared/deploy_keys/_form.html.haml
+++ b/app/views/shared/deploy_keys/_form.html.haml
@@ -27,6 +27,11 @@
.col-sm-10
= form.text_field :fingerprint, class: 'form-control gl-form-input', readonly: 'readonly'
+.form-group
+ .col-sm-10
+ = form.label :expires_at, _('Expiration date (optional)'), class: 'label-bold'
+ = form.text_field :expires_at, class: 'form-control gl-form-input', readonly: 'readonly'
+
- if deploy_keys_project.present?
= form.fields_for :deploy_keys_projects, deploy_keys_project do |deploy_keys_project_form|
.form-group
diff --git a/app/views/shared/deploy_keys/_project_group_form.html.haml b/app/views/shared/deploy_keys/_project_group_form.html.haml
index 11fa44fe282..c9e17b18264 100644
--- a/app/views/shared/deploy_keys/_project_group_form.html.haml
+++ b/app/views/shared/deploy_keys/_project_group_form.html.haml
@@ -15,6 +15,10 @@
.form-group.row
= deploy_keys_project_form.gitlab_ui_checkbox_component :can_push, _('Grant write permissions to this key'),
help_text: _('Allow this key to push to this repository')
+ .form-group.row
+ = f.label :expires_at, _('Expiration date (optional)'), class: 'label-bold'
+ = f.gitlab_ui_datepicker :expires_at, data: { qa_selector: 'deploy_key_expires_at_field' }, value: f.object.expires_at
+ %p.form-text.text-muted= ssh_key_expires_field_description
.form-group.row
= f.submit _("Add key"), data: { qa_selector: "add_deploy_key_button"}, pajamas_button: true
diff --git a/app/views/shared/doorkeeper/applications/_form.html.haml b/app/views/shared/doorkeeper/applications/_form.html.haml
index b40e2630011..628a34e1278 100644
--- a/app/views/shared/doorkeeper/applications/_form.html.haml
+++ b/app/views/shared/doorkeeper/applications/_form.html.haml
@@ -21,4 +21,4 @@
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: @application, scopes: @scopes, f: f
.gl-mt-3
- = f.submit _('Save application'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save application'), pajamas_button: true
diff --git a/app/views/shared/doorkeeper/applications/_index.html.haml b/app/views/shared/doorkeeper/applications/_index.html.haml
index 6a770a4fcb2..abfe3baf8b4 100644
--- a/app/views/shared/doorkeeper/applications/_index.html.haml
+++ b/app/views/shared/doorkeeper/applications/_index.html.haml
@@ -1,4 +1,4 @@
-- @content_class = "limit-container-width" unless fluid_layout
+- @force_desktop_expanded_sidebar = true
.row.gl-mt-3.js-search-settings-section
.col-lg-4.profile-settings-sidebar
diff --git a/app/views/shared/doorkeeper/applications/_show.html.haml b/app/views/shared/doorkeeper/applications/_show.html.haml
index 5b0cff2c1c0..b9095e2a1a1 100644
--- a/app/views/shared/doorkeeper/applications/_show.html.haml
+++ b/app/views/shared/doorkeeper/applications/_show.html.haml
@@ -8,21 +8,15 @@
%td
.clipboard-group
.input-group
- %input.label.label-monospace.monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true }
+ %input.label.label-monospace.monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true, data: { qa_selector: 'application_id_field' } }
.input-group-append
= clipboard_button(target: '#application_id', title: _("Copy ID"), class: "gl-button btn btn-default")
%tr
%td
= _('Secret')
%td
- - if Feature.enabled?('hash_oauth_secrets')
- - if @application.plaintext_secret
- = clipboard_button(clipboard_text: @application.plaintext_secret, button_text: _('Copy'), title: _("Copy secret"), class: "btn btn-default btn-md gl-button")
- %span= _('This is the only time the secret is accessible. Copy the secret and store it securely.')
- - else
- = _('The secret is only available when you first create the application.')
- - else
- = clipboard_button(clipboard_text: @application.secret, button_text: _('Copy'), title: _("Copy secret"), class: "btn btn-default btn-md gl-button")
+ #js-oauth-application-secret{ data: { initial_secret: @application.plaintext_secret, renew_path: renew_path } }
+
%tr
%td
= _('Callback URL')
@@ -52,3 +46,6 @@
= link_to _('Continue'), index_path, class: 'btn btn-confirm btn-md gl-button gl-mr-3'
= link_to _('Edit'), edit_path, class: 'btn btn-default btn-md gl-button'
= render 'shared/doorkeeper/applications/delete_form', path: delete_path
+
+-# Create a hidden field to save the ID of application created
+= hidden_field_tag(:id_of_application, @application.id, data: { qa_selector: 'id_of_application_field' })
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index 37f7fbc0de5..1ab9e288a9e 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -4,7 +4,6 @@
- opened_issues_count = issuables_count_for_state(:issues, :opened)
- is_opened_state = params[:state] == 'opened'
- is_closed_state = params[:state] == 'closed'
-- issuable_type = 'issues'
- can_edit = can?(current_user, :admin_project, @project)
.row.empty-state
@@ -43,7 +42,7 @@
= link_to _('New issue'), button_path, class: 'gl-button btn btn-confirm', id: 'new_issue_link'
- if show_import_button
- .js-csv-import-export-buttons{ data: { show_import_button: 'true', issuable_type: issuable_type, import_csv_issues_path: import_csv_namespace_project_issues_path, 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), container_class: 'gl-w-full gl-sm-w-auto gl-sm-mr-3 gl-display-inline-flex gl-vertical-align-middle', show_label: 'true' } }
+ .js-csv-import-export-buttons{ data: { show_import_button: 'true', issuable_type: 'issue', import_csv_issues_path: import_csv_namespace_project_issues_path, 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) } }
%hr
%p.gl-text-center.gl-mb-0
%strong
diff --git a/app/views/shared/empty_states/_labels.html.haml b/app/views/shared/empty_states/_labels.html.haml
index e96fcd11cef..da88c139a6e 100644
--- a/app/views/shared/empty_states/_labels.html.haml
+++ b/app/views/shared/empty_states/_labels.html.haml
@@ -1,7 +1,7 @@
.row.empty-state.labels
.col-12
- .svg-content{ data: { qa_selector: 'label_svg_content' } }
- = image_tag 'illustrations/labels.svg'
+ .svg-content.svg-150{ data: { qa_selector: 'label_svg_content' } }
+ = image_tag 'illustrations/empty-state/empty-labels-md.svg'
.col-12
.text-content
%h4= _("Labels can be applied to issues and merge requests to categorize them.")
diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml
index 8e4051fa335..94589996c3a 100644
--- a/app/views/shared/empty_states/_merge_requests.html.haml
+++ b/app/views/shared/empty_states/_merge_requests.html.haml
@@ -7,8 +7,8 @@
.row.empty-state.merge-requests
.col-12
- .svg-content
- = image_tag 'illustrations/merge_requests.svg', { auto_dark: true }
+ .svg-content.svg-150
+ = image_tag 'illustrations/empty-state/empty-merge-requests-md.svg', { auto_dark: true }
.col-12
.text-content
- if has_filter_bar_param?
diff --git a/app/views/shared/empty_states/_priority_labels.html.haml b/app/views/shared/empty_states/_priority_labels.html.haml
index 3381c5f0c67..b24fa0b3bdb 100644
--- a/app/views/shared/empty_states/_priority_labels.html.haml
+++ b/app/views/shared/empty_states/_priority_labels.html.haml
@@ -1,6 +1,8 @@
-.text-center
+.text-center.gl-mt-1.gl-mb-6
.svg-content{ data: { qa_selector: 'label_svg_content' } }
- = image_tag 'illustrations/priority_labels.svg'
+ = image_tag 'illustrations/empty-state/empty-labels-starred-md.svg'
- if can?(current_user, :admin_label, @project)
- %p
- = _("Star labels to start sorting by priority")
+ %div
+ = _("No prioritized labels yet!")
+ %div
+ = _("Star labels to start sorting by priority.")
diff --git a/app/views/shared/empty_states/_snippets.html.haml b/app/views/shared/empty_states/_snippets.html.haml
index e34166bac6c..87de756093d 100644
--- a/app/views/shared/empty_states/_snippets.html.haml
+++ b/app/views/shared/empty_states/_snippets.html.haml
@@ -2,8 +2,8 @@
.row.empty-state
.col-12
- .svg-content{ data: { qa_selector: 'svg_content' } }
- = image_tag 'illustrations/snippets_empty.svg'
+ .svg-content.svg-150{ data: { qa_selector: 'svg_content' } }
+ = image_tag 'illustrations/empty-state/empty-snippets-md.svg'
.text-content.gl-text-center.gl-pt-0
- if current_user
%h4
diff --git a/app/views/shared/empty_states/_topics.html.haml b/app/views/shared/empty_states/_topics.html.haml
index 0283e852c7d..cd60d966d71 100644
--- a/app/views/shared/empty_states/_topics.html.haml
+++ b/app/views/shared/empty_states/_topics.html.haml
@@ -1,7 +1,7 @@
.row.empty-state
.col-12
- .svg-content
- = image_tag 'illustrations/labels.svg'
+ .svg-content.svg-150
+ = image_tag 'illustrations/empty-state/empty-labels-md.svg'
.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/empty_states/_wikis.html.haml b/app/views/shared/empty_states/_wikis.html.haml
index 8304a2f18a0..57f1c9d381e 100644
--- a/app/views/shared/empty_states/_wikis.html.haml
+++ b/app/views/shared/empty_states/_wikis.html.haml
@@ -1,7 +1,8 @@
- layout_path = 'shared/empty_states/wikis_layout'
- messages = wiki_empty_state_messages(@wiki)
+- hide_create = local_assigns[:hide_create]
-- if can?(current_user, :create_wiki, @wiki.container)
+- if !hide_create && can?(current_user, :create_wiki, @wiki.container)
- create_path = wiki_page_path(@wiki, params[:id], view: 'create')
- create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn gl-button btn-confirm', title: s_('WikiEmpty|Create your first page'), data: { qa_selector: 'create_first_page_link' }
diff --git a/app/views/shared/form_elements/_description.html.haml b/app/views/shared/form_elements/_description.html.haml
index 2c46b2191c6..415849672b6 100644
--- a/app/views/shared/form_elements/_description.html.haml
+++ b/app/views/shared/form_elements/_description.html.haml
@@ -1,9 +1,9 @@
+- @gfm_form = true
- project = local_assigns.fetch(:project)
- model = local_assigns.fetch(:model)
- form = local_assigns.fetch(:form)
- placeholder = model.is_a?(MergeRequest) ? _('Describe the goal of the changes and what reviewers should be aware of.') : _('Write a description or drag your files here…')
-
-- supports_quick_actions = true
+- no_issuable_templates = issuable_templates(ref_project, model.to_ability_name).empty?
- preview_url = preview_markdown_path(project, target_type: model.class.name)
.form-group
@@ -16,12 +16,14 @@
= render 'shared/form_elements/apply_template_warning', issuable: model
- = render layout: 'shared/md_preview', locals: { url: preview_url, referenced_users: true } do
- = render 'shared/zen', f: form, attr: :description,
- classes: 'note-textarea rspec-issuable-form-description',
- placeholder: placeholder,
- supports_quick_actions: supports_quick_actions,
- qa_selector: 'issuable_form_description_field'
- = render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
- .clearfix
- .error-alert
+ .js-markdown-editor{ data: { render_markdown_path: preview_url,
+ markdown_docs_path: help_page_path('user/markdown'),
+ quick_actions_docs_path: help_page_path('user/project/quick_actions'),
+ qa_selector: 'issuable_form_description_field',
+ form_field_placeholder: placeholder,
+ form_field_classes: 'js-gfm-input markdown-area note-textarea rspec-issuable-form-description' } }
+ = form.hidden_field :description
+
+ - if no_issuable_templates && can?(current_user, :push_code, model.project)
+ = render 'shared/issuable/form/default_templates'
+
diff --git a/app/views/shared/groups/_list.html.haml b/app/views/shared/groups/_list.html.haml
index c5b39c7db08..550f079bf3b 100644
--- a/app/views/shared/groups/_list.html.haml
+++ b/app/views/shared/groups/_list.html.haml
@@ -1,4 +1,4 @@
-- illustration_path = 'illustrations/profile-page/groups.svg'
+- illustration_path = 'illustrations/empty-state/empty-groups-md.svg'
- current_user_empty_message_header = s_('UserProfile|You can create a group for several dependent projects.')
- current_user_empty_message_description = s_('UserProfile|Groups are the best way to manage projects and members.')
- primary_button_label = _('New group')
diff --git a/app/views/shared/hook_logs/_index.html.haml b/app/views/shared/hook_logs/_index.html.haml
index 6a46b0b3510..7dab14b95c1 100644
--- a/app/views/shared/hook_logs/_index.html.haml
+++ b/app/views/shared/hook_logs/_index.html.haml
@@ -1,4 +1,4 @@
-- docs_link_url = help_page_path('user/project/integrations/webhooks', anchor: 'troubleshoot-webhooks')
+- docs_link_url = help_page_path('user/project/integrations/webhooks', anchor: 'troubleshooting')
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
- link_end = '</a>'.html_safe
diff --git a/app/views/shared/icons/_mr_widget_empty_state.svg b/app/views/shared/icons/_mr_widget_empty_state.svg
deleted file mode 100644
index a75eee846c9..00000000000
--- a/app/views/shared/icons/_mr_widget_empty_state.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="256" height="146" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><mask id="d" x="0" y="0" width="178.7" height="115.4" fill="#FFF"><use xlink:href="#a"/></mask><mask id="e" x="0" y="0" width="43.1" height="36.4" fill="#FFF"><use xlink:href="#b"/></mask><mask id="f" x="0" y="0" width="43.1" height="36.4" fill="#FFF"><use xlink:href="#c"/></mask><path d="M8.8 31.5H33a10 10 0 0 0 10-10V10A10 10 0 0 0 33 0H10A10 10 0 0 0 0 10v11.6c0 1.2.2 2.4.7 3.5H0v7.5c0 4 2.4 5 5.3 2.2l3.5-3.3z" id="b"/><path d="M8.8 31.5H33a10 10 0 0 0 10-10V10A10 10 0 0 0 33 0H10A10 10 0 0 0 0 10v11.6c0 1.2.2 2.4.7 3.5H0v7.5c0 4 2.4 5 5.3 2.2l3.5-3.3z" id="c"/><rect id="a" width="178.7" height="115.4" rx="10"/></defs><g fill="none" fill-rule="evenodd"><g transform="translate(0 3.9)" fill="var(--gray-10, #f9f9f9)"><rect x="19.3" width="77.1" height="14.2" rx="7.1"/><rect y="28.4" width="84.9" height="14.2" rx="7.1"/><rect x="133.7" y="42.5" width="122.1" height="14.2" rx="7.1"/><rect x="82.9" y="127" width="101.6" height="14.2" rx="7.1"/><rect x="42.4" y="99.3" width="101.6" height="14.2" rx="7.1"/><rect x="19.9" y="70.9" width="225" height="14.2" rx="7.1"/><path d="M98.4 14.2h-85 13.9a7.1 7.1 0 0 1 7 7 7 7 0 0 1-7 7.2H13.5h84.9-23.5a7.1 7.1 0 0 1-7-7.1 7 7 0 0 1 7-7.1h23.5zm162 42.5H185h23.5a7.1 7.1 0 0 1 7 7.1 7 7 0 0 1-7 7.1H185h75.3-23.5a7.1 7.1 0 0 1-7-7 7 7 0 0 1 7-7.2h23.5zM103.5 85.1H28.3h23.4a7.1 7.1 0 0 1 7.1 7 7 7 0 0 1-7 7.2H28.2h75.2H80a7.1 7.1 0 0 1-7.1-7.1 7 7 0 0 1 7-7.1h23.5zm48.2 28.4H76.5h13.8a7.1 7.1 0 0 1 7 7 7 7 0 0 1-7 7.1H76.5h75.2-33a7.1 7.1 0 0 1-7.2-7 7 7 0 0 1 7.1-7.1h33.1z"/></g><g transform="translate(38.6 12.2)"><use stroke="var(--gray-200, #EEE)" mask="url(#d)" stroke-width="8" fill="var(--white, #fff)" xlink:href="#a"/><path fill="var(--gray-200, #EEE)" d="M2.6 18.7h174.2v2.6H2.6z"/><g fill="var(--gray-100, #EEE)"><g transform="translate(21.9 38.7)"><g fill="var(--dark-icon-color-purple-2, #B5A7DD)"><rect y=".6" width="3.9" height="1.3" rx=".6"/><rect y="7.7" width="3.9" height="1.3" rx=".6"/><rect y="14.8" width="3.9" height="1.3" rx=".6"/></g><rect x="9.6" width="9.6" height="2.6" rx="1.3"/><rect x="46.3" width="9.6" height="2.6" rx="1.3"/><rect x="25.1" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="34.1" y="7.1" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" opacity=".5" x="30.9" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="14.2" width="12.9" height="2.6" rx="1.3"/><rect x="18.6" y="7.1" width="12.9" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="21.9" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="7.1" width="6.4" height="2.6" rx="1.3"/></g><g transform="translate(21.9 60)"><g fill="var(--dark-icon-color-purple-2, #B5A7DD)"><rect y=".6" width="3.9" height="1.3" rx=".6"/><rect y="7.7" width="3.9" height="1.3" rx=".6"/><rect y="14.8" width="3.9" height="1.3" rx=".6"/></g><rect fill="#FC6D26" x="9.6" width="9.6" height="2.6" rx="1.3"/><rect x="46.3" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" opacity=".5" x="25.1" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect x="34.1" y="7.1" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="30.9" width="12.9" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="9.6" y="14.2" width="12.9" height="2.6" rx="1.3"/><rect x="18.6" y="7.1" width="12.9" height="2.6" rx="1.3"/><rect fill="#FC6D26" opacity=".5" x="21.9" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="7.1" width="6.4" height="2.6" rx="1.3"/></g><g transform="translate(21.9 81.2)"><g fill="var(--dark-icon-color-purple-2, #B5A7DD)"><rect y=".6" width="3.9" height="1.3" rx=".6"/><rect y="7.7" width="3.9" height="1.3" rx=".6"/><rect y="14.8" width="3.9" height="1.3" rx=".6"/></g><rect x="9.6" width="9.6" height="2.6" rx="1.3"/><rect x="46.3" width="9.6" height="2.6" rx="1.3"/><rect x="25.1" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect x="34.1" y="7.1" width="9.6" height="2.6" rx="1.3"/><rect fill="#FC6D26" x="30.9" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="14.2" width="12.9" height="2.6" rx="1.3"/><rect x="18.6" y="7.1" width="12.9" height="2.6" rx="1.3"/><rect fill="#FC6D26" opacity=".5" x="21.9" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="7.1" width="6.4" height="2.6" rx="1.3"/></g><g transform="translate(101 38)"><g fill="var(--dark-icon-color-purple-3, #6B4FBB)"><rect opacity=".5" x="25.1" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect x="34.1" y="7.1" width="9.6" height="2.6" rx="1.3"/><rect opacity=".5" x="30.9" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="14.2" width="12.9" height="2.6" rx="1.3"/><rect x="21.9" width="6.4" height="2.6" rx="1.3"/><rect opacity=".5" x="25.1" y="35.5" width="9.6" height="2.6" rx="1.3"/><rect x="18.6" y="28.4" width="9.6" height="2.6" rx="1.3"/><rect x="30.9" y="21.3" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="42.5" width="9.6" height="2.6" rx="1.3"/><rect opacity=".5" x="34.1" y="49.6" width="9.6" height="2.6" rx="1.3"/><rect x="18.6" y="49.6" width="12.9" height="2.6" rx="1.3"/></g><g fill="var(--dark-icon-color-orange-1, #FDE5D8)"><rect y=".6" width="3.9" height="1.3" rx=".6"/><rect y="7.7" width="3.9" height="1.3" rx=".6"/><rect y="14.8" width="3.9" height="1.3" rx=".6"/><rect y="21.9" width="3.9" height="1.3" rx=".6"/><rect y="29" width="3.9" height="1.3" rx=".6"/><rect y="36.1" width="3.9" height="1.3" rx=".6"/><rect y="43.2" width="3.9" height="1.3" rx=".6"/><rect y="50.3" width="3.9" height="1.3" rx=".6"/><rect y="57.4" width="3.9" height="1.3" rx=".6"/></g><rect x="9.6" width="9.6" height="2.6" rx="1.3"/><rect x="46.3" width="9.6" height="2.6" rx="1.3"/><rect x="18.6" y="7.1" width="12.9" height="2.6" rx="1.3"/><rect x="9.6" y="7.1" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="21.3" width="9.6" height="2.6" rx="1.3"/><rect x="37.3" y="14.2" width="9.6" height="2.6" rx="1.3"/><rect x="9.6" y="35.5" width="12.9" height="2.6" rx="1.3"/><rect x="21.9" y="21.3" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="28.4" width="6.4" height="2.6" rx="1.3"/><rect x="30.9" y="28.4" width="6.4" height="2.6" rx="1.3"/><rect x="39.9" y="28.4" width="6.4" height="2.6" rx="1.3"/><rect x="49.5" y="14.2" width="6.4" height="2.6" rx="1.3"/><rect x="25.1" y="56.7" width="9.6" height="2.6" rx="1.3"/><rect x="9.6" y="56.7" width="12.9" height="2.6" rx="1.3"/><rect x="21.9" y="42.5" width="6.4" height="2.6" rx="1.3"/><rect x="46.3" y="49.6" width="6.4" height="2.6" rx="1.3"/><rect x="9.6" y="49.6" width="6.4" height="2.6" rx="1.3"/></g></g></g><g transform="translate(196)"><use stroke="var(--dark-icon-color-orange-1, #FDE5D8)" mask="url(#e)" stroke-width="8" fill="var(--white, #fff)" xlink:href="#b"/><g fill="var(--dark-icon-color-orange-2, #FDB692)"><rect x="9" y="9" width="18.6" height="1.9" rx="1"/><rect x="9" y="14.8" width="25.1" height="1.9" rx="1"/><rect x="9" y="20.6" width="18.6" height="1.9" rx="1"/></g></g><g transform="translate(189 41.3)"><ellipse stroke="#FC6D26" stroke-width="3" fill="#fde5d8" cx="10.3" cy="9.7" rx="9.6" ry="9.7"/><path d="M0 9a8.4 8.4 0 0 0 8-4.3m1-4V0" stroke="#FC6D26" stroke-width="2"/><path d="M5 2a10.3 10.3 0 0 0 8.5 4.4c2.1 0 4-.6 5.7-1.7" stroke="#FC6D26" stroke-width="2"/><circle fill="#FC6D26" cx="6.8" cy="11.3" r="1"/><circle fill="#FC6D26" cx="13.8" cy="11.3" r="1"/></g><g transform="translate(47 96)"><ellipse stroke="var(--dark-icon-color-purple-3, #6B4FBB)" stroke-width="3" fill="#F4F1FA" cx="9.6" cy="10.3" rx="9.6" ry="9.7"/><path d="m12.9 4.5-1.7-2-1.6 2-1.6-2-1.6 2-1.6-2-1.6 2H1.5A9.6 9.6 0 0 1 9.6 0c3.5 0 6.5 1.8 8.2 4.5h-1.7l-1.6-2-1.6 2z" fill="var(--dark-icon-color-purple-3, #6B4FBB)"/><circle fill="var(--dark-icon-color-purple-3, #6B4FBB)" cx="6.1" cy="11.3" r="1"/><circle fill="var(--dark-icon-color-purple-3, #6B4FBB)" cx="13.2" cy="11.3" r="1"/></g><g transform="matrix(-1 0 0 1 56.6 54.8)" fill="var(--dark-icon-color-purple-2, #b5a8dd)"><use stroke="var(--dark-icon-color-purple-1, #E2DCF2)" mask="url(#f)" stroke-width="8" fill="var(--white, #fff)" xlink:href="#c"/><rect x="15.4" y="9" width="18.6" height="1.9" rx="1"/><rect x="21.9" y="14.8" width="12.2" height="1.9" rx="1"/><rect x="21.9" y="20.6" width="12.2" height="1.9" rx="1"/></g></g></svg>
diff --git a/app/views/shared/integrations/_slack_notifications_deprecation_alert.html.haml b/app/views/shared/integrations/_slack_notifications_deprecation_alert.html.haml
new file mode 100644
index 00000000000..de4439a8fde
--- /dev/null
+++ b/app/views/shared/integrations/_slack_notifications_deprecation_alert.html.haml
@@ -0,0 +1,20 @@
+- if Gitlab.com?
+ = render Pajamas::AlertComponent.new(title: _('Slack notifications integration is deprecated'),
+ variant: :warning,
+ dismissible: false,
+ alert_options: { class: 'gl-mt-5', data: { testid: "slack-notifications-deprecation" } }) do |c|
+ = c.body do
+ - help_page_link = help_page_url('user/project/integrations/gitlab_slack_application')
+ - learn_more_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_link }
+
+ = html_escape(s_('The Slack notifications integration is deprecated and will be removed in a future release. To continue to receive notifications from Slack, use the GitLab for Slack app instead. %{learn_more_link_start}Learn more%{link_end}.')) % { learn_more_link_start: learn_more_link, link_end: '</a>'.html_safe }
+- else
+ = render Pajamas::AlertComponent.new(title: _('Slack notifications will be deprecated'),
+ variant: :warning,
+ dismissible: false,
+ alert_options: { class: 'gl-mt-5', data: { testid: "slack-notifications-deprecation" } }) do |c|
+ = c.body do
+ - help_page_link = help_page_url('user/project/integrations/gitlab_slack_application')
+ - learn_more_link = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_link }
+
+ = html_escape(s_('Slack notifications will be brought into the GitLab for Slack app so you can manage both integrations from one place. %{learn_more_link_start}Learn more%{link_end}.')) % { learn_more_link_start: learn_more_link, link_end: '</a>'.html_safe }
diff --git a/app/views/shared/integrations/edit.html.haml b/app/views/shared/integrations/edit.html.haml
index 0ae0eea59d8..9d613d2ad94 100644
--- a/app/views/shared/integrations/edit.html.haml
+++ b/app/views/shared/integrations/edit.html.haml
@@ -1,7 +1,6 @@
- add_to_breadcrumbs _('Integrations'), scoped_integrations_path(project: @project, group: @group)
- breadcrumb_title @integration.title
- page_title @integration.title, _('Integrations')
-- @content_class = 'limit-container-width' unless fluid_layout
%h2.gl-mb-4
= @integration.title
diff --git a/app/views/shared/integrations/overrides.html.haml b/app/views/shared/integrations/overrides.html.haml
index a63053bde0a..c25527a605c 100644
--- a/app/views/shared/integrations/overrides.html.haml
+++ b/app/views/shared/integrations/overrides.html.haml
@@ -1,7 +1,6 @@
- add_to_breadcrumbs _('Integrations'), scoped_integrations_path(project: @project, group: @group)
- breadcrumb_title @integration.title
- page_title @integration.title, _('Integrations')
-- @content_class = 'limit-container-width' unless fluid_layout
%h1.page-title.gl-font-size-h-display
= @integration.title
diff --git a/app/views/shared/integrations/prometheus/_custom_metrics.html.haml b/app/views/shared/integrations/prometheus/_custom_metrics.html.haml
index dda84e0fb9e..beeb328aedf 100644
--- a/app/views/shared/integrations/prometheus/_custom_metrics.html.haml
+++ b/app/views/shared/integrations/prometheus/_custom_metrics.html.haml
@@ -3,16 +3,16 @@
.col-lg-3
%p
= s_('PrometheusService|Custom metrics require Prometheus installed on a cluster with environment scope "*" OR a manually configured Prometheus to be available.')
- = link_to s_('PrometheusService|More information'), help_page_path('operations/metrics/index.md', anchor: 'adding-custom-metrics'), target: '_blank', rel: "noopener noreferrer"
+ = link_to s_('PrometheusService|More information'), help_page_path('operations/metrics/index.md'), target: '_blank', rel: "noopener noreferrer"
.col-lg-9
- .card.custom-monitored-metrics.js-panel-custom-monitored-metrics{ data: { active_custom_metrics: project_prometheus_metrics_path(project), environments_data: environments_list_data, service_active: "#{integration.active}" } }
- .card-header
+ = render Pajamas::CardComponent.new(header_options: { class: 'gl-display-flex gl-align-items-center' }, body_options: { class: 'gl-p-0' }, card_options: { class: 'gl-mb-5 custom-monitored-metrics js-panel-custom-monitored-metrics', data: { active_custom_metrics: project_prometheus_metrics_path(project), environments_data: environments_list_data, service_active: "#{integration.active}" } }) do |c|
+ - c.header do
%strong
= s_('PrometheusService|Custom metrics')
- = gl_badge_tag 0, nil, class: 'js-custom-monitored-count'
+ = gl_badge_tag 0, nil, class: 'gl-ml-2 js-custom-monitored-count'
= link_to s_('PrometheusService|New metric'), new_project_prometheus_metric_path(project), class: 'btn gl-button btn-confirm gl-ml-auto js-new-metric-button hidden'
- .card-body
+ - c.body do
.flash-container.hidden
.flash-warning
.flash-text
diff --git a/app/views/shared/integrations/prometheus/_metrics.html.haml b/app/views/shared/integrations/prometheus/_metrics.html.haml
index c74dbfd8b15..7cd4eeee5f8 100644
--- a/app/views/shared/integrations/prometheus/_metrics.html.haml
+++ b/app/views/shared/integrations/prometheus/_metrics.html.haml
@@ -8,12 +8,12 @@
= link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus'), target: '_blank', rel: "noopener noreferrer"
.col-lg-9
- .card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/index') } }
- .card-header
+ = render Pajamas::CardComponent.new(body_options: { class: 'gl-p-0' }, card_options: { class: 'gl-mb-5 js-panel-monitored-metrics', data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/index') }}) do |c|
+ - c.header do
%strong
= s_('PrometheusService|Common metrics')
- = gl_badge_tag 0, nil, class: 'js-monitored-count'
- .card-body
+ = gl_badge_tag 0, nil, class: 'js-monitored-count'
+ - c.body do
.loading-metrics.js-loading-metrics
%p.m-3
= gl_loading_icon(inline: true, css_class: 'metrics-load-spinner')
@@ -23,16 +23,16 @@
= s_('PrometheusService|Waiting for your first deployment to an environment to find common metrics')
%ul.list-unstyled.metrics-list.hidden.js-metrics-list
- .card.hidden.js-panel-missing-env-vars
- .card-header
+ = render Pajamas::CardComponent.new(body_options: { class: 'hidden gl-p-0' }, card_options: { class: 'hidden js-panel-missing-env-vars' }) do |c|
+ - c.header do
= sprite_icon('chevron-lg-right', css_class: 'panel-toggle js-panel-toggle-right')
= sprite_icon('chevron-lg-down', css_class: 'panel-toggle js-panel-toggle-down hidden')
= s_('PrometheusService|Missing environment variable')
= gl_badge_tag 0, nil, class: 'js-env-var-count'
- .card-body.hidden
+ - c.body do
.flash-container
.flash-notice
.flash-text
- = s_("PrometheusService|To set up automatic monitoring, add the environment variable %{variable} to exporter's queries." % { variable: "<code>$CI_ENVIRONMENT_SLUG</code>" }).html_safe
- = link_to s_('PrometheusService|More information'), help_page_path('operations/metrics/dashboards/variables.md', anchor: 'query-variables')
+ = html_escape(s_("PrometheusService|To set up automatic monitoring, add the environment variable %{variable} to exporter's queries.")) % { variable: "<code>$CI_ENVIRONMENT_SLUG</code>".html_safe }
+ = link_to s_('PrometheusService|More information'), help_page_path('operations/metrics/index.md')
%ul.list-unstyled.metrics-list.js-missing-var-metrics-list
diff --git a/app/views/shared/issuable/_feed_buttons.html.haml b/app/views/shared/issuable/_feed_buttons.html.haml
index 94b7fe14721..1a9bbac6f05 100644
--- a/app/views/shared/issuable/_feed_buttons.html.haml
+++ b/app/views/shared/issuable/_feed_buttons.html.haml
@@ -1,8 +1,10 @@
- show_calendar_button = local_assigns.fetch(:show_calendar_button, true)
-= render Pajamas::ButtonComponent.new(href: safe_params.merge(rss_url_options), icon: 'rss', button_options: { class: 'has-tooltip', 'aria-label': _('Subscribe to RSS feed'), data: { container: 'body', testid: 'rss-feed-link' } }) do
- = _('Subscribe to RSS feed')
-
- if show_calendar_button
- = render Pajamas::ButtonComponent.new(href: safe_params.merge(calendar_url_options), icon: 'calendar', button_options: { class: 'has-tooltip', 'aria-label': _('Subscribe to calendar'), data: { container: 'body' } }) do
- = _('Subscribe to calendar')
+ = link_to safe_params.merge(calendar_url_options), class: 'dropdown-item' do
+ .gl-dropdown-item-text-wrapper
+ = _("Subscribe to calendar")
+
+= link_to safe_params.merge(rss_url_options), class: 'dropdown-item' do
+ .gl-dropdown-item-text-wrapper
+ = _("Subscribe to RSS feed")
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 07cdbbece8c..b6bd691213c 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -6,14 +6,8 @@
= form_errors(issuable)
- if @conflict
- = render Pajamas::AlertComponent.new(variant: :danger,
- dismissible: false,
- alert_options: { class: 'gl-mb-5' }) do |c|
- = c.body do
- Someone edited the #{issuable.class.model_name.human.downcase} the same time you did.
- Please check out
- = link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project, issuable]), target: "_blank", rel: 'noopener noreferrer'
- and make sure your changes will not unintentionally remove theirs
+ - model_name = _(issuable.class.model_name.human.downcase)
+ = render 'shared/model_version_conflict', model_name: model_name, link_path: polymorphic_path([@project, issuable])
= render 'shared/issuable/form/branch_chooser', issuable: issuable, form: form
@@ -62,9 +56,9 @@
= sanitize(html_escape(_('Please review the %{linkStart}contribution guidelines%{linkEnd} for this project.')) % { linkStart: contribution_guidelines_start, linkEnd: contribution_guidelines_end })
- if issuable.new_record?
- = form.submit "#{_('Create')} #{issuable.class.model_name.human.downcase}", pajamas_button: true, class: 'gl-mr-2', data: { qa_selector: 'issuable_create_button', track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
+ = form.submit "#{_('Create')} #{issuable.class.model_name.human.downcase}", pajamas_button: true, class: 'gl-mr-2 js-issuable-submit-button js-reset-autosave', data: { qa_selector: 'issuable_create_button', track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
- else
- = form.submit _('Save changes'), pajamas_button: true, class: 'gl-mr-2', data: { track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
+ = form.submit _('Save changes'), pajamas_button: true, class: 'gl-mr-2 js-issuable-submit-button js-reset-autosave', data: { track_action: 'click_button', track_label: 'submit_mr', track_value: 0 }
- if issuable.new_record?
= link_to _('Cancel'), polymorphic_path([@project, issuable.class]), class: 'btn gl-button btn-default js-reset-autosave'
diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml
index af63839d7c1..3c4ee01d04f 100644
--- a/app/views/shared/issuable/_label_dropdown.html.haml
+++ b/app/views/shared/issuable/_label_dropdown.html.haml
@@ -26,7 +26,7 @@
- apply_is_default_styles = (selected.nil? || selected.empty?) && !no_default_styles
%span.dropdown-toggle-text{ class: ("is-default" if apply_is_default_styles) }
= multi_label_name(selected, label_name)
- = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
+ = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon")
.dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
= render partial: "shared/issuable/label_page_default", locals: { title: dropdown_title, show_footer: show_footer, show_create: show_create }
- if show_create && project && can?(current_user, :admin_label, project)
diff --git a/app/views/shared/issuable/_label_page_create.html.haml b/app/views/shared/issuable/_label_page_create.html.haml
index eb3acd8e055..96167db80b4 100644
--- a/app/views/shared/issuable/_label_page_create.html.haml
+++ b/app/views/shared/issuable/_label_page_create.html.haml
@@ -10,9 +10,9 @@
%input#new_label_name.default-dropdown-input{ type: "text", placeholder: _('Name new label') }
.suggest-colors.suggest-colors-dropdown
= render_suggested_colors
- .dropdown-label-color-input
- .dropdown-label-color-preview.js-dropdown-label-color-preview
- %input#new_label_color.default-dropdown-input{ type: "text", placeholder: _('Assign custom color like #FF0000') }
+ .dropdown-label-color-input.gl-display-flex
+ %input.dropdown-label-color-preview.js-dropdown-label-color-preview.gl-w-7.gl-h-7.gl-border-1.gl-border-solid.gl-border-gray-500.gl-rounded-top-right-none.gl-rounded-bottom-right-none{ class: "gl-border-r-0!", type: "color", placeholder: _('Select color') }
+ %input#new_label_color.default-dropdown-input.gl-rounded-top-left-none.gl-rounded-bottom-left-none{ type: "text", placeholder: _('Assign custom color like #FF0000') }
- if show_add_list
.dropdown-label-input{ class: add_list_class }
%label
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 72940b64801..76678c48a86 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -162,6 +162,15 @@
%li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
%button.gl-button.btn.btn-link{ type: 'button' }
= _('No')
+ - if ::Feature.enabled?(:mr_approved_filter, type: :ops)
+ #js-dropdown-approved.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('Yes')
+ %li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
+ %button.gl-button.btn.btn-link{ type: 'button' }
+ = _('No')
#js-dropdown-confidential.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
@@ -186,7 +195,7 @@
= render_if_exists 'shared/issuable/filter_epic', type: type
- %button.clear-search.hidden{ type: 'button' }
+ %button.clear-search.hidden.gl-rounded-base{ type: 'button' }
= sprite_icon('close', size: 16, css_class: 'clear-search-icon')
.filter-dropdown-container.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-align-items-flex-start
- if type != :productivity_analytics && show_sorting_dropdown
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index f54354674e2..09162e6a349 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -9,14 +9,15 @@
- reviewers = local_assigns.fetch(:reviewers, nil)
- in_group_context_with_iterations = @project.group.present? && issuable_sidebar[:supports_iterations]
- is_merge_request = issuable_type === 'merge_request'
-- moved_sidebar_enabled = moved_mr_sidebar_enabled? && is_merge_request
+- moved_sidebar_enabled = moved_mr_sidebar_enabled?
+- is_merge_request_with_flag = is_merge_request && moved_sidebar_enabled
-%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class} #{'right-sidebar-merge-requests' if moved_sidebar_enabled}", 'aria-live' => 'polite', 'aria-label': issuable_type }
- .issuable-sidebar{ class: "#{'is-merge-request' if moved_sidebar_enabled}" }
- .issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end gl-lg-display-none!' if moved_sidebar_enabled}" }
+%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class(is_merge_request_with_flag)} #{'right-sidebar-merge-requests' if is_merge_request_with_flag}", 'aria-live' => 'polite', 'aria-label': issuable_type }
+ .issuable-sidebar{ class: "#{'is-merge-request' if is_merge_request_with_flag}" }
+ .issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end gl-lg-display-none!' if is_merge_request_with_flag}" }
%button.btn.gl-button.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ type: "reset", class: "gl-shadow-none! #{'gl-display-block' if moved_sidebar_enabled}", "aria-label" => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }
= sidebar_gutter_toggle_icon
- - if signed_in && !moved_sidebar_enabled
+ - if signed_in && !is_merge_request_with_flag
.js-sidebar-todo-widget-root{ data: { project_path: issuable_sidebar[:project_full_path], iid: issuable_sidebar[:iid], id: issuable_sidebar[:id] } }
= form_for issuable_type, url: issuable_sidebar[:issuable_json_path], remote: true, html: { class: 'issuable-context-form inline-update js-issuable-update' } do |f|
@@ -81,19 +82,19 @@
.js-sidebar-participants-widget-root
- .block.with-sub-blocks
- - if !moved_sidebar_enabled
+ - if !moved_sidebar_enabled
+ .block.with-sub-blocks
.js-sidebar-reference-widget-root
- - if issuable_type == 'merge_request' && !moved_sidebar_enabled
- .sub-block.js-sidebar-source-branch
- .sidebar-collapsed-icon.js-dont-change-state
- = clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy')
- .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
- = _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<span class='gl-font-monospace' data-testid='ref-name' title='#{html_escape(source_branch)}'>".html_safe, source_branch_close: "</span>".html_safe, source_branch: html_escape(source_branch) }
- = clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy')
-
- - if show_forwarding_email
+ - if is_merge_request && !moved_sidebar_enabled
+ .sub-block.js-sidebar-source-branch
+ .sidebar-collapsed-icon.js-dont-change-state
+ = clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy')
+ .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
+ = _('Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}').html_safe % { source_branch_open: "<span class='gl-font-monospace' data-testid='ref-name' title='#{html_escape(source_branch)}'>".html_safe, source_branch_close: "</span>".html_safe, source_branch: html_escape(source_branch) }
+ = clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport', class: 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm js-source-branch-copy')
+
+ - if show_forwarding_email && !moved_sidebar_enabled
.block
.js-sidebar-copy-email-root
- if issuable_sidebar.dig(:current_user, :can_move)
diff --git a/app/views/shared/issuable/_sidebar_user_dropdown.html.haml b/app/views/shared/issuable/_sidebar_user_dropdown.html.haml
index c058e7ebe3e..9bfdacc8cfd 100644
--- a/app/views/shared/issuable/_sidebar_user_dropdown.html.haml
+++ b/app/views/shared/issuable/_sidebar_user_dropdown.html.haml
@@ -14,8 +14,6 @@
%li
.js-invite-members-trigger{ data: { trigger_element: 'anchor',
display_text: _('Invite Members'),
- event: 'click_invite_members',
- trigger_source: local_assigns.fetch(:trigger_source),
- label: data['track-label'] } }
+ trigger_source: local_assigns.fetch(:trigger_source) } }
- else
= dropdown_tag(data['dropdown-title'], options: options)
diff --git a/app/views/shared/issuable/form/_default_templates.html.haml b/app/views/shared/issuable/form/_default_templates.html.haml
index 50f30e58b35..2dda0049c09 100644
--- a/app/views/shared/issuable/form/_default_templates.html.haml
+++ b/app/views/shared/issuable/form/_default_templates.html.haml
@@ -1,4 +1,4 @@
-%p.form-text.text-muted
+.gl-mt-3.gl-text-secondary
- template_link_url = help_page_path('user/project/description_templates')
- template_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: template_link_url }
= s_('Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!').html_safe % { link_start: template_link_start, link_end: '</a>'.html_safe }
diff --git a/app/views/shared/issuable/form/_merge_params.html.haml b/app/views/shared/issuable/form/_merge_params.html.haml
index 09086d3aa82..8e9793cdba5 100644
--- a/app/views/shared/issuable/form/_merge_params.html.haml
+++ b/app/views/shared/issuable/form/_merge_params.html.haml
@@ -9,22 +9,25 @@
%label
= _('Merge options')
- if issuable.can_remove_source_branch?(current_user)
- .form-check.gl-mb-3
+ .form-check.gl-pl-0
= hidden_field_tag 'merge_request[force_remove_source_branch]', '0', id: nil
- = check_box_tag 'merge_request[force_remove_source_branch]', '1', issuable.force_remove_source_branch?, class: 'form-check-input js-form-update'
- = label_tag 'merge_request[force_remove_source_branch]', class: 'form-check-label' do
- = _("Delete source branch when merge request is accepted.")
+ = render Pajamas::CheckboxTagComponent.new(name: 'merge_request[force_remove_source_branch]', checked: issuable.force_remove_source_branch?, value: '1', checkbox_options: { class: 'js-form-update' }) do |c|
+ = c.label do
+ = _("Delete source branch when merge request is accepted.")
+
- if !project.squash_never?
- .form-check
+ .form-check.gl-pl-0
- if project.squash_always?
= hidden_field_tag 'merge_request[squash]', '1', id: nil
- = check_box_tag 'merge_request[squash]', '1', project.squash_enabled_by_default?, class: 'form-check-input', disabled: 'true'
+ = render Pajamas::CheckboxTagComponent.new(name: 'merge_request[squash]', checked: project.squash_enabled_by_default?, value: '1', checkbox_options: { class: 'js-form-update', disabled: true }) do |c|
+ = c.label do
+ = _("Squash commits when merge request is accepted.")
+ = link_to sprite_icon('question-o'), help_page_path('user/project/merge_requests/squash_and_merge'), target: '_blank', rel: 'noopener noreferrer'
+ = c.help_text do
+ = _('Required in this project.')
- else
= hidden_field_tag 'merge_request[squash]', '0', id: nil
- = check_box_tag 'merge_request[squash]', '1', issuable_squash_option?(issuable, project), class: 'form-check-input js-form-update'
- = label_tag 'merge_request[squash]', class: 'form-check-label' do
- = _("Squash commits when merge request is accepted.")
- = link_to sprite_icon('question-o'), help_page_path('user/project/merge_requests/squash_and_merge'), target: '_blank', rel: 'noopener noreferrer'
- - if project.squash_always?
- .gl-text-gray-400
- = _('Required in this project.')
+ = render Pajamas::CheckboxTagComponent.new(name: 'merge_request[squash]', checked: issuable_squash_option?(issuable, project), value: '1', checkbox_options: { class: 'js-form-update' }) do |c|
+ = c.label do
+ = _("Squash commits when merge request is accepted.")
+ = link_to sprite_icon('question-o'), help_page_path('user/project/merge_requests/squash_and_merge'), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml
index 9603178f7de..b27fd8ab7d2 100644
--- a/app/views/shared/issuable/form/_metadata.html.haml
+++ b/app/views/shared/issuable/form/_metadata.html.haml
@@ -37,12 +37,15 @@
.issuable-form-select-holder
= render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]"
- .form-group.row
- = form.label :label_ids, _('Labels'), class: "col-12"
- = form.hidden_field :label_ids, multiple: true, value: ''
- .col-12
- .issuable-form-select-holder
- = render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false }, dropdown_title: "Select label"
+ - if Feature.enabled?(:visible_label_selection_on_metadata, project)
+ .js-issuable-form-label-selector{ data: issuable_label_selector_data(project, issuable) }
+ - else
+ .form-group.row
+ = form.label :label_ids, _('Labels'), class: "col-12"
+ = form.hidden_field :label_ids, multiple: true, value: ''
+ .col-12
+ .issuable-form-select-holder
+ = render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false }, dropdown_title: "Select label"
= render_if_exists "shared/issuable/form/merge_request_blocks", issuable: issuable, form: form
diff --git a/app/views/shared/issuable/form/_title.html.haml b/app/views/shared/issuable/form/_title.html.haml
index 4d31baee25b..be836f4b8a9 100644
--- a/app/views/shared/issuable/form/_title.html.haml
+++ b/app/views/shared/issuable/form/_title.html.haml
@@ -1,6 +1,5 @@
- issuable = local_assigns.fetch(:issuable)
- form = local_assigns.fetch(:form)
-- no_issuable_templates = issuable_templates(ref_project, issuable.to_ability_name).empty?
%div{ data: { testid: 'issue-title-input-field' } }
= form.text_field :title, required: true, aria: { required: true }, maxlength: 255, autofocus: true,
@@ -13,6 +12,3 @@
= s_('MergeRequests|Mark as draft')
= c.help_text do
= s_('MergeRequests|Drafts cannot be merged until marked ready.')
-
- - if no_issuable_templates && can?(current_user, :push_code, issuable.project)
- = render 'shared/issuable/form/default_templates'
diff --git a/app/views/shared/issuable/form/_type_selector.html.haml b/app/views/shared/issuable/form/_type_selector.html.haml
index a94ef70b2d5..0bcdcb9e963 100644
--- a/app/views/shared/issuable/form/_type_selector.html.haml
+++ b/app/views/shared/issuable/form/_type_selector.html.haml
@@ -5,30 +5,10 @@
= _('Type')
#js-type-popover
- .issuable-form-select-holder.selectbox.form-group.gl-mb-0.gl-display-block
- .dropdown.js-issuable-type-filter-dropdown-wrap
- %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
- %span.dropdown-toggle-text.is-default
- = issuable.issue_type.capitalize || _("Select type")
- = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
- .dropdown-menu.dropdown-menu-selectable.dropdown-select
- .dropdown-title.gl-display-flex
- %span.gl-ml-auto
- = _("Select type")
- %button.dropdown-title-button.dropdown-menu-close.gl-ml-auto{ type: 'button', "aria-label" => _('Close') }
- = sprite_icon('close', size: 16, css_class: 'dropdown-menu-close-icon')
- .dropdown-content{ data: { testid: 'issue-type-select-dropdown' } }
- %ul
- - if create_issue_type_allowed?(@project, :issue)
- %li.js-filter-issuable-type
- = link_to new_project_issue_path(@project), class: ("is-active" if issuable.issue?) do
- #{sprite_icon(work_item_type_icon(:issue), css_class: 'gl-icon')} #{_('Issue')}
- - if create_issue_type_allowed?(@project, :incident)
- %li.js-filter-issuable-type{ data: { track: { action: "select_issue_type_incident", label: "select_issue_type_incident_dropdown_option" } } }
- = link_to new_project_issue_path(@project, { issuable_template: 'incident', issue: { issue_type: 'incident' } }), class: ("is-active" if issuable.incident?) do
- #{sprite_icon(work_item_type_icon(:incident), css_class: 'gl-icon')} #{_('Incident')}
+ .issuable-form-select-holder.form-group.gl-mb-0.gl-display-block
+ #js-type-select{ data: issuable_type_selector_data(issuable) }
- - if issuable.incident?
+ - if issuable.incident_type_issue?
%p.form-text.text-muted
- incident_docs_url = help_page_path('operations/incident_management/incidents.md')
- incident_docs_start = format('<a href="%{url}" target="_blank" rel="noopener noreferrer">', url: incident_docs_url)
diff --git a/app/views/shared/issue_type/_details_content.html.haml b/app/views/shared/issue_type/_details_content.html.haml
index e1a9b30ef67..fdbe247c6ba 100644
--- a/app/views/shared/issue_type/_details_content.html.haml
+++ b/app/views/shared/issue_type/_details_content.html.haml
@@ -2,7 +2,7 @@
- api_awards_path = local_assigns.fetch(:api_awards_path, nil)
.issue-details.issuable-details.js-issue-details
- .detail-page-description.content-block.js-detail-page-description.gl-pb-0.gl-border-none
+ .detail-page-description.content-block.js-detail-page-description.gl-pt-4.gl-pb-0.gl-border-none
#js-issuable-app{ data: { initial: issuable_initial_data(issuable).to_json,
issuable_id: issuable.id,
full_path: @project.full_path,
@@ -30,14 +30,14 @@
#js-related-merge-requests{ data: { endpoint: expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: issuable.iid)), project_namespace: @project.namespace.path, project_path: @project.path } }
- - if can?(current_user, :admin_feature_flags_issue_links, @project)
- = render_if_exists 'projects/issues/related_feature_flags'
-
- if can?(current_user, :read_code, @project)
- add_page_startup_api_call related_branches_path
#related-branches{ data: { url: related_branches_path } }
-# This element is filled in using JavaScript.
+ - if can?(current_user, :admin_feature_flags_issue_links, @project)
+ = render_if_exists 'projects/issues/related_feature_flags'
+
.js-issue-widgets
= render 'projects/issues/discussion'
diff --git a/app/views/shared/issue_type/_details_header.html.haml b/app/views/shared/issue_type/_details_header.html.haml
index ccb501dae11..b6c0b73a83d 100644
--- a/app/views/shared/issue_type/_details_header.html.haml
+++ b/app/views/shared/issue_type/_details_header.html.haml
@@ -2,7 +2,7 @@
- badge_classes = 'issuable-status-badge gl-mr-3'
.detail-page-header
- .detail-page-header-body.gl-flex-wrap-wrap
+ .detail-page-header-body.gl-flex-wrap
= gl_badge_tag({ variant: :info, icon: 'issue-closed', icon_classes: 'gl-mr-0!' }, { class: "#{issue_status_visibility(issuable, status_box: :closed)} #{badge_classes} issuable-status-badge-closed" }) do
.gl-display-none.gl-sm-display-block.gl-ml-2
= issue_closed_text(issuable, current_user)
@@ -19,4 +19,4 @@
%a.btn.gl-button.btn-default.btn-icon.float-right.gl-display-block.d-sm-none.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ href: "#" }
= sprite_icon('chevron-double-lg-left')
- .js-issue-header-actions{ data: issue_header_actions_data(@project, issuable, current_user) }
+ .js-issue-header-actions{ data: issue_header_actions_data(@project, issuable, current_user, @issuable_sidebar) }
diff --git a/app/views/shared/labels/_form.html.haml b/app/views/shared/labels/_form.html.haml
index 9ef4b9e084d..899b2ed832e 100644
--- a/app/views/shared/labels/_form.html.haml
+++ b/app/views/shared/labels/_form.html.haml
@@ -9,19 +9,17 @@
.form-group.row
.col-12
- = f.label :description
- = f.text_field :description, class: "gl-form-input form-control js-quick-submit", data: { qa_selector: 'label_description_field' }
+ = f.label :description, _("Description (optional)")
+ = f.text_area :description, class: "gl-form-input form-control js-quick-submit", rows: 4, data: { qa_selector: 'label_description_field' }
.form-group.row
.col-12
= f.label :color, _("Background color")
.input-group
.input-group-prepend
- .input-group-text.label-color-preview &nbsp;
+ %input.label-color-preview.gl-w-7.gl-h-full.gl-border-1.gl-border-solid.gl-border-gray-500.gl-border-r-0.gl-rounded-top-right-none.gl-rounded-bottom-right-none{ type: "color", placeholder: _('Select color') }
= f.text_field :color, class: "gl-form-input form-control", data: { qa_selector: 'label_color_field' }
.form-text.text-muted
- = _('Choose any color.')
- %br
- = _("Or you can choose one of the suggested colors below")
+ = _('Select a color from the color picker or from the presets below.')
= render_suggested_colors
.gl-display-flex.gl-justify-content-space-between
%div
diff --git a/app/views/shared/milestones/_delete_button.html.haml b/app/views/shared/milestones/_delete_button.html.haml
index 432d2efc36e..caab7710fa8 100644
--- a/app/views/shared/milestones/_delete_button.html.haml
+++ b/app/views/shared/milestones/_delete_button.html.haml
@@ -1,8 +1,6 @@
- milestone_url = @milestone.project_milestone? ? project_milestone_path(@project, @milestone) : group_milestone_path(@group, @milestone)
-= render Pajamas::ButtonComponent.new(variant: :danger,
- button_options: { class: 'js-delete-milestone-button btn-grouped', data: { milestone_id: @milestone.id, milestone_title: markdown_field(@milestone, :title), milestone_url: milestone_url, milestone_issue_count: @milestone.issues.count, milestone_merge_request_count: @milestone.merge_requests.count }, disabled: true }) do
- = gl_loading_icon(inline: true, css_class: "gl-mr-2 js-loading-icon hidden")
- = _('Delete')
-
+%button.gl-button.btn.btn-link.menu-item.js-delete-milestone-button{ data: { milestone_id: @milestone.id, milestone_title: markdown_field(@milestone, :title), milestone_url: milestone_url, milestone_issue_count: @milestone.issues.count, milestone_merge_request_count: @milestone.merge_requests.count }, disabled: true }
+ .gl-dropdown-item-text-wrapper.gl-text-red-500
+ = _('Delete')
#js-delete-milestone-modal
diff --git a/app/views/shared/milestones/_description.html.haml b/app/views/shared/milestones/_description.html.haml
index fc25c7e8f89..a63702661d0 100644
--- a/app/views/shared/milestones/_description.html.haml
+++ b/app/views/shared/milestones/_description.html.haml
@@ -1,4 +1,4 @@
-.detail-page-description.milestone-detail
+.detail-page-description.milestone-detail.gl-py-4
%h2.gl-m-0{ data: { qa_selector: "milestone_title_content" } }
= markdown_field(milestone, :title)
.gl-font-sm.gl-text-secondary.gl-font-base.gl-font-weight-normal.gl-line-height-normal{ data: { qa_selector: 'milestone_id_content' }, itemprop: 'identifier' }
@@ -9,5 +9,5 @@
- if milestone.try(:description).present?
%div{ data: { qa_selector: "milestone_description_content" } }
- .description.md.gl-px-0.gl-pt-4.gl-border-1.gl-border-t-solid.gl-border-gray-100
+ .description.md.gl-px-0.gl-pt-4
= markdown_field(milestone, :description)
diff --git a/app/views/shared/milestones/_form_dates.html.haml b/app/views/shared/milestones/_form_dates.html.haml
index 50e3e8e195c..3e75775bf73 100644
--- a/app/views/shared/milestones/_form_dates.html.haml
+++ b/app/views/shared/milestones/_form_dates.html.haml
@@ -1,11 +1,14 @@
-.form-group.row
- .col-form-label.col-sm-2
+.gl-form-group
+ %div
= f.label :start_date, _('Start Date')
- .col-sm-4
- = f.gitlab_ui_datepicker :start_date, data: { qa_selector: "start_date_field" }, placeholder: _('Select start date'), autocomplete: 'off'
- %a.inline.float-right.gl-mt-2.js-clear-start-date{ href: "#" }= _('Clear start date')
- .col-form-label.col-sm-2
+ %div
+ .issuable-form-select-holder
+ = f.gitlab_ui_datepicker :start_date, data: { qa_selector: "start_date_field" }, placeholder: _('Select start date'), autocomplete: 'off'
+ %a.gl-white-space-nowrap.gl-pl-4.js-clear-start-date{ href: "#" }= _('Clear start date')
+.gl-form-group
+ %div
= f.label :due_date, _('Due Date')
- .col-sm-4
- = f.gitlab_ui_datepicker :due_date, data: { qa_selector: "due_date_field" }, placeholder: _('Select due date'), autocomplete: 'off'
- %a.inline.float-right.gl-mt-2.js-clear-due-date{ href: "#" }= _('Clear due date')
+ %div
+ .issuable-form-select-holder
+ = f.gitlab_ui_datepicker :due_date, data: { qa_selector: "due_date_field" }, placeholder: _('Select due date'), autocomplete: 'off'
+ %a.gl-white-space-nowrap.gl-pl-4.js-clear-due-date{ href: "#" }= _('Clear due date')
diff --git a/app/views/shared/milestones/_header.html.haml b/app/views/shared/milestones/_header.html.haml
index 900c71675d9..3413d6ff399 100644
--- a/app/views/shared/milestones/_header.html.haml
+++ b/app/views/shared/milestones/_header.html.haml
@@ -1,30 +1,57 @@
-.detail-page-header.milestone-page-header
- = gl_badge_tag milestone_status_string(milestone), { variant: milestone_badge_variant(milestone) }, { class: 'gl-mr-3' }
+.detail-page-header
+ .detail-page-header-body.gl-flex-wrap
+ = gl_badge_tag milestone_status_string(milestone), { variant: milestone_badge_variant(milestone) }, { class: 'gl-mr-3' }
- .header-text-content
- %span.identifier
- %strong
- = _('Milestone')
- - if milestone.due_date || milestone.start_date
- = milestone_date_range(milestone)
-
- .milestone-buttons
- - if can?(current_user, :admin_milestone, @group || @project)
- = render Pajamas::ButtonComponent.new(href: edit_milestone_path(milestone), button_options: { class: 'btn-grouped' }) do
- = _('Edit')
-
- - if milestone.project_milestone? && milestone.project.group
- = render Pajamas::ButtonComponent.new(button_options: { class: 'js-promote-project-milestone-button btn-grouped', data: { milestone_title: milestone.title, group_name: milestone.project.group.name, url: promote_project_milestone_path(milestone.project, milestone) }, disabled: true }) do
- = _('Promote')
- #promote-milestone-modal
+ .header-text-content
+ %span.identifier
+ %strong
+ = _('Milestone')
+ - if milestone.due_date || milestone.start_date
+ = milestone_date_range(milestone)
+ = render Pajamas::ButtonComponent.new(icon: 'chevron-double-lg-left', button_options: { 'aria-label' => _('Toggle sidebar'), class: 'btn-grouped gl-float-right! gl-sm-display-none js-sidebar-toggle' })
+ - if can?(current_user, :admin_milestone, @group || @project)
+ .milestone-buttons.detail-page-header-actions.gl-display-flex.gl-align-self-start
- if milestone.active?
- = render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :close }), method: :put, button_options: { class: 'btn-grouped btn-close' }) do
+ = render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :close }), method: :put, button_options: { class: 'btn-close gl-display-none gl-md-display-inline-block' }) do
= _('Close milestone')
- else
- = render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :activate }), method: :put, button_options: { class: 'btn-grouped' }) do
+ = render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :activate }), method: :put, button_options: { class: 'gl-display-none gl-md-display-inline-block' }) do
= _('Reopen milestone')
- = render 'shared/milestones/delete_button'
-
- = render Pajamas::ButtonComponent.new(icon: 'chevron-double-lg-left', button_options: { 'aria-label' => _('Toggle sidebar'), class: 'btn-grouped gl-float-right! gl-sm-display-none js-sidebar-toggle' })
+ .btn-group.gl-md-ml-3.gl-display-flex.dropdown.gl-dropdown.gl-md-w-auto.gl-w-full
+ = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle btn-default-tertiary dropdown-icon-only dropdown-toggle-no-caret has-tooltip gl-display-none! gl-md-display-inline-flex!", data: { toggle: 'dropdown', title: _('Milestone actions'), testid: 'milestone-actions', 'aria-label': _('Milestone actions') }, aria: { label: _('Milestone actions') } do
+ = sprite_icon "ellipsis_v", size: 16, css_class: "dropdown-icon gl-icon"
+ = button_tag type: 'button', class: "btn dropdown-toggle btn-default btn-md btn-block gl-button gl-dropdown-toggle gl-md-display-none!", data: { 'toggle' => 'dropdown' } do
+ %span.gl-dropdown-button-text= _('Milestone actions')
+ = sprite_icon "chevron-down", size: 16, css_class: "dropdown-icon gl-icon"
+ .dropdown-menu.dropdown-menu-right
+ .gl-dropdown-inner
+ .gl-dropdown-contents
+ %ul
+ %li.gl-dropdown-item
+ = link_to edit_milestone_path(milestone), class: 'menu-item' do
+ .gl-dropdown-item-text-wrapper
+ = _('Edit')
+ - if milestone.project_milestone? && milestone.project.group
+ %li.gl-dropdown-item
+ %button.gl-button.btn.btn-link.menu-item.js-promote-project-milestone-button{ data: { milestone_title: milestone.title,
+ group_name: milestone.project.group.name,
+ url: promote_project_milestone_path(milestone.project, milestone)},
+ disabled: true,
+ type: 'button' }
+ .gl-dropdown-item-text-wrapper
+ = _('Promote')
+ #promote-milestone-modal
+ - if milestone.active?
+ %li.gl-dropdown-item{ class: "gl-md-display-none!" }
+ = link_to update_milestone_path(milestone, { state_event: :close }), method: :put, class: 'menu-item' do
+ .gl-dropdown-item-text-wrapper
+ = _('Close milestone')
+ - else
+ %li.gl-dropdown-item{ class: "gl-md-display-none!" }
+ = link_to update_milestone_path(milestone, { state_event: :activate }), method: :put, class: 'menu-item' do
+ .gl-dropdown-item-text-wrapper
+ = _('Reopen milestone')
+ %li.gl-dropdown-item
+ = render 'shared/milestones/delete_button'
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index cc1965945ac..5477b9395ea 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -1,7 +1,7 @@
- affix_offset = local_assigns.fetch(:affix_offset, "50")
- project = local_assigns[:project]
-%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix", "always-show-toggle" => true }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite', 'aria-label': _('Milestone') }
+%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix", "always-show-toggle" => true }, class: sidebar_gutter_collapsed_class(false), 'aria-live' => 'polite', 'aria-label': _('Milestone') }
.issuable-sidebar.milestone-sidebar
.block.milestone-progress.issuable-sidebar-header
%a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", href: "#", "aria-label" => s_('MilestoneSidebar|Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }
diff --git a/app/views/shared/nav/_admin_scope_header.html.haml b/app/views/shared/nav/_admin_scope_header.html.haml
new file mode 100644
index 00000000000..3a18b3660d4
--- /dev/null
+++ b/app/views/shared/nav/_admin_scope_header.html.haml
@@ -0,0 +1,6 @@
+%li.context-header
+ = link_to admin_root_path, title: _('Admin Area'), class: 'has-tooltip', data: { container: 'body', placement: 'right' } do
+ %span.avatar-container.icon-avatar.rect-avatar.s32
+ = sprite_icon('admin', size: 18)
+ %span.sidebar-context-title
+ = _('Admin Area')
diff --git a/app/views/shared/nav/_explore_scope_header.html.haml b/app/views/shared/nav/_explore_scope_header.html.haml
new file mode 100644
index 00000000000..da22d6dbcf2
--- /dev/null
+++ b/app/views/shared/nav/_explore_scope_header.html.haml
@@ -0,0 +1,6 @@
+%li.context-header
+ = link_to explore_root_url, title: _('Explore'), class: 'has-tooltip', data: { container: 'body', placement: 'right' } do
+ %span.avatar-container.icon-avatar.rect-avatar.s32
+ = sprite_icon('compass', size: 18)
+ %span.sidebar-context-title
+ = _('Explore')
diff --git a/app/views/shared/nav/_user_settings_scope_header.html.haml b/app/views/shared/nav/_user_settings_scope_header.html.haml
new file mode 100644
index 00000000000..c1601822736
--- /dev/null
+++ b/app/views/shared/nav/_user_settings_scope_header.html.haml
@@ -0,0 +1,4 @@
+%li.context-header
+ = link_to profile_path, title: _('User Settings'), class: 'has-tooltip', data: { container: 'body', placement: 'right' } do
+ = render Pajamas::AvatarComponent.new(current_user, size: 32, alt: current_user.name, class: 'gl-mr-3 js-sidebar-user-avatar', avatar_options: { data: { testid: 'sidebar-user-avatar' } })
+ %span.sidebar-context-title= _('User Settings')
diff --git a/app/views/shared/notes/_edit_form.html.haml b/app/views/shared/notes/_edit_form.html.haml
index cbf0b6f1051..72081856da6 100644
--- a/app/views/shared/notes/_edit_form.html.haml
+++ b/app/views/shared/notes/_edit_form.html.haml
@@ -9,6 +9,7 @@
.note-form-actions.clearfix
.settings-message.note-edit-warning.js-finish-edit-warning
= _("Finish editing this message first!")
- = submit_tag _('Save comment'), class: 'gl-button btn btn-confirm js-comment-save-button', data: { qa_selector: 'save_comment_button' }
+ = render Pajamas::ButtonComponent.new(type: 'submit', variant: :confirm, button_options: { class: 'js-comment-save-button', data: { qa_selector: 'save_comment_button' } }) do
+ = _("Save comment")
= render Pajamas::ButtonComponent.new(button_options: { class: 'note-edit-cancel' }) do
= _("Cancel")
diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml
index fb000b9aab1..d7d6e477ab1 100644
--- a/app/views/shared/notes/_hints.html.haml
+++ b/app/views/shared/notes/_hints.html.haml
@@ -1,7 +1,7 @@
- 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
+.comment-toolbar.gl-mx-2.gl-mb-2.gl-px-4.gl-bg-gray-10.gl-rounded-bottom-left-base.gl-rounded-bottom-right-base.clearfix
+ .toolbar-text.gl-font-sm
- markdownLinkStart = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/markdown') }
- quickActionsLinkStart = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/quick_actions') }
- if supports_quick_actions
@@ -9,7 +9,7 @@
- else
= html_escape(s_('MarkdownToolbar|Supports %{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}')) % { markdownDocsLinkStart: markdownLinkStart, markdownDocsLinkEnd: '</a>'.html_safe }
- if supports_file_upload
- %span.uploading-container.gl-line-height-32
+ %span.uploading-container.gl-line-height-32.gl-font-sm
%span.uploading-progress-container.hide
= sprite_icon('paperclip', css_class: 'gl-icon gl-vertical-align-text-bottom')
%span.attaching-file-message
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index c552e94ac57..95e0beee5e0 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -12,7 +12,7 @@
note_id: note.id } }
.timeline-entry-inner
- if note.system
- .timeline-icon
+ .gl-float-left.gl--flex-center.gl-rounded-full.gl-mt-n1.gl-ml-2.gl-w-6.gl-h-6.gl-bg-gray-50.gl-text-gray-600
= icon_for_system_note(note)
- else
.timeline-avatar.gl-float-left
diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml
index 09d63347ed6..a2c831bfd1c 100644
--- a/app/views/shared/projects/_list.html.haml
+++ b/app/views/shared/projects/_list.html.haml
@@ -10,13 +10,12 @@
- skip_pagination = false unless local_assigns[:skip_pagination] == true
- compact_mode = false unless local_assigns[:compact_mode] == true
- css_classes = "#{'compact' if compact_mode} #{'explore' if explore_projects_tab?}"
-- contributed_projects_illustration_path = 'illustrations/profile-page/contributed-projects.svg'
- contributed_projects_current_user_empty_message_header = s_('UserProfile|Explore public groups to find projects to contribute to.')
- contributed_projects_visitor_empty_message = s_('UserProfile|This user hasn\'t contributed to any projects')
-- starred_projects_illustration_path = 'illustrations/starred_empty.svg'
+- starred_projects_illustration_path = 'illustrations/empty-state/empty-projects-starred-md.svg'
- starred_projects_current_user_empty_message_header = s_('UserProfile|Star projects to track their progress and show your appreciation.')
- starred_projects_visitor_empty_message = s_('UserProfile|This user hasn\'t starred any projects')
-- own_projects_illustration_path = 'illustrations/profile-page/personal-project.svg'
+- own_projects_illustration_path = 'illustrations/empty-state/empty-projects-md.svg'
- own_projects_current_user_empty_message_header = s_('UserProfile|You haven\'t created any personal projects.')
- own_projects_current_user_empty_message_description = s_('UserProfile|Your projects can be available publicly, internally, or privately, at your choice.')
- own_projects_visitor_empty_message = s_('UserProfile|There are no projects available to be displayed here.')
@@ -43,7 +42,7 @@
= paginate_collection(projects, remote: remote) unless skip_pagination
- else
- if @contributed_projects
- = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: contributed_projects_illustration_path,
+ = render partial: 'shared/empty_states/profile_tabs', locals: { illustration_path: own_projects_illustration_path,
current_user_empty_message_header: contributed_projects_current_user_empty_message_header,
primary_button_label: new_project_button_label,
primary_button_link: new_project_button_link,
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index 2adc7844a67..79a33316b1a 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -12,10 +12,9 @@
- cache_key = project_list_cache_key(project, pipeline_status: pipeline_status)
- updated_tooltip = time_ago_with_tooltip(project.last_activity_date)
- show_pipeline_status_icon = pipeline_status && can?(current_user, :read_cross_project) && project.pipeline_status.has_status? && can?(current_user, :read_build, project)
-- last_pipeline = project.last_pipeline if show_pipeline_status_icon
+- last_pipeline = last_pipeline_from_status_cache(project) if show_pipeline_status_icon
- css_controls_class = "with-pipeline-status" if show_pipeline_status_icon && last_pipeline.present?
-- css_controls_container_class = compact_mode ? "" : "gl-lg-flex-direction-row gl-justify-content-space-between"
-- css_metadata_classes = "gl-display-flex gl-align-items-center gl-mr-5 gl-reset-color! icon-wrapper has-tooltip"
+- css_metadata_classes = "gl-display-flex gl-align-items-center gl-ml-5 gl-reset-color! icon-wrapper has-tooltip"
%li.project-row
= cache(cache_key) do
@@ -28,7 +27,7 @@
= render Pajamas::AvatarComponent.new(project, size: 48, alt: '', class: 'gl-mr-5')
.project-cell{ class: css_class }
.project-details.gl-pr-9.gl-sm-pr-0.gl-w-full.gl-display-flex.gl-flex-direction-column{ data: { qa_selector: 'project_content', qa_project_name: project.name } }
- .gl-display-flex.gl-align-items-center.gl-flex-wrap-wrap
+ .gl-display-flex.gl-align-items-center.gl-flex-wrap
%h2.gl-font-base.gl-line-height-20.gl-my-0
= link_to project_path(project), class: 'text-plain gl-mr-3 js-prefetch-document' do
%span.namespace-name.gl-font-weight-normal
@@ -55,10 +54,10 @@
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: project, additional_classes: 'gl-ml-3!'
- if show_last_commit_as_description
- .description.gl-display-none.gl-sm-display-block.gl-overflow-hidden.gl-mr-3.gl-mt-2
+ .description.gl-display-none.gl-sm-display-block.gl-overflow-hidden.gl-mr-3.gl-mt-2.gl-font-sm
= link_to_markdown(project.commit.title, project_commit_path(project, project.commit), class: "commit-row-message")
- elsif project.description.present?
- .description.gl-display-none.gl-sm-display-block.gl-overflow-hidden.gl-mr-3.gl-mt-2
+ .description.gl-display-none.gl-sm-display-block.gl-overflow-hidden.gl-mr-3.gl-mt-2.gl-font-sm
= markdown_field(project, :description)
- if project.topics.any?
@@ -71,7 +70,7 @@
.controls.gl-display-flex.gl-align-items-center
- if show_pipeline_status_icon && last_pipeline.present?
- pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
- %span.icon-wrapper.pipeline-status.gl-mr-5
+ %span.icon-wrapper.pipeline-status
= render 'ci/status/icon', status: last_pipeline.detailed_status(current_user), tooltip_placement: 'top', path: pipeline_path
= render_if_exists 'shared/projects/archived', project: project
@@ -79,17 +78,17 @@
= link_to project_starrers_path(project), class: "#{css_metadata_classes} stars", title: _('Stars'), data: { container: 'body', placement: 'top' } do
= sprite_icon('star-o', size: 14, css_class: 'gl-mr-2')
= badge_count(project.star_count)
- .updated-note.gl-ml-3.gl-sm-ml-0
+ .updated-note.gl-font-sm.gl-ml-3.gl-sm-ml-0
%span
= _('Updated')
= updated_tooltip
.project-cell{ class: "#{css_class} gl-xs-display-none!" }
- .project-controls.gl-display-flex.gl-flex-direction-column.gl-w-full{ class: css_controls_container_class, data: { testid: 'project_controls'} }
- .controls.gl-display-flex.gl-align-items-center{ class: css_controls_class }
+ .project-controls.gl-display-flex.gl-flex-direction-column.gl-align-items-flex-end.gl-w-full{ data: { testid: 'project_controls'} }
+ .controls.gl-display-flex.gl-align-items-center.gl-mb-2{ class: "#{css_controls_class} gl-pr-0!" }
- if show_pipeline_status_icon && last_pipeline.present?
- pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
- %span.icon-wrapper.pipeline-status.gl-mr-5
+ %span.icon-wrapper.pipeline-status
= render 'ci/status/icon', status: last_pipeline.detailed_status(current_user), tooltip_placement: 'top', path: pipeline_path
= render_if_exists 'shared/projects/archived', project: project
@@ -109,7 +108,7 @@
= link_to project_issues_path(project), class: "#{css_metadata_classes} issues", title: _('Issues'), data: { container: 'body', placement: 'top' } do
= sprite_icon('issues', size: 14, css_class: 'gl-mr-2')
= badge_count(project.open_issues_count)
- .updated-note.gl-white-space-nowrap.gl-justify-content-end
+ .updated-note.gl-font-sm.gl-white-space-nowrap.gl-justify-content-end
%span
= _('Updated')
= updated_tooltip
diff --git a/app/views/shared/projects/_search_form.html.haml b/app/views/shared/projects/_search_form.html.haml
index 47e0e165276..72709b3ed2f 100644
--- a/app/views/shared/projects/_search_form.html.haml
+++ b/app/views/shared/projects/_search_form.html.haml
@@ -2,7 +2,7 @@
- admin_view ||= false
- top_padding = admin_view ? 'gl-lg-pt-3' : ''
-= form_tag filter_projects_path, method: :get, class: "project-filter-form gl-display-flex! gl-flex-wrap-wrap gl-w-full gl-gap-3 #{top_padding}", data: { qa_selector: 'project_filter_form_container' }, id: 'project-filter-form' do |f|
+= form_tag filter_projects_path, method: :get, class: "project-filter-form gl-display-flex! gl-flex-wrap gl-w-full gl-gap-3 #{top_padding}", data: { qa_selector: 'project_filter_form_container' }, id: 'project-filter-form' do |f|
= search_field_tag :name, params[:name],
placeholder: placeholder,
class: "project-filter-form-field form-control input-short js-projects-list-filter gl-m-0!",
diff --git a/app/views/shared/projects/_topics.html.haml b/app/views/shared/projects/_topics.html.haml
index be513af4e3f..12246d1dcfa 100644
--- a/app/views/shared/projects/_topics.html.haml
+++ b/app/views/shared/projects/_topics.html.haml
@@ -1,31 +1,29 @@
-- cache_enabled = false unless local_assigns[:cache_enabled] == true
- max_project_topic_length = 15
- if project.topics.present?
- = cache_if(cache_enabled, [project, :topic_list], expires_in: 1.day) do
- .gl-w-full.gl-display-inline-flex.gl-flex-wrap.gl-font-base.gl-font-weight-normal.gl-align-items-center.gl-mx-n2.gl-my-n2{ 'data-testid': 'project_topic_list' }
- %span.gl-p-2.gl-text-gray-500
- = _('Topics') + ':'
- - project.topics_to_show.each do |topic|
- - explore_project_topic_path = topic_explore_projects_path(topic_name: topic[:name])
- - if topic[:title].length > max_project_topic_length
- %a.gl-p-2.has-tooltip{ data: { container: "body" }, title: topic[:title], href: explore_project_topic_path, itemprop: 'keywords' }
- = gl_badge_tag truncate(topic[:title], length: max_project_topic_length)
- - else
- %a.gl-p-2{ href: explore_project_topic_path, itemprop: 'keywords' }
- = gl_badge_tag topic[:title]
+ .gl-w-full.gl-display-inline-flex.gl-flex-wrap.gl-font-base.gl-font-weight-normal.gl-align-items-center.gl-mx-n2.gl-my-n2{ 'data-testid': 'project_topic_list' }
+ %span.gl-p-2.gl-text-gray-500
+ = _('Topics') + ':'
+ - project.topics_to_show.each do |topic|
+ - explore_project_topic_path = topic_explore_projects_path(topic_name: topic[:name])
+ - if topic[:title].length > max_project_topic_length
+ %a.gl-p-2.has-tooltip{ data: { container: "body" }, title: topic[:title], href: explore_project_topic_path, itemprop: 'keywords' }
+ = gl_badge_tag truncate(topic[:title], length: max_project_topic_length)
+ - else
+ %a.gl-p-2{ href: explore_project_topic_path, itemprop: 'keywords' }
+ = gl_badge_tag topic[:title]
- - if project.has_extra_topics?
- - title = _('More topics')
- - content = capture do
- %span.gl-display-inline-flex.gl-flex-wrap
- - project.topics_not_shown.each do |topic|
- - explore_project_topic_path = topic_explore_projects_path(topic_name: topic[:name])
- - if topic[:title].length > max_project_topic_length
- %a.gl-mr-3.gl-mb-3.has-tooltip{ data: { container: "body" }, title: topic[:title], href: explore_project_topic_path, itemprop: 'keywords' }
- = gl_badge_tag truncate(topic[:title], length: max_project_topic_length)
- - else
- %a.gl-mr-3.gl-mb-3{ href: explore_project_topic_path, itemprop: 'keywords' }
- = gl_badge_tag topic[:title]
- .text-nowrap.gl-p-2{ role: 'button', tabindex: 0, data: { toggle: 'popover', triggers: 'focus hover', html: 'true', placement: 'top', title: title, content: content } }
- = _("+ %{count} more") % { count: project.count_of_extra_topics_not_shown }
+ - if project.has_extra_topics?
+ - title = _('More topics')
+ - content = capture do
+ %span.gl-display-inline-flex.gl-flex-wrap
+ - project.topics_not_shown.each do |topic|
+ - explore_project_topic_path = topic_explore_projects_path(topic_name: topic[:name])
+ - if topic[:title].length > max_project_topic_length
+ %a.gl-mr-3.gl-mb-3.has-tooltip{ data: { container: "body" }, title: topic[:title], href: explore_project_topic_path, itemprop: 'keywords' }
+ = gl_badge_tag truncate(topic[:title], length: max_project_topic_length)
+ - else
+ %a.gl-mr-3.gl-mb-3{ href: explore_project_topic_path, itemprop: 'keywords' }
+ = gl_badge_tag topic[:title]
+ .text-nowrap.gl-p-2{ role: 'button', tabindex: 0, data: { toggle: 'popover', triggers: 'focus hover', html: 'true', placement: 'top', title: title, content: content } }
+ = _("+ %{count} more") % { count: project.count_of_extra_topics_not_shown }
diff --git a/app/views/shared/runners/_runner_details.html.haml b/app/views/shared/runners/_runner_details.html.haml
index f6396168cb3..686cd1a081b 100644
--- a/app/views/shared/runners/_runner_details.html.haml
+++ b/app/views/shared/runners/_runner_details.html.haml
@@ -1,8 +1,5 @@
-- breadcrumb_title runner.short_sha
-- page_title "##{runner.id} (#{runner.short_sha})"
-
%h1.page-title.gl-font-size-h-display
- = s_('Runners|Runner #%{runner_id}' % { runner_id: runner.id })
+ = s_('Runners|Runner #%{runner_id}') % { runner_id: runner.id }
= render 'shared/runners/runner_type_badge', runner: runner
.table-holder
diff --git a/app/views/shared/topics/_topic.html.haml b/app/views/shared/topics/_topic.html.haml
index 83d5ecdb833..9b9630733fd 100644
--- a/app/views/shared/topics/_topic.html.haml
+++ b/app/views/shared/topics/_topic.html.haml
@@ -5,9 +5,8 @@
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' },
body_options: { class: 'gl-display-flex gl-align-items-center' }) do |c|
= c.body do
- .avatar-container.rect-avatar.s40.gl-flex-shrink-0
- = link_to detail_page_link do
- = topic_icon(topic, class: "avatar s40")
+ = link_to detail_page_link do
+ = render Pajamas::AvatarComponent.new(topic, size: 48, alt: '', class: 'gl-mr-3')
= link_to detail_page_link do
- if topic.title_or_name.length > max_topic_title_length
%h5.gl-str-truncated.has-tooltip{ title: topic.title_or_name }
diff --git a/app/views/shared/users/index.html.haml b/app/views/shared/users/index.html.haml
index dd6b14d6be2..ef5552943df 100644
--- a/app/views/shared/users/index.html.haml
+++ b/app/views/shared/users/index.html.haml
@@ -1,7 +1,7 @@
-- followers_illustration_path = 'illustrations/starred_empty.svg'
+- followers_illustration_path = 'illustrations/empty-state/empty-friends-md.svg'
- followers_visitor_empty_message = s_('UserProfile|This user doesn\'t have any followers.')
- followers_current_user_empty_message_header = s_('UserProfile|You do not have any followers.')
-- following_illustration_path = 'illustrations/starred_empty.svg'
+- following_illustration_path = 'illustrations/empty-state/empty-friends-md.svg'
- following_visitor_empty_message = s_('UserProfile|This user isn\'t following other users.')
- following_current_user_empty_message_header = s_('UserProfile|You are not following other users.')
diff --git a/app/views/shared/web_hooks/_web_hook_disabled_alert.html.haml b/app/views/shared/web_hooks/_web_hook_disabled_alert.html.haml
index d9155b397b8..f8e2dc3d8dd 100644
--- a/app/views/shared/web_hooks/_web_hook_disabled_alert.html.haml
+++ b/app/views/shared/web_hooks/_web_hook_disabled_alert.html.haml
@@ -8,6 +8,6 @@
= c.body do
= s_('Webhooks|A webhook in this project was automatically disabled after being retried multiple times.')
= succeed '.' do
- = link_to _('Learn more'), help_page_path('user/project/integrations/webhooks', anchor: 'troubleshoot-webhooks'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to _('Learn more'), help_page_path('user/project/integrations/webhooks', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
= c.actions do
= link_to s_('Webhooks|Go to webhooks'), project_hooks_path(@project, anchor: 'webhooks-index'), class: 'btn gl-alert-action btn-confirm gl-button'
diff --git a/app/views/shared/wikis/_sidebar_wiki_page.html.haml b/app/views/shared/wikis/_sidebar_wiki_page.html.haml
index 38a7e6fc813..2c5c3aa68a3 100644
--- a/app/views/shared/wikis/_sidebar_wiki_page.html.haml
+++ b/app/views/shared/wikis/_sidebar_wiki_page.html.haml
@@ -1,3 +1,7 @@
+- wiki_path = wiki_page_path(@wiki, wiki_page)
+
%li{ class: active_when(params[:id] == wiki_page.slug) }
- = link_to wiki_page_path(@wiki, wiki_page), data: { qa_selector: 'wiki_page_link', qa_page_name: wiki_page.human_title } do
- = wiki_page.human_title
+ .gl-relative.gl-display-flex.gl-align-items-center.js-wiki-list-toggle.wiki-list{ data: { testid: 'wiki-list' } }
+ = render Pajamas::ButtonComponent.new(icon: 'plus', href: "#{wiki_path}/{new_page_title}", button_options: { class: 'wiki-list-create-child-button gl-bg-transparent! gl-hover-bg-gray-50! gl-focus-bg-gray-50! gl-absolute gl-top-half gl-translate-y-n50 gl-cursor-pointer gl-right-3' })
+ = link_to wiki_path, data: { qa_selector: 'wiki_page_link', qa_page_name: wiki_page.human_title } do
+ = wiki_page.human_title
diff --git a/app/views/shared/wikis/_wiki_directory.html.haml b/app/views/shared/wikis/_wiki_directory.html.haml
index 5c2233a4db2..6a066e0a838 100644
--- a/app/views/shared/wikis/_wiki_directory.html.haml
+++ b/app/views/shared/wikis/_wiki_directory.html.haml
@@ -1,6 +1,12 @@
+- wiki_path = wiki_page_path(@wiki, wiki_directory)
+
%li{ class: active_when(params[:id] == wiki_directory.slug), data: { qa_selector: 'wiki_directory_content' } }
- = link_to wiki_page_path(@wiki, wiki_directory), data: { qa_selector: 'wiki_dir_page_link', qa_page_name: wiki_directory.title } do
- = wiki_directory.title
+ .gl-relative.gl-display-flex.gl-align-items-center.js-wiki-list-toggle.wiki-list{ data: { testid: 'wiki-list' } }<
+ = sprite_icon('chevron-right', css_class: 'js-wiki-list-expand-button wiki-list-expand-button gl-mr-2 gl-cursor-pointer')
+ = sprite_icon('chevron-down', css_class: 'js-wiki-list-collapse-button wiki-list-collapse-button gl-mr-2 gl-cursor-pointer')
+ = render Pajamas::ButtonComponent.new(icon: 'plus', href: "#{wiki_path}/{new_page_title}", button_options: { class: 'wiki-list-create-child-button gl-bg-transparent! gl-hover-bg-gray-50! gl-focus-bg-gray-50! gl-absolute gl-top-half gl-translate-y-n50 gl-cursor-pointer gl-right-3' })
+ = link_to wiki_path, data: { qa_selector: 'wiki_dir_page_link', qa_page_name: wiki_directory.title } do
+ = wiki_directory.title
%ul
- wiki_directory.entries.each do |entry|
= render partial: entry.to_partial_path, object: entry, locals: { context: context }
diff --git a/app/views/shared/wikis/diff.html.haml b/app/views/shared/wikis/diff.html.haml
index c39739ac422..ee6c7f307a7 100644
--- a/app/views/shared/wikis/diff.html.haml
+++ b/app/views/shared/wikis/diff.html.haml
@@ -28,5 +28,5 @@
%pre.commit-description<
= preserve(markdown_field(commit, :description))
-= render 'projects/diffs/diffs', diffs: @diffs
+= render 'projects/diffs/diffs', diffs: @diffs, diff_page_context: "is-wiki"
= render 'shared/wikis/sidebar'
diff --git a/app/views/shared/wikis/empty.html.haml b/app/views/shared/wikis/empty.html.haml
index c52ead74b4c..d30a37aaa3e 100644
--- a/app/views/shared/wikis/empty.html.haml
+++ b/app/views/shared/wikis/empty.html.haml
@@ -2,4 +2,12 @@
- @right_sidebar = false
- add_page_specific_style 'page_bundles/wiki'
-= render 'shared/empty_states/wikis'
+- if @error.present?
+ = render Pajamas::AlertComponent.new(alert_options: { id: 'error_explanation', class: 'gl-mb-3'},
+ dismissible: false,
+ variant: :danger) do |c|
+ = c.body do
+ %ul.gl-pl-4
+ = @error
+
+= render 'shared/empty_states/wikis', hide_create: @error.present?
diff --git a/app/views/snippets/_snippets.html.haml b/app/views/snippets/_snippets.html.haml
index 1d22575803b..eeea8a34002 100644
--- a/app/views/snippets/_snippets.html.haml
+++ b/app/views/snippets/_snippets.html.haml
@@ -1,5 +1,5 @@
- link_project = local_assigns.fetch(:link_project, false)
-- illustration_path = 'illustrations/profile-page/activity.svg'
+- illustration_path = 'illustrations/empty-state/empty-snippets-md.svg'
- current_user_empty_message_header = s_('UserProfile|You haven\'t created any snippets.')
- current_user_empty_message_description = s_('UserProfile|Snippets in GitLab can either be private, internal, or public.')
- primary_button_label = _('New snippet')
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index eb9465a409f..fe05a3de13a 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -4,8 +4,9 @@
- add_page_startup_graphql_call('snippet/project_permissions', { fullPath: @snippet.project_id })
- else
- add_page_startup_graphql_call('snippet/user_permissions')
-- @hide_top_links = true
-- add_to_breadcrumbs _("Snippets"), dashboard_snippets_path
+- if @snippet.author != current_user
+ -# If current user is not the snippet author, then it renders with the Explore layout which doesn't have this breadcrumb.
+ - add_to_breadcrumbs _("Snippets"), explore_snippets_path
- breadcrumb_title @snippet.to_reference
- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
- content_for :prefetch_asset_tags do
diff --git a/app/views/time_tracking/timelogs/index.html.haml b/app/views/time_tracking/timelogs/index.html.haml
new file mode 100644
index 00000000000..b0bfc749606
--- /dev/null
+++ b/app/views/time_tracking/timelogs/index.html.haml
@@ -0,0 +1,7 @@
+- @force_fluid_layout = true
+- page_title _('Time tracking report')
+
+.page-title-holder.gl-display-flex.gl-flex-align-items-center
+ %h1.page-title.gl-font-size-h-display= _('Time tracking report')
+
+#js-timelogs-app{ data: { limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s } }
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index a7875f9b089..ce82a5e1614 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -14,9 +14,10 @@
.gl-display-flex
%ol.breadcrumb.gl-breadcrumb-list.gl-mb-4
%li.breadcrumb-item.gl-breadcrumb-item
- = link_to @user.username, project_path(@user.user_project)
- %span.gl-breadcrumb-separator
- = sprite_icon("chevron-right", size: 16)
+ = link_to project_path(@user.user_project) do
+ = @user.username
+ %span.gl-breadcrumb-separator
+ = sprite_icon("chevron-right", size: 16)
%li.breadcrumb-item.gl-breadcrumb-item
= link_to @user.user_readme.path, @user.user_project.readme_url
- if current_user == @user
diff --git a/app/views/users/_profile_basic_info.html.haml b/app/views/users/_profile_basic_info.html.haml
index b62440fcbde..c916b6c3d45 100644
--- a/app/views/users/_profile_basic_info.html.haml
+++ b/app/views/users/_profile_basic_info.html.haml
@@ -1,9 +1,9 @@
-.gl-text-gray-900.gl-mt-4
- = render 'middle_dot_divider' do
+.gl-text-gray-900
+ = render 'middle_dot_divider', stacking: true do
@#{@user.username}
- if can?(current_user, :read_user_profile, @user)
- = render 'middle_dot_divider' do
+ = render 'middle_dot_divider', stacking: true do
= s_('UserProfile|User ID: %{id}') % { id: @user.id }
= clipboard_button(title: s_('UserProfile|Copy user ID'), text: @user.id)
- = render 'middle_dot_divider' do
+ = render 'middle_dot_divider', stacking: true do
= s_('Member since %{date}') % { date: @user.created_at.to_date.to_s(:long) }
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index b9290972656..1ebf02ffd39 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -1,141 +1,139 @@
- @hide_top_links = true
-- @hide_breadcrumbs = true
- @no_container = true
+- breadcrumb_title user_display_name(@user)
- page_title user_display_name(@user)
- page_description @user.bio unless @user.blocked? || !@user.confirmed?
- page_itemtype 'http://schema.org/Person'
- add_page_specific_style 'page_bundles/profile'
- link_classes = "flex-grow-1 mx-1 "
+- if show_super_sidebar?
+ - @left_sidebar = true
+ - @force_desktop_expanded_sidebar = true
+ - nav "user_profile"
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity")
.user-profile
- .cover-block.user-cover-block{ class: [('border-bottom' if profile_tabs.empty?)] }
- = render layout: 'users/cover_controls' do
- - if @user == current_user
- = render Pajamas::ButtonComponent.new(href: profile_path,
- icon: 'pencil',
- button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' }})
- - elsif current_user
- #js-report-abuse{ data: { report_abuse_path: add_category_abuse_reports_path, reported_user_id: @user.id, reported_from_url: user_url(@user) } }
- - verified_gpg_keys = @user.gpg_keys.select(&:verified?)
- - if verified_gpg_keys.any?
- = render Pajamas::ButtonComponent.new(href: user_gpg_keys_path,
- icon: 'key',
- button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: n_('View public GPG key', 'View public GPG keys', verified_gpg_keys.length), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' }})
- - if can?(current_user, :read_user_profile, @user)
- = render Pajamas::ButtonComponent.new(href: user_path(@user, rss_url_options),
- icon: 'rss',
- button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: s_('UserProfile|Subscribe'), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' }})
- - if current_user && current_user.admin?
- = render Pajamas::ButtonComponent.new(href: [:admin, @user],
- icon: 'user',
- button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: s_('UserProfile|View user in admin area'), data: {toggle: 'tooltip', placement: 'bottom', container: 'body'}})
- - if current_user && current_user.id != @user.id
- - if current_user.following?(@user)
- = form_tag user_unfollow_path(@user, :json), class: link_classes + 'gl-display-inline-block' do
- = render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-w-full', data: { track_action: 'click_button', track_label: 'unfollow_from_profile' } }) do
- = _('Unfollow')
- - else
- = form_tag user_follow_path(@user, :json), class: link_classes + 'gl-display-inline-block' do
- = render Pajamas::ButtonComponent.new(variant: :confirm, type: :submit, button_options: { class: 'gl-w-full', data: { qa_selector: 'follow_user_link', track_action: 'click_button', track_label: 'follow_from_profile' } }) do
- = _('Follow')
-
- .profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
- .avatar-holder
- = link_to avatar_icon_for_user(@user, 400, current_user: current_user), target: '_blank', rel: 'noopener noreferrer' do
- = render Pajamas::AvatarComponent.new(@user, alt: "", size: 96, avatar_options: { itemprop: "image" })
-
- - if @user.blocked? || !@user.confirmed?
- .user-info
- %h1.cover-title
- = user_display_name(@user)
- = render "users/profile_basic_info"
- - else
- .user-info
- %h1.cover-title{ itemprop: 'name' }
- = @user.name
- - if @user.pronouns.present?
- %span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle
- = "(#{@user.pronouns})"
- - if @user.status&.busy?
- %span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle= s_("UserProfile|(Busy)")
-
- - if @user.pronunciation.present?
- .gl-align-items-center
- %p.gl-mb-4.gl-text-gray-500= s_("UserProfile|Pronounced as: %{pronunciation}") % { pronunciation: @user.pronunciation }
-
- - if @user.status&.customized?
- .cover-status.gl-display-inline-flex.gl-align-items-center
- = emoji_icon(@user.status.emoji, class: 'gl-mr-2')
- = markdown_field(@user.status, :message)
- = render "users/profile_basic_info"
- .gl-text-gray-900.mb-1.mb-sm-2
- - unless @user.location.blank?
- = render 'middle_dot_divider', stacking: true, itemprop: 'address', itemscope: true, itemtype: 'https://schema.org/PostalAddress' do
- = sprite_icon('location', css_class: 'fgray')
- %span{ itemprop: 'addressLocality' }
- = @user.location
- - 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')
- %span
- = work_information(@user, with_schema_markup: true)
- .gl-text-gray-900
- - unless @user.skype.blank?
- = render 'middle_dot_divider' do
- = link_to "skype:#{@user.skype}", class: 'gl-hover-text-decoration-none', title: "Skype" do
- = sprite_icon('skype', css_class: 'skype-icon')
- - unless @user.linkedin.blank?
- = render 'middle_dot_divider' do
- = link_to linkedin_url(@user), class: 'gl-hover-text-decoration-none', title: "LinkedIn", target: '_blank', rel: 'noopener noreferrer nofollow' do
- = sprite_icon('linkedin', css_class: 'linkedin-icon')
- - unless @user.twitter.blank?
- = render 'middle_dot_divider', breakpoint: 'sm' do
- = link_to twitter_url(@user), class: 'gl-hover-text-decoration-none', title: "Twitter", target: '_blank', rel: 'noopener noreferrer nofollow' do
- = sprite_icon('twitter', css_class: 'twitter-icon')
- - unless @user.discord.blank?
- = render 'middle_dot_divider', breakpoint: 'sm' do
- = link_to discord_url(@user), class: 'gl-hover-text-decoration-none', title: "Discord", target: '_blank', rel: 'noopener noreferrer nofollow' do
- = sprite_icon('discord', css_class: 'discord-icon')
- - unless @user.website_url.blank?
- = render 'middle_dot_divider', stacking: true do
- - if Feature.enabled?(:security_auto_fix) && @user.bot?
- = sprite_icon('question', css_class: 'gl-text-blue-600')
- = link_to @user.short_website_url, @user.full_website_url, target: '_blank', rel: 'me noopener noreferrer nofollow', itemprop: 'url'
- - if display_public_email?(@user)
- = render 'middle_dot_divider', stacking: true do
- = link_to @user.public_email, "mailto:#{@user.public_email}", itemprop: 'email'
- .gl-text-gray-900
- = sprite_icon('users', css_class: 'gl-vertical-align-middle gl-text-gray-500')
- = render 'middle_dot_divider' do
- = link_to user_followers_path do
- - count = @user.followers.count
- = n_('1 follower', '%{count} followers', count) % { count: count }
- = render 'middle_dot_divider' do
- = link_to user_following_path, data: { qa_selector: 'following_link' } do
- = @user.followees.count
- = _('following')
- - if @user.bio.present?
- .gl-text-gray-900
- .profile-user-bio
- = @user.bio
-
- - unless profile_tabs.empty?
- - if Feature.enabled?(:profile_tabs_vue, current_user)
- #js-profile-tabs
- - else
- .scrolling-tabs-container
+ .cover-block.user-cover-block.gl-border-t.gl-border-b.gl-mt-n1
+ %div{ class: container_class }
+ = render layout: 'users/cover_controls' do
+ - if @user == current_user
+ = render Pajamas::ButtonComponent.new(href: profile_path,
+ icon: 'pencil',
+ button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' }})
+ - elsif current_user
+ #js-report-abuse{ data: { report_abuse_path: add_category_abuse_reports_path, reported_user_id: @user.id, reported_from_url: user_url(@user) } }
+ - verified_gpg_keys = @user.gpg_keys.select(&:verified?)
+ - if verified_gpg_keys.any?
+ = render Pajamas::ButtonComponent.new(href: user_gpg_keys_path,
+ icon: 'key',
+ button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: n_('View public GPG key', 'View public GPG keys', verified_gpg_keys.length), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' }})
+ - if can?(current_user, :read_user_profile, @user)
+ = render Pajamas::ButtonComponent.new(href: user_path(@user, rss_url_options),
+ icon: 'rss',
+ button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: s_('UserProfile|Subscribe'), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' }})
+ - if current_user && current_user.admin?
+ = render Pajamas::ButtonComponent.new(href: [:admin, @user],
+ icon: 'user',
+ button_options: { class: 'gl-flex-grow-1 gl-mx-1 has-tooltip', title: s_('UserProfile|View user in admin area'), data: {toggle: 'tooltip', placement: 'bottom', container: 'body'}})
+ - if current_user && current_user.following_users_allowed?(@user)
+ - if current_user.following?(@user)
+ = form_tag user_unfollow_path(@user, :json), class: link_classes + 'gl-display-inline-block' do
+ = render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-w-full', data: { track_action: 'click_button', track_label: 'unfollow_from_profile' } }) do
+ = _('Unfollow')
+ - else
+ = form_tag user_follow_path(@user, :json), class: link_classes + 'gl-display-inline-block' do
+ = render Pajamas::ButtonComponent.new(variant: :confirm, type: :submit, button_options: { class: 'gl-w-full', data: { qa_selector: 'follow_user_link', track_action: 'click_button', track_label: 'follow_from_profile' } }) do
+ = _('Follow')
+
+ .profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?), ('gl-mb-4!' if show_super_sidebar?)] }
+ .gl-display-inline-block.gl-mx-8.gl-vertical-align-top
+ .avatar-holder
+ = link_to avatar_icon_for_user(@user, 400, current_user: current_user), target: '_blank', rel: 'noopener noreferrer' do
+ = render Pajamas::AvatarComponent.new(@user, alt: "", size: 96, avatar_options: { itemprop: "image" })
+ - if @user.achievements_enabled && Ability.allowed?(current_user, :read_user_profile, @user)
+ #js-user-achievements{ data: { root_url: root_url, user_id: @user.id } }
+ .gl-display-inline-block.gl-vertical-align-top.gl-text-left.gl-max-w-80
+ - if @user.blocked? || !@user.confirmed?
+ .user-info
+ %h1.cover-title.gl-my-0
+ = user_display_name(@user)
+ = render "users/profile_basic_info"
+ - else
+ .user-info
+ %h1.cover-title.gl-my-0{ itemprop: 'name' }
+ = @user.name
+ - if @user.pronouns.present?
+ %span.gl-font-base.gl-text-gray-500.gl-vertical-align-middle
+ = "(#{@user.pronouns})"
+ - if @user.status&.busy?
+ = render Pajamas::BadgeComponent.new(s_('UserProfile|Busy'), size: 'sm', variant: 'warning', class: 'gl-vertical-align-middle')
+
+ - if @user.pronunciation.present?
+ .gl-align-items-center
+ %p.gl-mb-4.gl-text-gray-500= s_("UserProfile|Pronounced as: %{pronunciation}") % { pronunciation: @user.pronunciation }
+
+ - if @user.status&.customized?
+ .cover-status.gl-display-inline-flex.gl-align-items-center.gl-mb-3
+ = emoji_icon(@user.status.emoji, class: 'gl-mr-2')
+ = markdown_field(@user.status, :message)
+ = render "users/profile_basic_info"
+ - user_local_time = local_time(@user.timezone)
+ - if @user.location.present? || user_local_time.present? || work_information(@user).present?
+ .gl-text-gray-900
+ - if @user.location.present?
+ = render 'middle_dot_divider', stacking: true, itemprop: 'address', itemscope: true, itemtype: 'https://schema.org/PostalAddress' do
+ = sprite_icon('location', css_class: 'fgray')
+ %span{ itemprop: 'addressLocality' }
+ = @user.location
+ - if user_local_time.present?
+ = render 'middle_dot_divider', stacking: true, data: { testid: 'user-local-time' } do
+ = sprite_icon('clock', css_class: 'fgray')
+ %span
+ = user_local_time
+ - if work_information(@user).present?
+ = render 'middle_dot_divider', stacking: true do
+ = sprite_icon('work', css_class: 'fgray')
+ %span
+ = work_information(@user, with_schema_markup: true)
+ .gl-text-gray-900
+ - if @user.skype.present?
+ = render 'middle_dot_divider' do
+ = link_to "skype:#{@user.skype}", class: 'gl-hover-text-decoration-none', title: "Skype" do
+ = sprite_icon('skype', css_class: 'skype-icon')
+ - if @user.linkedin.present?
+ = render 'middle_dot_divider' do
+ = link_to linkedin_url(@user), class: 'gl-hover-text-decoration-none', title: "LinkedIn", target: '_blank', rel: 'noopener noreferrer nofollow' do
+ = sprite_icon('linkedin', css_class: 'linkedin-icon')
+ - if @user.twitter.present?
+ = render 'middle_dot_divider', breakpoint: 'sm' do
+ = link_to twitter_url(@user), class: 'gl-hover-text-decoration-none', title: "Twitter", target: '_blank', rel: 'noopener noreferrer nofollow' do
+ = sprite_icon('twitter', css_class: 'twitter-icon')
+ - if @user.discord.present?
+ = render 'middle_dot_divider', breakpoint: 'sm' do
+ = link_to discord_url(@user), class: 'gl-hover-text-decoration-none', title: "Discord", target: '_blank', rel: 'noopener noreferrer nofollow' do
+ = sprite_icon('discord', css_class: 'discord-icon')
+ - if @user.website_url.present?
+ = render 'middle_dot_divider', stacking: true do
+ - if Feature.enabled?(:security_auto_fix) && @user.bot?
+ = sprite_icon('question-o', css_class: 'gl-text-blue-500')
+ = link_to @user.short_website_url, @user.full_website_url, target: '_blank', rel: 'me noopener noreferrer nofollow', itemprop: 'url'
+ - if display_public_email?(@user)
+ = render 'middle_dot_divider', stacking: true do
+ = link_to @user.public_email, "mailto:#{@user.public_email}", itemprop: 'email'
+
+ -# Ensure this stays indented one level less than the social links
+ -# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118314
+ - if @user.bio.present? && @user.confirmed? && !@user.blocked?
+ %p.profile-user-bio.gl-mb-3
+ = @user.bio
+
+ - if !profile_tabs.empty? && !Feature.enabled?(:profile_tabs_vue, current_user)
+ .scrolling-tabs-container{ class: [('gl-display-none' if show_super_sidebar?)] }
.fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= sprite_icon('chevron-lg-right', size: 12)
- %ul.nav-links.user-profile-nav.scrolling-tabs.nav.nav-tabs
+ %ul.nav-links.user-profile-nav.scrolling-tabs.nav.nav-tabs.gl-border-b-0
- if profile_tab?(:overview)
%li.js-overview-tab
= link_to user_path, data: { target: 'div#js-overview', action: 'overview', toggle: 'tab' } do
@@ -169,11 +167,14 @@
%li.js-followers-tab
= link_to user_followers_path, data: { target: 'div#followers', action: 'followers', toggle: 'tab', endpoint: user_followers_path(format: :json) } do
= s_('UserProfile|Followers')
+ = gl_badge_tag @user.followers.count, size: :sm
- if profile_tab?(:following)
%li.js-following-tab
- = link_to user_following_path, data: { target: 'div#following', action: 'following', toggle: 'tab', endpoint: user_following_path(format: :json) } do
+ = link_to user_following_path, data: { target: 'div#following', action: 'following', toggle: 'tab', endpoint: user_following_path(format: :json), qa_selector: 'following_tab' } do
= s_('UserProfile|Following')
-
+ = gl_badge_tag @user.followees.count, size: :sm
+ - if !profile_tabs.empty? && Feature.enabled?(:profile_tabs_vue, current_user)
+ #js-profile-tabs{ data: user_profile_tabs_app_data(@user) }
%div{ class: container_class }
- unless Feature.enabled?(:profile_tabs_vue, current_user)
.tab-content