diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-20 18:19:03 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-03-20 18:19:03 +0300 |
commit | 14bd84b61276ef29b97d23642d698de769bacfd2 (patch) | |
tree | f9eba90140c1bd874211dea17750a0d422c04080 /app/views | |
parent | 891c388697b2db0d8ee0c8358a9bdbf6dc56d581 (diff) |
Add latest changes from gitlab-org/gitlab@15-10-stable-eev15.10.0-rc42
Diffstat (limited to 'app/views')
222 files changed, 1203 insertions, 1039 deletions
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml index eeedd58ec15..1a0f4132d49 100644 --- a/app/views/admin/abuse_reports/_abuse_report.html.haml +++ b/app/views/admin/abuse_reports/_abuse_report.html.haml @@ -24,13 +24,13 @@ = 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 + = 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 + = 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') - 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 + = 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') = 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/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml index 8fafa52cd4c..fd671f72238 100644 --- a/app/views/admin/application_settings/_ci_cd.html.haml +++ b/app/views/admin/application_settings/_ci_cd.html.haml @@ -77,31 +77,31 @@ %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.label :ci_active_pipelines, plan_limit_setting_description(:ci_active_pipelines) = 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/_outbound.html.haml b/app/views/admin/application_settings/_outbound.html.haml index 1821c8ef4bb..6efafa3c415 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.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/_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/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml index 0305a9487ca..b64617f3f11 100644 --- a/app/views/admin/application_settings/_visibility_and_access.html.haml +++ b/app/views/admin/application_settings/_visibility_and_access.html.haml @@ -38,6 +38,8 @@ = 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..cd255d961f4 100644 --- a/app/views/admin/application_settings/appearances/show.html.haml +++ b/app/views/admin/application_settings/appearances/show.html.haml @@ -1,5 +1,4 @@ - page_title _("Appearance") -- @content_class = "limit-container-width" unless fluid_layout - add_page_specific_style 'page_bundles/settings' = 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..c2dc3c3707e 100644 --- a/app/views/admin/application_settings/ci_cd.html.haml +++ b/app/views/admin/application_settings/ci_cd.html.haml @@ -1,7 +1,6 @@ - breadcrumb_title _("CI/CD") - page_title _("CI/CD") - add_page_specific_style 'page_bundles/settings' -- @content_class = "limit-container-width" unless fluid_layout %section.settings.no-animate#js-ci-cd-variables{ class: ('expanded' if expanded_by_default?) } .settings-header @@ -42,7 +41,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..a7c80abdbc9 100644 --- a/app/views/admin/application_settings/general.html.haml +++ b/app/views/admin/application_settings/general.html.haml @@ -1,7 +1,6 @@ - breadcrumb_title _("General") - page_title _("General") - add_page_specific_style 'page_bundles/settings' -- @content_class = "limit-container-width" unless fluid_layout %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..396e6f3e7d6 100644 --- a/app/views/admin/application_settings/integrations.html.haml +++ b/app/views/admin/application_settings/integrations.html.haml @@ -1,7 +1,6 @@ - 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 %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..711b2c97d65 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,6 @@ - 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 %section.settings.as-prometheus.no-animate#js-prometheus-settings{ class: ('expanded' if expanded_by_default?) } .settings-header diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml index 779263b439f..32b10fd36e8 100644 --- a/app/views/admin/application_settings/network.html.haml +++ b/app/views/admin/application_settings/network.html.haml @@ -1,7 +1,6 @@ - breadcrumb_title _("Network") - page_title _("Network") - add_page_specific_style 'page_bundles/settings' -- @content_class = "limit-container-width" unless fluid_layout %section.settings.as-performance.no-animate#js-performance-settings{ class: ('expanded' if expanded_by_default?) } .settings-header @@ -92,7 +91,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 +145,9 @@ .settings-content = render 'users_api_limits' +- if Feature.enabled?(:rate_limit_for_unauthenticated_projects_api_access) + = 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..3843fc8e863 100644 --- a/app/views/admin/application_settings/preferences.html.haml +++ b/app/views/admin/application_settings/preferences.html.haml @@ -1,7 +1,6 @@ - breadcrumb_title _("Preferences") - page_title _("Preferences") - add_page_specific_style 'page_bundles/settings' -- @content_class = "limit-container-width" unless fluid_layout %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..0046275c7d1 100644 --- a/app/views/admin/application_settings/reporting.html.haml +++ b/app/views/admin/application_settings/reporting.html.haml @@ -1,7 +1,6 @@ - breadcrumb_title _("Reporting") - page_title _("Reporting") - add_page_specific_style 'page_bundles/settings' -- @content_class = "limit-container-width" unless fluid_layout %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..518b40a0326 100644 --- a/app/views/admin/application_settings/repository.html.haml +++ b/app/views/admin/application_settings/repository.html.haml @@ -1,7 +1,6 @@ - breadcrumb_title _("Repository") - page_title _("Repository") - add_page_specific_style 'page_bundles/settings' -- @content_class = "limit-container-width" unless fluid_layout %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..af646d79c29 100644 --- a/app/views/admin/application_settings/service_usage_data.html.haml +++ b/app/views/admin/application_settings/service_usage_data.html.haml @@ -3,7 +3,6 @@ - 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' %section.js-search-settings-section 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..00859bf6b66 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 } 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/dev_ops_report/show.html.haml b/app/views/admin/dev_ops_report/show.html.haml index a2425b93ad3..d92d13260fe 100644 --- a/app/views/admin/dev_ops_report/show.html.haml +++ b/app/views/admin/dev_ops_report/show.html.haml @@ -1,5 +1,5 @@ - 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 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..73fe1941818 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -20,8 +20,7 @@ - c.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 diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml index 98427cb6419..e7aa4f38634 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') diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml new file mode 100644 index 00000000000..18bef523168 --- /dev/null +++ b/app/views/admin/projects/_form.html.haml @@ -0,0 +1,23 @@ += 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.title { _('Naming') } + = c.description do + = _('Update your project name and description.') + = c.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 + + .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..2803bec49c3 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? diff --git a/app/views/admin/runners/register.html.haml b/app/views/admin/runners/register.html.haml new file mode 100644 index 00000000000..662bb9ea00e --- /dev/null +++ b/app/views/admin/runners/register.html.haml @@ -0,0 +1,7 @@ +- runner_name = "##{@runner.id} (#{@runner.short_sha})" +- breadcrumb_title s_('Runners|Register') +- page_title s_('Runners|Register'), "##{@runner.id} (#{@runner.short_sha})" +- 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/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..3950170e486 100644 --- a/app/views/admin/sessions/new.html.haml +++ b/app/views/admin/sessions/new.html.haml @@ -1,4 +1,3 @@ -- @hide_breadcrumbs = true - page_title _('Enter Admin Mode') .row.justify-content-center diff --git a/app/views/admin/sessions/two_factor.html.haml b/app/views/admin/sessions/two_factor.html.haml index 3f915846dd8..d05cc51af41 100644 --- a/app/views/admin/sessions/two_factor.html.haml +++ b/app/views/admin/sessions/two_factor.html.haml @@ -1,4 +1,3 @@ -- @hide_breadcrumbs = true - page_title _('Enter 2FA for Admin Mode') .row.justify-content-center @@ -11,5 +10,5 @@ .login-body - if current_user.two_factor_otp_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/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/authentication/_register.html.haml b/app/views/authentication/_register.html.haml index d6fe20e48bf..dc4511a8159 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) && 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/clusters/clusters/_integrations.html.haml b/app/views/clusters/clusters/_integrations.html.haml index 4a3062def8c..0f62b640b97 100644 --- a/app/views/clusters/clusters/_integrations.html.haml +++ b/app/views/clusters/clusters/_integrations.html.haml @@ -6,7 +6,7 @@ - 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') diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index 09e2e35c617..7734c0a7c9a 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-p-3.gl-justify-content-end .nav-controls = render 'shared/groups/search_form' = render 'shared/groups/dropdown' 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..87bd5209fdf 100644 --- a/app/views/dashboard/_projects_nav.html.haml +++ b/app/views/dashboard/_projects_nav.html.haml @@ -1,5 +1,4 @@ - 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 @@ -8,6 +7,4 @@ = 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' } } = 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/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/snippets/index.html.haml b/app/views/dashboard/snippets/index.html.haml index 68457ab33f7..42386e5b9cc 100644 --- a/app/views/dashboard/snippets/index.html.haml +++ b/app/views/dashboard/snippets/index.html.haml @@ -5,7 +5,7 @@ = 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..7ca89651282 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -62,7 +62,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 +82,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 +102,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..4b586b2f580 100644 --- a/app/views/devise/confirmations/new.html.haml +++ b/app/views/devise/confirmations/new.html.haml @@ -1,7 +1,7 @@ = 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 @@ -13,7 +13,8 @@ = 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/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index 8a960602536..3bd7147f195 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -8,7 +8,7 @@ = render "layouts/google_tag_manager_body" .signup-page - = render 'devise/shared/signup_box', + = render signup_box_template, url: registration_path(resource_name, glm_tracking_params.to_hash), button_text: _('Register'), borderless: Feature.enabled?(:restyle_login_page, @project), diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml index f63f1aa9197..12e5a7263f7 100644 --- a/app/views/devise/sessions/two_factor.html.haml +++ b/app/views/devise/sessions/two_factor.html.haml @@ -2,15 +2,15 @@ = 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_otp_enabled? || (Feature.enabled?(:webauthn_without_totp) && @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) %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/_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..57cd819cb89 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -66,7 +66,7 @@ = 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/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml index 0428b9c340c..d087d85a94e 100644 --- a/app/views/doorkeeper/applications/show.html.haml +++ b/app/views/doorkeeper/applications/show.html.haml @@ -9,4 +9,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/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/_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..53b252db4fe 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -1,14 +1,15 @@ -- @hide_top_links = true -- page_title _("Projects") -- header_title _("Projects"), dashboard_projects_path +- breadcrumb_title _("Projects") +- page_title _("Explore projects") - 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' +.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") = render 'explore/projects/nav' = render 'projects', projects: @projects diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index ec7eefea264..c765c086027 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -1,13 +1,14 @@ - @hide_top_links = true -- page_title _("Projects") +- page_title _("Explore 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' +.page-title-holder.gl-display-flex.gl-align-items-center + %h1.page-title.gl-font-size-h-display= page_title + .page-title-controls + = render Pajamas::ButtonComponent.new(href: new_project_path, variant: :confirm) do + = _("New project") = 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..043189315b4 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -1,13 +1,15 @@ - @hide_top_links = true -- page_title _("Projects") +- page_title _("Explore 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' +.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") = 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/_import_group_from_another_instance_panel.html.haml b/app/views/groups/_import_group_from_another_instance_panel.html.haml index 24ba060a89a..4a34e124c4c 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 @@ -25,9 +25,9 @@ = 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') } + - 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..775b9c79817 100644 --- a/app/views/groups/_import_group_from_file_panel.html.haml +++ b/app/views/groups/_import_group_from_file_panel.html.haml @@ -10,14 +10,14 @@ 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') } + - 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/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index 298ed2c0806..a2a5f519221 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -1,6 +1,9 @@ - add_page_specific_style 'page_bundles/members' - page_title _('Group members') += content_for :page_level_alert do + = render_if_exists 'shared/unlimited_members_during_trial_alert', group: @group.root_ancestor + .row.gl-mt-3 .col-lg-12 .gl-display-flex.gl-flex-wrap @@ -16,7 +19,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/milestones/_form.html.haml b/app/views/groups/milestones/_form.html.haml index a99d76f99a7..1fd8e12016c 100644 --- a/app/views/groups/milestones/_form.html.haml +++ b/app/views/groups/milestones/_form.html.haml @@ -1,30 +1,25 @@ = 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 + .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") + - 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..a5cbc443fa4 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -4,9 +4,9 @@ - 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), + .js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s, groups_url: dashboard_groups_url }.merge(subgroup_creation_data(@group), verification_for_group_creation_data) } .row{ 'v-cloak': true } diff --git a/app/views/groups/settings/_export.html.haml b/app/views/groups/settings/_export.html.haml index 5d79d0f8e79..6b505755727 100644 --- a/app/views/groups/settings/_export.html.haml +++ b/app/views/groups/settings/_export.html.haml @@ -5,13 +5,12 @@ %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') } + - 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 %p.gl-mb-0 diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml index 658109fde64..5258854c931 100644 --- a/app/views/groups/settings/_general.html.haml +++ b/app/views/groups/settings/_general.html.haml @@ -23,8 +23,7 @@ = 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/_transfer.html.haml b/app/views/groups/settings/_transfer.html.haml index a4a83330fa9..415459f1584 100644 --- a/app/views/groups/settings/_transfer.html.haml +++ b/app/views/groups/settings/_transfer.html.haml @@ -10,7 +10,7 @@ - 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? diff --git a/app/views/groups/settings/applications/show.html.haml b/app/views/groups/settings/applications/show.html.haml index 4a83d96aae4..e24aa993b26 100644 --- a/app/views/groups/settings/applications/show.html.haml +++ b/app/views/groups/settings/applications/show.html.haml @@ -9,4 +9,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..8c45809261c 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.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/show.html.haml b/app/views/groups/show.html.haml index 72b7bec1b92..7983274f319 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -14,7 +14,6 @@ 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") 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..0a5cbb710e3 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,34 @@ %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') + %td= plan_limit_setting_description(:ci_active_pipelines) - 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/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index dd441d0d155..2dd6eab2e17 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -10,6 +10,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 } @@ -57,6 +58,8 @@ = yield :page_specific_javascripts + = webpack_bundle_tag 'super_sidebar' if show_super_sidebar? + = webpack_controller_bundle_tags = yield :project_javascripts 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..74567af3554 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -2,8 +2,12 @@ - @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).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 } } - if display_whats_new? #whats-new-app{ data: { version_digest: whats_new_version_digest } } @@ -44,4 +48,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 content-wrapper-margin' unless show_super_sidebar? 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..1ac5f0a8497 100644 --- a/app/views/layouts/dashboard.html.haml +++ b/app/views/layouts/dashboard.html.haml @@ -2,6 +2,6 @@ - header_title _("Dashboard"), root_path unless header_title - @left_sidebar = true -- nav "your_work" +- nav (@parent_group ? "group" : "your_work") = render template: "layouts/application" 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..40ec1ff199b 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -16,6 +16,10 @@ :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 = render template: base_layout || "layouts/application" 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/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml index 98d6af28cf5..06dff99718c 100644 --- a/app/views/layouts/nav/_breadcrumbs.html.haml +++ b/app/views/layouts/nav/_breadcrumbs.html.haml @@ -3,25 +3,26 @@ - 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 +.gl-relative + .breadcrumbs{ class: [container, @content_class] } + .breadcrumbs-container{ class: ("border-bottom-0" if @no_breadcrumb_border) } + - if show_super_sidebar? + = render Pajamas::ButtonComponent.new(icon: 'sidebar', category: :tertiary, button_options: { class: 'js-super-sidebar-toggle super-sidebar-toggle gl-ml-n3 gl-mr-2', title: _('Expand sidebar'), aria: { label: _('Expand sidebar') }, data: {toggle: 'tooltip', placement: 'right' } }) + - 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') } }) + %nav.breadcrumbs-links{ '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/_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/_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..09fa8575106 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -18,6 +18,9 @@ :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 diff --git a/app/views/layouts/snippets.html.haml b/app/views/layouts/snippets.html.haml index 95a204a3319..e396f38499a 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 _("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/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/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_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/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 } @@ -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/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..6de5f183981 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 -.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..8ff2e6f34a0 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= s_('SlackIntegration|Authorize GitLab for Slack app (%{user}) to use your account?').html_safe % { user: @chat_name_params[:chat_name] } + - c.body do + %p + = s_('SlackIntegration|An application called GitLab for Slack app is requesting access to your GitLab account. This application was created by GitLab Inc.') + %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/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/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/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml index b10d05efc4f..5f74a4c4427 100644 --- a/app/views/profiles/preferences/show.html.haml +++ b/app/views/profiles/preferences/show.html.haml @@ -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| diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 5ffffb80d97..659b218bdef 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -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 diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml index 3add3af3c65..61fe6ba8e47 100644 --- a/app/views/profiles/two_factor_auths/show.html.haml +++ b/app/views/profiles/two_factor_auths/show.html.haml @@ -8,24 +8,13 @@ .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 +25,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 +47,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 +64,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 webauthn_enabled && 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 +113,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: { 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 a one-time password authenticator or a WebAuthn device first.") diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml index e2d1a50ae5e..6ac084b7749 100644 --- a/app/views/projects/_files.html.haml +++ b/app/views/projects/_files.html.haml @@ -8,7 +8,7 @@ - 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 + .info-well.gl-display-none.gl-sm-display-flex.project-last-commit.gl-flex-direction-column.gl-mt-2 #js-last-commit.gl-m-auto = gl_loading_icon(size: 'md') #js-code-owners diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index b9aeed188fa..65fd02b291c 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -3,7 +3,7 @@ - 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-2.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' } 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/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml index 53a1abdff33..27211ffb1e5 100644 --- a/app/views/projects/_new_project_fields.html.haml +++ b/app/views/projects/_new_project_fields.html.haml @@ -98,4 +98,4 @@ -# 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/_self_monitoring_deprecation_notice.html.haml b/app/views/projects/_self_monitoring_deprecation_notice.html.haml new file mode 100644 index 00000000000..b9e32356688 --- /dev/null +++ b/app/views/projects/_self_monitoring_deprecation_notice.html.haml @@ -0,0 +1,13 @@ +- return unless project.self_monitoring? + += content_for :page_level_alert do + .flash-container.flash-container-page.sticky + %div{ class: [container_class, 'limit-container-width', 'gl-pt-5!'] } + = render Pajamas::AlertComponent.new(title: _('Deprecation notice'), + variant: :danger, + alert_options: { class: 'gl-mb-3 gl-sticky' }) do |c| + = c.body do + - deprecation_link = '<a href="%{url}">'.html_safe % { url: help_page_path('update/deprecations', anchor: 'gitlab-self-monitoring-project') } + - removal_link = '<a href="%{url}">'.html_safe % { url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/348909' } + - opstrace_link = '<a href="%{url}">'.html_safe % { url: 'https://gitlab.com/groups/gitlab-org/-/epics/6976' } + = _("Self-monitoring was %{deprecation}deprecated%{link_end} in GitLab 14.9, and is %{removal}scheduled for removal%{link_end} in GitLab 16.0. For information on a possible replacement, %{opstrace}learn more about Opstrace%{link_end}.").html_safe % { deprecation: deprecation_link, removal: removal_link, opstrace: opstrace_link, link_end: '</a>'.html_safe } 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/blame/show.html.haml b/app/views/projects/blame/show.html.haml index 74b85a93c8e..ee7ca9cd351 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,6 +1,15 @@ - 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 } +- if @streaming_enabled && total_extra_pages > 0 + - content_for :startup_js do + = javascript_tag do + :plain + window.blamePageStream = (() => { + const url = new URL("#{@blame_pages_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_per_page, total_extra_pages: total_extra_pages - 1, pages_url: @blame_pages_url } #blob-content-holder.tree-holder.js-per-page{ data: dataset } = render "projects/blob/breadcrumb", blob: @blob, blame: true @@ -26,11 +35,21 @@ .blame-table-wrapper = render partial: 'page' + - if @streaming_enabled + #blame-stream-container.blame-stream-container + - if @blame_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, size: :small, button_options: { class: 'gl-mt-3' }) do |c| + = _('Show full blame') + + - if @streaming_enabled + #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") + diff --git a/app/views/projects/blob/_breadcrumb.html.haml b/app/views/projects/blob/_breadcrumb.html.haml index 7c2caf34fd1..e77367a7b42 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 } } %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..ff95e9a1088 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -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,15 @@ 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) + - unless Feature.enabled?(:source_editor_toolbar, current_user) + .file-buttons.gl-display-flex.gl-align-items-center.gl-justify-content-end + - if is_markdown = 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") + %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/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..3bdb81f02ad 100644 --- a/app/views/projects/branch_defaults/_branch_names_fields.html.haml +++ b/app/views/projects/branch_defaults/_branch_names_fields.html.haml @@ -12,3 +12,4 @@ = 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') = 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..6e70dc42776 100644 --- a/app/views/projects/branch_rules/_show.html.haml +++ b/app/views/projects/branch_rules/_show.html.haml @@ -1,4 +1,7 @@ - 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) } .settings-header @@ -7,6 +10,7 @@ = 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_rules_info.haml b/app/views/projects/branches/_branch_rules_info.haml new file mode 100644 index 00000000000..15bee31c596 --- /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.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.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/index.html.haml b/app/views/projects/branches/index.html.haml index f43d19e2542..518292effd8 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -1,6 +1,8 @@ - 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 -# @@ -22,16 +24,24 @@ sorted_by: @sort } } - - if can? current_user, :push_code, @project + - if can_push_code .js-delete-merged-branches{ data: { default_branch: @project.repository.root_ref, form_path: project_merged_branches_path(@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') = 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/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/_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/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/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..bc378182057 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 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/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index 8ff6d348d95..03e26fd4456 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -3,7 +3,7 @@ - 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 +- 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) @@ -32,7 +32,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..b2270e0faf7 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -7,6 +7,13 @@ = 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.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,7 +34,6 @@ %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, diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 43159a759f4..ca3f49bae95 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -8,6 +8,7 @@ = render "home_panel" = render "archived_notice", project: @project += render "self_monitoring_deprecation_notice", project: @project = render "invite_members_empty_project" if can_admin_project_member?(@project) diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index 53b2af88511..4666ee738d7 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 + = s_('Read more') + - else .table-holder.gl-overflow-visible .ci-table.environments{ role: 'grid' } diff --git a/app/views/projects/feature_flags/index.html.haml b/app/views/projects/feature_flags/index.html.haml index 53fe30422ca..a6eaeacc61f 100644 --- a/app/views/projects/feature_flags/index.html.haml +++ b/app/views/projects/feature_flags/index.html.haml @@ -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/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/issues/_design_management.html.haml b/app/views/projects/issues/_design_management.html.haml index c5ce0549816..5e2b2bbfcc4 100644 --- a/app/views/projects/issues/_design_management.html.haml +++ b/app/views/projects/issues/_design_management.html.haml @@ -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'), + saved_replies_new_path: profile_saved_replies_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..8f259fe73e1 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, + saved_replies_new_path: profile_saved_replies_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..911260308b4 100644 --- a/app/views/projects/issues/_work_item_links.html.haml +++ b/app/views/projects/issues/_work_item_links.html.haml @@ -1,4 +1,4 @@ -.js-work-item-links-root{ data: { issuable_id: @issue.id, iid: @issue.iid, +.js-work-item-links-root{ data: { issuable_id: @issue.id, project_path: @project.full_path, wi: work_items_index_data(@project), register_path: new_user_registration_path(redirect_to_referer: 'yes'), 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..818de77dc89 100644 --- a/app/views/projects/issues/service_desk/_nav_btns.html.haml +++ b/app/views/projects/issues/service_desk/_nav_btns.html.haml @@ -1,7 +1,7 @@ - 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 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/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml index 9d25603994a..d0bd176028f 100644 --- a/app/views/projects/merge_requests/_mr_title.html.haml +++ b/app/views/projects/merge_requests/_mr_title.html.haml @@ -27,7 +27,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..beb6de4698c 100644 --- a/app/views/projects/merge_requests/_nav_btns.html.haml +++ b/app/views/projects/merge_requests/_nav_btns.html.haml @@ -1,4 +1,4 @@ -- 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 diff --git a/app/views/projects/merge_requests/_page.html.haml b/app/views/projects/merge_requests/_page.html.haml index 880bffc43ab..5bd33cd210d 100644 --- a/app/views/projects/merge_requests/_page.html.haml +++ b/app/views/projects/merge_requests/_page.html.haml @@ -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, + saved_replies_new_path: profile_saved_replies_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: { saved_replies_new_path: profile_saved_replies_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/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index cdb8a63bca9..91c161e8602 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -1,32 +1,26 @@ -= 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 @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 - .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/mirrors/_mirror_repos_list.html.haml b/app/views/projects/mirrors/_mirror_repos_list.html.haml index 46833b5986b..5dbbb72db56 100644 --- a/app/views/projects/mirrors/_mirror_repos_list.html.haml +++ b/app/views/projects/mirrors/_mirror_repos_list.html.haml @@ -3,11 +3,11 @@ .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.header do %strong = _('Mirrored repositories') + ' (0)' - .gl-card-body + - c.body do = _('There are currently no mirrored repositories.') - else %table.table.push-pull-table diff --git a/app/views/projects/ml/candidates/show.html.haml b/app/views/projects/ml/candidates/show.html.haml index 77262243efb..aea74ecfb48 100644 --- a/app/views/projects/ml/candidates/show.html.haml +++ b/app/views/projects/ml/candidates/show.html.haml @@ -2,5 +2,6 @@ - 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' #js-show-ml-candidate{ data: { view_model: show_candidate_view_model(@candidate) } } 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/show.html.haml b/app/views/projects/ml/experiments/show.html.haml index 4433d1fafe9..52145eb0964 100644 --- a/app/views/projects/ml/experiments/show.html.haml +++ b/app/views/projects/ml/experiments/show.html.haml @@ -1,6 +1,8 @@ - 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' + - items = candidates_table_items(@candidates) - metrics = unique_logged_names(@candidates, &:latest_metrics) - params = unique_logged_names(@candidates, &:params) diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 56581fe7b18..f4a5862b2c0 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -4,11 +4,19 @@ - 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"), + parent_group_url: @project.parent && group_url(@project.parent), + parent_group_name: @project.parent&.name, + projects_url: dashboard_projects_url } } .row{ 'v-cloak': true } #blank-project-pane.tab-pane.active diff --git a/app/views/projects/pages/_pages_settings.html.haml b/app/views/projects/pages/_pages_settings.html.haml index 0010564081e..11e105d349d 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) + .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_domains/_certificate.html.haml b/app/views/projects/pages_domains/_certificate.html.haml index 4ba3e084dc4..3433958a397 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 - = _('Certificate') - .d-flex.justify-content-between.align-items-center.p-3 + = 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.header do + = s_('Certificate') + - c.body do %span = domain_presenter.pages_domain.subject || _('missing') = link_to _('Remove'), 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..7a889570f56 100644 --- a/app/views/projects/pipelines/_info.html.haml +++ b/app/views/projects/pipelines/_info.html.haml @@ -11,17 +11,20 @@ = 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' } + - if Feature.enabled?(:refactor_ci_minutes_consumption, @project) + = render_if_exists 'projects/pipelines/pipeline_stats_text', duration: duration, pipeline: @pipeline, queued_duration: queued_duration + - else + = s_("in %{duration} and was queued for %{queued_duration}").html_safe % { duration: duration, 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..ee51ee9b0e2 100644 --- a/app/views/projects/pipelines/new.html.haml +++ b/app/views/projects/pipelines/new.html.haml @@ -9,6 +9,8 @@ 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..15d729c89b9 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.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..0cfb5ff6a3d 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -3,6 +3,10 @@ = render_if_exists 'shared/ultimate_feature_removal_banner', project: @project += content_for :page_level_alert do + - if can_invite_members_for_project?(@project) + = render_if_exists 'shared/unlimited_members_during_trial_alert', group: @project.root_ancestor + .row.gl-mt-3 .col-lg-12 .gl-display-flex.gl-flex-wrap @@ -25,7 +29,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/security/configuration/show.html.haml b/app/views/projects/security/configuration/show.html.haml index 4b82f74d035..2904fb81afe 100644 --- a/app/views/projects/security/configuration/show.html.haml +++ b/app/views/projects/security/configuration/show.html.haml @@ -1,5 +1,5 @@ -- breadcrumb_title _("Security Configuration") -- page_title _("Security Configuration") +- breadcrumb_title _("Security configuration") +- page_title _("Security configuration") - @content_class = "limit-container-width" unless fluid_layout #js-security-configuration{ data: { **@configuration.to_html_data_attribute, 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/branch_rules/index.html.haml b/app/views/projects/settings/branch_rules/index.html.haml index 80a41bb579b..f05a528745c 100644 --- a/app/views/projects/settings/branch_rules/index.html.haml +++ b/app/views/projects/settings/branch_rules/index.html.haml @@ -3,4 +3,4 @@ %h3.gl-mb-5= s_('BranchRules|Branch rules details') -#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..5afbace3f26 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.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.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..76a7b42e0e5 100644 --- a/app/views/projects/settings/ci_cd/_badge.html.haml +++ b/app/views/projects/settings/ci_cd/_badge.html.haml @@ -9,7 +9,7 @@ = badge.title.capitalize · = badge.to_html - = render 'shared/ref_switcher', destination: 'badges', align_right: true + .js-ref-switcher-badge{ id: "js-project-ci-cd-ref-switcher-#{badge.title.parameterize(separator: '-') }", data: { project_id: @project.id, ref: @ref } } - c.body do .row .col-md-2.gl-text-center 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/integrations/_form.html.haml b/app/views/projects/settings/integrations/_form.html.haml index 9d74f99bb19..97d90976f18 100644 --- a/app/views/projects/settings/integrations/_form.html.haml +++ b/app/views/projects/settings/integrations/_form.html.haml @@ -11,6 +11,9 @@ = c.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/index.html.haml b/app/views/projects/settings/integrations/index.html.haml index 2077d244b24..c316b4e9cac 100644 --- a/app/views/projects/settings/integrations/index.html.haml +++ b/app/views/projects/settings/integrations/index.html.haml @@ -2,6 +2,8 @@ - breadcrumb_title _('Integration Settings') - page_title _('Integrations') += render 'shared/integrations/slack_notifications_deprecation_alert' + %section.js-search-settings-section %h3= _('Integrations') - integrations_link_start = '<a href="%{url}">'.html_safe % { url: help_page_url('user/project/integrations/index') } diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 5fa70c3af32..f47f4ebc7ee 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -9,6 +9,8 @@ = render_if_exists 'shared/ultimate_feature_removal_banner', project: @project = render partial: 'flash_messages', locals: { project: @project } += render "self_monitoring_deprecation_notice", project: @project + = render 'clusters_deprecation_alert' = render "projects/last_push" diff --git a/app/views/projects/starrers/_starrer.html.haml b/app/views/projects/starrers/_starrer.html.haml index c1cd2488142..d9fda2a6e36 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.body do = render Pajamas::AvatarComponent.new(starrer.user, size: 48, alt: "", class: 'gl-mr-3') .user-info diff --git a/app/views/projects/work_items/index.html.haml b/app/views/projects/work_items/index.html.haml index 69597aab7ef..dad8bb09ff6 100644 --- a/app/views/projects/work_items/index.html.haml +++ b/app/views/projects/work_items/index.html.haml @@ -4,4 +4,3 @@ - @noteable_type = 'WorkItem' #js-work-items{ data: work_items_index_data(@project) } -= render 'projects/invite_members_modal', project: @project diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml index f4e9a597fe2..2796f0c0a7e 100644 --- a/app/views/registrations/welcome/show.html.haml +++ b/app/views/registrations/welcome/show.html.haml @@ -38,4 +38,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..3280dcf2cd4 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -5,5 +5,5 @@ .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_status' if @search_objects.present? = 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..c36acaf9ea8 100644 --- a/app/views/search/_results_list.html.haml +++ b/app/views/search/_results_list.html.haml @@ -2,19 +2,20 @@ = 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 + .gl-md-pl-5 + - 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) + - 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..4ab68caaf22 100644 --- a/app/views/search/_results_status.html.haml +++ b/app/views/search/_results_status.html.haml @@ -1,25 +1,26 @@ - return unless @search_service_presenter.show_results_status? - -.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 +.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? + .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..826d78c470d 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -1,6 +1,6 @@ - @hide_top_links = true +- breadcrumb_title _('Search') - page_title @search_term -- @hide_breadcrumbs = true - if params[:group_id].present? = hidden_field_tag :group_id, params[:group_id] - if params[:project_id].present? @@ -19,7 +19,6 @@ %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 } } +#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' diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml index 8a626f1620b..547f12ac8fc 100644 --- a/app/views/shared/_label.html.haml +++ b/app/views/shared/_label.html.haml @@ -31,14 +31,13 @@ %ul - if label.project_label? && label.project.group && can?(current_user, :admin_label, label.project.group) %li - = render Pajamas::ButtonComponent.new(category: :tertiary, + = 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 - %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') + = 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') - 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? 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/doorkeeper/applications/_show.html.haml b/app/views/shared/doorkeeper/applications/_show.html.haml index 5b0cff2c1c0..19f4c971c1d 100644 --- a/app/views/shared/doorkeeper/applications/_show.html.haml +++ b/app/views/shared/doorkeeper/applications/_show.html.haml @@ -15,14 +15,17 @@ %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.') + - if @application.plaintext_secret + = render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_options: { class: 'gl-mb-5'}) do |c| + = c.body do + = _('This is the only time the secret is accessible. Copy the secret and store it securely.') + = clipboard_button(clipboard_text: @application.plaintext_secret, button_text: _('Copy'), title: _("Copy secret"), class: "btn btn-default btn-md gl-button") - else - = clipboard_button(clipboard_text: @application.secret, button_text: _('Copy'), title: _("Copy secret"), class: "btn btn-default btn-md gl-button") + = render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_options: { class: 'gl-mb-5'}) do |c| + = c.body do + = _('The secret is only available when you create the application or renew the secret.') + = render 'shared/doorkeeper/applications/update_form', path: renew_path + %tr %td = _('Callback URL') diff --git a/app/views/shared/doorkeeper/applications/_update_form.html.haml b/app/views/shared/doorkeeper/applications/_update_form.html.haml new file mode 100644 index 00000000000..1bee3288639 --- /dev/null +++ b/app/views/shared/doorkeeper/applications/_update_form.html.haml @@ -0,0 +1,3 @@ +- path = local_assigns.fetch(:path) += form_for(@application, url: path, html: {class: 'gl-display-inline-block', method: "put"}) do |f| + = submit_tag s_('AuthorizedApplication|Renew secret'), data: { confirm: s_("AuthorizedApplication|Are you sure you want to renew this secret? Any applications using the old secret will no longer be able to authenticate with GitLab."), confirm_btn_variant: "danger" }, aria: { label: s_('AuthorizedApplication|Renew secret') }, class: 'gl-button btn btn-md btn-default' diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml index 37f7fbc0de5..ad6e5578878 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), container_class: 'gl-w-full gl-sm-w-auto gl-sm-mr-3 gl-display-inline-flex gl-vertical-align-middle', show_label: 'true' } } %hr %p.gl-text-center.gl-mb-0 %strong 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/prometheus/_custom_metrics.html.haml b/app/views/shared/integrations/prometheus/_custom_metrics.html.haml index dda84e0fb9e..e5ddc055aef 100644 --- a/app/views/shared/integrations/prometheus/_custom_metrics.html.haml +++ b/app/views/shared/integrations/prometheus/_custom_metrics.html.haml @@ -6,13 +6,13 @@ = link_to s_('PrometheusService|More information'), help_page_path('operations/metrics/index.md', anchor: 'adding-custom-metrics'), 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..a8125c3e3ec 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,13 +23,13 @@ = 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 diff --git a/app/views/shared/issuable/_feed_buttons.html.haml b/app/views/shared/issuable/_feed_buttons.html.haml index 94b7fe14721..e0f676021a1 100644 --- a/app/views/shared/issuable/_feed_buttons.html.haml +++ b/app/views/shared/issuable/_feed_buttons.html.haml @@ -1,8 +1,8 @@ - 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') += render Pajamas::ButtonComponent.new(href: safe_params.merge(rss_url_options), button_options: { class: 'has-tooltip btn-icon', title: _('Subscribe to RSS feed'), 'aria-label': _('Subscribe to RSS feed'), data: { container: 'body', testid: 'rss-feed-link' } }) do + = sprite_icon('rss') - 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') + = render Pajamas::ButtonComponent.new(href: safe_params.merge(calendar_url_options), button_options: { class: 'has-tooltip btn-icon', title: _('Subscribe to calendar'), 'aria-label': _('Subscribe to calendar'), data: { container: 'body' } }) do + = sprite_icon('calendar') 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..95c5f51c339 100644 --- a/app/views/shared/issuable/_search_bar.html.haml +++ b/app/views/shared/issuable/_search_bar.html.haml @@ -162,6 +162,14 @@ %li.filter-dropdown-item{ data: { value: 'no', capitalize: true } } %button.gl-button.btn.btn-link{ type: 'button' } = _('No') + #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 } } 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/_type_selector.html.haml b/app/views/shared/issuable/form/_type_selector.html.haml index a94ef70b2d5..6d4cd83d55b 100644 --- a/app/views/shared/issuable/form/_type_selector.html.haml +++ b/app/views/shared/issuable/form/_type_selector.html.haml @@ -10,7 +10,7 @@ %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") + = sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon") .dropdown-menu.dropdown-menu-selectable.dropdown-select .dropdown-title.gl-display-flex %span.gl-ml-auto diff --git a/app/views/shared/issue_type/_details_content.html.haml b/app/views/shared/issue_type/_details_content.html.haml index e1a9b30ef67..e189cc34899 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-2.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, diff --git a/app/views/shared/labels/_form.html.haml b/app/views/shared/labels/_form.html.haml index 9ef4b9e084d..5d749b16eee 100644 --- a/app/views/shared/labels/_form.html.haml +++ b/app/views/shared/labels/_form.html.haml @@ -16,7 +16,7 @@ = f.label :color, _("Background color") .input-group .input-group-prepend - .input-group-text.label-color-preview + %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.') diff --git a/app/views/shared/milestones/_description.html.haml b/app/views/shared/milestones/_description.html.haml index fc25c7e8f89..d7908b1c210 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-5 %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/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/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/wikis/_wiki_directory.html.haml b/app/views/shared/wikis/_wiki_directory.html.haml index 5c2233a4db2..ced51e1f697 100644 --- a/app/views/shared/wikis/_wiki_directory.html.haml +++ b/app/views/shared/wikis/_wiki_directory.html.haml @@ -1,6 +1,9 @@ %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< + = 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') + = 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 %ul - wiki_directory.entries.each do |entry| = render partial: entry.to_partial_path, object: entry, locals: { context: context } diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index eb9465a409f..583f25b68eb 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 + -# Different breadcrumbs if this page is rendered as part of the Explore section + - 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/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..3543d5c4336 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -6,6 +6,9 @@ - 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 + - nav "user_profile" = content_for :meta_tags do = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity") @@ -43,137 +46,129 @@ = _('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) + .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" }) + #js-user-achievements{ data: { root_url: root_url, user_id: @user.id } } + .gl-display-inline-block.gl-vertical-align-top.gl-text-left + - if @user.blocked? || !@user.confirmed? + .user-info + %h1.cover-title.gl-my-0 + = user_display_name(@user) = 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 + - 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? + %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.gl-max-w-80.gl-mx-auto= 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) - - 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 - .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 - - if profile_tab?(:overview) - %li.js-overview-tab - = link_to user_path, data: { target: 'div#js-overview', action: 'overview', toggle: 'tab' } do - = s_('UserProfile|Overview') - - if profile_tab?(:activity) - %li.js-activity-tab - = link_to user_activity_path, data: { target: 'div#activity', action: 'activity', toggle: 'tab' } do - = s_('UserProfile|Activity') - - unless Feature.enabled?(:security_auto_fix) && @user.bot? - - if profile_tab?(:groups) - %li.js-groups-tab - = link_to user_groups_path, data: { target: 'div#groups', action: 'groups', toggle: 'tab', endpoint: user_groups_path(format: :json) } do - = s_('UserProfile|Groups') - - if profile_tab?(:contributed) - %li.js-contributed-tab - = link_to user_contributed_projects_path, data: { target: 'div#contributed', action: 'contributed', toggle: 'tab', endpoint: user_contributed_projects_path(format: :json) } do - = s_('UserProfile|Contributed projects') - - if profile_tab?(:projects) - %li.js-projects-tab - = link_to user_projects_path, data: { target: 'div#projects', action: 'projects', toggle: 'tab', endpoint: user_projects_path(format: :json) } do - = s_('UserProfile|Personal projects') - - if profile_tab?(:starred) - %li.js-starred-tab - = link_to user_starred_projects_path, data: { target: 'div#starred', action: 'starred', toggle: 'tab', endpoint: user_starred_projects_path(format: :json) } do - = s_('UserProfile|Starred projects') - - if profile_tab?(:snippets) - %li.js-snippets-tab - = link_to user_snippets_path, data: { target: 'div#snippets', action: 'snippets', toggle: 'tab', endpoint: user_snippets_path(format: :json) } do - = s_('UserProfile|Snippets') - - if profile_tab?(:followers) - %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') - - 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 - = s_('UserProfile|Following') - + - 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', 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' + - 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 + - if profile_tab?(:overview) + %li.js-overview-tab + = link_to user_path, data: { target: 'div#js-overview', action: 'overview', toggle: 'tab' } do + = s_('UserProfile|Overview') + - if profile_tab?(:activity) + %li.js-activity-tab + = link_to user_activity_path, data: { target: 'div#activity', action: 'activity', toggle: 'tab' } do + = s_('UserProfile|Activity') + - unless Feature.enabled?(:security_auto_fix) && @user.bot? + - if profile_tab?(:groups) + %li.js-groups-tab + = link_to user_groups_path, data: { target: 'div#groups', action: 'groups', toggle: 'tab', endpoint: user_groups_path(format: :json) } do + = s_('UserProfile|Groups') + - if profile_tab?(:contributed) + %li.js-contributed-tab + = link_to user_contributed_projects_path, data: { target: 'div#contributed', action: 'contributed', toggle: 'tab', endpoint: user_contributed_projects_path(format: :json) } do + = s_('UserProfile|Contributed projects') + - if profile_tab?(:projects) + %li.js-projects-tab + = link_to user_projects_path, data: { target: 'div#projects', action: 'projects', toggle: 'tab', endpoint: user_projects_path(format: :json) } do + = s_('UserProfile|Personal projects') + - if profile_tab?(:starred) + %li.js-starred-tab + = link_to user_starred_projects_path, data: { target: 'div#starred', action: 'starred', toggle: 'tab', endpoint: user_starred_projects_path(format: :json) } do + = s_('UserProfile|Starred projects') + - if profile_tab?(:snippets) + %li.js-snippets-tab + = link_to user_snippets_path, data: { target: 'div#snippets', action: 'snippets', toggle: 'tab', endpoint: user_snippets_path(format: :json) } do + = s_('UserProfile|Snippets') + - if profile_tab?(:followers) + %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), 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 |