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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-08-18 13:50:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-08-18 13:50:51 +0300
commitdb384e6b19af03b4c3c82a5760d83a3fd79f7982 (patch)
tree34beaef37df5f47ccbcf5729d7583aae093cffa0 /app/helpers
parent54fd7b1bad233e3944434da91d257fa7f63c3996 (diff)
Add latest changes from gitlab-org/gitlab@16-3-stable-eev16.3.0-rc42
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/admin/application_settings/settings_helper.rb60
-rw-r--r--app/helpers/admin/broadcast_messages_helper.rb123
-rw-r--r--app/helpers/admin/deploy_key_helper.rb2
-rw-r--r--app/helpers/application_helper.rb21
-rw-r--r--app/helpers/application_settings_helper.rb11
-rw-r--r--app/helpers/broadcast_messages_helper.rb121
-rw-r--r--app/helpers/ci/runners_helper.rb37
-rw-r--r--app/helpers/commits_helper.rb27
-rw-r--r--app/helpers/dropdowns_helper.rb5
-rw-r--r--app/helpers/emails_helper.rb39
-rw-r--r--app/helpers/environments_helper.rb4
-rw-r--r--app/helpers/integrations_helper.rb5
-rw-r--r--app/helpers/issuables_helper.rb29
-rw-r--r--app/helpers/issues_helper.rb9
-rw-r--r--app/helpers/jira_connect_helper.rb2
-rw-r--r--app/helpers/labels_helper.rb8
-rw-r--r--app/helpers/markup_helper.rb32
-rw-r--r--app/helpers/merge_requests_helper.rb6
-rw-r--r--app/helpers/mirror_helper.rb5
-rw-r--r--app/helpers/nav_helper.rb2
-rw-r--r--app/helpers/notes_helper.rb4
-rw-r--r--app/helpers/packages_helper.rb2
-rw-r--r--app/helpers/profiles_helper.rb15
-rw-r--r--app/helpers/projects/cluster_agents_helper.rb2
-rw-r--r--app/helpers/projects/observability_helper.rb10
-rw-r--r--app/helpers/projects_helper.rb36
-rw-r--r--app/helpers/sessions_helper.rb23
-rw-r--r--app/helpers/sidebars_helper.rb44
-rw-r--r--app/helpers/snippets_helper.rb34
-rw-r--r--app/helpers/time_helper.rb24
-rw-r--r--app/helpers/todos_helper.rb1
-rw-r--r--app/helpers/tree_helper.rb3
-rw-r--r--app/helpers/users/callouts_helper.rb2
-rw-r--r--app/helpers/users_helper.rb36
34 files changed, 481 insertions, 303 deletions
diff --git a/app/helpers/admin/application_settings/settings_helper.rb b/app/helpers/admin/application_settings/settings_helper.rb
index 9ea07ba4e6e..1741d6a953a 100644
--- a/app/helpers/admin/application_settings/settings_helper.rb
+++ b/app/helpers/admin/application_settings/settings_helper.rb
@@ -15,66 +15,6 @@ module Admin
def project_missing_pipeline_yaml?(project)
project.repository&.gitlab_ci_yml.blank?
end
-
- def code_suggestions_description
- link_start = code_suggestions_link_start(code_suggestions_docs_url)
-
- # rubocop:disable Layout/LineLength
- # rubocop:disable Style/FormatString
- s_('CodeSuggestionsSM|Enable Code Suggestions for users of this instance. %{link_start}What are Code Suggestions?%{link_end}')
- .html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- # rubocop:enable Style/FormatString
- # rubocop:enable Layout/LineLength
- end
-
- def code_suggestions_token_explanation
- link_start = code_suggestions_link_start(code_suggestions_pat_docs_url)
-
- # rubocop:disable Layout/LineLength
- # rubocop:disable Style/FormatString
- s_('CodeSuggestionsSM|On GitLab.com, create a token. This token is required to use Code Suggestions on your self-managed instance. %{link_start}How do I create a token?%{link_end}')
- .html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
- # rubocop:enable Style/FormatString
- # rubocop:enable Layout/LineLength
- end
-
- def code_suggestions_agreement
- terms_link_start = code_suggestions_link_start(code_suggestions_agreement_url)
- ai_docs_link_start = code_suggestions_link_start(code_suggestions_ai_docs_url)
-
- # rubocop:disable Layout/LineLength
- # rubocop:disable Style/FormatString
- s_('CodeSuggestionsSM|By enabling this feature, you agree to the %{terms_link_start}GitLab Testing Agreement%{link_end} and acknowledge that GitLab will send data from the instance, including personal data, to our %{ai_docs_link_start}AI providers%{link_end} to provide this feature.')
- .html_safe % { terms_link_start: terms_link_start, ai_docs_link_start: ai_docs_link_start, link_end: '</a>'.html_safe }
- # rubocop:enable Style/FormatString
- # rubocop:enable Layout/LineLength
- end
-
- private
-
- # rubocop:disable Gitlab/DocUrl
- # We want to link SaaS docs for flexibility for every URL related to Code Suggestions on Self Managed.
- # We expect to update docs often during the Beta and we want to point user to the most up to date information.
- def code_suggestions_docs_url
- 'https://docs.gitlab.com/ee/user/project/repository/code_suggestions.html'
- end
-
- def code_suggestions_agreement_url
- 'https://about.gitlab.com/handbook/legal/testing-agreement/'
- end
-
- def code_suggestions_ai_docs_url
- 'https://docs.gitlab.com/ee/user/ai_features.html#third-party-services'
- end
-
- def code_suggestions_pat_docs_url
- 'https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token'
- end
- # rubocop:enable Gitlab/DocUrl
-
- def code_suggestions_link_start(url)
- "<a href=\"#{url}\" target=\"_blank\" rel=\"noopener noreferrer\">".html_safe
- end
end
end
end
diff --git a/app/helpers/admin/broadcast_messages_helper.rb b/app/helpers/admin/broadcast_messages_helper.rb
new file mode 100644
index 00000000000..e087361d52e
--- /dev/null
+++ b/app/helpers/admin/broadcast_messages_helper.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+module Admin
+ module BroadcastMessagesHelper
+ include Gitlab::Utils::StrongMemoize
+
+ def current_broadcast_banner_messages
+ System::BroadcastMessage.current_banner_messages(
+ current_path: request.path,
+ user_access_level: current_user_access_level_for_project_or_group
+ ).select do |message|
+ cookies["hide_broadcast_message_#{message.id}"].blank?
+ end
+ end
+
+ def current_broadcast_notification_message
+ not_hidden_messages = System::BroadcastMessage.current_notification_messages(
+ current_path: request.path,
+ user_access_level: current_user_access_level_for_project_or_group
+ ).select do |message|
+ cookies["hide_broadcast_message_#{message.id}"].blank?
+ end
+ not_hidden_messages.last
+ end
+
+ def broadcast_message(message, opts = {})
+ return unless message.present?
+
+ render "shared/broadcast_message", { message: message, **opts }
+ end
+
+ def broadcast_message_status(broadcast_message)
+ if broadcast_message.active?
+ 'Active'
+ elsif broadcast_message.ended?
+ 'Expired'
+ else
+ 'Pending'
+ end
+ end
+
+ def render_broadcast_message(broadcast_message)
+ if broadcast_message.notification?
+ Banzai.render_field_and_post_process(broadcast_message, :message, {
+ current_user: current_user,
+ skip_project_check: true,
+ broadcast_message_placeholders: true
+ }).html_safe
+ else
+ Banzai.render_field(broadcast_message, :message).html_safe
+ end
+ end
+
+ def target_access_level_options
+ System::BroadcastMessage::ALLOWED_TARGET_ACCESS_LEVELS.map do |access_level|
+ [Gitlab::Access.human_access(access_level), access_level]
+ end
+ end
+
+ def target_access_levels_display(access_levels)
+ access_levels.map do |access_level|
+ Gitlab::Access.human_access(access_level)
+ end.join(', ')
+ end
+
+ def admin_broadcast_messages_data(broadcast_messages)
+ broadcast_messages.map do |message|
+ {
+ id: message.id,
+ status: broadcast_message_status(message),
+ message: message.message,
+ theme: message.theme,
+ broadcast_type: message.broadcast_type,
+ dismissable: message.dismissable,
+ starts_at: message.starts_at.iso8601,
+ ends_at: message.ends_at.iso8601,
+ target_roles: target_access_levels_display(message.target_access_levels),
+ target_path: message.target_path,
+ type: message.broadcast_type.capitalize,
+ edit_path: edit_admin_broadcast_message_path(message),
+ delete_path: "#{admin_broadcast_message_path(message)}.js"
+ }
+ end.to_json
+ end
+
+ def broadcast_message_data(broadcast_message)
+ {
+ id: broadcast_message.id,
+ message: broadcast_message.message,
+ broadcast_type: broadcast_message.broadcast_type,
+ theme: broadcast_message.theme,
+ dismissable: broadcast_message.dismissable.to_s,
+ target_access_levels: broadcast_message.target_access_levels,
+ messages_path: admin_broadcast_messages_path,
+ preview_path: preview_admin_broadcast_messages_path,
+ target_path: broadcast_message.target_path,
+ starts_at: broadcast_message.starts_at.iso8601,
+ ends_at: broadcast_message.ends_at.iso8601,
+ target_access_level_options: target_access_level_options.to_json,
+ show_in_cli: broadcast_message.show_in_cli.to_s
+ }
+ end
+
+ private
+
+ def current_user_access_level_for_project_or_group
+ return unless current_user.present?
+
+ strong_memoize(:current_user_access_level_for_project_or_group) do
+ case controller
+ when Projects::ApplicationController
+ next unless @project
+
+ @project.team.max_member_access(current_user.id)
+ when Groups::ApplicationController
+ next unless @group
+
+ @group.max_member_access_for_user(current_user)
+ end
+ end
+ end
+ end
+end
diff --git a/app/helpers/admin/deploy_key_helper.rb b/app/helpers/admin/deploy_key_helper.rb
index caf3757a68e..8b23c3e1e13 100644
--- a/app/helpers/admin/deploy_key_helper.rb
+++ b/app/helpers/admin/deploy_key_helper.rb
@@ -7,7 +7,7 @@ module Admin
edit_path: edit_admin_deploy_key_path(':id'),
delete_path: admin_deploy_key_path(':id'),
create_path: new_admin_deploy_key_path,
- empty_state_svg_path: image_path('illustrations/empty-state/empty-deploy-keys-lg.svg')
+ empty_state_svg_path: image_path('illustrations/empty-state/empty-access-token-md.svg')
}
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index ce338a8afdc..2bf239979f7 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -317,7 +317,7 @@ module ApplicationHelper
class_names << 'with-performance-bar' if performance_bar_enabled?
class_names << 'with-top-bar' if show_super_sidebar? && !@hide_top_bar
class_names << system_message_class
- class_names << 'logged-out-marketing-header' if !current_user && ::Gitlab.com?
+ class_names << 'logged-out-marketing-header' if !current_user && ::Gitlab.com? && !show_super_sidebar?
class_names
end
@@ -466,6 +466,25 @@ module ApplicationHelper
form_with(**args.merge({ builder: ::Gitlab::FormBuilders::GitlabUiFormBuilder }), &block)
end
+ def hidden_resource_icon(resource, css_class: nil)
+ issuable_title = _('This %{issuable} is hidden because its author has been banned')
+
+ case resource
+ when Issue
+ title = format(issuable_title, issuable: _('issue'))
+ when MergeRequest
+ title = format(issuable_title, issuable: _('merge request'))
+ when Project
+ title = _('This project is hidden because its creator has been banned')
+ end
+
+ return unless title
+
+ content_tag(:span, class: 'has-tooltip', title: title) do
+ sprite_icon('spam', css_class: ['gl-vertical-align-text-bottom', css_class].compact_blank.join(' '))
+ end
+ end
+
private
def browser_id
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index aa2466372e1..a45425474b5 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -218,7 +218,6 @@ module ApplicationSettingsHelper
:admin_mode,
:after_sign_out_path,
:after_sign_up_text,
- :ai_access_token,
:akismet_api_key,
:akismet_enabled,
:allow_local_requests_from_hooks_and_services,
@@ -242,6 +241,7 @@ module ApplicationSettingsHelper
:default_artifacts_expire_in,
:default_branch_name,
:default_branch_protection,
+ :default_branch_protection_defaults,
:default_ci_config_path,
:default_group_visibility,
:default_preferred_language,
@@ -310,7 +310,6 @@ module ApplicationSettingsHelper
:inactive_projects_delete_after_months,
:inactive_projects_min_size_mb,
:inactive_projects_send_warning_email_after_months,
- :instance_level_code_suggestions_enabled,
:invisible_captcha_enabled,
:jira_connect_application_key,
:jira_connect_public_key_storage_enabled,
@@ -319,6 +318,8 @@ module ApplicationSettingsHelper
:max_attachment_size,
:max_export_size,
:max_import_size,
+ :max_import_remote_file_size,
+ :max_decompressed_archive_size,
:max_pages_size,
:max_pages_custom_domains_per_project,
:max_terraform_state_size_bytes,
@@ -457,6 +458,7 @@ module ApplicationSettingsHelper
:wiki_asciidoc_allow_uri_includes,
:container_registry_delete_tags_service_timeout,
:rate_limiting_response_text,
+ :package_registry_allow_anyone_to_pull_option,
:package_registry_cleanup_policies_worker_capacity,
:container_registry_expiration_policies_worker_capacity,
:container_registry_cleanup_tags_service_max_list_size,
@@ -491,6 +493,7 @@ module ApplicationSettingsHelper
:invitation_flow_enforcement,
:can_create_group,
:bulk_import_enabled,
+ :bulk_import_max_download_file_size,
:allow_runner_registration_token,
:user_defaults_to_private_profile,
:deactivation_email_additional_text,
@@ -498,7 +501,9 @@ module ApplicationSettingsHelper
:gitlab_dedicated_instance,
:ci_max_includes,
:allow_account_deletion,
- :gitlab_shell_operation_limit
+ :gitlab_shell_operation_limit,
+ :namespace_aggregation_schedule_lease_duration_in_seconds,
+ :ci_max_total_yaml_size_bytes
].tap do |settings|
next if Gitlab.com?
diff --git a/app/helpers/broadcast_messages_helper.rb b/app/helpers/broadcast_messages_helper.rb
deleted file mode 100644
index a62ffa144f1..00000000000
--- a/app/helpers/broadcast_messages_helper.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-# frozen_string_literal: true
-
-module BroadcastMessagesHelper
- include Gitlab::Utils::StrongMemoize
-
- def current_broadcast_banner_messages
- BroadcastMessage.current_banner_messages(
- current_path: request.path,
- user_access_level: current_user_access_level_for_project_or_group
- ).select do |message|
- cookies["hide_broadcast_message_#{message.id}"].blank?
- end
- end
-
- def current_broadcast_notification_message
- not_hidden_messages = BroadcastMessage.current_notification_messages(
- current_path: request.path,
- user_access_level: current_user_access_level_for_project_or_group
- ).select do |message|
- cookies["hide_broadcast_message_#{message.id}"].blank?
- end
- not_hidden_messages.last
- end
-
- def broadcast_message(message, opts = {})
- return unless message.present?
-
- render "shared/broadcast_message", { message: message, **opts }
- end
-
- def broadcast_message_status(broadcast_message)
- if broadcast_message.active?
- 'Active'
- elsif broadcast_message.ended?
- 'Expired'
- else
- 'Pending'
- end
- end
-
- def render_broadcast_message(broadcast_message)
- if broadcast_message.notification?
- Banzai.render_field_and_post_process(broadcast_message, :message, {
- current_user: current_user,
- skip_project_check: true,
- broadcast_message_placeholders: true
- }).html_safe
- else
- Banzai.render_field(broadcast_message, :message).html_safe
- end
- end
-
- def target_access_level_options
- BroadcastMessage::ALLOWED_TARGET_ACCESS_LEVELS.map do |access_level|
- [Gitlab::Access.human_access(access_level), access_level]
- end
- end
-
- def target_access_levels_display(access_levels)
- access_levels.map do |access_level|
- Gitlab::Access.human_access(access_level)
- end.join(', ')
- end
-
- def admin_broadcast_messages_data(broadcast_messages)
- broadcast_messages.map do |message|
- {
- id: message.id,
- status: broadcast_message_status(message),
- message: message.message,
- theme: message.theme,
- broadcast_type: message.broadcast_type,
- dismissable: message.dismissable,
- starts_at: message.starts_at.iso8601,
- ends_at: message.ends_at.iso8601,
- target_roles: target_access_levels_display(message.target_access_levels),
- target_path: message.target_path,
- type: message.broadcast_type.capitalize,
- edit_path: edit_admin_broadcast_message_path(message),
- delete_path: "#{admin_broadcast_message_path(message)}.js"
- }
- end.to_json
- end
-
- def broadcast_message_data(broadcast_message)
- {
- id: broadcast_message.id,
- message: broadcast_message.message,
- broadcast_type: broadcast_message.broadcast_type,
- theme: broadcast_message.theme,
- dismissable: broadcast_message.dismissable.to_s,
- target_access_levels: broadcast_message.target_access_levels,
- messages_path: admin_broadcast_messages_path,
- preview_path: preview_admin_broadcast_messages_path,
- target_path: broadcast_message.target_path,
- starts_at: broadcast_message.starts_at.iso8601,
- ends_at: broadcast_message.ends_at.iso8601,
- target_access_level_options: target_access_level_options.to_json,
- show_in_cli: broadcast_message.show_in_cli.to_s
- }
- end
-
- private
-
- def current_user_access_level_for_project_or_group
- return unless current_user.present?
-
- strong_memoize(:current_user_access_level_for_project_or_group) do
- case controller
- when Projects::ApplicationController
- next unless @project
-
- @project.team.max_member_access(current_user.id)
- when Groups::ApplicationController
- next unless @group
-
- @group.max_member_access_for_user(current_user)
- end
- end
- end
-end
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index b1481f668bb..7cc554bbeeb 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -71,21 +71,35 @@ module Ci
new_runner_path: new_admin_runner_path,
registration_token: Gitlab::CurrentSettings.runners_registration_token,
online_contact_timeout_secs: ::Ci::Runner::ONLINE_CONTACT_TIMEOUT.to_i,
- stale_timeout_secs: ::Ci::Runner::STALE_TIMEOUT.to_i
+ stale_timeout_secs: ::Ci::Runner::STALE_TIMEOUT.to_i,
+ tag_suggestions_path: tag_list_admin_runners_path(format: :json)
}
end
def group_shared_runners_settings_data(group)
- {
+ data = {
group_id: group.id,
group_name: group.name,
group_is_empty: (group.projects.empty? && group.children.empty?).to_s,
shared_runners_setting: group.shared_runners_setting,
- parent_shared_runners_setting: group.parent&.shared_runners_setting,
+
runner_enabled_value: Namespace::SR_ENABLED,
runner_disabled_value: Namespace::SR_DISABLED_AND_UNOVERRIDABLE,
- runner_allow_override_value: Namespace::SR_DISABLED_AND_OVERRIDABLE
+ runner_allow_override_value: Namespace::SR_DISABLED_AND_OVERRIDABLE,
+
+ parent_shared_runners_setting: group.parent&.shared_runners_setting,
+ parent_name: nil,
+ parent_settings_path: nil
}
+
+ if group.parent && can?(current_user, :admin_group, group.parent)
+ data.merge!({
+ parent_name: group.parent.name,
+ parent_settings_path: group_settings_ci_cd_path(group.parent, anchor: 'runners-settings')
+ })
+ end
+
+ data
end
def group_runners_data_attributes(group)
@@ -99,11 +113,22 @@ module Ci
end
def toggle_shared_runners_settings_data(project)
- {
+ data = {
is_enabled: project.shared_runners_enabled?.to_s,
is_disabled_and_unoverridable: (project.group&.shared_runners_setting == Namespace::SR_DISABLED_AND_UNOVERRIDABLE).to_s,
- update_path: toggle_shared_runners_project_runners_path(project)
+ update_path: toggle_shared_runners_project_runners_path(project),
+ group_name: nil,
+ group_settings_path: nil
}
+
+ if project.group && can?(current_user, :admin_group, project.group)
+ data.merge!({
+ group_name: project.group.name,
+ group_settings_path: group_settings_ci_cd_path(project.group, anchor: 'runners-settings')
+ })
+ end
+
+ data
end
end
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index ee86553d75d..42871dcc56f 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -111,7 +111,7 @@ module CommitsHelper
tooltip = _("Browse Directory")
end
- link_to url, class: "btn gl-button btn-default btn-icon has-tooltip", title: tooltip, data: { container: "body" } do
+ render Pajamas::ButtonComponent.new(href: url, button_options: { title: tooltip, class: 'has-tooltip btn-icon', data: { container: 'body' } }) do
sprite_icon('folder-open')
end
end
@@ -143,6 +143,16 @@ module CommitsHelper
end
end
+ def local_committed_date(commit, user)
+ server_timezone = Time.zone
+ user_timezone = user.timezone if user
+ user_timezone = ActiveSupport::TimeZone.new(user_timezone) if user_timezone
+
+ timezone = user_timezone || server_timezone
+
+ commit.committed_date.in_time_zone(timezone).to_date
+ end
+
def cherry_pick_projects_data(project)
[project, project.forked_from_project].compact.map do |project|
{
@@ -188,12 +198,11 @@ module CommitsHelper
entity = mode == 'raw' ? 'rawButton' : 'renderedButton'
title = "Display #{mode} diff"
- link_to(
- "##{mode}-diff-#{file_hash}",
- class: "btn gl-button btn-default btn-file-option has-tooltip btn-show-#{mode}-diff",
- title: title,
- data: { file_hash: file_hash, diff_toggle_entity: entity }
- ) do
+ render Pajamas::ButtonComponent.new(
+ href: "##{mode}-diff-#{file_hash}",
+ button_options: { title: title,
+ class: "btn-file-option has-tooltip btn-show-#{mode}-diff",
+ data: { file_hash: file_hash, diff_toggle_entity: entity } }) do
sprite_icon(icon)
end
end
@@ -242,7 +251,7 @@ module CommitsHelper
path = project_blob_path(project, tree_join(commit_sha, diff_new_path))
title = replaced ? _('View replaced file @ ') : _('View file @ ')
- link_to(path, class: 'btn gl-button btn-default gl-ml-3') do
+ render Pajamas::ButtonComponent.new(href: path, button_options: { class: 'gl-ml-3' }) do
raw(title) + content_tag(:span, truncate_sha(commit_sha), class: 'commit-sha')
end
end
@@ -253,7 +262,7 @@ module CommitsHelper
external_url = environment.external_url_for(diff_new_path, commit_sha)
return unless external_url
- link_to(external_url, class: 'btn gl-button btn-default btn-file-option has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: "View on #{environment.formatted_external_url}", data: { container: 'body' }) do
+ render Pajamas::ButtonComponent.new(href: external_url, target: '_blank', button_options: { rel: 'noopener noreferrer', title: "View on #{environment.formatted_external_url}", data: { container: 'body' } }) do
sprite_icon('external-link')
end
end
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 475ba3dcba8..ce18bedd25f 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -1,6 +1,11 @@
# frozen_string_literal: true
module DropdownsHelper
+ def dropdown_data_attr(options: {})
+ output = content_tag(:div, "", id: "js-template-selectors-menu", data: options[:data])
+ output.html_safe
+ end
+
# rubocop:disable Metrics/CyclomaticComplexity
def dropdown_tag(toggle_text, options: {}, &block)
content_tag :div, class: "dropdown #{options[:wrapper_class] if options.key?(:wrapper_class)}" do
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index 7213bd074fc..af0f1bd6808 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -2,6 +2,7 @@
module EmailsHelper
include AppearancesHelper
+ include SafeFormatHelper
# Google Actions
# https://developers.google.com/gmail/markup/reference/go-to-action
@@ -236,6 +237,44 @@ module EmailsHelper
end
end
+ def member_about_to_expire_text(member_source, days_to_expire, format: nil)
+ days_formatted = pluralize(days_to_expire, 'day')
+
+ case member_source
+ when Project
+ url = project_url(member_source)
+ when Group
+ url = group_url(member_source)
+ end
+
+ case format
+ when :html
+ link_to = generate_link(member_source.human_name, url).html_safe
+ safe_format(_("Your membership in %{link_to} %{project_or_group_name} will expire in %{days_formatted}."), link_to: link_to, project_or_group_name: member_source.model_name.singular, days_formatted: days_formatted)
+ else
+ _("Your membership in %{project_or_group} %{project_or_group_name} will expire in %{days_formatted}.") % { project_or_group: member_source.human_name, project_or_group_name: member_source.model_name.singular, days_formatted: days_formatted }
+ end
+ end
+
+ def member_about_to_expire_link(member, member_source, format: nil)
+ project_or_group = member_source.human_name
+
+ case member_source
+ when Project
+ url = project_project_members_url(member_source, search: member.user.username)
+ when Group
+ url = group_group_members_url(member_source, search: member.user.username)
+ end
+
+ case format
+ when :html
+ link_to = generate_link("#{member_source.class.name.downcase} membership", url).html_safe
+ safe_format(_('For additional information, review your %{link_to} or contact your %{project_or_group} owner.'), link_to: link_to, project_or_group: project_or_group)
+ else
+ _('For additional information, review your %{project_or_group} membership: %{url} or contact your %{project_or_group} owner.') % { project_or_group: project_or_group, url: url }
+ end
+ end
+
def group_membership_expiration_changed_text(member, group)
if member.expires?
days = (member.expires_at - Date.today).to_i
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 3360a5256af..cd768ba8a7b 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -54,7 +54,6 @@ module EnvironmentsHelper
{
'settings_path' => edit_project_settings_integration_path(project, 'prometheus'),
'clusters_path' => project_clusters_path(project),
- 'dashboards_endpoint' => project_performance_monitoring_dashboards_path(project, format: :json),
'default_branch' => project.default_branch,
'project_path' => project_path(project),
'tags_path' => project_tags_path(project),
@@ -82,8 +81,7 @@ module EnvironmentsHelper
{
'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json),
'operations_settings_path' => project_settings_operations_path(project),
- 'can_access_operations_settings' => can?(current_user, :admin_operations, project).to_s,
- 'panel_preview_endpoint' => project_metrics_dashboards_builder_path(project, format: :json)
+ 'can_access_operations_settings' => can?(current_user, :admin_operations, project).to_s
}
end
diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb
index 4b5fadf3397..645a08bfcc0 100644
--- a/app/helpers/integrations_helper.rb
+++ b/app/helpers/integrations_helper.rb
@@ -162,7 +162,7 @@ module IntegrationsHelper
end
def integrations_help_page_path
- help_page_path('user/admin_area/settings/project_integration_management')
+ help_page_path('administration/settings/project_integration_management')
end
def project_jira_issues_integration?
@@ -179,7 +179,8 @@ module IntegrationsHelper
'incident' => _('Incident'),
'test_case' => _('Test case'),
'requirement' => _('Requirement'),
- 'task' => _('Task')
+ 'task' => _('Task'),
+ 'ticket' => _('Service Desk Ticket')
}
issue_type_i18n_map[issue_type] || issue_type
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index e921e9bae4d..c83545fa7a7 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -251,9 +251,16 @@ module IssuablesHelper
def issue_only_initial_data(issuable)
return {} unless issuable.is_a?(Issue)
- {
+ data = {
+ authorId: issuable.author.id,
+ authorName: issuable.author.name,
+ authorUsername: issuable.author.username,
+ authorWebUrl: url_for(user_path(issuable.author)),
+ createdAt: issuable.created_at.to_time.iso8601,
hasClosingMergeRequest: issuable.merge_requests_count(current_user) != 0,
+ isFirstContribution: issuable.first_contribution?,
issueType: issuable.issue_type,
+ serviceDeskReplyTo: issuable.present(current_user: current_user).service_desk_reply_to,
zoomMeetingUrl: ZoomMeeting.canonical_meeting_url(issuable),
sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier, # rubocop:disable CodeReuse/ActiveRecord
iid: issuable.iid.to_s,
@@ -261,6 +268,16 @@ module IssuablesHelper
canCreateIncident: create_issue_type_allowed?(issuable.project, :incident),
**incident_only_initial_data(issuable)
}
+
+ data.tap do |d|
+ if issuable.duplicated? && can?(current_user, :read_issue, issuable.duplicated_to)
+ d[:duplicatedToIssueUrl] = url_for([issuable.duplicated_to.project, issuable.duplicated_to, { only_path: false }])
+ end
+
+ if issuable.moved? && can?(current_user, :read_issue, issuable.moved_to)
+ d[:movedToIssueUrl] = url_for([issuable.moved_to.project, issuable.moved_to, { only_path: false }])
+ end
+ end
end
def incident_only_initial_data(issue)
@@ -366,16 +383,6 @@ module IssuablesHelper
end
end
- def hidden_issuable_icon(issuable)
- title = format(
- _('This %{issuable} is hidden because its author has been banned'),
- issuable: issuable.is_a?(Issue) ? _('issue') : _('merge request')
- )
- content_tag(:span, class: 'has-tooltip', title: title) do
- sprite_icon('spam', css_class: 'gl-vertical-align-text-bottom')
- end
- end
-
def issuable_type_selector_data(issuable)
{
selected_type: issuable.issue_type,
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index d9b9b27d16c..ed655b562c2 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -55,7 +55,7 @@ module IssuesHelper
def hidden_issue_icon(issue)
return unless issue_hidden?(issue)
- hidden_issuable_icon(issue)
+ hidden_resource_icon(issue)
end
def award_user_list(awards, current_user, limit: 10)
@@ -195,7 +195,8 @@ module IssuesHelper
is_signed_in: current_user.present?.to_s,
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
rss_path: url_for(safe_params.merge(rss_url_options)),
- sign_in_path: new_user_session_path
+ sign_in_path: new_user_session_path,
+ has_issue_date_filter_feature: Feature.enabled?(:issue_date_filter, namespace).to_s
}
end
@@ -220,7 +221,9 @@ module IssuesHelper
quick_actions_help_path: help_page_path('user/project/quick_actions'),
releases_path: project_releases_path(project, format: :json),
reset_path: new_issuable_address_project_path(project, issuable_type: 'issue'),
- show_new_issue_link: show_new_issue_link?(project).to_s
+ show_new_issue_link: show_new_issue_link?(project).to_s,
+ report_abuse_path: add_category_abuse_reports_path,
+ register_path: new_user_registration_path(redirect_to_referer: 'yes')
)
end
diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb
index 5cf68db0611..2309dfc2a2b 100644
--- a/app/helpers/jira_connect_helper.rb
+++ b/app/helpers/jira_connect_helper.rb
@@ -5,7 +5,7 @@ module JiraConnectHelper
skip_groups = subscriptions.map(&:namespace_id)
{
- groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }),
+ groups_path: api_v4_groups_path(params: { skip_groups: skip_groups }),
subscriptions: subscriptions.map { |s| serialize_subscription(s) }.to_json,
subscriptions_path: jira_connect_subscriptions_path(format: :json),
gitlab_user_path: current_user ? user_path(current_user) : nil,
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index c4967a42a45..79bab0969d1 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -46,11 +46,11 @@ module LabelsHelper
end
end
- def render_label(label, link: nil, tooltip: true, dataset: nil, small: false)
+ def render_label(label, link: nil, tooltip: true, dataset: nil, small: false, tooltip_shows_title: false)
html = render_colored_label(label)
if link
- title = label_tooltip_title(label) if tooltip
+ title = label_tooltip_title(label, tooltip_shows_title: tooltip_shows_title) if tooltip
html = render_label_link(html, link: link, title: title, dataset: dataset)
end
@@ -74,8 +74,8 @@ module LabelsHelper
%(<span class="#{wrapper_classes.join(' ')}">#{label_html}</span>).html_safe
end
- def label_tooltip_title(label)
- Sanitize.clean(label.description)
+ def label_tooltip_title(label, tooltip_shows_title: false)
+ Sanitize.clean(tooltip_shows_title ? label.title : label.description)
end
def suggested_colors
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index 91fce6d6820..1a44f3554b0 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -110,8 +110,8 @@ module MarkupHelper
prepare_asciidoc_context(file_name, context)
html = Markup::RenderingService
- .new(text, file_name: file_name, context: context, postprocess_context: postprocess_context)
- .execute
+ .new(text, file_name: file_name, context: context, postprocess_context: postprocess_context)
+ .execute
Hamlit::RailsHelpers.preserve(html)
end
@@ -124,8 +124,8 @@ module MarkupHelper
prepare_asciidoc_context(wiki_page.path, context)
html = Markup::RenderingService
- .new(text, file_name: wiki_page.path, context: context, postprocess_context: postprocess_context)
- .execute
+ .new(text, file_name: wiki_page.path, context: context, postprocess_context: postprocess_context)
+ .execute
Hamlit::RailsHelpers.preserve(html)
end
@@ -192,15 +192,21 @@ module MarkupHelper
def markdown_toolbar_button(options = {})
data = options[:data].merge({ container: 'body' })
- css_classes = %w[gl-button btn btn-default-tertiary btn-icon btn-sm js-md has-tooltip] << options[:css_class].to_s
- content_tag :button,
- type: 'button',
- class: css_classes.join(' '),
- data: data,
- title: options[:title],
- aria: { label: options[:title] } do
- sprite_icon(options[:icon])
- end
+ css_classes = %w[js-md has-tooltip] << options[:css_class].to_s
+
+ render Pajamas::ButtonComponent.new(
+ category: :tertiary,
+ size: :small,
+ icon: options[:icon],
+ button_options: {
+ class: css_classes.join(' '),
+ data: data,
+ title: options[:title],
+ aria: {
+ label: options[:title]
+ }
+ }
+ )
end
def render_markdown_field(object, field, context = {})
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index af1c85532c3..32a183d6cd8 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -303,12 +303,16 @@ module MergeRequestsHelper
def hidden_merge_request_icon(merge_request)
return unless merge_request.hidden?
- hidden_issuable_icon(merge_request)
+ hidden_resource_icon(merge_request)
end
def tab_count_display(merge_request, count)
merge_request.preparing? ? "-" : count
end
+
+ def review_bar_data(_merge_request, _user)
+ { new_comment_template_path: profile_comment_templates_path }
+ end
end
MergeRequestsHelper.prepend_mod_with('MergeRequestsHelper')
diff --git a/app/helpers/mirror_helper.rb b/app/helpers/mirror_helper.rb
index 06deaeb5e9e..158aa5e0944 100644
--- a/app/helpers/mirror_helper.rb
+++ b/app/helpers/mirror_helper.rb
@@ -15,6 +15,11 @@ module MirrorHelper
html_escape(_('Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH.')) %
{ docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
end
+
+ def mirrored_repositories_count
+ count = @project.mirror == true ? 1 : 0
+ count + @project.remote_mirrors.to_a.count(&:enabled)
+ end
end
MirrorHelper.prepend_mod_with('MirrorHelper')
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index c7864c1d45f..4cbd5029ac9 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -90,7 +90,7 @@ module NavHelper
# The new sidebar is not enabled for anonymous use
# Once we enable the new sidebar by default, this
# should return true
- return false unless user
+ return Feature.enabled?(:super_sidebar_logged_out) unless user
# Users who got the special `super_sidebar_nav_enrolled` enabled,
# see the new nav as long as they don't explicitly opt-out via the toggle
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 3e8872dc199..af8da86b391 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -178,6 +178,10 @@ module NotesHelper
def notes_data(issuable)
data = {
+ noteableType: @noteable.class.underscore,
+ noteableId: @noteable.id,
+ projectId: @project&.id,
+ groupId: @group&.id,
discussionsPath: discussions_path(issuable),
registerPath: new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'),
newSessionPath: new_session_path(:user, redirect_to_referer: 'yes'),
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index 31fcc77925b..fefc19d7c1a 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -16,7 +16,7 @@ module PackagesHelper
end
def package_registry_project_url(project_id, registry_type = :maven)
- project_api_path = expose_path(api_v4_projects_path(id: project_id))
+ project_api_path = api_v4_projects_path(id: project_id)
package_registry_project_path = "#{project_api_path}/packages/#{registry_type}"
expose_url(package_registry_project_path)
end
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 26463003f8d..05605394d57 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -73,6 +73,21 @@ module ProfilesHelper
def prevent_delete_account?
false
end
+
+ def user_profile_data(user)
+ {
+ profile_path: profile_path,
+ profile_avatar_path: profile_avatar_path,
+ avatar_url: avatar_icon_for_user(user, current_user: current_user),
+ has_avatar: user.avatar?.to_s,
+ gravatar_enabled: gravatar_enabled?.to_s,
+ gravatar_link: { hostname: Gitlab.config.gravatar.host, url: "https://#{Gitlab.config.gravatar.host}" }.to_json,
+ brand_profile_image_guidelines: current_appearance&.profile_image_guidelines? ? brand_profile_image_guidelines : '',
+ cropper_css_path: ActionController::Base.helpers.stylesheet_path('lazy_bundles/cropper.css'),
+ user_path: user_path(current_user),
+ **user_status_properties(user)
+ }
+ end
end
ProfilesHelper.prepend_mod
diff --git a/app/helpers/projects/cluster_agents_helper.rb b/app/helpers/projects/cluster_agents_helper.rb
index f62f5eadfb4..d285cfa03c2 100644
--- a/app/helpers/projects/cluster_agents_helper.rb
+++ b/app/helpers/projects/cluster_agents_helper.rb
@@ -6,7 +6,7 @@ module Projects::ClusterAgentsHelper
activity_empty_state_image: image_path('illustrations/empty-state/empty-state-agents.svg'),
agent_name: agent_name,
can_admin_vulnerability: can?(current_user, :admin_vulnerability, project).to_s,
- empty_state_svg_path: image_path('illustrations/operations-dashboard_empty.svg'),
+ empty_state_svg_path: image_path('illustrations/empty-state/empty-radar-md.svg'),
project_path: project.full_path,
kas_address: Gitlab::Kas.external_url,
kas_version: Gitlab::Kas.version_info,
diff --git a/app/helpers/projects/observability_helper.rb b/app/helpers/projects/observability_helper.rb
index 24bc1928a36..4515fdb1bc3 100644
--- a/app/helpers/projects/observability_helper.rb
+++ b/app/helpers/projects/observability_helper.rb
@@ -9,5 +9,15 @@ module Projects
oauthUrl: Gitlab::Observability.oauth_url
})
end
+
+ def observability_tracing_details_model(project, trace_id)
+ Gitlab::Json.generate({
+ tracingIndexUrl: namespace_project_tracing_index_path(project.group, project),
+ traceId: trace_id,
+ tracingUrl: Gitlab::Observability.tracing_url(project),
+ provisioningUrl: Gitlab::Observability.provisioning_url(project),
+ oauthUrl: Gitlab::Observability.oauth_url
+ })
+ end
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index e27ee1acb22..754e1b7c2a2 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -464,14 +464,23 @@ module ProjectsHelper
project.forking_enabled? && can?(user, :read_code, project)
end
- def fork_button_disabled_tooltip(project)
+ def fork_button_data_attributes(project)
return unless current_user
- if !current_user.can?(:fork_project, project)
- s_("ProjectOverview|You don't have permission to fork this project")
- elsif !current_user.can?(:create_fork)
- s_('ProjectOverview|You have reached your project limit')
+ if current_user.already_forked?(project) && current_user.forkable_namespaces.size < 2
+ user_fork_url = namespace_project_path(current_user, current_user.fork_of(project))
end
+
+ {
+ forks_count: project.forks_count,
+ project_full_path: project.full_path,
+ project_forks_url: project_forks_path(project),
+ user_fork_url: user_fork_url,
+ new_fork_url: new_project_fork_path(project),
+ can_read_code: can?(current_user, :read_code, project).to_s,
+ can_fork_project: can?(current_user, :fork_project, project).to_s,
+ can_create_fork: can?(current_user, :create_fork).to_s
+ }
end
def import_from_bitbucket_message
@@ -551,6 +560,20 @@ module ProjectsHelper
project_settings_repository_path(@project, anchor: 'js-branch-rules')
end
+ def visibility_level_content(project, css_class: nil, icon_css_class: nil)
+ if project.created_and_owned_by_banned_user? && Feature.enabled?(:hide_projects_of_banned_users)
+ return hidden_resource_icon(project, css_class: css_class)
+ end
+
+ title = visibility_icon_description(project)
+ container_class = ['has-tooltip', css_class].compact.join(' ')
+ data = { container: 'body', placement: 'top' }
+
+ content_tag(:span, class: container_class, data: data, title: title) do
+ visibility_level_icon(project.visibility_level, options: { class: icon_css_class })
+ end
+ end
+
private
def can_admin_project_clusters?(project)
@@ -706,6 +729,7 @@ module ProjectsHelper
{
packagesEnabled: !!project.packages_enabled,
packageRegistryAccessLevel: feature.package_registry_access_level,
+ packageRegistryAllowAnyoneToPullOption: ::Gitlab::CurrentSettings.package_registry_allow_anyone_to_pull_option,
visibilityLevel: project.visibility_level,
requestAccessEnabled: !!project.request_access_enabled,
issuesAccessLevel: feature.issues_access_level,
@@ -719,7 +743,7 @@ module ProjectsHelper
analyticsAccessLevel: feature.analytics_access_level,
containerRegistryEnabled: !!project.container_registry_enabled,
lfsEnabled: !!project.lfs_enabled,
- emailsDisabled: project.emails_disabled?,
+ emailsEnabled: project.emails_enabled?,
monitorAccessLevel: feature.monitor_access_level,
showDefaultAwardEmojis: project.show_default_award_emojis?,
warnAboutPotentiallyUnwantedCharacters: project.warn_about_potentially_unwanted_characters?,
diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb
index 9ef347fff16..cf5cc92587f 100644
--- a/app/helpers/sessions_helper.rb
+++ b/app/helpers/sessions_helper.rb
@@ -40,10 +40,6 @@ module SessionsHelper
request.env['rack.session.options'][:expire_after] = expiry_s
end
- def send_rate_limited?(user)
- Gitlab::ApplicationRateLimiter.peek(:email_verification_code_send, scope: user)
- end
-
def obfuscated_email(email)
# Moved to Gitlab::Utils::Email in 15.9
Gitlab::Utils::Email.obfuscated_email(email)
@@ -52,4 +48,23 @@ module SessionsHelper
def remember_me_enabled?
Gitlab::CurrentSettings.remember_me_enabled?
end
+
+ def unconfirmed_verification_email?(user)
+ token_valid_from = ::Users::EmailVerification::ValidateTokenService::TOKEN_VALID_FOR_MINUTES.minutes.ago
+ user.email_reset_offered_at.nil? && user.pending_reconfirmation? && user.confirmation_sent_at >= token_valid_from
+ end
+
+ def verification_email(user)
+ unconfirmed_verification_email?(user) ? user.unconfirmed_email : user.email
+ end
+
+ def verification_data(user)
+ {
+ obfuscated_email: obfuscated_email(verification_email(user)),
+ verify_path: session_path(:user),
+ resend_path: users_resend_verification_code_path,
+ offer_email_reset: user.email_reset_offered_at.nil?.to_s,
+ update_email_path: users_update_email_path
+ }
+ end
end
diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb
index 90917cb96e0..1bd7da0a352 100644
--- a/app/helpers/sidebars_helper.rb
+++ b/app/helpers/sidebars_helper.rb
@@ -45,14 +45,37 @@ module SidebarsHelper
end
def super_sidebar_context(user, group:, project:, panel:, panel_type:) # rubocop:disable Metrics/AbcSize
+ return super_sidebar_logged_out_context(panel: panel, panel_type: panel_type) unless user
+
+ super_sidebar_logged_in_context(user, group: group, project: project, panel: panel, panel_type: panel_type)
+ end
+
+ def super_sidebar_logged_out_context(panel:, panel_type:) # rubocop:disable Metrics/AbcSize
{
+ is_logged_in: false,
+ context_switcher_links: context_switcher_links,
current_menu_items: panel.super_sidebar_menu_items,
current_context_header: panel.super_sidebar_context_header,
+ support_path: support_url,
+ display_whats_new: display_whats_new?,
+ whats_new_most_recent_release_items_count: whats_new_most_recent_release_items_count,
+ whats_new_version_digest: whats_new_version_digest,
+ show_version_check: show_version_check?,
+ gitlab_version: Gitlab.version_info,
+ gitlab_version_check: gitlab_version_check,
+ search: search_data,
+ panel_type: panel_type
+ }
+ end
+
+ def super_sidebar_logged_in_context(user, group:, project:, panel:, panel_type:) # rubocop:disable Metrics/AbcSize
+ super_sidebar_logged_out_context(panel: panel, panel_type: panel_type).merge({
+ is_logged_in: true,
name: user.name,
username: user.username,
avatar_url: user.avatar_url,
has_link_to_profile: current_user_menu?(:profile),
- link_to_profile: user_url(user),
+ link_to_profile: user_path(user),
logo_url: current_appearance&.header_logo_path,
status: user_status_menu_data(user),
settings: {
@@ -75,26 +98,16 @@ module SidebarsHelper
merge_request_menu: create_merge_request_menu(user),
projects_path: dashboard_projects_path,
groups_path: dashboard_groups_path,
- support_path: support_url,
- display_whats_new: display_whats_new?,
- whats_new_most_recent_release_items_count: whats_new_most_recent_release_items_count,
- whats_new_version_digest: whats_new_version_digest,
- show_version_check: show_version_check?,
- gitlab_version: Gitlab.version_info,
- gitlab_version_check: gitlab_version_check,
gitlab_com_but_not_canary: Gitlab.com_but_not_canary?,
gitlab_com_and_canary: Gitlab.com_and_canary?,
canary_toggle_com_url: Gitlab::Saas.canary_toggle_com_url,
current_context: super_sidebar_current_context(project: project, group: group),
- context_switcher_links: context_switcher_links,
- search: search_data,
pinned_items: user.pinned_nav_items[panel_type] || super_sidebar_default_pins(panel_type),
- panel_type: panel_type,
- update_pins_url: pins_url,
+ update_pins_url: pins_path,
is_impersonating: impersonating?,
stop_impersonation_path: admin_impersonation_path,
shortcut_links: shortcut_links(user, project: project)
- }
+ })
end
def super_sidebar_nav_panel(
@@ -331,8 +344,7 @@ module SidebarsHelper
def context_switcher_links
links = [
- # We should probably not return "You work" when used is not logged-in
- { title: s_('Navigation|Your work'), link: root_path, icon: 'work' },
+ ({ title: s_('Navigation|Your work'), link: root_path, icon: 'work' } if current_user),
{ title: s_('Navigation|Explore'), link: explore_root_path, icon: 'compass' }
]
@@ -368,7 +380,7 @@ module SidebarsHelper
end
# rubocop: enable Cop/UserAdmin
- links
+ links.compact
end
def impersonating?
diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb
index 2f9117a74be..31ce8317d51 100644
--- a/app/helpers/snippets_helper.rb
+++ b/app/helpers/snippets_helper.rb
@@ -45,36 +45,26 @@ module SnippetsHelper
def embedded_raw_snippet_button(snippet, blob)
return if blob.empty? || blob.binary? || blob.stored_externally?
- link_to(
- external_snippet_icon('doc-code'),
- gitlab_raw_snippet_blob_url(snippet, blob.path),
- class: 'gl-button btn btn-default',
- target: '_blank',
- rel: 'noopener noreferrer',
- title: 'Open raw'
- )
+ render Pajamas::ButtonComponent.new(href: gitlab_raw_snippet_blob_url(snippet, blob.path), target: '_blank',
+ button_options: { rel: 'noopener noreferrer', title: 'Open raw' }) do
+ external_snippet_icon('doc-code')
+ end
end
def embedded_snippet_download_button(snippet, blob)
- link_to(
- external_snippet_icon('download'),
- gitlab_raw_snippet_blob_url(snippet, blob.path, nil, inline: false),
- class: 'gl-button btn btn-default',
- target: '_blank',
- title: 'Download',
- rel: 'noopener noreferrer'
- )
+ render Pajamas::ButtonComponent.new(href: gitlab_raw_snippet_blob_url(snippet, blob.path, nil, inline: false),
+ target: '_blank', button_options: { rel: 'noopener noreferrer', title: 'Download' }) do
+ external_snippet_icon('download')
+ end
end
def embedded_copy_snippet_button(blob)
return unless blob.rendered_as_text?(ignore_errors: false)
- content_tag(
- :button,
- class: 'gl-button btn btn-default copy-to-clipboard-btn',
- title: 'Copy snippet contents',
- onclick: "copyToClipboard('.blob-content[data-blob-id=\"#{blob.id}\"] > pre')"
- ) do
+ button_options = { title: 'Copy snippet contents',
+ onclick: "copyToClipboard('.blob-content[data-blob-id=\"#{blob.id}\"] > pre')" }
+
+ render Pajamas::ButtonComponent.new(button_options: button_options) do
external_snippet_icon('copy-to-clipboard')
end
end
diff --git a/app/helpers/time_helper.rb b/app/helpers/time_helper.rb
index ad473875a53..0a5751c5221 100644
--- a/app/helpers/time_helper.rb
+++ b/app/helpers/time_helper.rb
@@ -1,20 +1,20 @@
# frozen_string_literal: true
module TimeHelper
+ TIME_UNIT_TRANSLATION = {
+ seconds: ->(seconds) { n_('%d second', '%d seconds', seconds) % seconds },
+ minutes: ->(minutes) { n_('%d minute', '%d minutes', minutes) % minutes },
+ hours: ->(hours) { n_('%d hour', '%d hours', hours) % hours },
+ days: ->(days) { n_('%d day', '%d days', days) % days },
+ weeks: ->(weeks) { n_('%d week', '%d weeks', weeks) % weeks },
+ months: ->(months) { n_('%d month', '%d months', months) % months },
+ years: ->(years) { n_('%d year', '%d years', years) % years }
+ }.freeze
+
def time_interval_in_words(interval_in_seconds)
- interval_in_seconds = interval_in_seconds.to_i
- minutes = interval_in_seconds / 60
- seconds = interval_in_seconds - minutes * 60
+ time_parts = ActiveSupport::Duration.build(interval_in_seconds.to_i).parts
- if minutes >= 1
- if seconds % 60 == 0
- n_('%d minute', '%d minutes', minutes) % minutes
- else
- [n_('%d minute', '%d minutes', minutes) % minutes, n_('%d second', '%d seconds', seconds) % seconds].to_sentence
- end
- else
- n_('%d second', '%d seconds', seconds) % seconds
- end
+ time_parts.map { |unit, value| TIME_UNIT_TRANSLATION[unit].call(value) }.to_sentence
end
def duration_in_numbers(duration_in_seconds)
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index 9b0810f3d17..4f17634f3e4 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -30,6 +30,7 @@ module TodosHelper
when Todo::MEMBER_ACCESS_REQUESTED then format(
s_("Todos|has requested access to %{what} %{which}"), what: _(todo.member_access_type), which: _(todo.target.name)
)
+ when Todo::REVIEW_SUBMITTED then s_('Todos|reviewed your merge request')
end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 84512453b7c..880fb8aa9d8 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -153,7 +153,8 @@ module TreeHelper
project_short_path: project.path,
ref: ref,
escaped_ref: ActionDispatch::Journey::Router::Utils.escape_path(ref),
- full_name: project.name_with_namespace
+ full_name: project.name_with_namespace,
+ ref_type: @ref_type
}
end
diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb
index 0f4cbd6642b..12f78d9bd16 100644
--- a/app/helpers/users/callouts_helper.rb
+++ b/app/helpers/users/callouts_helper.rb
@@ -89,6 +89,8 @@ module Users
end
def gitlab_com_user_created_after_new_nav_rollout?
+ return true unless current_user
+
Gitlab.com? && current_user.created_at >= Date.new(2023, 6, 2)
end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 29998a996e2..ac279904fd2 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -104,6 +104,24 @@ module UsersHelper
Gitlab.config.gitlab.impersonation_enabled
end
+ def can_impersonate_user(user, impersonation_in_progress)
+ can?(user, :log_in) && !user.password_expired? && !impersonation_in_progress
+ end
+
+ def impersonation_error_text(user, impersonation_in_progress)
+ if impersonation_in_progress
+ _("You are already impersonating another user")
+ elsif user.blocked?
+ _("You cannot impersonate a blocked user")
+ elsif user.password_expired?
+ _("You cannot impersonate a user with an expired password")
+ elsif user.internal?
+ _("You cannot impersonate an internal user")
+ else
+ _("You cannot impersonate a user who cannot log in")
+ end
+ end
+
def user_badges_in_admin_section(user)
[].tap do |badges|
badges << blocked_user_badge(user) if user.blocked?
@@ -208,6 +226,24 @@ module UsersHelper
end
end
+ def user_profile_actions_data(user)
+ basic_actions_data = {
+ user_id: user.id
+ }
+
+ if can?(current_user, :read_user_profile, user)
+ basic_actions_data[:rss_subscription_path] = user_path(user, rss_url_options)
+ end
+
+ return basic_actions_data if !current_user || current_user == user
+
+ basic_actions_data.merge(
+ report_abuse_path: add_category_abuse_reports_path,
+ reported_user_id: user.id,
+ reported_from_url: user_url(user)
+ )
+ end
+
private
def admin_users_paths