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>2022-09-20 02:18:09 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-20 02:18:09 +0300
commit6ed4ec3e0b1340f96b7c043ef51d1b33bbe85fde (patch)
treedc4d20fe6064752c0bd323187252c77e0a89144b /app/helpers
parent9868dae7fc0655bd7ce4a6887d4e6d487690eeed (diff)
Add latest changes from gitlab-org/gitlab@15-4-stable-eev15.4.0-rc42
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/application_settings_helper.rb22
-rw-r--r--app/helpers/badges_helper.rb66
-rw-r--r--app/helpers/blob_helper.rb26
-rw-r--r--app/helpers/ci/builds_helper.rb2
-rw-r--r--app/helpers/ci/jobs_helper.rb2
-rw-r--r--app/helpers/ci/runners_helper.rb1
-rw-r--r--app/helpers/deploy_tokens_helper.rb8
-rw-r--r--app/helpers/diff_helper.rb12
-rw-r--r--app/helpers/dropdowns_helper.rb5
-rw-r--r--app/helpers/form_helper.rb4
-rw-r--r--app/helpers/groups_helper.rb9
-rw-r--r--app/helpers/ide_helper.rb3
-rw-r--r--app/helpers/issuables_helper.rb3
-rw-r--r--app/helpers/javascript_helper.rb7
-rw-r--r--app/helpers/jira_connect_helper.rb14
-rw-r--r--app/helpers/kerberos_helper.rb (renamed from app/helpers/kerberos_spnego_helper.rb)6
-rw-r--r--app/helpers/labels_helper.rb2
-rw-r--r--app/helpers/learn_gitlab_helper.rb25
-rw-r--r--app/helpers/merge_requests_helper.rb20
-rw-r--r--app/helpers/nav/new_dropdown_helper.rb2
-rw-r--r--app/helpers/nav/top_nav_helper.rb101
-rw-r--r--app/helpers/notify_helper.rb11
-rw-r--r--app/helpers/packages_helper.rb4
-rw-r--r--app/helpers/page_layout_helper.rb4
-rw-r--r--app/helpers/profiles_helper.rb2
-rw-r--r--app/helpers/projects/google_cloud/cloudsql_helper.rb55
-rw-r--r--app/helpers/projects/pages_helper.rb11
-rw-r--r--app/helpers/projects/pipeline_helper.rb1
-rw-r--r--app/helpers/projects_helper.rb12
-rw-r--r--app/helpers/search_helper.rb40
-rw-r--r--app/helpers/sorting_helper.rb4
-rw-r--r--app/helpers/sorting_titles_values_helper.rb16
-rw-r--r--app/helpers/storage_helper.rb115
-rw-r--r--app/helpers/system_note_helper.rb6
-rw-r--r--app/helpers/timeboxes_helper.rb11
-rw-r--r--app/helpers/todos_helper.rb10
-rw-r--r--app/helpers/users/callouts_helper.rb20
-rw-r--r--app/helpers/users_helper.rb13
-rw-r--r--app/helpers/web_hooks/web_hooks_helper.rb5
39 files changed, 359 insertions, 321 deletions
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 321a6e9395e..ddc682bc08a 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -7,6 +7,7 @@ module ApplicationSettingsHelper
:gravatar_enabled?,
:password_authentication_enabled_for_web?,
:akismet_enabled?,
+ :spam_check_endpoint_enabled?,
to: :'Gitlab::CurrentSettings.current_application_settings'
def user_oauth_applications?
@@ -60,6 +61,10 @@ module ApplicationSettingsHelper
all_protocols_enabled? || Gitlab::CurrentSettings.enabled_git_access_protocol == 'http'
end
+ def anti_spam_service_enabled?
+ akismet_enabled? || spam_check_endpoint_enabled?
+ end
+
def enabled_protocol_button(container, protocol)
case protocol
when 'ssh'
@@ -278,6 +283,7 @@ module ApplicationSettingsHelper
:max_export_size,
:max_import_size,
:max_pages_size,
+ :max_pages_custom_domains_per_project,
:max_yaml_size_bytes,
:max_yaml_depth,
:metrics_method_call_threshold,
@@ -434,12 +440,24 @@ module ApplicationSettingsHelper
:runner_token_expiration_interval,
:group_runner_token_expiration_interval,
:project_runner_token_expiration_interval,
- :pipeline_limit_per_project_user_sha
+ :pipeline_limit_per_project_user_sha,
+ :invitation_flow_enforcement
].tap do |settings|
- settings << :deactivate_dormant_users unless Gitlab.com?
+ next if Gitlab.com?
+
+ settings << :deactivate_dormant_users
+ settings << :deactivate_dormant_users_period
end
end
+ def runner_token_expiration_interval_attributes
+ {
+ instance_runner_token_expiration_interval: @application_setting.runner_token_expiration_interval,
+ group_runner_token_expiration_interval: @application_setting.group_runner_token_expiration_interval,
+ project_runner_token_expiration_interval: @application_setting.project_runner_token_expiration_interval
+ }
+ end
+
def external_authorization_service_attributes
[
:external_auth_client_cert,
diff --git a/app/helpers/badges_helper.rb b/app/helpers/badges_helper.rb
index d48eae26a90..069c15433a5 100644
--- a/app/helpers/badges_helper.rb
+++ b/app/helpers/badges_helper.rb
@@ -1,25 +1,6 @@
# frozen_string_literal: true
module BadgesHelper
- VARIANT_CLASSES = {
- muted: "badge-muted",
- neutral: "badge-neutral",
- info: "badge-info",
- success: "badge-success",
- warning: "badge-warning",
- danger: "badge-danger"
- }.tap { |hash| hash.default = hash.fetch(:muted) }.freeze
-
- SIZE_CLASSES = {
- sm: "sm",
- md: "md",
- lg: "lg"
- }.tap { |hash| hash.default = hash.fetch(:md) }.freeze
-
- GL_BADGE_CLASSES = %w[gl-badge badge badge-pill].freeze
-
- GL_ICON_CLASSES = %w[gl-icon gl-badge-icon].freeze
-
# Creates a GitLab UI badge.
#
# Examples:
@@ -53,47 +34,16 @@ module BadgesHelper
#
# See also https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-badge--default.
def gl_badge_tag(*args, &block)
+ # Merge the options and html_options hashes if both are present,
+ # because the badge component wants a flat list of keyword args.
+ args.compact!
+ hashes, params = args.partition { |a| a.is_a? Hash }
+ options_hash = hashes.reduce({}, :merge)
+
if block
- build_gl_badge_tag(capture(&block), *args)
+ render Pajamas::BadgeComponent.new(**options_hash), &block
else
- build_gl_badge_tag(*args)
+ render Pajamas::BadgeComponent.new(*params, **options_hash)
end
end
-
- private
-
- def build_gl_badge_tag(content, options = nil, html_options = nil)
- options ||= {}
- html_options ||= {}
-
- icon_only = options[:icon_only]
- variant_class = VARIANT_CLASSES[options.fetch(:variant, :muted)]
- size_class = SIZE_CLASSES[options.fetch(:size, :md)]
- icon_classes = GL_ICON_CLASSES.dup << options.fetch(:icon_classes, nil)
-
- html_options = html_options.merge(
- class: [
- *GL_BADGE_CLASSES,
- variant_class,
- size_class,
- *html_options[:class]
- ]
- )
-
- if icon_only
- html_options['aria-label'] = content
- html_options['role'] = 'img'
- end
-
- if options[:icon]
- icon_classes << "gl-mr-2" unless icon_only
- icon = sprite_icon(options[:icon], css_class: icon_classes.join(' '))
-
- content = icon_only ? icon : icon + content
- end
-
- tag = html_options[:href].nil? ? :span : :a
-
- content_tag(tag, content, html_options)
- end
end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 2c84da4862a..6c09e15f56f 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -92,32 +92,6 @@ module BlobHelper
end
end
- def replace_blob_link(project = @project, ref = @ref, path = @path, blob:)
- modify_file_button(
- project,
- ref,
- path,
- blob: blob,
- label: _("Replace"),
- action: "replace",
- btn_class: "default",
- modal_type: "upload"
- )
- end
-
- def delete_blob_link(project = @project, ref = @ref, path = @path, blob:)
- modify_file_button(
- project,
- ref,
- path,
- blob: blob,
- label: _("Delete"),
- action: "delete",
- btn_class: "default",
- modal_type: "remove"
- )
- end
-
def can_modify_blob?(blob, project = @project, ref = @ref)
!blob.stored_externally? && can_edit_tree?(project, ref)
end
diff --git a/app/helpers/ci/builds_helper.rb b/app/helpers/ci/builds_helper.rb
index b4a2cf7bb1e..afd0af18ba7 100644
--- a/app/helpers/ci/builds_helper.rb
+++ b/app/helpers/ci/builds_helper.rb
@@ -25,7 +25,7 @@ module Ci
{
page_path: project_job_path(@project, @build),
build_status: @build.status,
- build_stage: @build.stage,
+ build_stage: @build.stage_name,
log_state: ''
}
end
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index 6d63151769f..7b8290ac9ef 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -11,7 +11,7 @@ module Ci
"runner_settings_url" => project_runners_path(@build.project, anchor: 'js-runners-settings'),
"page_path" => project_job_path(@project, @build),
"build_status" => @build.status,
- "build_stage" => @build.stage,
+ "build_stage" => @build.stage_name,
"log_state" => '',
"build_options" => javascript_build_options,
"retry_outdated_job_docs_url" => help_page_path('ci/pipelines/settings', anchor: 'retry-outdated-jobs')
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index 852eaeca5e3..0de84c0d61f 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -84,7 +84,6 @@ module Ci
def group_runners_data_attributes(group)
{
- registration_token: group.runners_token,
group_id: group.id,
group_full_path: group.full_path,
runner_install_help_page: 'https://docs.gitlab.com/runner/install/',
diff --git a/app/helpers/deploy_tokens_helper.rb b/app/helpers/deploy_tokens_helper.rb
index 560d2fcd29f..597823cdac7 100644
--- a/app/helpers/deploy_tokens_helper.rb
+++ b/app/helpers/deploy_tokens_helper.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
module DeployTokensHelper
- def expand_deploy_tokens_section?(deploy_token)
- deploy_token.persisted? ||
- deploy_token.errors.present? ||
+ def expand_deploy_tokens_section?(new_deploy_token, created_deploy_token)
+ created_deploy_token ||
+ new_deploy_token.errors.present? ||
Rails.env.test?
end
@@ -14,7 +14,7 @@ module DeployTokensHelper
def packages_registry_enabled?(group_or_project)
Gitlab.config.packages.enabled &&
- can?(current_user, :read_package, group_or_project)
+ can?(current_user, :read_package, group_or_project&.packages_policy_subject)
end
def deploy_token_revoke_button_data(token:, group_or_project:)
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 457502347ee..5c3b9d4b5ab 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -140,12 +140,12 @@ module DiffHelper
if compare_url
link_text = [
- _('Compare'),
- ' ',
- content_tag(:span, Commit.truncate_sha(diff_file.old_blob.id), class: 'commit-sha'),
- '...',
- content_tag(:span, Commit.truncate_sha(diff_file.blob.id), class: 'commit-sha')
- ].join('').html_safe
+ _('Compare'),
+ ' ',
+ content_tag(:span, Commit.truncate_sha(diff_file.old_blob.id), class: 'commit-sha'),
+ '...',
+ content_tag(:span, Commit.truncate_sha(diff_file.blob.id), class: 'commit-sha')
+ ].join('').html_safe
tooltip = _('Compare submodule commit revisions')
link = content_tag(:span, link_to(link_text, compare_url, class: 'btn gl-button has-tooltip', title: tooltip), class: 'submodule-compare')
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index a910d3d7c9d..62e66b9a3ea 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
module DropdownsHelper
+ # 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
data_attr = { toggle: "dropdown" }
@@ -16,7 +17,8 @@ module DropdownsHelper
end
content_tag_options = { class: "dropdown-menu dropdown-select #{options[:dropdown_class] if options.key?(:dropdown_class)}" }
- content_tag_options[:data] = { qa_selector: "#{options[:dropdown_qa_selector]}" } if options[:dropdown_qa_selector]
+ content_tag_options[:data] = options[:dropdown_qa_selector] ? { qa_selector: "#{options[:dropdown_qa_selector]}" } : {}
+ content_tag_options[:data][:testid] = "#{options[:dropdown_testid]}" if options[:dropdown_testid]
dropdown_output << content_tag(:div, content_tag_options) do
output = []
@@ -46,6 +48,7 @@ module DropdownsHelper
dropdown_output.html_safe
end
end
+ # rubocop:enable Metrics/CyclomaticComplexity
def dropdown_toggle(toggle_text, data_attr, options = {})
default_label = data_attr[:default_label]
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index f74eeeb8c6a..f2e24f54391 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module FormHelper
- def form_errors(model, type: 'form', truncate: [], pajamas_alert: true)
+ def form_errors(model, type: 'form', truncate: [])
errors = model.errors
return unless errors.any?
@@ -64,7 +64,7 @@ module FormHelper
field_name: "#{issuable_type}[assignee_ids][]",
default_label: _('Unassigned'),
'max-select': 1,
- 'dropdown-header': _('Assignee'),
+ 'dropdown-header': s_('SearchToken|Assignee'),
multi_select: true,
'input-meta': 'name',
'always-show-selectbox': true,
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index bb92792de2d..f77bd6621f9 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -172,6 +172,15 @@ module GroupsHelper
}
end
+ def group_overview_tabs_app_data(group)
+ {
+ subgroups_and_projects_endpoint: group_children_path(group, format: :json),
+ shared_projects_endpoint: group_shared_projects_path(group, format: :json),
+ archived_projects_endpoint: group_children_path(group, format: :json, archived: 'only'),
+ current_group_visibility: group.visibility
+ }.merge(subgroups_and_projects_list_app_data(group))
+ end
+
def enabled_git_access_protocol_options_for_group
case ::Gitlab::CurrentSettings.enabled_git_access_protocol
when nil, ""
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index 4b463b9971d..ec1327cf7ae 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -24,7 +24,8 @@ module IdeHelper
'web-terminal-svg-path' => image_path('illustrations/web-ide_promotion.svg'),
'web-terminal-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'interactive-web-terminals-for-the-web-ide'),
'web-terminal-config-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'web-ide-configuration-file'),
- 'web-terminal-runners-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'runner-configuration')
+ 'web-terminal-runners-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'runner-configuration'),
+ 'csp-nonce' => content_security_policy_nonce
}
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 8fd004233e2..96daf398243 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -156,7 +156,7 @@ module IssuablesHelper
output = []
if issuable.respond_to?(:work_item_type) && WorkItems::Type::WI_TYPES_WITH_CREATED_HEADER.include?(issuable.work_item_type.base_type)
- output << content_tag(:span, sprite_icon("#{issuable.work_item_type.icon_name}", css_class: 'gl-icon gl-vertical-align-middle'), class: 'gl-mr-2', aria: { hidden: 'true' })
+ output << content_tag(:span, sprite_icon("#{issuable.work_item_type.icon_name}", css_class: 'gl-icon gl-vertical-align-middle gl-text-gray-500'), class: 'gl-mr-2', aria: { hidden: 'true' })
output << s_('IssuableStatus|%{wi_type} created %{created_at} by ').html_safe % { wi_type: issuable.issue_type.capitalize, created_at: time_ago_with_tooltip(issuable.created_at) }
else
output << s_('IssuableStatus|Created %{created_at} by').html_safe % { created_at: time_ago_with_tooltip(issuable.created_at) }
@@ -240,6 +240,7 @@ module IssuablesHelper
updateEndpoint: "#{issuable_path(issuable)}.json",
canUpdate: can?(current_user, :"update_#{issuable.to_ability_name}", issuable),
canDestroy: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable),
+ canUpdateTimelineEvent: can?(current_user, :admin_incident_management_timeline_event, issuable),
issuableRef: issuable.to_reference,
markdownPreviewPath: preview_markdown_path(parent, target_type: issuable.model_name, target_id: issuable.iid),
markdownDocsPath: help_page_path('user/markdown'),
diff --git a/app/helpers/javascript_helper.rb b/app/helpers/javascript_helper.rb
deleted file mode 100644
index 7cb6da26236..00000000000
--- a/app/helpers/javascript_helper.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-module JavascriptHelper
- def page_specific_javascript_tag(js)
- javascript_include_tag asset_path(js)
- end
-end
diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb
index 4ddfb0224d1..0971fdae8dd 100644
--- a/app/helpers/jira_connect_helper.rb
+++ b/app/helpers/jira_connect_helper.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module JiraConnectHelper
- def jira_connect_app_data(subscriptions)
+ def jira_connect_app_data(subscriptions, installation)
skip_groups = subscriptions.map(&:namespace_id)
{
@@ -11,14 +11,16 @@ module JiraConnectHelper
subscriptions_path: jira_connect_subscriptions_path(format: :json),
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.to_json : nil
+ oauth_metadata: Feature.enabled?(:jira_connect_oauth, current_user) ? jira_connect_oauth_data(installation).to_json : nil
}
end
private
- def jira_connect_oauth_data
- oauth_authorize_url = oauth_authorization_url(
+ def jira_connect_oauth_data(installation)
+ oauth_instance_url = installation.oauth_authorization_url
+
+ oauth_authorize_path = oauth_authorization_path(
client_id: Gitlab::CurrentSettings.jira_connect_application_key,
response_type: 'code',
scope: 'api',
@@ -27,8 +29,8 @@ module JiraConnectHelper
)
{
- oauth_authorize_url: oauth_authorize_url,
- oauth_token_url: oauth_token_url,
+ oauth_authorize_url: Gitlab::Utils.append_path(oauth_instance_url, oauth_authorize_path),
+ oauth_token_path: oauth_token_path,
state: oauth_state,
oauth_token_payload: {
grant_type: :authorization_code,
diff --git a/app/helpers/kerberos_spnego_helper.rb b/app/helpers/kerberos_helper.rb
index 0f6812bc31b..31166772367 100644
--- a/app/helpers/kerberos_spnego_helper.rb
+++ b/app/helpers/kerberos_helper.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
-module KerberosSpnegoHelper
+module KerberosHelper
def allow_basic_auth?
true # different behavior in GitLab Enterprise Edition
end
- def allow_kerberos_spnego_auth?
+ def allow_kerberos_auth?
false # different behavior in GitLab Enterprise Edition
end
end
-KerberosSpnegoHelper.prepend_mod_with('KerberosSpnegoHelper')
+KerberosHelper.prepend_mod_with('KerberosHelper')
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index e865db128c1..0123eb68c9a 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -87,7 +87,7 @@ module LabelsHelper
'#013220' => s_('SuggestedColors|Dark green'),
'#6699cc' => s_('SuggestedColors|Blue-gray'),
'#0000ff' => s_('SuggestedColors|Blue'),
- '#e6e6fa' => s_('SuggestedColors|Lavendar'),
+ '#e6e6fa' => s_('SuggestedColors|Lavender'),
'#9400d3' => s_('SuggestedColors|Dark violet'),
'#330066' => s_('SuggestedColors|Deep violet'),
'#808080' => s_('SuggestedColors|Gray'),
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
index 421cf84f98c..a07922e451a 100644
--- a/app/helpers/learn_gitlab_helper.rb
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -21,8 +21,8 @@ module LearnGitlabHelper
end
def learn_gitlab_onboarding_available?(project)
- OnboardingProgress.onboarding?(project.namespace) &&
- LearnGitlab::Project.new(current_user).available?
+ Onboarding::Progress.onboarding?(project.namespace) &&
+ Onboarding::LearnGitlab.new(current_user).available?
end
private
@@ -33,10 +33,12 @@ module LearnGitlabHelper
action_urls(project).to_h do |action, url|
[
action,
- url: url,
- completed: attributes[OnboardingProgress.column_name(action)].present?,
- svg: image_path("learn_gitlab/#{action}.svg"),
- enabled: true
+ {
+ url: url,
+ completed: attributes[Onboarding::Progress.column_name(action)].present?,
+ svg: image_path("learn_gitlab/#{action}.svg"),
+ enabled: true
+ }
]
end
end
@@ -70,11 +72,14 @@ module LearnGitlabHelper
end
def action_issue_urls
- LearnGitlab::Onboarding::ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) }
+ Onboarding::Completion::ACTION_ISSUE_IDS.transform_values do |id|
+ project_issue_url(learn_gitlab_project, id)
+ end
end
def deploy_section_action_urls(project)
- experiment(:security_actions_continuous_onboarding,
+ experiment(
+ :security_actions_continuous_onboarding,
namespace: project.namespace,
user: current_user,
sticky_to: current_user
@@ -91,11 +96,11 @@ module LearnGitlabHelper
end
def learn_gitlab_project
- @learn_gitlab_project ||= LearnGitlab::Project.new(current_user).project
+ @learn_gitlab_project ||= Onboarding::LearnGitlab.new(current_user).project
end
def onboarding_progress(project)
- OnboardingProgress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord
+ Onboarding::Progress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord
end
end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 4581da4a063..45ded6e35d8 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -256,6 +256,26 @@ module MergeRequestsHelper
def moved_mr_sidebar_enabled?
Feature.enabled?(:moved_mr_sidebar, @project) && defined?(@merge_request)
end
+
+ def sticky_header_data
+ data = {
+ iid: @merge_request.iid,
+ projectPath: @project.full_path,
+ title: markdown_field(@merge_request, :title),
+ isFluidLayout: fluid_layout.to_s,
+ tabs: [
+ ['show', _('Overview'), project_merge_request_path(@project, @merge_request), @merge_request.related_notes.user.count],
+ ['commits', _('Commits'), commits_project_merge_request_path(@project, @merge_request), @commits_count],
+ ['diffs', _('Changes'), diffs_project_merge_request_path(@project, @merge_request), @diffs_count]
+ ]
+ }
+
+ if @project.builds_enabled?
+ data[:tabs].insert(2, ['pipelines', _('Pipelines'), pipelines_project_merge_request_path(@project, @merge_request), @number_of_pipelines])
+ end
+
+ data
+ end
end
MergeRequestsHelper.prepend_mod_with('MergeRequestsHelper')
diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb
index dc7d8049556..b017c9a81d1 100644
--- a/app/helpers/nav/new_dropdown_helper.rb
+++ b/app/helpers/nav/new_dropdown_helper.rb
@@ -135,7 +135,7 @@ module Nav
id: 'general_new_group',
title: _('New group'),
href: new_group_path,
- data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown' }
+ data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_group_link' }
)
)
end
diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb
index efec6f2d0d8..32d3f4aebb4 100644
--- a/app/helpers/nav/top_nav_helper.rb
+++ b/app/helpers/nav/top_nav_helper.rb
@@ -48,6 +48,13 @@ module Nav
private
+ def top_nav_localized_headers
+ {
+ explore: s_('TopNav|Explore'),
+ switch_to: s_('TopNav|Switch to')
+ }.freeze
+ end
+
def build_base_view_model(builder:, project:, group:)
if current_user
build_view_model(builder: builder, project: project, group: group)
@@ -60,6 +67,7 @@ module Nav
# 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],
href: explore_root_path,
active: nav == 'project' || active_nav_link?(path: %w[dashboard#show root#show projects#trending projects#starred projects#index]),
**projects_menu_item_attrs
@@ -68,6 +76,7 @@ module Nav
if explore_nav_link?(:groups)
builder.add_primary_menu_item_with_shortcut(
+ header: top_nav_localized_headers[:explore],
href: explore_groups_path,
active: nav == 'group' || active_nav_link?(controller: [:groups, 'groups/milestones', 'groups/group_members']),
**groups_menu_item_attrs
@@ -76,6 +85,7 @@ module Nav
if explore_nav_link?(:snippets)
builder.add_primary_menu_item_with_shortcut(
+ header: top_nav_localized_headers[:explore],
active: active_nav_link?(controller: :snippets),
href: explore_snippets_path,
**snippets_menu_item_attrs
@@ -89,6 +99,7 @@ module Nav
current_item = project ? current_project(project: project) : {}
builder.add_primary_menu_item_with_shortcut(
+ header: top_nav_localized_headers[:switch_to],
active: nav == 'project' || active_nav_link?(path: %w[root#index projects#trending projects#starred dashboard/projects#index]),
css_class: 'qa-projects-dropdown',
data: { track_label: "projects_dropdown", track_action: "click_dropdown" },
@@ -103,6 +114,7 @@ module Nav
current_item = group ? current_group(group: group) : {}
builder.add_primary_menu_item_with_shortcut(
+ header: top_nav_localized_headers[:switch_to],
active: nav == 'group' || active_nav_link?(path: %w[dashboard/groups explore/groups]),
css_class: 'qa-groups-dropdown',
data: { track_label: "groups_dropdown", track_action: "click_dropdown" },
@@ -116,6 +128,7 @@ module Nav
if dashboard_nav_link?(:milestones)
builder.add_primary_menu_item_with_shortcut(
id: 'milestones',
+ header: top_nav_localized_headers[:explore],
title: _('Milestones'),
href: dashboard_milestones_path,
active: active_nav_link?(controller: 'dashboard/milestones'),
@@ -127,6 +140,7 @@ module Nav
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') },
href: dashboard_snippets_path,
@@ -137,6 +151,7 @@ module Nav
if dashboard_nav_link?(:activity)
builder.add_primary_menu_item_with_shortcut(
id: 'activity',
+ header: top_nav_localized_headers[:explore],
title: _('Activity'),
href: activity_dashboard_path,
active: active_nav_link?(path: 'dashboard#activity'),
@@ -266,52 +281,74 @@ module Nav
end
def projects_submenu_items(builder:)
- # These project links come from `app/views/layouts/nav/projects_dropdown/_show.html.haml`
- [
- { id: 'your', title: _('Your projects'), href: dashboard_projects_path },
- { id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path },
- { id: 'explore', title: _('Explore projects'), href: explore_root_path },
- { id: 'topics', title: _('Explore topics'), href: topics_explore_projects_path }
- ].each do |item|
+ if Feature.enabled?(:remove_extra_primary_submenu_options)
+ title = _('View all projects')
+
builder.add_primary_menu_item(
- **item,
- data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) }
+ id: 'your',
+ title: title,
+ href: dashboard_projects_path,
+ data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
)
- end
+ else
+ # These project links come from `app/views/layouts/nav/projects_dropdown/_show.html.haml`
+ [
+ { id: 'your', title: _('Your projects'), href: dashboard_projects_path },
+ { id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path },
+ { id: 'explore', title: _('Explore projects'), href: explore_root_path },
+ { id: 'topics', title: _('Explore topics'), href: topics_explore_projects_path }
+ ].each do |item|
+ builder.add_primary_menu_item(
+ **item,
+ data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) }
+ )
+ end
- title = _('Create new project')
+ title = _('Create new project')
- builder.add_secondary_menu_item(
- id: 'create',
- title: title,
- href: new_project_path,
- data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
- )
+ builder.add_secondary_menu_item(
+ id: 'create',
+ title: title,
+ href: new_project_path,
+ data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
+ )
+ end
end
def groups_submenu
# These group links come from `app/views/layouts/nav/groups_dropdown/_show.html.haml`
builder = ::Gitlab::Nav::TopNavMenuBuilder.new
- [
- { id: 'your', title: _('Your groups'), href: dashboard_groups_path },
- { id: 'explore', title: _('Explore groups'), href: explore_groups_path }
- ].each do |item|
- builder.add_primary_menu_item(
- **item,
- data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) }
- )
- end
+ if Feature.enabled?(:remove_extra_primary_submenu_options)
+ title = _('View all groups')
- if current_user.can_create_group?
- title = _('Create group')
-
- builder.add_secondary_menu_item(
- id: 'create',
+ builder.add_primary_menu_item(
+ id: 'your',
title: title,
- href: new_group_path,
+ href: dashboard_groups_path,
data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
)
+ else
+ [
+ { id: 'your', title: _('Your groups'), href: dashboard_groups_path },
+ { id: 'explore', title: _('Explore groups'), href: explore_groups_path }
+ ].each do |item|
+ builder.add_primary_menu_item(
+ **item,
+ data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) }
+ )
+ end
+
+ if current_user.can_create_group?
+ title = _('Create group')
+
+ builder.add_secondary_menu_item(
+ id: 'create',
+ title: title,
+ href: new_group_path,
+ data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
+ )
+ end
end
builder.build
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
index c0ba93f4a30..b7ab1c2e2d1 100644
--- a/app/helpers/notify_helper.rb
+++ b/app/helpers/notify_helper.rb
@@ -20,4 +20,15 @@ module NotifyHelper
(source.description || default_description).truncate(200, separator: ' ')
end
+
+ def merge_request_hash_param(merge_request, reviewer)
+ {
+ mr_highlight: '<span style="font-weight: 600;color:#333333;">'.html_safe,
+ highlight_end: '</span>'.html_safe,
+ mr_link: link_to(merge_request.to_reference, merge_request_url(merge_request), style: "font-weight: 600;color:#3777b0;text-decoration:none").html_safe,
+ reviewer_highlight: '<span>'.html_safe,
+ reviewer_avatar: content_tag(:img, nil, height: "24", src: avatar_icon_for_user(reviewer, 24, only_path: false), style: "border-radius:12px;margin:-7px 0 -7px 3px;", width: "24", alt: "Avatar", class: "avatar").html_safe,
+ reviewer_link: link_to(reviewer.name, user_url(reviewer), style: "color:#333333;text-decoration:none;", class: "muted").html_safe
+ }
+ end
end
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index b52357bc891..f9ec20bdd01 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -73,6 +73,7 @@ module PackagesHelper
older_than_options: older_than_options.to_json,
is_admin: current_user&.admin.to_s,
admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
+ project_settings_path: project_settings_packages_and_registries_path(@project),
enable_historic_entries: container_expiration_policies_historic_entry_enabled?.to_s,
help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy'),
show_cleanup_policy_link: show_cleanup_policy_link(@project).to_s,
@@ -83,7 +84,8 @@ module PackagesHelper
def settings_data
cleanup_settings_data.merge(
show_container_registry_settings: show_container_registry_settings(@project).to_s,
- show_package_registry_settings: show_package_registry_settings(@project).to_s
+ show_package_registry_settings: show_package_registry_settings(@project).to_s,
+ cleanup_settings_path: cleanup_image_tags_project_settings_packages_and_registries_path(@project)
)
end
end
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 0c057a29bec..c0665463706 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -150,6 +150,10 @@ module PageLayoutHelper
css_class.join(' ')
end
+ def full_content_class
+ "#{container_class} #{@content_class}" # rubocop:disable Rails/HelperInstanceVariable
+ end
+
def page_itemtype(itemtype = nil)
if itemtype
@page_itemtype = { itemscope: true, itemtype: itemtype }
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 104026ff21e..bfe39bbc211 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -53,7 +53,7 @@ module ProfilesHelper
# Overridden in EE::ProfilesHelper#ssh_key_expires_field_description
def ssh_key_expires_field_description
- s_('Profiles|Key becomes invalid on this date.')
+ s_('Profiles|Optional but recommended. If set, key becomes invalid on the specified date.')
end
# Overridden in EE::ProfilesHelper#ssh_key_expiration_policy_enabled?
diff --git a/app/helpers/projects/google_cloud/cloudsql_helper.rb b/app/helpers/projects/google_cloud/cloudsql_helper.rb
new file mode 100644
index 00000000000..0c24254d9b4
--- /dev/null
+++ b/app/helpers/projects/google_cloud/cloudsql_helper.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+module Projects
+ module GoogleCloud
+ module CloudsqlHelper
+ # Sources:
+ # - https://cloud.google.com/sql/docs/postgres/instance-settings
+ # - https://cloud.google.com/sql/docs/mysql/instance-settings
+ # - https://cloud.google.com/sql/docs/sqlserver/instance-settings
+
+ TIERS = [
+ { value: 'db-custom-1-3840', label: '1 vCPU, 3840 MB RAM - Standard' },
+ { value: 'db-custom-2-7680', label: '2 vCPU, 7680 MB RAM - Standard' },
+ { value: 'db-custom-2-13312', label: '2 vCPU, 13312 MB RAM - High memory' },
+ { value: 'db-custom-4-15360', label: '4 vCPU, 15360 MB RAM - Standard' },
+ { value: 'db-custom-4-26624', label: '4 vCPU, 26624 MB RAM - High memory' },
+ { value: 'db-custom-8-30720', label: '8 vCPU, 30720 MB RAM - Standard' },
+ { value: 'db-custom-8-53248', label: '8 vCPU, 53248 MB RAM - High memory' },
+ { value: 'db-custom-16-61440', label: '16 vCPU, 61440 MB RAM - Standard' },
+ { value: 'db-custom-16-106496', label: '16 vCPU, 106496 MB RAM - High memory' },
+ { value: 'db-custom-32-122880', label: '32 vCPU, 122880 MB RAM - Standard' },
+ { value: 'db-custom-32-212992', label: '32 vCPU, 212992 MB RAM - High memory' },
+ { value: 'db-custom-64-245760', label: '64 vCPU, 245760 MB RAM - Standard' },
+ { value: 'db-custom-64-425984', label: '64 vCPU, 425984 MB RAM - High memory' },
+ { value: 'db-custom-96-368640', label: '96 vCPU, 368640 MB RAM - Standard' },
+ { value: 'db-custom-96-638976', label: '96 vCPU, 638976 MB RAM - High memory' }
+ ].freeze
+
+ VERSIONS = {
+ postgres: [
+ { value: 'POSTGRES_14', label: 'PostgreSQL 14' },
+ { value: 'POSTGRES_13', label: 'PostgreSQL 13' },
+ { value: 'POSTGRES_12', label: 'PostgreSQL 12' },
+ { value: 'POSTGRES_11', label: 'PostgreSQL 11' },
+ { value: 'POSTGRES_10', label: 'PostgreSQL 10' },
+ { value: 'POSTGRES_9_6', label: 'PostgreSQL 9.6' }
+ ],
+ mysql: [
+ { value: 'MYSQL_8_0', label: 'MySQL 8' },
+ { value: 'MYSQL_5_7', label: 'MySQL 5.7' },
+ { value: 'MYSQL_5_6', label: 'MySQL 5.6' }
+ ],
+ sqlserver: [
+ { value: 'SQLSERVER_2017_STANDARD', label: 'SQL Server 2017 Standard' },
+ { value: 'SQLSERVER_2017_ENTERPRISE', label: 'SQL Server 2017 Enterprise' },
+ { value: 'SQLSERVER_2017_EXPRESS', label: 'SQL Server 2017 Express' },
+ { value: 'SQLSERVER_2017_WEB', label: 'SQL Server 2017 Web' },
+ { value: 'SQLSERVER_2019_STANDARD', label: 'SQL Server 2019 Standard' },
+ { value: 'SQLSERVER_2019_ENTERPRISE', label: 'SQL Server 2019 Enterprise' },
+ { value: 'SQLSERVER_2019_EXPRESS', label: 'SQL Server 2019 Express' },
+ { value: 'SQLSERVER_2019_WEB', label: 'SQL Server 2019 Web' }
+ ]
+ }.freeze
+ end
+ end
+end
diff --git a/app/helpers/projects/pages_helper.rb b/app/helpers/projects/pages_helper.rb
new file mode 100644
index 00000000000..f46c11db1db
--- /dev/null
+++ b/app/helpers/projects/pages_helper.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Projects
+ module PagesHelper
+ def can_create_pages_custom_domains?(current_user, project)
+ current_user.can?(:update_pages, project) &&
+ (Gitlab.config.pages.external_http || Gitlab.config.pages.external_https) &&
+ project.can_create_custom_domains?
+ end
+ end
+end
diff --git a/app/helpers/projects/pipeline_helper.rb b/app/helpers/projects/pipeline_helper.rb
index 5f2a9f7bf21..c72beb4d722 100644
--- a/app/helpers/projects/pipeline_helper.rb
+++ b/app/helpers/projects/pipeline_helper.rb
@@ -6,7 +6,6 @@ module Projects
def js_pipeline_tabs_data(project, pipeline, _user)
{
- can_generate_codequality_reports: pipeline.can_generate_codequality_reports?.to_json,
failed_jobs_count: pipeline.failed_builds.count,
failed_jobs_summary: prepare_failed_jobs_summary_data(pipeline.failed_builds),
full_path: project.full_path,
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index dfc270adf8b..e760fad7be9 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -172,6 +172,7 @@ module ProjectsHelper
def project_list_cache_key(project, pipeline_status: true)
key = [
+ project.star_count,
project.route.cache_key,
project.cache_key,
project.last_activity_date,
@@ -389,7 +390,10 @@ module ProjectsHelper
pagesAccessControlForced: ::Gitlab::Pages.access_control_is_forced?,
pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control'),
issuesHelpPath: help_page_path('user/project/issues/index'),
- membersPagePath: project_project_members_path(project)
+ membersPagePath: project_project_members_path(project),
+ environmentsHelpPath: help_page_path('ci/environments/index'),
+ featureFlagsHelpPath: help_page_path('operations/feature_flags'),
+ releasesHelpPath: help_page_path('user/project/releases/index')
}
end
@@ -437,7 +441,6 @@ module ProjectsHelper
def show_inactive_project_deletion_banner?(project)
return false unless project.present? && project.saved?
return false unless delete_inactive_projects?
- return false unless Feature.enabled?(:inactive_projects_deletion, project.root_namespace)
project.inactive?
end
@@ -452,9 +455,9 @@ 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 November 2022. 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} or reach out to GitLab support.')
else
- s_('ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of November 2022. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}.')
+ 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
end
@@ -635,6 +638,7 @@ module ProjectsHelper
emailsDisabled: project.emails_disabled?,
metricsDashboardAccessLevel: feature.metrics_dashboard_access_level,
operationsAccessLevel: feature.operations_access_level,
+ monitorAccessLevel: feature.monitor_access_level,
showDefaultAwardEmojis: project.show_default_award_emojis?,
warnAboutPotentiallyUnwantedCharacters: project.warn_about_potentially_unwanted_characters?,
enforceAuthChecksOnUploads: project.enforce_auth_checks_on_uploads?,
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index dc53be330fe..b16235893ae 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -239,26 +239,26 @@ module SearchHelper
if can?(current_user, :download_code, @project)
result.concat([
- { category: "In this project", label: _("Files"), url: project_tree_path(@project, ref) },
- { category: "In this project", label: _("Commits"), url: project_commits_path(@project, ref) }
- ])
+ { category: "In this project", label: _("Files"), url: project_tree_path(@project, ref) },
+ { category: "In this project", label: _("Commits"), url: project_commits_path(@project, ref) }
+ ])
end
if can?(current_user, :read_repository_graphs, @project)
result.concat([
- { category: "In this project", label: _("Network"), url: project_network_path(@project, ref) },
- { category: "In this project", label: _("Graph"), url: project_graph_path(@project, ref) }
- ])
+ { category: "In this project", label: _("Network"), url: project_network_path(@project, ref) },
+ { category: "In this project", label: _("Graph"), url: project_graph_path(@project, ref) }
+ ])
end
result.concat([
- { category: "In this project", label: _("Issues"), url: project_issues_path(@project) },
- { category: "In this project", label: _("Merge requests"), url: project_merge_requests_path(@project) },
- { category: "In this project", label: _("Milestones"), url: project_milestones_path(@project) },
- { category: "In this project", label: _("Snippets"), url: project_snippets_path(@project) },
- { category: "In this project", label: _("Members"), url: project_project_members_path(@project) },
- { category: "In this project", label: _("Wiki"), url: project_wikis_path(@project) }
- ])
+ { category: "In this project", label: _("Issues"), url: project_issues_path(@project) },
+ { category: "In this project", label: _("Merge requests"), url: project_merge_requests_path(@project) },
+ { category: "In this project", label: _("Milestones"), url: project_milestones_path(@project) },
+ { category: "In this project", label: _("Snippets"), url: project_snippets_path(@project) },
+ { category: "In this project", label: _("Members"), url: project_project_members_path(@project) },
+ { category: "In this project", label: _("Wiki"), url: project_wikis_path(@project) }
+ ])
if can?(current_user, :read_feature_flag, @project)
result << { category: "In this project", label: _("Feature Flags"), url: project_feature_flags_path(@project) }
@@ -294,13 +294,13 @@ module SearchHelper
return [] unless issue && Ability.allowed?(current_user, :read_issue, issue)
[
- {
- category: 'In this project',
- id: issue.id,
- label: search_result_sanitize("#{issue.title} (#{issue.to_reference})"),
- url: issue_path(issue),
- avatar_url: issue.project.avatar_url || ''
- }
+ {
+ category: 'In this project',
+ id: issue.id,
+ label: search_result_sanitize("#{issue.title} (#{issue.to_reference})"),
+ url: issue_path(issue),
+ avatar_url: issue.project.avatar_url || ''
+ }
]
end
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 58f0af883f5..a711f36fe05 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -157,7 +157,9 @@ module SortingHelper
{
sort_value_name => sort_title_name,
sort_value_oldest_updated => sort_title_oldest_updated,
- sort_value_recently_updated => sort_title_recently_updated
+ sort_value_recently_updated => sort_title_recently_updated,
+ sort_value_version_desc => sort_title_version_desc,
+ sort_value_version_asc => sort_title_version_asc
}
end
diff --git a/app/helpers/sorting_titles_values_helper.rb b/app/helpers/sorting_titles_values_helper.rb
index 4dfa7689110..b49cb617d80 100644
--- a/app/helpers/sorting_titles_values_helper.rb
+++ b/app/helpers/sorting_titles_values_helper.rb
@@ -86,6 +86,14 @@ module SortingTitlesValuesHelper
s_('SortOptions|Name, descending')
end
+ def sort_title_version_desc
+ s_('SortOptions|Latest version')
+ end
+
+ def sort_title_version_asc
+ s_('SortOptions|Oldest version')
+ end
+
def sort_title_oldest_activity
s_('SortOptions|Oldest updated')
end
@@ -275,6 +283,14 @@ module SortingTitlesValuesHelper
'updated_asc'
end
+ def sort_value_version_asc
+ 'version_asc'
+ end
+
+ def sort_value_version_desc
+ 'version_desc'
+ end
+
def sort_value_popularity
'popularity'
end
diff --git a/app/helpers/storage_helper.rb b/app/helpers/storage_helper.rb
index 9e516d726c1..a60143db739 100644
--- a/app/helpers/storage_helper.rb
+++ b/app/helpers/storage_helper.rb
@@ -23,119 +23,4 @@ module StorageHelper
_("Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}") % counters
end
-
- def storage_enforcement_banner_info(context)
- root_ancestor = context.root_ancestor
-
- return unless should_show_storage_enforcement_banner?(context, current_user, root_ancestor)
-
- text_args = storage_enforcement_banner_text_args(root_ancestor, context)
-
- text_paragraph_2 = if root_ancestor.user_namespace?
- html_escape_once(s_("UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. " \
- "View and manage your usage from %{strong_start}User settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more%{link_end} " \
- "about how to reduce your storage.")).html_safe % text_args[:p2]
- else
- html_escape_once(s_("UsageQuota|The namespace is currently using %{strong_start}%{used_storage}%{strong_end} of namespace storage. " \
- "Group owners can view namespace storage usage and purchase more from %{strong_start}Group settings &gt; Usage quotas%{strong_end}. %{docs_link_start}Learn more.%{link_end}" \
- )).html_safe % text_args[:p2]
- end
-
- {
- text_paragraph_1: html_escape_once(s_("UsageQuota|Effective %{storage_enforcement_date}, namespace storage limits will apply " \
- "to the %{strong_start}%{namespace_name}%{strong_end} namespace. %{extra_message}" \
- "View the %{rollout_link_start}rollout schedule for this change%{link_end}.")).html_safe % text_args[:p1],
- text_paragraph_2: text_paragraph_2,
- text_paragraph_3: html_escape_once(s_("UsageQuota|See our %{faq_link_start}FAQ%{link_end} for more information.")).html_safe % text_args[:p3],
- variant: 'warning',
- namespace_id: root_ancestor.id,
- callouts_path: root_ancestor.user_namespace? ? callouts_path : group_callouts_path,
- callouts_feature_name: storage_enforcement_banner_user_callouts_feature_name(root_ancestor)
- }
- end
-
- private
-
- def should_show_storage_enforcement_banner?(context, current_user, root_ancestor)
- return false unless user_allowed_storage_enforcement_banner?(context, current_user, root_ancestor)
- return false if root_ancestor.paid?
- return false unless future_enforcement_date?(root_ancestor)
- return false if user_dismissed_storage_enforcement_banner?(root_ancestor)
-
- ::Feature.enabled?(:namespace_storage_limit_show_preenforcement_banner, root_ancestor)
- end
-
- def user_allowed_storage_enforcement_banner?(context, current_user, root_ancestor)
- return can?(current_user, :maintainer_access, context) unless context.respond_to?(:user_namespace?) && context.user_namespace?
-
- can?(current_user, :owner_access, context)
- end
-
- def storage_enforcement_banner_text_args(root_ancestor, context)
- strong_tags = {
- strong_start: "<strong>".html_safe,
- strong_end: "</strong>".html_safe
- }
-
- extra_message = if context.is_a?(Project)
- html_escape_once(s_("UsageQuota|The %{strong_start}%{context_name}%{strong_end} project will be affected by this. "))
- .html_safe % strong_tags.merge(context_name: context.name)
- elsif !context.root?
- html_escape_once(s_("UsageQuota|The %{strong_start}%{context_name}%{strong_end} group will be affected by this. "))
- .html_safe % strong_tags.merge(context_name: context.name)
- else
- ''
- end
-
- {
- p1: {
- storage_enforcement_date: root_ancestor.storage_enforcement_date,
- namespace_name: root_ancestor.name,
- extra_message: extra_message,
- rollout_link_start: '<a href="%{url}" >'.html_safe % { url: help_page_path('user/usage_quotas', anchor: 'namespace-storage-limit-enforcement-schedule') },
- link_end: "</a>".html_safe
- }.merge(strong_tags),
- p2: {
- used_storage: storage_counter(root_ancestor.root_storage_statistics&.storage_size || 0),
- docs_link_start: '<a href="%{url}" >'.html_safe % { url: help_page_path('user/usage_quotas', anchor: 'manage-your-storage-usage') },
- link_end: "</a>".html_safe
- }.merge(strong_tags),
- p3: {
- faq_link_start: '<a href="%{url}" >'.html_safe % { url: "#{Gitlab::Saas.about_pricing_url}faq-efficient-free-tier/#storage-limits-on-gitlab-saas-free-tier" },
- link_end: "</a>".html_safe
- }
- }
- end
-
- def storage_enforcement_banner_user_callouts_feature_name(namespace)
- "storage_enforcement_banner_#{storage_enforcement_banner_threshold(namespace)}_enforcement_threshold"
- end
-
- def storage_enforcement_banner_threshold(namespace)
- days_to_enforcement_date = (namespace.storage_enforcement_date - Date.today)
-
- return :first if days_to_enforcement_date > 30
- return :second if days_to_enforcement_date > 15 && days_to_enforcement_date <= 30
- return :third if days_to_enforcement_date > 7 && days_to_enforcement_date <= 15
- return :fourth if days_to_enforcement_date >= 0 && days_to_enforcement_date <= 7
- end
-
- def user_dismissed_storage_enforcement_banner?(namespace)
- return false unless current_user
-
- if namespace.user_namespace?
- current_user.dismissed_callout?(feature_name: storage_enforcement_banner_user_callouts_feature_name(namespace))
- else
- current_user.dismissed_callout_for_group?(
- feature_name: storage_enforcement_banner_user_callouts_feature_name(namespace),
- group: namespace
- )
- end
- end
-
- def future_enforcement_date?(namespace)
- return true if ::Feature.enabled?(:namespace_storage_limit_bypass_date_check, namespace)
-
- namespace.storage_enforcement_date.present? && namespace.storage_enforcement_date >= Date.today
- end
end
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index a957c9ce9e0..3e5f63796b2 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -45,7 +45,11 @@ module SystemNoteHelper
'attention_requested' => 'user',
'attention_request_removed' => 'user',
'contact' => 'users',
- 'timeline_event' => 'clock'
+ 'timeline_event' => 'clock',
+ 'relate_to_child' => 'link',
+ 'unrelate_from_child' => 'link',
+ 'relate_to_parent' => 'link',
+ 'unrelate_from_parent' => 'link'
}.freeze
def system_note_icon_name(note)
diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb
index 39993bbfb44..11d09a79dcf 100644
--- a/app/helpers/timeboxes_helper.rb
+++ b/app/helpers/timeboxes_helper.rb
@@ -172,18 +172,19 @@ module TimeboxesHelper
def timebox_date_range(timebox)
if timebox.start_date && timebox.due_date
- "#{timebox.start_date.to_s(:medium)}–#{timebox.due_date.to_s(:medium)}"
+ s_("DateRange|%{start_date}–%{end_date}") % { start_date: l(timebox.start_date, format: Date::DATE_FORMATS[:medium]),
+ end_date: l(timebox.due_date, format: Date::DATE_FORMATS[:medium]) }
elsif timebox.due_date
if timebox.due_date.past?
- _("expired on %{timebox_due_date}") % { timebox_due_date: timebox.due_date.to_s(:medium) }
+ _("expired on %{timebox_due_date}") % { timebox_due_date: l(timebox.due_date, format: Date::DATE_FORMATS[:medium]) }
else
- _("expires on %{timebox_due_date}") % { timebox_due_date: timebox.due_date.to_s(:medium) }
+ _("expires on %{timebox_due_date}") % { timebox_due_date: l(timebox.due_date, format: Date::DATE_FORMATS[:medium]) }
end
elsif timebox.start_date
if timebox.start_date.past?
- _("started on %{timebox_start_date}") % { timebox_start_date: timebox.start_date.to_s(:medium) }
+ _("started on %{timebox_start_date}") % { timebox_start_date: l(timebox.start_date, format: Date::DATE_FORMATS[:medium]) }
else
- _("starts on %{timebox_start_date}") % { timebox_start_date: timebox.start_date.to_s(:medium) }
+ _("starts on %{timebox_start_date}") % { timebox_start_date: l(timebox.start_date, format: Date::DATE_FORMATS[:medium]) }
end
end
end
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index 5977f51cab1..ecf29c41100 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -142,6 +142,16 @@ module TodosHelper
todos_filter_params.values.none?
end
+ def no_todos_messages
+ [
+ s_('Todos|Good job! Looks like you don\'t have anything left on your To-Do List'),
+ s_('Todos|Isn\'t an empty To-Do List beautiful?'),
+ s_('Todos|Give yourself a pat on the back!'),
+ s_('Todos|Nothing left to do. High five!'),
+ s_('Todos|Henceforth, you shall be known as "To-Do Destroyer"')
+ ]
+ end
+
def todos_filter_path(options = {})
without = options.delete(:without)
diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb
index 3dd6b3f4a80..d8baa185370 100644
--- a/app/helpers/users/callouts_helper.rb
+++ b/app/helpers/users/callouts_helper.rb
@@ -10,8 +10,10 @@ module Users
REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout'
UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout'
SECURITY_NEWSLETTER_CALLOUT = 'security_newsletter_callout'
+ MERGE_REQUEST_SETTINGS_MOVED_CALLOUT = 'merge_request_settings_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'
def show_gke_cluster_integration_callout?(project)
active_nav_link?(controller: sidebar_operations_paths) &&
@@ -71,18 +73,28 @@ module Users
last_failure = DateTime.parse(last_failure) if last_failure
- user_dismissed?(WEB_HOOK_DISABLED, last_failure, namespace: project.namespace)
+ user_dismissed?(WEB_HOOK_DISABLED, last_failure, project: project)
+ end
+
+ def show_merge_request_settings_callout?
+ !user_dismissed?(MERGE_REQUEST_SETTINGS_MOVED_CALLOUT)
+ end
+
+ def ultimate_feature_removal_banner_dismissed?(project)
+ return false unless project
+
+ user_dismissed?(ULTIMATE_FEATURE_REMOVAL_BANNER, project: project)
end
private
- def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil, namespace: nil)
+ def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil, project: nil)
return false unless current_user
query = { feature_name: feature_name, ignore_dismissal_earlier_than: ignore_dismissal_earlier_than }
- if namespace
- current_user.dismissed_callout_for_namespace?(namespace: namespace, **query)
+ if project
+ current_user.dismissed_callout_for_project?(project: project, **query)
else
current_user.dismissed_callout?(**query)
end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index cae2addea9c..271fa47dd97 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -18,10 +18,11 @@ module UsersHelper
return _('We also use email for avatar detection if no avatar is uploaded.') unless user.unconfirmed_email.present?
confirmation_link = link_to _('Resend confirmation e-mail'), user_confirmation_path(user: { email: user.unconfirmed_email }), method: :post
-
- h(_('Please click the link in the confirmation email before continuing. It was sent to ')) +
- content_tag(:strong) { user.unconfirmed_email } + h('.') +
- content_tag(:p) { confirmation_link }
+ h(_('Please click the link in the confirmation email before continuing. It was sent to %{html_tag_strong_start}%{email}%{html_tag_strong_end}.')) % {
+ html_tag_strong_start: '<strong>'.html_safe,
+ html_tag_strong_end: '</strong>'.html_safe,
+ email: user.unconfirmed_email
+ } + content_tag(:p) { confirmation_link }
end
def profile_tabs
@@ -93,6 +94,7 @@ module UsersHelper
[].tap do |badges|
badges << blocked_user_badge(user) if user.blocked?
badges << { text: s_('AdminUsers|Admin'), variant: 'success' } if user.admin?
+ badges << { text: s_('AdminUsers|Bot'), variant: 'muted' } if user.bot?
badges << { text: s_('AdminUsers|External'), variant: 'secondary' } if user.external?
badges << { text: s_("AdminUsers|It's you!"), variant: 'muted' } if current_user == user
badges << { text: s_("AdminUsers|Locked"), variant: 'warning' } if user.access_locked?
@@ -197,6 +199,9 @@ module UsersHelper
banned_badge = { text: s_('AdminUsers|Banned'), variant: 'danger' }
return banned_badge if user.banned?
+ ldap_blocked_badge = { text: s_('AdminUsers|LDAP Blocked'), variant: 'danger' }
+ return ldap_blocked_badge if user.ldap_blocked?
+
{ text: s_('AdminUsers|Blocked'), variant: 'danger' }
end
diff --git a/app/helpers/web_hooks/web_hooks_helper.rb b/app/helpers/web_hooks/web_hooks_helper.rb
index 95122750c2f..e95b90c69ef 100644
--- a/app/helpers/web_hooks/web_hooks_helper.rb
+++ b/app/helpers/web_hooks/web_hooks_helper.rb
@@ -5,6 +5,7 @@ module WebHooks
EXPIRY_TTL = 1.hour
def show_project_hook_failed_callout?(project:)
+ return false if project_hook_page?
return false unless current_user
return false unless Feature.enabled?(:webhooks_failed_callout, project)
return false unless Feature.enabled?(:web_hooks_disable_failed, project)
@@ -23,5 +24,9 @@ module WebHooks
ProjectHook.for_projects(project).disabled.exists?
end
end
+
+ def project_hook_page?
+ current_controller?('projects/hooks') || current_controller?('projects/hook_logs')
+ end
end
end