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-03-20 18:19:03 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-20 18:19:03 +0300
commit14bd84b61276ef29b97d23642d698de769bacfd2 (patch)
treef9eba90140c1bd874211dea17750a0d422c04080 /app/helpers
parent891c388697b2db0d8ee0c8358a9bdbf6dc56d581 (diff)
Add latest changes from gitlab-org/gitlab@15-10-stable-eev15.10.0-rc42
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/admin/abuse_reports_helper.rb19
-rw-r--r--app/helpers/analytics/cycle_analytics_helper.rb29
-rw-r--r--app/helpers/application_helper.rb22
-rw-r--r--app/helpers/application_settings_helper.rb17
-rw-r--r--app/helpers/artifacts_helper.rb1
-rw-r--r--app/helpers/blob_helper.rb30
-rw-r--r--app/helpers/ci/catalog/resources_helper.rb15
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb2
-rw-r--r--app/helpers/ci/status_helper.rb4
-rw-r--r--app/helpers/commits_helper.rb45
-rw-r--r--app/helpers/dashboard_helper.rb13
-rw-r--r--app/helpers/device_registration_helper.rb11
-rw-r--r--app/helpers/diff_helper.rb6
-rw-r--r--app/helpers/dropdowns_helper.rb2
-rw-r--r--app/helpers/events_helper.rb46
-rw-r--r--app/helpers/explore_helper.rb2
-rw-r--r--app/helpers/feature_flags_helper.rb6
-rw-r--r--app/helpers/groups/observability_helper.rb19
-rw-r--r--app/helpers/groups_helper.rb1
-rw-r--r--app/helpers/ide_helper.rb22
-rw-r--r--app/helpers/issuables_helper.rb12
-rw-r--r--app/helpers/jira_connect_helper.rb2
-rw-r--r--app/helpers/markup_helper.rb21
-rw-r--r--app/helpers/merge_requests_helper.rb5
-rw-r--r--app/helpers/mirror_helper.rb2
-rw-r--r--app/helpers/nav/new_dropdown_helper.rb38
-rw-r--r--app/helpers/nav/top_nav_helper.rb72
-rw-r--r--app/helpers/nav_helper.rb35
-rw-r--r--app/helpers/notes_helper.rb7
-rw-r--r--app/helpers/operations_helper.rb2
-rw-r--r--app/helpers/packages_helper.rb11
-rw-r--r--app/helpers/page_layout_helper.rb2
-rw-r--r--app/helpers/plan_limits_helper.rb28
-rw-r--r--app/helpers/projects/error_tracking_helper.rb3
-rw-r--r--app/helpers/projects/settings/branch_rules_helper.rb23
-rw-r--r--app/helpers/projects_helper.rb17
-rw-r--r--app/helpers/registrations_helper.rb4
-rw-r--r--app/helpers/routing/projects_helper.rb7
-rw-r--r--app/helpers/search_helper.rb4
-rw-r--r--app/helpers/sidebars_helper.rb112
-rw-r--r--app/helpers/snippets_helper.rb37
-rw-r--r--app/helpers/sorting_helper.rb6
-rw-r--r--app/helpers/system_note_helper.rb2
-rw-r--r--app/helpers/todos_helper.rb14
-rw-r--r--app/helpers/users/callouts_helper.rb35
-rw-r--r--app/helpers/users/group_callouts_helper.rb8
-rw-r--r--app/helpers/users_helper.rb34
-rw-r--r--app/helpers/visibility_level_helper.rb5
-rw-r--r--app/helpers/web_hooks/web_hooks_helper.rb22
-rw-r--r--app/helpers/work_items_helper.rb3
50 files changed, 609 insertions, 276 deletions
diff --git a/app/helpers/admin/abuse_reports_helper.rb b/app/helpers/admin/abuse_reports_helper.rb
new file mode 100644
index 00000000000..3218ecfd1db
--- /dev/null
+++ b/app/helpers/admin/abuse_reports_helper.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Admin
+ module AbuseReportsHelper
+ def abuse_reports_list_data(reports)
+ {
+ abuse_reports_data: {
+ categories: AbuseReport.categories.keys,
+ reports: Admin::AbuseReportSerializer.new.represent(reports),
+ pagination: {
+ current_page: reports.current_page,
+ per_page: reports.limit_value,
+ total_items: reports.total_count
+ }
+ }.to_json
+ }
+ end
+ end
+end
diff --git a/app/helpers/analytics/cycle_analytics_helper.rb b/app/helpers/analytics/cycle_analytics_helper.rb
deleted file mode 100644
index 35a5d4f469d..00000000000
--- a/app/helpers/analytics/cycle_analytics_helper.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Analytics
- module CycleAnalyticsHelper
- def cycle_analytics_default_stage_config
- Gitlab::Analytics::CycleAnalytics::DefaultStages.all.map do |stage_params|
- Analytics::CycleAnalytics::StagePresenter.new(stage_params)
- end
- end
-
- def cycle_analytics_initial_data(project, group = nil)
- base_data = { project_id: project.id, group_path: project.group&.path, request_path: project_cycle_analytics_path(project), full_path: project.full_path }
- svgs = { empty_state_svg_path: image_path("illustrations/analytics/cycle-analytics-empty-chart.svg"), no_data_svg_path: image_path("illustrations/analytics/cycle-analytics-empty-chart.svg"), no_access_svg_path: image_path("illustrations/analytics/no-access.svg") }
- api_paths = group.present? ? cycle_analytics_group_api_paths(group) : cycle_analytics_project_api_paths(project)
-
- base_data.merge(svgs, api_paths)
- end
-
- private
-
- def cycle_analytics_group_api_paths(group)
- { milestones_path: group_milestones_path(group, format: :json), labels_path: group_labels_path(group, format: :json), group_path: group_path(group), group_id: group&.id }
- end
-
- def cycle_analytics_project_api_paths(project)
- { milestones_path: project_milestones_path(project, format: :json), labels_path: project_labels_path(project, format: :json), group_path: project.parent&.path, group_id: project.parent&.id }
- end
- end
-end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 93b7c8c0b94..d0602952f9a 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -181,14 +181,14 @@ module ApplicationHelper
css_classes << html_class unless html_class.blank?
content_tag :time, l(time, format: "%b %d, %Y"),
- class: css_classes.join(' '),
- title: l(time.to_time.in_time_zone, format: :timeago_tooltip),
- datetime: time.to_time.getutc.iso8601,
- data: {
- toggle: 'tooltip',
- placement: placement,
- container: 'body'
- }
+ class: css_classes.join(' '),
+ title: l(time.to_time.in_time_zone, format: :timeago_tooltip),
+ datetime: time.to_time.getutc.iso8601,
+ data: {
+ toggle: 'tooltip',
+ placement: placement,
+ container: 'body'
+ }
end
def edited_time_ago_with_tooltip(object, placement: 'top', html_class: 'time_ago', exclude_author: false)
@@ -200,7 +200,7 @@ module ApplicationHelper
if !exclude_author && object.last_edited_by
output << content_tag(:span, ' by ')
- output << link_to_member(object.project, object.last_edited_by, avatar: false, author_class: nil)
+ output << link_to_member(object.project, object.last_edited_by, avatar: false, extra_class: 'gl-hover-text-decoration-underline', author_class: nil)
end
output
@@ -374,6 +374,10 @@ module ApplicationHelper
cookies["sidebar_collapsed"] == "true"
end
+ def collapsed_super_sidebar?
+ cookies["super_sidebar_collapsed"] == "true"
+ end
+
def locale_path
asset_path("locale/#{Gitlab::I18n.locale}/app.js")
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 3abaae98c29..fd684ee5ecb 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -4,11 +4,11 @@ module ApplicationSettingsHelper
extend self
delegate :allow_signup?,
- :gravatar_enabled?,
- :password_authentication_enabled_for_web?,
- :akismet_enabled?,
- :spam_check_endpoint_enabled?,
- to: :'Gitlab::CurrentSettings.current_application_settings'
+ :gravatar_enabled?,
+ :password_authentication_enabled_for_web?,
+ :akismet_enabled?,
+ :spam_check_endpoint_enabled?,
+ to: :'Gitlab::CurrentSettings.current_application_settings'
def user_oauth_applications?
Gitlab::CurrentSettings.user_oauth_applications
@@ -248,7 +248,9 @@ module ApplicationSettingsHelper
:default_project_visibility,
:default_projects_limit,
:default_snippet_visibility,
+ :default_syntax_highlighting_theme,
:delete_inactive_projects,
+ :deny_all_requests_except_allowed,
:disable_admin_oauth_scopes,
:disable_feed_token,
:disabled_oauth_sign_in_sources,
@@ -401,6 +403,7 @@ module ApplicationSettingsHelper
:protected_paths_raw,
:time_tracking_limit_to_hours,
:two_factor_grace_period,
+ :update_runner_versions_enabled,
:unique_ips_limit_enabled,
:unique_ips_limit_per_user,
:unique_ips_limit_time_window,
@@ -478,7 +481,9 @@ module ApplicationSettingsHelper
:bulk_import_enabled,
:allow_runner_registration_token,
:user_defaults_to_private_profile,
- :deactivation_email_additional_text
+ :deactivation_email_additional_text,
+ :projects_api_rate_limit_unauthenticated,
+ :gitlab_dedicated_instance
].tap do |settings|
next if Gitlab.com?
diff --git a/app/helpers/artifacts_helper.rb b/app/helpers/artifacts_helper.rb
index df0432105d5..f90d59409ed 100644
--- a/app/helpers/artifacts_helper.rb
+++ b/app/helpers/artifacts_helper.rb
@@ -4,6 +4,7 @@ module ArtifactsHelper
def artifacts_app_data(project)
{
project_path: project.full_path,
+ project_id: project.id,
can_destroy_artifacts: can?(current_user, :destroy_artifacts, project).to_s,
artifacts_management_feedback_image_path: image_path('illustrations/chat-bubble-sm.svg')
}
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 281d5c923d0..bb6fd6c3dad 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -2,9 +2,7 @@
module BlobHelper
def edit_blob_path(project = @project, ref = @ref, path = @path, options = {})
- project_edit_blob_path(project,
- tree_join(ref, path),
- options[:link_opts])
+ project_edit_blob_path(project, tree_join(ref, path), options[:link_opts])
end
def ide_edit_path(project = @project, ref = @ref, path = @path)
@@ -52,9 +50,11 @@ module BlobHelper
def fork_path_for_current_user(project, path, with_notice: true)
return unless current_user
- project_forks_path(project,
- namespace_key: current_user.namespace&.id,
- continue: edit_blob_fork_params(path, with_notice: with_notice))
+ project_forks_path(
+ project,
+ namespace_key: current_user.namespace&.id,
+ continue: edit_blob_fork_params(path, with_notice: with_notice)
+ )
end
def encode_ide_path(path)
@@ -66,12 +66,14 @@ module BlobHelper
common_classes = "btn gl-button btn-confirm js-edit-blob gl-ml-3 #{options[:extra_class]}"
- edit_button_tag(blob,
- common_classes,
- _('Edit'),
- edit_blob_path(project, ref, path, options),
- project,
- ref)
+ edit_button_tag(
+ blob,
+ common_classes,
+ _('Edit'),
+ edit_blob_path(project, ref, path, options),
+ project,
+ ref
+ )
end
def can_modify_blob?(blob, project = @project, ref = @ref)
@@ -282,8 +284,8 @@ module BlobHelper
fork_path = project_forks_path(project, namespace_key: current_user.namespace.id, continue: params)
button_tag label,
- class: "#{common_classes} js-edit-blob-link-fork-toggler",
- data: { action: action, fork_path: fork_path }
+ class: "#{common_classes} js-edit-blob-link-fork-toggler",
+ data: { action: action, fork_path: fork_path }
end
def edit_disabled_button_tag(button_text, common_classes)
diff --git a/app/helpers/ci/catalog/resources_helper.rb b/app/helpers/ci/catalog/resources_helper.rb
new file mode 100644
index 00000000000..46d78cd6b24
--- /dev/null
+++ b/app/helpers/ci/catalog/resources_helper.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Ci
+ module Catalog
+ module ResourcesHelper
+ def can_view_private_catalog?(_project)
+ false
+ end
+
+ def js_ci_catalog_data
+ {}
+ end
+ end
+ end
+end
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index 99a92ba9b59..4d1bdf5fa7f 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -18,12 +18,12 @@ module Ci
"ci-examples-help-page-path" => help_page_path('ci/examples/index'),
"ci-help-page-path" => help_page_path('ci/index'),
"ci-lint-path" => project_ci_lint_path(project),
+ "ci-troubleshooting-path" => help_page_path('ci/troubleshooting', anchor: 'common-cicd-issues'),
"default-branch" => project.default_branch_or_main,
"empty-state-illustration-path" => image_path('illustrations/empty-state/empty-dag-md.svg'),
"initial-branch-name" => initial_branch,
"includes-help-page-path" => help_page_path('ci/yaml/includes'),
"lint-help-page-path" => help_page_path('ci/lint', anchor: 'check-cicd-syntax'),
- "lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'),
"needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'),
"new-merge-request-path" => namespace_project_new_merge_request_path,
"pipeline_etag" => latest_commit ? graphql_etag_pipeline_sha_path(latest_commit.sha) : '',
diff --git a/app/helpers/ci/status_helper.rb b/app/helpers/ci/status_helper.rb
index bca49324a19..ea5b613cb78 100644
--- a/app/helpers/ci/status_helper.rb
+++ b/app/helpers/ci/status_helper.rb
@@ -131,10 +131,10 @@ module Ci
if path
link_to ci_icon_for_status(status, size: icon_size), path,
- class: klass, title: title, data: data
+ class: klass, title: title, data: data
else
content_tag :span, ci_icon_for_status(status, size: icon_size),
- class: klass, title: title, data: data
+ class: klass, title: title, data: data
end
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index f75d3657986..519508f1c02 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -27,12 +27,11 @@ module CommitsHelper
end
def commit_to_html(commit, ref, project)
- render partial: 'projects/commits/commit', formats: :html,
- locals: {
- commit: commit,
- ref: ref,
- project: project
- }
+ render partial: 'projects/commits/commit', formats: :html, locals: {
+ commit: commit,
+ ref: ref,
+ project: project
+ }
end
# Breadcrumb links for a Project and, if applicable, a tree path
@@ -161,17 +160,23 @@ module CommitsHelper
# This includes a keyed hash for values that can be nil, to prevent invalid cache entries
# being served if the order should change in future.
def commit_partial_cache_key(commit, ref:, merge_request:, request:)
+ keyed_hash = {
+ merge_request: merge_request&.cache_key,
+ pipeline_status: commit.detailed_status_for(ref)&.cache_key,
+ xhr: request.xhr?,
+ controller: controller.controller_path,
+ path: @path # referred to in #link_to_browse_code
+ }
+
+ if Feature.enabled?(:show_tags_on_commits_view, commit.project)
+ keyed_hash[:referenced_by] = tag_checksum(commit.referenced_by)
+ end
+
[
commit,
commit.author,
ref,
- {
- merge_request: merge_request&.cache_key,
- pipeline_status: commit.detailed_status_for(ref)&.cache_key,
- xhr: request.xhr?,
- controller: controller.controller_path,
- path: @path # referred to in #link_to_browse_code
- }
+ keyed_hash
]
end
@@ -188,16 +193,22 @@ 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
+ 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
sprite_icon(icon)
end
end
protected
+ def tag_checksum(tags_array)
+ ::Zlib.crc32(tags_array.sort.join)
+ end
+
# Private: Returns a link to a person. If the person has a matching user and
# is a member of the current @project it will link to the team member page.
# Otherwise it will link to the person email as specified in the commit.
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index f0e1f252917..0352f5a1dfc 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -40,9 +40,14 @@ module DashboardHelper
end)
if doc_href.present?
- link_to_doc = link_to(sprite_icon('question'), doc_href,
- class: 'gl-ml-2', title: _('Documentation'),
- target: '_blank', rel: 'noopener noreferrer')
+ link_to_doc = link_to(
+ sprite_icon('question'),
+ doc_href,
+ class: 'gl-ml-2',
+ title: _('Documentation'),
+ target: '_blank',
+ rel: 'noopener noreferrer'
+ )
concat(link_to_doc)
end
@@ -52,7 +57,7 @@ module DashboardHelper
private
def get_dashboard_nav_links
- links = [:projects, :groups, :snippets]
+ links = [:projects, :groups, :snippets, :your_work, :explore]
if can?(current_user, :read_cross_project)
links += [:activity, :milestones]
diff --git a/app/helpers/device_registration_helper.rb b/app/helpers/device_registration_helper.rb
new file mode 100644
index 00000000000..bbdcab76bf5
--- /dev/null
+++ b/app/helpers/device_registration_helper.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module DeviceRegistrationHelper
+ def device_registration_data(current_password_required:, target_path:, webauthn_error:)
+ {
+ initial_error: webauthn_error && webauthn_error[:message],
+ target_path: target_path,
+ password_required: current_password_required.to_s
+ }
+ end
+end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index e0a1697cfa9..c5df53ec606 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -34,6 +34,12 @@ module DiffHelper
options[:expanded] = true
options[:paths] = params.values_at(:old_path, :new_path)
options[:use_extra_viewer_as_main] = false
+
+ if Feature.enabled?(:large_ipynb_diffs, @project) && params[:file_identifier]&.include?('.ipynb')
+ options[:max_patch_bytes_for_file_extension] = {
+ '.ipynb' => 1.megabyte
+ }
+ end
end
options
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 427cbe18fbf..475ba3dcba8 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -54,7 +54,7 @@ module DropdownsHelper
default_label = data_attr[:default_label]
content_tag(:button, disabled: options[:disabled], class: "dropdown-menu-toggle #{options[:toggle_class] if options.key?(:toggle_class)}", id: (options[:id] if options.key?(:id)), type: "button", data: data_attr) do
output = content_tag(:span, toggle_text, class: "dropdown-toggle-text #{'is-default' if toggle_text == default_label}")
- output << sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon gl-top-3")
+ output << sprite_icon('chevron-down', css_class: "dropdown-menu-toggle-icon")
output.html_safe
end
end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index bef2da495b0..795d35ec81f 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -29,10 +29,11 @@ module EventsHelper
opened: s_('Event|opened'),
updated: s_('Event|updated'),
'removed due to membership expiration from': s_('Event|removed due to membership expiration from')
- }.merge(localized_push_action_name_map,
- localized_created_project_action_name_map,
- localized_design_action_names
- ).freeze
+ }.merge(
+ localized_push_action_name_map,
+ localized_created_project_action_name_map,
+ localized_design_action_names
+ ).freeze
end
def localized_push_action_name_map
@@ -183,13 +184,11 @@ module EventsHelper
def event_feed_url(event)
if event.issue?
- project_issue_url(event.project,
- event.issue)
+ project_issue_url(event.project, event.issue)
elsif event.merge_request?
project_merge_request_url(event.project, event.merge_request)
elsif event.commit_note?
- project_commit_url(event.project,
- event.note_target)
+ project_commit_url(event.project, event.note_target)
elsif event.note?
if event.note_target
event_note_target_url(event)
@@ -204,16 +203,12 @@ module EventsHelper
def push_event_feed_url(event)
if event.push_with_commits? && event.md_ref?
if event.commits_count > 1
- project_compare_url(event.project,
- from: event.commit_from, to:
- event.commit_to)
+ project_compare_url(event.project, from: event.commit_from, to: event.commit_to)
else
- project_commit_url(event.project,
- id: event.commit_to)
+ project_commit_url(event.project, id: event.commit_to)
end
elsif event.ref_name
- project_commits_url(event.project,
- event.ref_name)
+ project_commits_url(event.project, event.ref_name)
end
end
@@ -241,26 +236,31 @@ module EventsHelper
elsif event.design_note?
design_url(event.note_target, anchor: dom_id(event.note))
else
- polymorphic_url([event.project, event.note_target],
- anchor: dom_id(event.target))
+ polymorphic_url([event.project, event.note_target], anchor: dom_id(event.target))
end
end
def event_wiki_title_html(event)
capture do
concat content_tag(:span, _('wiki page'), class: "event-target-type gl-mr-2")
- concat link_to(event.target_title, event_wiki_page_target_url(event),
- title: event.target_title,
- class: 'has-tooltip event-target-link gl-mr-2')
+ concat link_to(
+ event.target_title,
+ event_wiki_page_target_url(event),
+ title: event.target_title,
+ class: 'has-tooltip event-target-link gl-mr-2'
+ )
end
end
def event_design_title_html(event)
capture do
concat content_tag(:span, _('design'), class: "event-target-type gl-mr-2")
- concat link_to(event.design.reference_link_text, design_url(event.design),
- title: event.target_title,
- class: 'has-tooltip event-design event-target-link gl-mr-2')
+ concat link_to(
+ event.design.reference_link_text,
+ design_url(event.design),
+ title: event.target_title,
+ class: 'has-tooltip event-design event-target-link gl-mr-2'
+ )
end
end
diff --git a/app/helpers/explore_helper.rb b/app/helpers/explore_helper.rb
index 2967501f628..ed24f2509e8 100644
--- a/app/helpers/explore_helper.rb
+++ b/app/helpers/explore_helper.rb
@@ -57,7 +57,7 @@ module ExploreHelper
private
def get_explore_nav_links
- [:projects, :groups, :snippets]
+ [:projects, :groups, :topics, :snippets]
end
def request_path_with_options(options = {})
diff --git a/app/helpers/feature_flags_helper.rb b/app/helpers/feature_flags_helper.rb
index 3dde29dce91..fe8d8e6b5d9 100644
--- a/app/helpers/feature_flags_helper.rb
+++ b/app/helpers/feature_flags_helper.rb
@@ -18,8 +18,10 @@ module FeatureFlagsHelper
feature_flags_path: project_feature_flags_path(@project),
environments_endpoint: search_project_environments_path(@project, format: :json),
strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
- environments_scope_docs_path: help_page_path('ci/environments/index.md',
- anchor: 'limit-the-environment-scope-of-a-cicd-variable')
+ environments_scope_docs_path: help_page_path(
+ 'ci/environments/index.md',
+ anchor: 'limit-the-environment-scope-of-a-cicd-variable'
+ )
}
end
end
diff --git a/app/helpers/groups/observability_helper.rb b/app/helpers/groups/observability_helper.rb
index 6cd6566cee1..7661817da7b 100644
--- a/app/helpers/groups/observability_helper.rb
+++ b/app/helpers/groups/observability_helper.rb
@@ -22,19 +22,8 @@ module Groups
}.freeze
def observability_iframe_src(group)
- # Format: https://observe.gitlab.com/GROUP_ID
-
- # When running Observability UI in standalone mode (i.e. not backed by Observability Backend)
- # the group-id is not required. This is mostly used for local dev
- base_url = ENV['STANDALONE_OBSERVABILITY_UI'] == 'true' ? observability_url : "#{observability_url}/-/#{group.id}"
-
- sanitized_path = if params[:observability_path] && sanitize(params[:observability_path]) != ''
- CGI.unescapeHTML(sanitize(params[:observability_path]))
- else
- observability_config_for(params).fetch(:path)
- end
-
- "#{base_url}#{sanitized_path}"
+ Gitlab::Observability.build_full_url(group, params[:observability_path],
+ observability_config_for(params).fetch(:path))
end
def observability_page_title
@@ -43,10 +32,6 @@ module Groups
private
- def observability_url
- Gitlab::Observability.observability_url
- end
-
def observability_config_for(params)
ACTION_TO_PATH.fetch(params[:action], ACTION_TO_PATH['dashboards'])
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 129871ca3fd..ce64ac1f21f 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -126,6 +126,7 @@ module GroupsHelper
def subgroup_creation_data(group)
{
+ parent_group_url: group.parent && group_url(group.parent),
parent_group_name: group.parent&.name,
import_existing_group_path: new_group_path(parent_id: group.parent_id, anchor: 'import-group-pane')
}
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index c5be044a27b..063eef41f77 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -1,20 +1,26 @@
# frozen_string_literal: true
module IdeHelper
- def ide_data(project:, branch:, path:, merge_request:, fork_info:)
- {
+ # Overridden in EE
+ def ide_data(project:, fork_info:, params:)
+ base_data = {
'can-use-new-web-ide' => can_use_new_web_ide?.to_s,
'use-new-web-ide' => use_new_web_ide?.to_s,
'new-web-ide-help-page-path' => help_page_path('user/project/web_ide/index.md', anchor: 'vscode-reimplementation'),
'user-preferences-path' => profile_preferences_path,
- 'branch-name' => branch,
- 'file-path' => path,
- 'fork-info' => fork_info&.to_json,
'editor-font-src-url' => font_url('jetbrains-mono/JetBrainsMono.woff2'),
'editor-font-family' => 'JetBrains Mono',
- 'editor-font-format' => 'woff2',
- 'merge-request' => merge_request
+ 'editor-font-format' => 'woff2'
}.merge(use_new_web_ide? ? new_ide_data(project: project) : legacy_ide_data(project: project))
+
+ return base_data unless project
+
+ base_data.merge(
+ 'fork-info' => fork_info&.to_json,
+ 'branch-name' => params[:branch],
+ 'file-path' => params[:path],
+ 'merge-request' => params[:merge_request_id]
+ )
end
def can_use_new_web_ide?
@@ -76,3 +82,5 @@ module IdeHelper
current_user.dismissed_callout?(feature_name: 'web_ide_ci_environments_guidance')
end
end
+
+IdeHelper.prepend_mod_with('IdeHelper')
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 46d2d2c42d9..9c68f54f42e 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -156,7 +156,7 @@ module IssuablesHelper
end
output << content_tag(:strong) do
- author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "d-none d-sm-inline")
+ author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "d-none d-sm-inline-block")
author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "d-inline d-sm-none")
author_output << issuable_meta_author_slot(issuable.author, css_class: 'ml-1')
@@ -281,7 +281,9 @@ module IssuablesHelper
{
hasLinkedAlerts: issue.alert_management_alerts.any?,
- canUpdateTimelineEvent: can?(current_user, :admin_incident_management_timeline_event, issue)
+ canUpdateTimelineEvent: can?(current_user, :admin_incident_management_timeline_event, issue),
+ currentPath: url_for(safe_params),
+ currentTab: safe_params[:incident_tab]
}
end
@@ -378,8 +380,10 @@ module IssuablesHelper
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'))
+ 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
diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb
index 50e3c3cc5fe..28b30ae051c 100644
--- a/app/helpers/jira_connect_helper.rb
+++ b/app/helpers/jira_connect_helper.rb
@@ -12,7 +12,7 @@ module JiraConnectHelper
users_path: current_user ? nil : jira_connect_users_path, # users_path is used to determine if user is signed in
gitlab_user_path: current_user ? user_path(current_user) : nil,
oauth_metadata: Feature.enabled?(:jira_connect_oauth, current_user) ? jira_connect_oauth_data(installation).to_json : nil,
- public_key_storage_enabled: Gitlab.config.jira_connect.enable_public_keys_storage || Gitlab::CurrentSettings.jira_connect_public_key_storage_enabled?
+ public_key_storage_enabled: Gitlab::CurrentSettings.jira_connect_public_key_storage_enabled?
}
end
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index 4a5720e757d..bec6cccb977 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -80,9 +80,7 @@ module MarkupHelper
)
)
- # since <img> tags are stripped, this can leave empty <a> tags hanging around
- # (as our markdown wraps images in links)
- strip_empty_link_tags(text).html_safe
+ render_links(text)
end
def markdown(text, context = {})
@@ -171,9 +169,22 @@ module MarkupHelper
{ project: wiki.container }
end
- def strip_empty_link_tags(text)
+ # Sanitize and style user references links
+ #
+ # @param String text the string to be sanitized
+ #
+ # 1. Remove empty <a> tags which are caused by the <img> tags being stripped
+ # (as our markdown wraps images in links)
+ # 2. Strip all link tags, except user references, leaving just the link text
+ # 3. Add a highlight class for current user's references
+ #
+ # @return sanitized HTML string
+ def render_links(text)
scrubber = Loofah::Scrubber.new do |node|
- node.remove if node.name == 'a' && node.children.empty?
+ next unless node.name == 'a'
+ next node.remove if node.children.empty?
+ next node.replace(node.children) if node['data-reference-type'] != 'user'
+ next node.append_class('current-user') if current_user && node['data-user'] == current_user.id.to_s
end
sanitize text, scrubber: scrubber
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index ec395baef9e..7d9be2f93fd 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -2,6 +2,7 @@
module MergeRequestsHelper
include Gitlab::Utils::StrongMemoize
+ include CompareHelper
def create_mr_button_from_event?(event)
create_mr_button?(from: event.branch_name, source_project: event.project)
@@ -185,6 +186,7 @@ module MergeRequestsHelper
endpoint_metadata: @endpoint_metadata_url,
endpoint_batch: diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params),
endpoint_coverage: @coverage_path,
+ endpoint_diff_for_path: diff_for_path_namespace_project_merge_request_path(format: 'json', id: merge_request.iid, namespace_id: project.namespace.path, project_id: project.path),
help_page_path: help_page_path('user/project/merge_requests/reviews/suggestions.md'),
current_user_data: @current_user_data,
update_current_user_path: @update_current_user_path,
@@ -198,7 +200,8 @@ module MergeRequestsHelper
default_suggestion_commit_message: default_suggestion_commit_message,
source_project_default_url: @merge_request.source_project && default_url_to_repo(@merge_request.source_project),
source_project_full_path: @merge_request.source_project&.full_path,
- is_forked: @project.forked?.to_s
+ is_forked: @project.forked?.to_s,
+ saved_replies_new_path: profile_saved_replies_path
}
end
diff --git a/app/helpers/mirror_helper.rb b/app/helpers/mirror_helper.rb
index 3dfd30f07db..06deaeb5e9e 100644
--- a/app/helpers/mirror_helper.rb
+++ b/app/helpers/mirror_helper.rb
@@ -13,7 +13,7 @@ module MirrorHelper
docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
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 }
+ { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
end
end
diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb
index ddd6469a9e4..201007863b2 100644
--- a/app/helpers/nav/new_dropdown_helper.rb
+++ b/app/helpers/nav/new_dropdown_helper.rb
@@ -6,19 +6,19 @@ module Nav
return unless current_user
menu_sections = []
+ data = { title: _('Create new...') }
- if group&.persisted?
- menu_sections.push(group_menu_section(group))
- elsif project&.persisted?
+ if project&.persisted?
menu_sections.push(project_menu_section(project))
+ elsif group&.persisted?
+ menu_sections.push(group_menu_section(group))
end
menu_sections.push(general_menu_section)
- {
- title: _("Create new..."),
- menu_sections: menu_sections.select { |x| x.fetch(:menu_items).any? }
- }
+ data[:menu_sections] = menu_sections.select { |x| x.fetch(:menu_items).any? }
+
+ data
end
private
@@ -51,11 +51,7 @@ module Nav
menu_items.push(create_epic_menu_item(group))
if can?(current_user, :admin_group_member, group)
- menu_items.push(
- invite_members_menu_item(
- href: group_group_members_path(group)
- )
- )
+ menu_items.push(invite_members_menu_item(partial: 'groups/invite_members_top_nav_link'))
end
{
@@ -102,11 +98,7 @@ module Nav
end
if can_admin_project_member?(project)
- menu_items.push(
- invite_members_menu_item(
- href: project_project_members_path(project)
- )
- )
+ menu_items.push(invite_members_menu_item(partial: 'projects/invite_members_top_nav_link'))
end
{
@@ -157,16 +149,16 @@ module Nav
}
end
- def invite_members_menu_item(href:)
+ def invite_members_menu_item(partial:)
::Gitlab::Nav::TopNavMenuItem.build(
id: 'invite',
title: s_('InviteMember|Invite members'),
- emoji: 'shaking_hands',
- href: href,
+ icon: 'shaking_hands',
+ partial: partial,
+ component: 'invite_members',
data: {
- track_action: 'click_link_invite_members',
- track_label: 'plus_menu_dropdown',
- track_property: 'navigation_top'
+ trigger_source: 'top-nav',
+ trigger_element: 'text-emoji'
}
)
end
diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb
index fb11c183aeb..756baabd249 100644
--- a/app/helpers/nav/top_nav_helper.rb
+++ b/app/helpers/nav/top_nav_helper.rb
@@ -64,7 +64,6 @@ module Nav
end
def build_anonymous_view_model(builder:)
- # These come from `app/views/layouts/nav/_explore.html.ham`
if explore_nav_link?(:projects)
builder.add_primary_menu_item_with_shortcut(
header: top_nav_localized_headers[:explore],
@@ -83,6 +82,15 @@ module Nav
)
end
+ if explore_nav_link?(:topics)
+ builder.add_primary_menu_item_with_shortcut(
+ header: top_nav_localized_headers[:explore],
+ active: active_nav_link?(page: topics_explore_projects_path, path: 'projects#topic'),
+ href: topics_explore_projects_path,
+ **topics_menu_item_attrs
+ )
+ end
+
if explore_nav_link?(:snippets)
builder.add_primary_menu_item_with_shortcut(
header: top_nav_localized_headers[:explore],
@@ -123,39 +131,54 @@ module Nav
builder.add_view(GROUPS_VIEW, container_view_props(namespace: 'groups', current_item: current_item, submenu: groups_submenu))
end
+ if dashboard_nav_link?(:your_work)
+ builder.add_primary_menu_item(
+ id: 'your-work',
+ header: top_nav_localized_headers[:switch_to],
+ title: _('Your work'),
+ href: dashboard_projects_path,
+ active: active_nav_link?(controller: []),
+ icon: 'work',
+ data: { **menu_data_tracking_attrs('your-work') }
+ )
+ end
+
+ if dashboard_nav_link?(:explore)
+ builder.add_primary_menu_item(
+ id: 'explore',
+ header: top_nav_localized_headers[:switch_to],
+ title: _('Explore'),
+ href: explore_projects_path,
+ active: active_nav_link?(controller: ["explore/groups", "explore/snippets"], page: ["/explore/projects", "/explore", "/explore/projects/topics"], path: ["projects#topic"]),
+ icon: 'compass',
+ data: { **menu_data_tracking_attrs('explore') }
+ )
+ end
+
if dashboard_nav_link?(:milestones)
- builder.add_primary_menu_item_with_shortcut(
- id: 'milestones',
- header: top_nav_localized_headers[:explore],
+ builder.add_shortcut(
+ id: 'milestones-shortcut',
title: _('Milestones'),
href: dashboard_milestones_path,
- active: active_nav_link?(controller: 'dashboard/milestones'),
- icon: 'clock',
- data: { **menu_data_tracking_attrs('milestones') },
- shortcut_class: 'dashboard-shortcuts-milestones'
+ css_class: 'dashboard-shortcuts-milestones'
)
end
if dashboard_nav_link?(:snippets)
- builder.add_primary_menu_item_with_shortcut(
- header: top_nav_localized_headers[:explore],
- active: active_nav_link?(controller: 'dashboard/snippets'),
- data: { qa_selector: 'snippets_link', **menu_data_tracking_attrs('snippets') },
+ builder.add_shortcut(
+ id: 'snippets-shortcut',
+ title: _('Snippets'),
href: dashboard_snippets_path,
- **snippets_menu_item_attrs
+ css_class: 'dashboard-shortcuts-snippets'
)
end
if dashboard_nav_link?(:activity)
- builder.add_primary_menu_item_with_shortcut(
- id: 'activity',
- header: top_nav_localized_headers[:explore],
+ builder.add_shortcut(
+ id: 'activity-shortcut',
title: _('Activity'),
href: activity_dashboard_path,
- active: active_nav_link?(path: 'dashboard#activity'),
- icon: 'history',
- data: { **menu_data_tracking_attrs('activity') },
- shortcut_class: 'dashboard-shortcuts-activity'
+ css_class: 'dashboard-shortcuts-activity'
)
end
@@ -220,6 +243,15 @@ module Nav
}
end
+ def topics_menu_item_attrs
+ {
+ id: 'topics',
+ title: _('Topics'),
+ icon: 'labels',
+ shortcut_class: 'dashboard-shortcuts-topics'
+ }
+ end
+
def snippets_menu_item_attrs
{
id: 'snippets',
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index d0421cd5184..59ffe6a183e 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -9,10 +9,29 @@ module NavHelper
header_links.include?(link)
end
+ def page_has_sidebar?
+ defined?(@left_sidebar) && @left_sidebar
+ end
+
+ def page_has_collapsed_sidebar?
+ page_has_sidebar? && collapsed_sidebar?
+ end
+
+ def page_has_collapsed_super_sidebar?
+ page_has_sidebar? && collapsed_super_sidebar?
+ end
+
def page_with_sidebar_class
class_name = page_gutter_class
- class_name << 'page-with-contextual-sidebar' if defined?(@left_sidebar) && @left_sidebar
- class_name << 'page-with-icon-sidebar' if collapsed_sidebar? && @left_sidebar
+
+ if show_super_sidebar?
+ class_name << 'page-with-super-sidebar' if page_has_sidebar?
+ class_name << 'page-with-super-sidebar-collapsed' if page_has_collapsed_super_sidebar?
+ else
+ class_name << 'page-with-contextual-sidebar' if page_has_sidebar?
+ class_name << 'page-with-icon-sidebar' if page_has_collapsed_sidebar?
+ end
+
class_name -= ['right-sidebar-expanded'] if defined?(@right_sidebar) && !@right_sidebar
class_name
@@ -66,11 +85,21 @@ module NavHelper
end
def show_super_sidebar?
- Feature.enabled?(:super_sidebar_nav, current_user) && current_user&.use_new_navigation
+ Feature.enabled?(:super_sidebar_nav, current_user) && current_user&.use_new_navigation && super_sidebar_supported?
end
private
+ # This is a temporary measure until we support all other existing sidebars:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/391500
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/391501
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/391502
+ def super_sidebar_supported?
+ return true if @nav.nil?
+
+ %w(your_work explore project group profile user_profile).include?(@nav)
+ end
+
def get_header_links
links = if current_user
[:user_dropdown]
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index b47f4633348..3e8872dc199 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -77,8 +77,10 @@ module NotesHelper
line_type: line_type
}
- button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
- data: data, title: 'Add a reply'
+ button_tag 'Reply...',
+ class: 'btn btn-text-field js-discussion-reply-button',
+ data: data,
+ title: 'Add a reply'
end
def note_max_access_for_user(note)
@@ -151,7 +153,6 @@ module NotesHelper
def initial_notes_data(autocomplete)
{
notesUrl: notes_url,
- notesIds: @noteable.notes.pluck(:id), # rubocop: disable CodeReuse/ActiveRecord
now: Time.now.to_i,
diffView: diff_view,
enableGFM: {
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index baeb9a477c3..8528f5f04f7 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -12,7 +12,7 @@ module OperationsHelper
def alerts_settings_data(disabled: false)
setting = project_incident_management_setting
- templates = setting.available_issue_templates.map { |t| { key: t.key, name: t.name } }
+ templates = setting.available_issue_templates.map { |t| { value: t.key, text: t.name } }
{
'prometheus_activated' => prometheus_integration.manual_configuration?.to_s,
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index f9ec20bdd01..dec1943db54 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -27,9 +27,14 @@ module PackagesHelper
presenter.detail_view.to_json
end
- def pypi_registry_url(project_id)
- full_url = expose_url(api_v4_projects_packages_pypi_simple_package_name_path({ id: project_id, package_name: '' }, true))
- full_url.sub!('://', '://__token__:<your_personal_token>@')
+ def pypi_registry_url(project)
+ full_url = expose_url(api_v4_projects_packages_pypi_simple_package_name_path({ id: project.id, package_name: '' }, true))
+
+ if project.project_feature.public_packages?
+ full_url
+ else
+ full_url.sub!('://', '://__token__:<your_personal_token>@')
+ end
end
def composer_registry_url(group_id)
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 4a218984af1..9bcabd7d9c6 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -175,7 +175,7 @@ module PageLayoutHelper
current_emoji: user.status.emoji.to_s,
current_message: user.status.message.to_s,
current_availability: user.status.availability.to_s,
- current_clear_status_after: user.status.clear_status_at&.to_s(:iso8601)
+ current_clear_status_after: user_clear_status_at(user)
})
end
diff --git a/app/helpers/plan_limits_helper.rb b/app/helpers/plan_limits_helper.rb
new file mode 100644
index 00000000000..71869b3ba30
--- /dev/null
+++ b/app/helpers/plan_limits_helper.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module PlanLimitsHelper
+ def plan_limit_setting_description(limit_name)
+ case limit_name
+ when :ci_pipeline_size
+ s_('AdminSettings|Maximum number of jobs in a single pipeline')
+ when :ci_active_jobs
+ s_('AdminSettings|Total number of jobs in currently active pipelines')
+ when :ci_active_pipelines
+ s_('AdminSettings|Maximum number of active pipelines per project')
+ when :ci_project_subscriptions
+ s_('AdminSettings|Maximum number of pipeline subscriptions to and from a project')
+ when :ci_pipeline_schedules
+ s_('AdminSettings|Maximum number of pipeline schedules')
+ when :ci_needs_size_limit
+ s_('AdminSettings|Maximum number of DAG dependencies that a job can have')
+ when :ci_registered_group_runners
+ s_('AdminSettings|Maximum number of runners registered per group')
+ when :ci_registered_project_runners
+ s_('AdminSettings|Maximum number of runners registered per project')
+ when :pipeline_hierarchy_size
+ s_("AdminSettings|Maximum number of downstream pipelines in a pipeline's hierarchy tree")
+ else
+ raise ArgumentError, "No description available for plan limit #{limit_name}"
+ end
+ end
+end
diff --git a/app/helpers/projects/error_tracking_helper.rb b/app/helpers/projects/error_tracking_helper.rb
index 471565d162c..fc4ad10db21 100644
--- a/app/helpers/projects/error_tracking_helper.rb
+++ b/app/helpers/projects/error_tracking_helper.rb
@@ -5,8 +5,7 @@ module Projects::ErrorTrackingHelper
error_tracking_enabled = !!project.error_tracking_setting&.enabled?
{
- 'index-path' => project_error_tracking_index_path(project,
- format: :json),
+ 'index-path' => project_error_tracking_index_path(project, format: :json),
'user-can-enable-error-tracking' => can?(current_user, :admin_operations, project).to_s,
'enable-error-tracking-link' => project_settings_operations_path(project),
'error-tracking-enabled' => error_tracking_enabled.to_s,
diff --git a/app/helpers/projects/settings/branch_rules_helper.rb b/app/helpers/projects/settings/branch_rules_helper.rb
new file mode 100644
index 00000000000..e53275d8183
--- /dev/null
+++ b/app/helpers/projects/settings/branch_rules_helper.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Projects
+ module Settings
+ module BranchRulesHelper
+ def branch_rules_data(project)
+ {
+ 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),
+ show_status_checks: 'false',
+ show_approvers: 'false',
+ show_code_owners: 'false'
+ }
+ end
+ end
+ end
+end
+
+Projects::Settings::BranchRulesHelper.prepend_mod
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 04190bc442b..a854b9990d2 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -133,6 +133,7 @@ module ProjectsHelper
{
source_name: source_project.full_name,
source_path: project_path(source_project),
+ source_default_branch: source_default_branch,
ahead_compare_path: project_compare_path(
project, from: source_default_branch, to: ref, from_project_id: source_project.id
),
@@ -474,7 +475,7 @@ module ProjectsHelper
def clusters_deprecation_alert_message
if has_active_license?
- s_('ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd} or reach out to GitLab support.')
+ s_('ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}. Contact GitLab Support if you have any additional questions.')
else
s_('ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}.')
end
@@ -498,6 +499,18 @@ module ProjectsHelper
format_cached_count(1000, number)
end
+ def remote_mirror_setting_enabled?
+ false
+ end
+
+ def http_clone_url_to_repo(project)
+ project.http_url_to_repo
+ end
+
+ def ssh_clone_url_to_repo(project)
+ project.ssh_url_to_repo
+ end
+
private
def localized_access_names
@@ -753,7 +766,7 @@ module ProjectsHelper
end
def show_visibility_confirm_modal?(project)
- project.unlink_forks_upon_visibility_decrease_enabled? && project.visibility_level > Gitlab::VisibilityLevel::PRIVATE && project.forks_count > 0
+ project.visibility_level > Gitlab::VisibilityLevel::PRIVATE && project.forks_count > 0
end
def confirm_reduce_visibility_message(project)
diff --git a/app/helpers/registrations_helper.rb b/app/helpers/registrations_helper.rb
index 1724e11a6f1..fcd560dbe8c 100644
--- a/app/helpers/registrations_helper.rb
+++ b/app/helpers/registrations_helper.rb
@@ -11,8 +11,8 @@ module RegistrationsHelper
}
end
- def arkose_labs_challenge_enabled?
- false
+ def signup_box_template
+ 'devise/shared/signup_box'
end
end
diff --git a/app/helpers/routing/projects_helper.rb b/app/helpers/routing/projects_helper.rb
index f4732e398f0..a0073f9c5ba 100644
--- a/app/helpers/routing/projects_helper.rb
+++ b/app/helpers/routing/projects_helper.rb
@@ -43,9 +43,10 @@ module Routing
end
def work_item_url(entity, *args)
- unless Feature.enabled?(:use_iid_in_work_items_path, entity.project.group)
- return project_work_items_url(entity.project, entity.id, *args)
- end
+ # TODO: we do not have a route to access group level work items yet.
+ # That is to be done as part of view group level work item issue:
+ # see https://gitlab.com/gitlab-org/gitlab/-/work_items/393987?iid_path=true
+ return unless entity.project.present?
options = args.first || {}
options[:iid_path] = true
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index ca5436ff019..d62dc038388 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -204,7 +204,9 @@ module SearchHelper
if search_has_project?
hash[:project] = { id: @project.id, name: @project.name }
- hash[:project_metadata] = { issues_path: project_issues_path(@project), mr_path: project_merge_requests_path(@project) }
+ hash[:project_metadata] = { mr_path: project_merge_requests_path(@project) }
+ hash[:project_metadata][:issues_path] = project_issues_path(@project) if @project.feature_available?(:issues, current_user)
+
hash[:code_search] = search_scope.nil?
hash[:ref] = @ref if @ref && can?(current_user, :read_code, @project)
end
diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb
index 27020738515..6c9688b0f9d 100644
--- a/app/helpers/sidebars_helper.rb
+++ b/app/helpers/sidebars_helper.rb
@@ -23,38 +23,100 @@ module SidebarsHelper
end
end
- def project_sidebar_context(project, user, current_ref, ref_type: nil)
+ def project_sidebar_context(project, user, current_ref, ref_type: nil, **args)
context_data = project_sidebar_context_data(project, user, current_ref, ref_type: ref_type)
- Sidebars::Projects::Context.new(**context_data)
+ Sidebars::Projects::Context.new(**context_data, **args)
end
- def group_sidebar_context(group, user)
+ def group_sidebar_context(group, user, **args)
context_data = group_sidebar_context_data(group, user)
- Sidebars::Groups::Context.new(**context_data)
+ Sidebars::Groups::Context.new(**context_data, **args)
end
- def super_sidebar_context(user, group:, project:)
+ def your_work_sidebar_context(user, **args)
+ context_data = your_work_context_data(user)
+
+ Sidebars::Context.new(**context_data, **args)
+ end
+
+ def super_sidebar_context(user, group:, project:, panel:)
{
+ current_menu_items: panel.super_sidebar_menu_items,
+ current_context_header: panel.super_sidebar_context_header,
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),
+ logo_url: current_appearance&.header_logo_path,
+ status: {
+ can_update: can?(current_user, :update_user_status, current_user),
+ busy: user.status&.busy?,
+ customized: user.status&.customized?,
+ availability: user.status&.availability.to_s,
+ emoji: user.status&.emoji,
+ message: user.status&.message_html&.html_safe,
+ clear_after: user_clear_status_at(user)
+ },
+ trial: {
+ has_start_trial: current_user_menu?(:start_trial),
+ url: trials_link_url
+ },
+ settings: {
+ has_settings: current_user_menu?(:settings),
+ profile_path: profile_path,
+ profile_preferences_path: profile_preferences_path
+ },
+ can_sign_out: current_user_menu?(:sign_out),
+ sign_out_link: destroy_user_session_path,
assigned_open_issues_count: user.assigned_open_issues_count,
todos_pending_count: user.todos_pending_count,
issues_dashboard_path: issues_dashboard_path(assignee_username: user.username),
total_merge_requests_count: user_merge_requests_counts[:total],
create_new_menu_groups: create_new_menu_groups(group: group, project: project),
merge_request_menu: create_merge_request_menu(user),
+ projects_path: projects_path,
+ groups_path: 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_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)
}
end
+ def super_sidebar_nav_panel(
+ nav: nil, project: nil, user: nil, group: nil, current_ref: nil, ref_type: nil,
+ viewed_user: nil)
+ context_adds = { route_is_active: method(:active_nav_link?), is_super_sidebar: true }
+ case nav
+ when 'project'
+ context = project_sidebar_context(project, user, current_ref, ref_type: ref_type, **context_adds)
+ Sidebars::Projects::SuperSidebarPanel.new(context)
+ when 'group'
+ context = group_sidebar_context(group, user, **context_adds)
+ Sidebars::Groups::SuperSidebarPanel.new(context)
+ when 'profile'
+ context = Sidebars::Context.new(current_user: user, container: user, **context_adds)
+ Sidebars::UserSettings::Panel.new(context)
+ when 'user_profile'
+ context = Sidebars::Context.new(current_user: user, container: viewed_user, **context_adds)
+ Sidebars::UserProfile::Panel.new(context)
+ when 'explore'
+ Sidebars::Explore::Panel.new(Sidebars::Context.new(current_user: user, container: nil, **context_adds))
+ else
+ context = your_work_sidebar_context(user, **context_adds)
+ Sidebars::YourWork::Panel.new(context)
+ end
+ end
+
private
def create_new_menu_groups(group:, project:)
@@ -160,6 +222,44 @@ module SidebarsHelper
container: group
}
end
+
+ def your_work_context_data(user)
+ {
+ current_user: user,
+ container: user,
+ show_security_dashboard: false
+ }
+ end
+
+ def super_sidebar_current_context(project: nil, group: nil)
+ if project&.persisted?
+ return {
+ namespace: 'projects',
+ item: {
+ id: project.id,
+ name: project.name,
+ namespace: project.full_name,
+ webUrl: project_path(project),
+ avatarUrl: project.avatar_url
+ }
+ }
+ end
+
+ if group&.persisted?
+ return {
+ namespace: 'groups',
+ item: {
+ id: group.id,
+ name: group.name,
+ namespace: group.full_name,
+ webUrl: group_path(group),
+ avatarUrl: group.avatar_url
+ }
+ }
+ end
+
+ {}
+ end
end
SidebarsHelper.prepend_mod_with('SidebarsHelper')
diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb
index 8558c664977..2f9117a74be 100644
--- a/app/helpers/snippets_helper.rb
+++ b/app/helpers/snippets_helper.rb
@@ -45,30 +45,35 @@ 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')
+ 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'
+ )
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')
+ 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'
+ )
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')"
+ 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
external_snippet_icon('copy-to-clipboard')
end
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 4a9596a1347..9038d972f65 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -227,7 +227,7 @@ module SortingHelper
options.concat([due_date_option]) if viewing_issues
options.concat([popularity_option, label_priority_option])
- options.concat([merged_option]) if viewing_merge_requests
+ options.concat([merged_option]) if can_sort_by_merged_date?(viewing_merge_requests)
options.concat([relative_position_option]) if viewing_issues
options.concat([title_option])
@@ -237,6 +237,10 @@ module SortingHelper
false
end
+ def can_sort_by_merged_date?(viewing_merge_requests)
+ viewing_merge_requests && %w[all merged].include?(params[:state])
+ end
+
def due_date_option
{ value: sort_value_due_date, text: sort_title_due_date, href: page_filter_path(sort: sort_value_due_date) }
end
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 3e5f63796b2..a1b6e896475 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -42,8 +42,6 @@ module SystemNoteHelper
'severity' => 'information-o',
'cloned' => 'documents',
'issue_type' => 'pencil',
- 'attention_requested' => 'user',
- 'attention_request_removed' => 'user',
'contact' => 'users',
'timeline_event' => 'clock',
'relate_to_child' => 'link',
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index 4a9dd30a5a2..9b0810f3d17 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -232,13 +232,15 @@ module TodosHelper
''
end
+ due_date =
+ if is_due_today
+ _("today")
+ else
+ l(todo.target.due_date, format: Date::DATE_FORMATS[:medium])
+ end
+
content = content_tag(:span, class: css_class) do
- format(s_("Todos|Due %{due_date}"), due_date: if is_due_today
- _("today")
- else
- l(todo.target.due_date,
- format: Date::DATE_FORMATS[:medium])
- end)
+ format(s_("Todos|Due %{due_date}"), due_date: due_date)
end
"#{content} &middot;".html_safe
diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb
index 2b8368dd29f..af3ac495164 100644
--- a/app/helpers/users/callouts_helper.rb
+++ b/app/helpers/users/callouts_helper.rb
@@ -11,9 +11,11 @@ module Users
UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout'
SECURITY_NEWSLETTER_CALLOUT = 'security_newsletter_callout'
MERGE_REQUEST_SETTINGS_MOVED_CALLOUT = 'merge_request_settings_moved_callout'
+ PAGES_MOVED_CALLOUT = 'pages_moved_callout'
REGISTRATION_ENABLED_CALLOUT_ALLOWED_CONTROLLER_PATHS = [/^root/, /^dashboard\S*/, /^admin\S*/].freeze
WEB_HOOK_DISABLED = 'web_hook_disabled'
ULTIMATE_FEATURE_REMOVAL_BANNER = 'ultimate_feature_removal_banner'
+ BRANCH_RULES_INFO_CALLOUT = 'branch_rules_info_callout'
def show_gke_cluster_integration_callout?(project)
active_nav_link?(controller: sidebar_operations_paths) &&
@@ -59,42 +61,47 @@ module Users
!user_dismissed?(SECURITY_NEWSLETTER_CALLOUT)
end
- def web_hook_disabled_dismissed?(project)
- return false unless project
-
- last_failure = Gitlab::Redis::SharedState.with do |redis|
- key = "web_hooks:last_failure:project-#{project.id}"
- redis.get(key)
- end
+ def web_hook_disabled_dismissed?(object)
+ return false unless object.is_a?(::WebHooks::HasWebHooks)
- last_failure = DateTime.parse(last_failure) if last_failure
-
- user_dismissed?(WEB_HOOK_DISABLED, last_failure, project: project)
+ user_dismissed?(WEB_HOOK_DISABLED, object.last_webhook_failure, object: object)
end
def show_merge_request_settings_callout?(project)
!user_dismissed?(MERGE_REQUEST_SETTINGS_MOVED_CALLOUT) && project.merge_requests_enabled?
end
+ def show_pages_menu_callout?
+ !user_dismissed?(PAGES_MOVED_CALLOUT)
+ end
+
+ def show_branch_rules_info?
+ !user_dismissed?(BRANCH_RULES_INFO_CALLOUT)
+ end
+
def ultimate_feature_removal_banner_dismissed?(project)
return false unless project
- user_dismissed?(ULTIMATE_FEATURE_REMOVAL_BANNER, project: project)
+ user_dismissed?(ULTIMATE_FEATURE_REMOVAL_BANNER, object: project)
end
private
- def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil, project: nil)
+ def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil, object: nil)
return false unless current_user
query = { feature_name: feature_name, ignore_dismissal_earlier_than: ignore_dismissal_earlier_than }
- if project
- current_user.dismissed_callout_for_project?(project: project, **query)
+ if object
+ dismissed_callout?(object, query)
else
current_user.dismissed_callout?(**query)
end
end
+
+ def dismissed_callout?(object, query)
+ current_user.dismissed_callout_for_project?(project: object, **query)
+ end
end
end
diff --git a/app/helpers/users/group_callouts_helper.rb b/app/helpers/users/group_callouts_helper.rb
index 0aa4eb89499..92cf41400e7 100644
--- a/app/helpers/users/group_callouts_helper.rb
+++ b/app/helpers/users/group_callouts_helper.rb
@@ -17,9 +17,11 @@ module Users
def user_dismissed_for_group(feature_name, group, ignore_dismissal_earlier_than = nil)
return false unless current_user
- current_user.dismissed_callout_for_group?(feature_name: feature_name,
- group: group,
- ignore_dismissal_earlier_than: ignore_dismissal_earlier_than)
+ current_user.dismissed_callout_for_group?(
+ feature_name: feature_name,
+ group: group,
+ ignore_dismissal_earlier_than: ignore_dismissal_earlier_than
+ )
end
def just_created?
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 62b9eb2b506..e0cf7aa61ee 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -8,10 +8,15 @@ module UsersHelper
}
end
+ def user_clear_status_at(user)
+ # The user.status can be nil when the user has no status, so we need to protect against that case.
+ # iso8601 is the official RFC supported format for frontend parsing of date:
+ # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
+ user.status&.clear_status_at&.to_s(:iso8601)
+ end
+
def user_link(user)
- link_to(user.name, user_path(user),
- title: user.email,
- class: 'has-tooltip commit-committer-link')
+ link_to(user.name, user_path(user), title: user.email, class: 'has-tooltip commit-committer-link')
end
def user_email_help_text(user)
@@ -79,9 +84,9 @@ module UsersHelper
return unless user.status
content_tag :span,
- class: 'user-status-emoji has-tooltip',
- title: user.status.message_html,
- data: { html: true, placement: 'top' } do
+ class: 'user-status-emoji has-tooltip',
+ title: user.status.message_html,
+ data: { html: true, placement: 'top' } do
emoji_icon user.status.emoji
end
end
@@ -168,6 +173,19 @@ module UsersHelper
user.public_email.present?
end
+ def trials_link_url
+ 'https://about.gitlab.com/free-trial/'
+ end
+
+ def user_profile_tabs_app_data(user)
+ {
+ followees: user.followees.count,
+ followers: user.followers.count,
+ user_calendar_path: user_calendar_path(user, :json),
+ utc_offset: local_timezone_instance(user.timezone).now.utc_offset
+ }
+ end
+
private
def admin_users_paths
@@ -211,10 +229,6 @@ module UsersHelper
tabs
end
- def trials_link_url
- 'https://about.gitlab.com/free-trial/'
- end
-
def trials_allowed?(user)
false
end
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index 5ed341ee5e5..c577e2da1bb 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -44,9 +44,8 @@ module VisibilityLevelHelper
Gitlab::CurrentSettings.restricted_visibility_levels || []
end
- delegate :default_project_visibility,
- :default_group_visibility,
- to: :'Gitlab::CurrentSettings.current_application_settings'
+ delegate :default_project_visibility, :default_group_visibility,
+ to: :'Gitlab::CurrentSettings.current_application_settings'
def disallowed_visibility_level?(form_model, level)
return false unless form_model.respond_to?(:visibility_level_allowed?)
diff --git a/app/helpers/web_hooks/web_hooks_helper.rb b/app/helpers/web_hooks/web_hooks_helper.rb
index 514db6ba8a2..ad792f761f8 100644
--- a/app/helpers/web_hooks/web_hooks_helper.rb
+++ b/app/helpers/web_hooks/web_hooks_helper.rb
@@ -4,19 +4,31 @@ module WebHooks
module WebHooksHelper
def show_project_hook_failed_callout?(project:)
return false if project_hook_page?
+
+ show_hook_failed_callout?(project)
+ end
+
+ private
+
+ def show_hook_failed_callout?(object)
return false unless current_user
- return false unless Ability.allowed?(current_user, :read_web_hooks, project)
+
+ return false unless can_access_web_hooks?(object)
# Assumes include of Users::CalloutsHelper
- return false if web_hook_disabled_dismissed?(project)
+ return false if web_hook_disabled_dismissed?(object)
- project.fetch_web_hook_failure
+ object.fetch_web_hook_failure
end
- private
-
def project_hook_page?
current_controller?('projects/hooks') || current_controller?('projects/hook_logs')
end
+
+ def can_access_web_hooks?(object)
+ Ability.allowed?(current_user, :admin_project, object)
+ end
end
end
+
+WebHooks::WebHooksHelper.prepend_mod
diff --git a/app/helpers/work_items_helper.rb b/app/helpers/work_items_helper.rb
index efa9a2bd463..bc270380fca 100644
--- a/app/helpers/work_items_helper.rb
+++ b/app/helpers/work_items_helper.rb
@@ -6,7 +6,8 @@ module WorkItemsHelper
full_path: project.full_path,
issues_list_path: project_issues_path(project),
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
}
end
end