summaryrefslogtreecommitdiff
path: root/app/helpers
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 13:37:47 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 13:37:47 +0000
commitaee0a117a889461ce8ced6fcf73207fe017f1d99 (patch)
tree891d9ef189227a8445d83f35c1b0fc99573f4380 /app/helpers
parent8d46af3258650d305f53b819eabf7ab18d22f59e (diff)
downloadgitlab-ce-aee0a117a889461ce8ced6fcf73207fe017f1d99.tar.gz
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/access_tokens_helper.rb23
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/auth_helper.rb34
-rw-r--r--app/helpers/badges_helper.rb99
-rw-r--r--app/helpers/blame_helper.rb15
-rw-r--r--app/helpers/boards_helper.rb9
-rw-r--r--app/helpers/ci/jobs_helper.rb7
-rw-r--r--app/helpers/ci/runners_helper.rb2
-rw-r--r--app/helpers/diff_helper.rb2
-rw-r--r--app/helpers/export_helper.rb2
-rw-r--r--app/helpers/form_helper.rb8
-rw-r--r--app/helpers/ide_helper.rb2
-rw-r--r--app/helpers/integrations_helper.rb54
-rw-r--r--app/helpers/invite_members_helper.rb36
-rw-r--r--app/helpers/issuables_description_templates_helper.rb2
-rw-r--r--app/helpers/issuables_helper.rb11
-rw-r--r--app/helpers/issues_helper.rb4
-rw-r--r--app/helpers/jira_connect_helper.rb3
-rw-r--r--app/helpers/learn_gitlab_helper.rb7
-rw-r--r--app/helpers/markup_helper.rb2
-rw-r--r--app/helpers/merge_requests_helper.rb2
-rw-r--r--app/helpers/namespaces_helper.rb18
-rw-r--r--app/helpers/nav/new_dropdown_helper.rb11
-rw-r--r--app/helpers/notifications_helper.rb1
-rw-r--r--app/helpers/notify_helper.rb17
-rw-r--r--app/helpers/operations_helper.rb2
-rw-r--r--app/helpers/packages_helper.rb11
-rw-r--r--app/helpers/profiles_helper.rb5
-rw-r--r--app/helpers/projects/cluster_agents_helper.rb3
-rw-r--r--app/helpers/projects_helper.rb19
-rw-r--r--app/helpers/routing/graphql_helper.rb4
-rw-r--r--app/helpers/routing/pseudonymization_helper.rb11
-rw-r--r--app/helpers/sorting_helper.rb25
-rw-r--r--app/helpers/system_note_helper.rb4
-rw-r--r--app/helpers/tab_helper.rb36
-rw-r--r--app/helpers/time_zone_helper.rb5
-rw-r--r--app/helpers/tree_helper.rb2
-rw-r--r--app/helpers/user_callouts_helper.rb98
-rw-r--r--app/helpers/users/callouts_helper.rb71
-rw-r--r--app/helpers/users/group_callouts_helper.rb32
-rw-r--r--app/helpers/version_check_helper.rb2
-rw-r--r--app/helpers/x509_helper.rb2
42 files changed, 466 insertions, 241 deletions
diff --git a/app/helpers/access_tokens_helper.rb b/app/helpers/access_tokens_helper.rb
index 877ad6db576..1d38262159f 100644
--- a/app/helpers/access_tokens_helper.rb
+++ b/app/helpers/access_tokens_helper.rb
@@ -1,7 +1,30 @@
# frozen_string_literal: true
module AccessTokensHelper
+ include AccountsHelper
+ include ApplicationHelper
+
def scope_description(prefix)
prefix == :project_access_token ? [:doorkeeper, :project_access_token_scope_desc] : [:doorkeeper, :scope_desc]
end
+
+ def tokens_app_data
+ {
+ feed_token: {
+ enabled: !Gitlab::CurrentSettings.disable_feed_token,
+ token: current_user.feed_token,
+ reset_path: reset_feed_token_profile_path
+ },
+ incoming_email_token: {
+ enabled: incoming_email_token_enabled?,
+ token: current_user.enabled_incoming_email_token,
+ reset_path: reset_incoming_email_token_profile_path
+ },
+ static_object_token: {
+ enabled: static_objects_external_storage_enabled?,
+ token: current_user.enabled_static_object_token,
+ reset_path: reset_static_object_token_profile_path
+ }
+ }.to_json
+ end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 58f933a7fe0..02a87979f40 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -206,10 +206,6 @@ module ApplicationHelper
'https://' + promo_host
end
- def contact_sales_url
- promo_url + '/sales'
- end
-
def support_url
Gitlab::CurrentSettings.current_application_settings.help_page_support_url.presence || promo_url + '/getting-help/'
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 6fe92a5a978..c1a74382d46 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -86,6 +86,17 @@ module AuthHelper
auth_providers.select { |provider| form_based_provider?(provider) }
end
+ def saml_providers
+ auth_providers.select { |provider| auth_strategy_class(provider) == 'OmniAuth::Strategies::SAML' }
+ end
+
+ def auth_strategy_class(provider)
+ config = Gitlab::Auth::OAuth::Provider.config_for(provider)
+ return if config.nil? || config['args'].blank?
+
+ config.args['strategy_class']
+ end
+
def any_form_based_providers_enabled?
form_based_providers.any? { |provider| form_enabled_for_sign_in?(provider) }
end
@@ -164,10 +175,25 @@ module AuthHelper
end
def google_tag_manager_enabled?
- Gitlab.com? &&
- extra_config.has_key?('google_tag_manager_id') &&
- extra_config.google_tag_manager_id.present? &&
- !current_user
+ return false unless Gitlab.dev_env_or_com?
+
+ has_config_key = if Feature.enabled?(:gtm_nonce, type: :ops)
+ extra_config.has_key?('google_tag_manager_nonce_id') &&
+ extra_config.google_tag_manager_nonce_id.present?
+ else
+ extra_config.has_key?('google_tag_manager_id') &&
+ extra_config.google_tag_manager_id.present?
+ end
+
+ has_config_key && !current_user
+ end
+
+ def google_tag_manager_id
+ return unless google_tag_manager_enabled?
+
+ return extra_config.google_tag_manager_nonce_id if Feature.enabled?(:gtm_nonce, type: :ops)
+
+ extra_config.google_tag_manager_id
end
def auth_app_owner_text(owner)
diff --git a/app/helpers/badges_helper.rb b/app/helpers/badges_helper.rb
new file mode 100644
index 00000000000..a03f7f4097a
--- /dev/null
+++ b/app/helpers/badges_helper.rb
@@ -0,0 +1,99 @@
+# 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:
+ # # Plain text badge
+ # gl_badge_tag("foo")
+ #
+ # # Danger variant
+ # gl_badge_tag("foo", variant: :danger)
+ #
+ # # Small size
+ # gl_badge_tag("foo", size: :sm)
+ #
+ # # With icon
+ # gl_badge_tag("foo", icon: "question-o")
+ #
+ # # Icon-only
+ # gl_badge_tag("foo", icon: "question-o", icon_only: true)
+ #
+ # # Badge link
+ # gl_badge_tag("foo", nil, href: some_path)
+ #
+ # # Custom classes
+ # gl_badge_tag("foo", nil, class: "foo-bar")
+ #
+ # # Block content
+ # gl_badge_tag({ variant: :danger }, { class: "foo-bar" }) do
+ # "foo"
+ # end
+ #
+ # For accessibility, ensure that the given text or block is non-empty.
+ #
+ # See also https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-badge--default.
+ def gl_badge_tag(*args, &block)
+ if block_given?
+ build_gl_badge_tag(capture(&block), *args)
+ else
+ build_gl_badge_tag(*args)
+ 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)]
+
+ 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_ICON_CLASSES.dup
+ 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/blame_helper.rb b/app/helpers/blame_helper.rb
index 82c74e2416d..5117f7c6d9c 100644
--- a/app/helpers/blame_helper.rb
+++ b/app/helpers/blame_helper.rb
@@ -1,6 +1,13 @@
# frozen_string_literal: true
module BlameHelper
+ BODY_FONT_SIZE = "0.875rem"
+ COMMIT_LINE_HEIGHT = 3 # 150% * 2 lines of text
+ COMMIT_PADDING = "10px" # 5px from both top and bottom
+ COMMIT_BLOCK_HEIGHT_EXP = "(#{BODY_FONT_SIZE} * #{COMMIT_LINE_HEIGHT}) + #{COMMIT_PADDING}"
+ CODE_LINE_HEIGHT = 1.1875
+ CODE_PADDING = "20px" # 10px from both top and bottom
+
def age_map_duration(blame_groups, project)
now = Time.zone.now
start_date = blame_groups.map { |blame_group| blame_group[:commit].committed_date }
@@ -24,4 +31,12 @@ module BlameHelper
"blame-commit-age-#{age_group}"
end
end
+
+ def intrinsic_row_css(line_count)
+ # using rems here because the size of the row depends on the text size
+ # which can be customized via user agent styles and browser preferences
+ total_line_height_exp = "#{line_count * CODE_LINE_HEIGHT}rem + #{CODE_PADDING}"
+ row_height_exp = line_count == 1 ? COMMIT_BLOCK_HEIGHT_EXP : total_line_height_exp
+ "contain-intrinsic-size: 1px calc(#{row_height_exp})"
+ end
end
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index c26a73028b9..57da04b38cc 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -23,6 +23,7 @@ module BoardsHelper
labels_filter_base_path: build_issue_link_base,
labels_fetch_path: labels_fetch_path,
labels_manage_path: labels_manage_path,
+ releases_fetch_path: releases_fetch_path,
board_type: board.to_type
}
end
@@ -65,6 +66,14 @@ module BoardsHelper
end
end
+ def releases_fetch_path
+ if board.group_board?
+ group_releases_path(@group)
+ else
+ project_releases_path(@project)
+ end
+ end
+
def board_base_url
if board.group_board?
group_boards_url(@group)
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index d02fe3f20b0..c7f40decae8 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -19,6 +19,13 @@ module Ci
}
end
+ def bridge_data(build)
+ {
+ "build_name" => build.name,
+ "empty-state-illustration-path" => image_path('illustrations/job-trigger-md.svg')
+ }
+ end
+
def job_counts
{
"all" => limited_counter_with_delimiter(@all_builds),
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index 17057505173..8f219656b71 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -23,7 +23,7 @@ module Ci
icon = 'status-paused'
span_class = 'gl-text-gray-600'
end
- when :not_connected
+ when :not_connected, :never_contacted
title = s_("Runners|New runner, has not connected yet")
icon = 'warning-solid'
when :offline
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index ca5fe38576e..2b5f726dad1 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -283,7 +283,7 @@ module DiffHelper
return path unless path.size > max && max > 3
- "...#{path[-(max - 3)..-1]}"
+ "...#{path[-(max - 3)..]}"
end
def code_navigation_path(diffs)
diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb
index 92d06471384..2699681fed7 100644
--- a/app/helpers/export_helper.rb
+++ b/app/helpers/export_helper.rb
@@ -18,7 +18,7 @@ module ExportHelper
[
_('Milestones'),
_('Labels'),
- _('Boards and Board Lists'),
+ _('Boards and board lists'),
_('Badges'),
_('Subgroups')
]
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index 9b4d0c0b9b3..3a5dcb4e664 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -35,7 +35,7 @@ module FormHelper
def assignees_dropdown_options(issuable_type)
dropdown_data = {
toggle_class: 'js-user-search js-assignee-search js-multiselect js-save-user-data',
- title: 'Select assignee',
+ title: _('Select assignee'),
filter: true,
dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee',
placeholder: _('Search users'),
@@ -45,9 +45,9 @@ module FormHelper
current_user: true,
project_id: (@target_project || @project)&.id,
field_name: "#{issuable_type}[assignee_ids][]",
- default_label: 'Unassigned',
+ default_label: _('Unassigned'),
'max-select': 1,
- 'dropdown-header': 'Assignee',
+ 'dropdown-header': _('Assignee'),
multi_select: true,
'input-meta': 'name',
'always-show-selectbox': true,
@@ -123,7 +123,7 @@ module FormHelper
def multiple_assignees_dropdown_options(options)
new_options = options.dup
- new_options[:title] = 'Select assignee(s)'
+ new_options[:title] = _('Select assignee(s)')
new_options[:data][:'dropdown-header'] = 'Assignee(s)'
new_options[:data].delete(:'max-select')
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index 09ff57e2baf..4d81aeca37a 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -29,7 +29,7 @@ module IdeHelper
def convert_to_project_entity_json(project)
return unless project
- API::Entities::Project.represent(project).to_json
+ API::Entities::Project.represent(project, current_user: current_user).to_json
end
def enable_environments_guidance?
diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb
index bb4a7fef6be..c5e767c6f64 100644
--- a/app/helpers/integrations_helper.rb
+++ b/app/helpers/integrations_helper.rb
@@ -17,31 +17,31 @@ module IntegrationsHelper
"#{event}_events"
end
- def scoped_integrations_path
- if @project.present?
- project_settings_integrations_path(@project)
- elsif @group.present?
- group_settings_integrations_path(@group)
+ def scoped_integrations_path(project: nil, group: nil)
+ if project.present?
+ project_settings_integrations_path(project)
+ elsif group.present?
+ group_settings_integrations_path(group)
else
integrations_admin_application_settings_path
end
end
- def scoped_integration_path(integration)
- if @project.present?
- project_service_path(@project, integration)
- elsif @group.present?
- group_settings_integration_path(@group, integration)
+ def scoped_integration_path(integration, project: nil, group: nil)
+ if project.present?
+ project_service_path(project, integration)
+ elsif group.present?
+ group_settings_integration_path(group, integration)
else
admin_application_settings_integration_path(integration)
end
end
- def scoped_edit_integration_path(integration)
- if @project.present?
- edit_project_service_path(@project, integration)
- elsif @group.present?
- edit_group_settings_integration_path(@group, integration)
+ def scoped_edit_integration_path(integration, project: nil, group: nil)
+ if project.present?
+ edit_project_service_path(project, integration)
+ elsif group.present?
+ edit_group_settings_integration_path(group, integration)
else
edit_admin_application_settings_integration_path(integration)
end
@@ -51,11 +51,11 @@ module IntegrationsHelper
overrides_admin_application_settings_integration_path(integration, options)
end
- def scoped_test_integration_path(integration)
- if @project.present?
- test_project_service_path(@project, integration)
- elsif @group.present?
- test_group_settings_integration_path(@group, integration)
+ def scoped_test_integration_path(integration, project: nil, group: nil)
+ if project.present?
+ test_project_service_path(project, integration)
+ elsif group.present?
+ test_group_settings_integration_path(group, integration)
else
test_admin_application_settings_integration_path(integration)
end
@@ -71,7 +71,7 @@ module IntegrationsHelper
end
end
- def integration_form_data(integration, group: nil)
+ def integration_form_data(integration, project: nil, group: nil)
form_data = {
id: integration.id,
show_active: integration.show_active_box?.to_s,
@@ -87,9 +87,9 @@ module IntegrationsHelper
inherit_from_id: integration.inherit_from_id,
integration_level: integration_level(integration),
editable: integration.editable?.to_s,
- cancel_path: scoped_integrations_path,
+ cancel_path: scoped_integrations_path(project: project, group: group),
can_test: integration.testable?.to_s,
- test_path: scoped_test_integration_path(integration),
+ test_path: scoped_test_integration_path(integration, project: project, group: group),
reset_path: scoped_reset_integration_path(integration, group: group)
}
@@ -107,9 +107,9 @@ module IntegrationsHelper
}
end
- def integration_list_data(integrations)
+ def integration_list_data(integrations, group: nil, project: nil)
{
- integrations: integrations.map { |i| serialize_integration(i) }.to_json
+ integrations: integrations.map { |i| serialize_integration(i, group: group, project: project) }.to_json
}
end
@@ -215,13 +215,13 @@ module IntegrationsHelper
end
end
- def serialize_integration(integration)
+ def serialize_integration(integration, group: nil, project: nil)
{
active: integration.operating?,
title: integration.title,
description: integration.description,
updated_at: integration.updated_at,
- edit_path: scoped_edit_integration_path(integration),
+ edit_path: scoped_edit_integration_path(integration, group: group, project: project),
name: integration.to_param
}
end
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index 01ae0ce4f31..8b26b646fdd 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -35,14 +35,7 @@ module InviteMembersHelper
default_access_level: Gitlab::Access::GUEST
}
- experiment(:member_areas_of_focus, user: current_user) do |e|
- e.publish_to_database
-
- e.control { dataset.merge!(areas_of_focus_options: [], no_selection_areas_of_focus: []) }
- e.candidate { dataset.merge!(areas_of_focus_options: member_areas_of_focus_options.to_json, no_selection_areas_of_focus: ['no_selection']) }
- end
-
- if show_invite_members_for_task?
+ if show_invite_members_for_task?(source)
dataset.merge!(
tasks_to_be_done_options: tasks_to_be_done_options.to_json,
projects: projects_for_source(source).to_json,
@@ -55,35 +48,16 @@ module InviteMembersHelper
private
- def member_areas_of_focus_options
- [
- {
- value: 'Contribute to the codebase', text: s_('InviteMembersModal|Contribute to the codebase')
- },
- {
- value: 'Collaborate on open issues and merge requests', text: s_('InviteMembersModal|Collaborate on open issues and merge requests')
- },
- {
- value: 'Configure CI/CD', text: s_('InviteMembersModal|Configure CI/CD')
- },
- {
- value: 'Configure security features', text: s_('InviteMembersModal|Configure security features')
- },
- {
- value: 'Other', text: s_('InviteMembersModal|Other')
- }
- ]
- end
-
# Overridden in EE
def users_filter_data(group)
{}
end
- def show_invite_members_for_task?
- return unless current_user && experiment(:invite_members_for_task).enabled?
+ def show_invite_members_for_task?(source)
+ return unless current_user
- params[:open_modal] == 'invite_members_for_task'
+ invite_for_help_continuous_onboarding = source.is_a?(Project) && experiment(:invite_for_help_continuous_onboarding, namespace: source.namespace).variant.name == 'candidate'
+ params[:open_modal] == 'invite_members_for_task' || invite_for_help_continuous_onboarding
end
def tasks_to_be_done_options
diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb
index 6b546d5c6fc..6c23f888823 100644
--- a/app/helpers/issuables_description_templates_helper.rb
+++ b/app/helpers/issuables_description_templates_helper.rb
@@ -6,7 +6,7 @@ module IssuablesDescriptionTemplatesHelper
def template_dropdown_tag(issuable, &block)
selected_template = selected_template(issuable)
- title = selected_template || "Choose a template"
+ title = selected_template || _('Choose a template')
options = {
toggle_class: 'js-issuable-selector',
title: title,
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 07f5adae272..53a7487741e 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -80,7 +80,7 @@ module IssuablesHelper
def users_dropdown_label(selected_users)
case selected_users.length
when 0
- "Unassigned"
+ _('Unassigned')
when 1
selected_users[0].name
else
@@ -133,7 +133,7 @@ module IssuablesHelper
end
# rubocop: enable CodeReuse/ActiveRecord
- def milestone_dropdown_label(milestone_title, default_label = "Milestone")
+ def milestone_dropdown_label(milestone_title, default_label = _('Milestone'))
title =
case milestone_title
when Milestone::Upcoming.name then Milestone::Upcoming.title
@@ -188,7 +188,12 @@ module IssuablesHelper
end
def issuables_state_counter_text(issuable_type, state, display_count)
- titles = { opened: "Open" }
+ titles = {
+ opened: _("Open"),
+ closed: _("Closed"),
+ merged: _("Merged"),
+ all: _("All")
+ }
state_title = titles[state] || state.to_s.humanize
html = content_tag(:span, state_title)
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index a88ca6f6b11..cddf740a0e6 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -193,11 +193,13 @@ module IssuesHelper
{
can_create_issue: show_new_issue_link?(project).to_s,
can_create_incident: create_issue_type_allowed?(project, :incident).to_s,
+ can_destroy_issue: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable).to_s,
can_reopen_issue: can?(current_user, :reopen_issue, issuable).to_s,
can_report_spam: issuable.submittable_as_spam_by?(current_user).to_s,
can_update_issue: can?(current_user, :update_issue, issuable).to_s,
iid: issuable.iid,
is_issue_author: (issuable.author == current_user).to_s,
+ issue_path: issuable_path(issuable),
issue_type: issuable_display_type(issuable),
new_issue_path: new_project_issue_path(project, new_issuable_params),
project_path: project.full_path,
@@ -212,6 +214,8 @@ module IssuesHelper
calendar_path: url_for(safe_params.merge(calendar_url_options)),
empty_state_svg_path: image_path('illustrations/issues.svg'),
full_path: namespace.full_path,
+ is_anonymous_search_disabled: Feature.enabled?(:disable_anonymous_search, type: :ops).to_s,
+ is_issue_repositioning_disabled: issue_repositioning_disabled?.to_s,
is_signed_in: current_user.present?.to_s,
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
rss_path: url_for(safe_params.merge(rss_url_options)),
diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb
index 475469a6df9..9a0f0944fd1 100644
--- a/app/helpers/jira_connect_helper.rb
+++ b/app/helpers/jira_connect_helper.rb
@@ -8,7 +8,8 @@ module JiraConnectHelper
groups_path: api_v4_groups_path(params: { min_access_level: Gitlab::Access::MAINTAINER, skip_groups: skip_groups }),
subscriptions: subscriptions.map { |s| serialize_subscription(s) }.to_json,
subscriptions_path: jira_connect_subscriptions_path,
- users_path: current_user ? nil : jira_connect_users_path
+ 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
}
end
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
index 08a30c4d53b..7f8f6d77ff4 100644
--- a/app/helpers/learn_gitlab_helper.rb
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -10,7 +10,8 @@ module LearnGitlabHelper
def learn_gitlab_data(project)
{
actions: onboarding_actions_data(project).to_json,
- sections: onboarding_sections_data.to_json
+ sections: onboarding_sections_data.to_json,
+ project: onboarding_project_data(project).to_json
}
end
@@ -56,6 +57,10 @@ module LearnGitlabHelper
}
end
+ def onboarding_project_data(project)
+ { name: project.name }
+ end
+
def action_urls
LearnGitlab::Onboarding::ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) }
.merge(LearnGitlab::Onboarding::ACTION_DOC_URLS)
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index f185d6cd002..f16d9f6325b 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -181,7 +181,7 @@ module MarkupHelper
wiki: wiki,
repository: wiki.repository,
page_slug: wiki_page.slug,
- issuable_state_filter_enabled: true
+ issuable_reference_expansion_enabled: true
).merge(render_wiki_content_context_container(wiki))
end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index d5d692f2d6e..abb7128470f 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -182,7 +182,7 @@ module MergeRequestsHelper
project_path: project_path(merge_request.project),
changes_empty_state_illustration: image_path('illustrations/merge_request_changes_empty.svg'),
is_fluid_layout: fluid_layout.to_s,
- dismiss_endpoint: user_callouts_path,
+ dismiss_endpoint: callouts_path,
show_suggest_popover: show_suggest_popover?.to_s,
show_whitespace_default: @show_whitespace_default.to_s,
file_by_file_default: @file_by_file_default.to_s,
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index 106df168080..6acec417a75 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -88,6 +88,13 @@ module NamespacesHelper
group.namespace_settings.public_send(method_name, **args) # rubocop:disable GitlabSecurity/PublicSend
end
+ def namespaces_as_json(selected = :current_user)
+ {
+ group: formatted_namespaces(current_user.manageable_groups_with_routes),
+ user: formatted_namespaces([current_user.namespace])
+ }.to_json
+ end
+
private
# Many importers create a temporary Group, so use the real
@@ -119,6 +126,17 @@ module NamespacesHelper
[group_label.camelize, elements]
end
+
+ def formatted_namespaces(namespaces)
+ namespaces.sort_by(&:human_name).map! do |n|
+ {
+ id: n.id,
+ display_path: n.full_path,
+ human_name: n.human_name,
+ name: n.name
+ }
+ end
+ end
end
NamespacesHelper.prepend_mod_with('NamespacesHelper')
diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb
index e7d69c38a54..715a5a02b50 100644
--- a/app/helpers/nav/new_dropdown_helper.rb
+++ b/app/helpers/nav/new_dropdown_helper.rb
@@ -50,7 +50,7 @@ module Nav
menu_items.push(create_epic_menu_item(group))
- if Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can?(current_user, :admin_group_member, group)
+ if can?(current_user, :admin_group_member, group)
menu_items.push(
invite_members_menu_item(
href: group_group_members_path(group)
@@ -101,7 +101,7 @@ module Nav
)
end
- if Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can_admin_project_member?(project)
+ if can_admin_project_member?(project)
menu_items.push(
invite_members_menu_item(
href: project_project_members_path(project)
@@ -161,12 +161,11 @@ module Nav
::Gitlab::Nav::TopNavMenuItem.build(
id: 'invite',
title: s_('InviteMember|Invite members'),
- emoji: ('shaking_hands' if experiment_enabled?(:invite_members_new_dropdown)),
+ emoji: 'shaking_hands',
href: href,
data: {
- track_action: 'click_link',
- track_label: tracking_label,
- track_property: experiment_tracking_category_and_group(:invite_members_new_dropdown)
+ track_action: 'click_link_invite_members',
+ track_label: 'plus_menu_dropdown'
}
)
end
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 9db28b54fe9..ddaef4652b4 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -67,7 +67,6 @@ module NotificationsHelper
when :custom
_('You will only receive notifications for the events you choose')
when :owner_disabled
- # Any change must be reflected in board_sidebar_subscription.vue
_('Notifications have been disabled by the project or group owner')
end
end
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
index ed96f3cef4f..c0ba93f4a30 100644
--- a/app/helpers/notify_helper.rb
+++ b/app/helpers/notify_helper.rb
@@ -20,21 +20,4 @@ module NotifyHelper
(source.description || default_description).truncate(200, separator: ' ')
end
-
- def invited_join_url(token, member)
- additional_params = { invite_type: Emails::Members::INITIAL_INVITE }
-
- # order important below to our scheduled testing of these
- # `from` experiment will be after the `text` on, but we may not cleanup
- # from the `text` one by the time we run the `from` experiment,
- # therefore we want to support `text` being fully enabled
- # but if `from` is also enabled, then we only care about `from`
- if experiment(:invite_email_from, actor: member).enabled?
- additional_params[:experiment_name] = 'invite_email_from'
- elsif experiment(:invite_email_preview_text, actor: member).enabled?
- additional_params[:experiment_name] = 'invite_email_preview_text'
- end
-
- invite_url(token, additional_params)
- end
end
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index 5d2f225edcf..baeb9a477c3 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -16,7 +16,7 @@ module OperationsHelper
{
'prometheus_activated' => prometheus_integration.manual_configuration?.to_s,
- 'prometheus_form_path' => scoped_integration_path(prometheus_integration),
+ 'prometheus_form_path' => scoped_integration_path(prometheus_integration, project: prometheus_integration.project, group: prometheus_integration.group),
'prometheus_reset_key_path' => reset_alerting_token_project_settings_operations_path(@project),
'prometheus_authorization_key' => @project.alerting_setting&.token,
'prometheus_api_url' => prometheus_integration.api_url,
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index c69d9eb1326..66f80e7eeb8 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -38,17 +38,6 @@ module PackagesHelper
"#{Gitlab.config.gitlab.host}/#{group_id}"
end
- def packages_list_data(type, resource)
- {
- resource_id: resource.id,
- full_path: resource.full_path,
- page_type: type,
- empty_list_help_url: help_page_path('user/packages/package_registry/index'),
- empty_list_illustration: image_path('illustrations/no-packages.svg'),
- package_help_url: help_page_path('user/packages/index')
- }
- end
-
def track_package_event(event_name, scope, **args)
::Packages::CreateEventService.new(nil, current_user, event_name: event_name, scope: scope).execute
category = args.delete(:category) || self.class.name
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 09fc1ab9d50..0d514773891 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -61,6 +61,11 @@ module ProfilesHelper
def ssh_key_expires_field_description
s_('Profiles|Key can still be used after expiration.')
end
+
+ # Overridden in EE::ProfilesHelper#ssh_key_expiration_policy_enabled?
+ def ssh_key_expiration_policy_enabled?
+ false
+ end
end
ProfilesHelper.prepend_mod
diff --git a/app/helpers/projects/cluster_agents_helper.rb b/app/helpers/projects/cluster_agents_helper.rb
index 20fa721cc3b..aeeab250c7a 100644
--- a/app/helpers/projects/cluster_agents_helper.rb
+++ b/app/helpers/projects/cluster_agents_helper.rb
@@ -4,7 +4,8 @@ module Projects::ClusterAgentsHelper
def js_cluster_agent_details_data(agent_name, project)
{
agent_name: agent_name,
- project_path: project.full_path
+ project_path: project.full_path,
+ activity_empty_state_image: image_path('illustrations/empty-state/empty-state-agents.svg')
}
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 8366b25d2bc..827d2cb7164 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -120,6 +120,15 @@ module ProjectsHelper
{ project_full_name: project.full_name }
end
+ def remove_fork_project_confirm_json(project, remove_form_id)
+ {
+ remove_form_id: remove_form_id,
+ button_text: _('Remove fork relationship'),
+ confirm_danger_message: remove_fork_project_warning_message(project),
+ phrase: @project.path
+ }
+ end
+
def visible_fork_source(project)
project.fork_source if project.fork_source && can?(current_user, :read_project, project.fork_source)
end
@@ -405,6 +414,16 @@ module ProjectsHelper
project.path_with_namespace
end
+ def fork_button_disabled_tooltip(project)
+ return unless current_user
+
+ if !current_user.can?(:fork_project, project)
+ s_("ProjectOverview|You don't have permission to fork this project")
+ elsif !current_user.can?(:create_fork)
+ s_('ProjectOverview|You have reached your project limit')
+ end
+ end
+
private
def tab_ability_map
diff --git a/app/helpers/routing/graphql_helper.rb b/app/helpers/routing/graphql_helper.rb
index beefbb9b387..2e1d084e3cc 100644
--- a/app/helpers/routing/graphql_helper.rb
+++ b/app/helpers/routing/graphql_helper.rb
@@ -9,5 +9,9 @@ module Routing
def graphql_etag_pipeline_sha_path(sha)
[api_graphql_path, "pipelines/sha/#{sha}"].join(':')
end
+
+ def graphql_etag_project_on_demand_scan_counts_path(project)
+ [api_graphql_path, "on_demand_scan/counts/#{project.full_path}"].join(':')
+ end
end
end
diff --git a/app/helpers/routing/pseudonymization_helper.rb b/app/helpers/routing/pseudonymization_helper.rb
index ac30669dc83..fd9907edc37 100644
--- a/app/helpers/routing/pseudonymization_helper.rb
+++ b/app/helpers/routing/pseudonymization_helper.rb
@@ -3,7 +3,10 @@
module Routing
module PseudonymizationHelper
class MaskHelper
- QUERY_PARAMS_TO_NOT_MASK = %w[].freeze
+ QUERY_PARAMS_TO_NOT_MASK = %w[
+ scope
+ state
+ ].freeze
def initialize(request_object, group, project)
@request = request_object
@@ -69,12 +72,10 @@ module Routing
end
end
- def masked_page_url
+ def masked_page_url(group:, project:)
return unless Feature.enabled?(:mask_page_urls, type: :ops)
- current_group = group if defined?(group)
- current_project = project if defined?(project)
- mask_helper = MaskHelper.new(request, current_group, current_project)
+ mask_helper = MaskHelper.new(request, group, project)
mask_helper.mask_params
# We rescue all exception for time being till we test this helper extensively.
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index b28e5ff39b2..fb30e8ca059 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -70,6 +70,15 @@ module SortingHelper
options
end
+ def forks_sort_options_hash
+ {
+ sort_value_recently_created => sort_title_created_date,
+ sort_value_oldest_created => sort_title_created_date,
+ sort_value_latest_activity => sort_title_latest_activity,
+ sort_value_oldest_activity => sort_title_latest_activity
+ }
+ end
+
def projects_sort_option_titles
# Only used for the project filter search bar
projects_sort_options_hash.merge({
@@ -93,6 +102,15 @@ module SortingHelper
}
end
+ def forks_reverse_sort_options_hash
+ {
+ sort_value_recently_created => sort_value_oldest_created,
+ sort_value_oldest_created => sort_value_recently_created,
+ sort_value_latest_activity => sort_value_oldest_activity,
+ sort_value_oldest_activity => sort_value_latest_activity
+ }
+ end
+
def groups_sort_options_hash
{
sort_value_name => sort_title_name,
@@ -303,6 +321,13 @@ module SortingHelper
sort_direction_button(url, reverse_sort, sort_value)
end
+
+ def forks_sort_direction_button(sort_value, without = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id])
+ reverse_sort = forks_reverse_sort_options_hash[sort_value]
+ url = page_filter_path(sort: reverse_sort, without: without)
+
+ sort_direction_button(url, reverse_sort, sort_value)
+ end
end
SortingHelper.prepend_mod_with('SortingHelper')
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 1d8b657025c..f2e1d158c2d 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -40,7 +40,9 @@ module SystemNoteHelper
'new_alert_added' => 'warning',
'severity' => 'information-o',
'cloned' => 'documents',
- 'issue_type' => 'pencil-square'
+ 'issue_type' => 'pencil-square',
+ 'attention_requested' => 'user',
+ 'attention_request_removed' => 'user'
}.freeze
def system_note_icon_name(note)
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index e53e35baac3..2efc3f27dc7 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -14,8 +14,7 @@ module TabHelper
gl_tabs_classes = %w[nav gl-tabs-nav]
html_options = html_options.merge(
- class: [*html_options[:class], gl_tabs_classes].join(' '),
- role: 'tablist'
+ class: [*html_options[:class], gl_tabs_classes].join(' ')
)
content = capture(&block) if block_given?
@@ -54,7 +53,7 @@ module TabHelper
extra_tab_classes = html_options.delete(:tab_class)
tab_class = %w[nav-item].push(*extra_tab_classes)
- content_tag(:li, class: tab_class, role: 'presentation') do
+ content_tag(:li, class: tab_class) do
if block_given?
link_to(options, html_options, &block)
else
@@ -63,6 +62,19 @@ module TabHelper
end
end
+ # Creates a <gl-badge> for use inside tabs.
+ #
+ # html_options - The html_options hash (default: {})
+ def gl_tab_counter_badge(count, html_options = {})
+ gl_badge_tag(
+ count,
+ { size: :sm },
+ html_options.merge(
+ class: ['gl-tab-counter-badge', *html_options[:class]]
+ )
+ )
+ end
+
# Navigation link helper
#
# Returns an `li` element with an 'active' class if the supplied
@@ -150,7 +162,7 @@ module TabHelper
action = options.delete(:action)
route_matches_paths?(options.delete(:path)) ||
- route_matches_pages?(options.delete(:page)) ||
+ route_matches_page_without_exclusion?(options.delete(:page), options.delete(:exclude_page)) ||
route_matches_controllers_and_or_actions?(controller, action)
end
@@ -175,6 +187,13 @@ module TabHelper
end
end
+ def route_matches_page_without_exclusion?(pages, exclude_page)
+ return false unless route_matches_pages?(pages)
+ return true unless exclude_page.present?
+
+ !route_matches_pages?(exclude_page)
+ end
+
def route_matches_pages?(pages)
Array(pages).compact.any? do |single_page|
# We need to distinguish between Hash argument and other types of
@@ -211,12 +230,3 @@ module TabHelper
current_page?(options)
end
end
-
-def gl_tab_counter_badge(count, html_options = {})
- badge_classes = %w[badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge]
- content_tag(:span,
- count,
- class: [*html_options[:class], badge_classes].join(' '),
- data: html_options[:data]
- )
-end
diff --git a/app/helpers/time_zone_helper.rb b/app/helpers/time_zone_helper.rb
index db355f5ff65..d16f13304e5 100644
--- a/app/helpers/time_zone_helper.rb
+++ b/app/helpers/time_zone_helper.rb
@@ -3,6 +3,7 @@
module TimeZoneHelper
TIME_ZONE_FORMAT_ATTRS = {
short: %i[identifier name offset],
+ abbr: %i[identifier abbr],
full: %i[identifier name abbr offset formatted_offset]
}.freeze
private_constant :TIME_ZONE_FORMAT_ATTRS
@@ -32,7 +33,7 @@ module TimeZoneHelper
end
end
- def local_time_instance(timezone)
+ def local_timezone_instance(timezone)
return Time.zone if timezone.blank?
ActiveSupport::TimeZone.new(timezone) || Time.zone
@@ -41,7 +42,7 @@ module TimeZoneHelper
def local_time(timezone)
return if timezone.blank?
- time_zone_instance = local_time_instance(timezone)
+ time_zone_instance = local_timezone_instance(timezone)
time_zone_instance.now.strftime("%-l:%M %p")
end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index d1f33f99ad0..d089b540282 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -81,7 +81,7 @@ module TreeHelper
end
def commit_in_fork_help
- _("A new branch will be created in your fork and a new merge request will be started.")
+ _("GitLab will create a branch in your fork and start a merge request.")
end
def commit_in_single_accessible_branch
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
deleted file mode 100644
index d8e69145c40..00000000000
--- a/app/helpers/user_callouts_helper.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: true
-
-module UserCalloutsHelper
- GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
- GCP_SIGNUP_OFFER = 'gcp_signup_offer'
- SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
- TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
- CUSTOMIZE_HOMEPAGE = 'customize_homepage'
- FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version'
- REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout'
- UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout'
- INVITE_MEMBERS_BANNER = 'invite_members_banner'
- SECURITY_NEWSLETTER_CALLOUT = 'security_newsletter_callout'
-
- def show_gke_cluster_integration_callout?(project)
- active_nav_link?(controller: sidebar_operations_paths) &&
- can?(current_user, :create_cluster, project) &&
- !user_dismissed?(GKE_CLUSTER_INTEGRATION)
- end
-
- def show_gcp_signup_offer?
- !user_dismissed?(GCP_SIGNUP_OFFER)
- end
-
- def render_flash_user_callout(flash_type, message, feature_name)
- render 'shared/flash_user_callout', flash_type: flash_type, message: message, feature_name: feature_name
- end
-
- def render_dashboard_ultimate_trial(user)
- end
-
- def render_two_factor_auth_recovery_settings_check
- end
-
- def show_suggest_popover?
- !user_dismissed?(SUGGEST_POPOVER_DISMISSED)
- end
-
- def show_customize_homepage_banner?
- current_user.default_dashboard? && !user_dismissed?(CUSTOMIZE_HOMEPAGE)
- end
-
- def show_feature_flags_new_version?
- !user_dismissed?(FEATURE_FLAGS_NEW_VERSION)
- end
-
- def show_unfinished_tag_cleanup_callout?
- !user_dismissed?(UNFINISHED_TAG_CLEANUP_CALLOUT)
- end
-
- def show_registration_enabled_user_callout?
- !Gitlab.com? &&
- current_user&.admin? &&
- signup_enabled? &&
- !user_dismissed?(REGISTRATION_ENABLED_CALLOUT)
- end
-
- def dismiss_two_factor_auth_recovery_settings_check
- end
-
- def show_invite_banner?(group)
- Ability.allowed?(current_user, :admin_group, group) &&
- !just_created? &&
- !user_dismissed_for_group(INVITE_MEMBERS_BANNER, group) &&
- !multiple_members?(group)
- end
-
- def show_security_newsletter_user_callout?
- current_user&.admin? &&
- !user_dismissed?(SECURITY_NEWSLETTER_CALLOUT)
- end
-
- private
-
- def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
- return false unless current_user
-
- current_user.dismissed_callout?(feature_name: feature_name, ignore_dismissal_earlier_than: ignore_dismissal_earlier_than)
- end
-
- 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)
- end
-
- def just_created?
- flash[:notice]&.include?('successfully created')
- end
-
- def multiple_members?(group)
- group.member_count > 1 || group.members_with_parents.count > 1
- end
-end
-
-UserCalloutsHelper.prepend_mod
diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb
new file mode 100644
index 00000000000..32b0d7b3fe3
--- /dev/null
+++ b/app/helpers/users/callouts_helper.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Users
+ module CalloutsHelper
+ GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
+ GCP_SIGNUP_OFFER = 'gcp_signup_offer'
+ SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
+ TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
+ FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version'
+ REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout'
+ UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout'
+ SECURITY_NEWSLETTER_CALLOUT = 'security_newsletter_callout'
+
+ def show_gke_cluster_integration_callout?(project)
+ active_nav_link?(controller: sidebar_operations_paths) &&
+ can?(current_user, :create_cluster, project) &&
+ !user_dismissed?(GKE_CLUSTER_INTEGRATION)
+ end
+
+ def show_gcp_signup_offer?
+ !user_dismissed?(GCP_SIGNUP_OFFER)
+ end
+
+ def render_flash_user_callout(flash_type, message, feature_name)
+ render 'shared/flash_user_callout', flash_type: flash_type, message: message, feature_name: feature_name
+ end
+
+ def render_dashboard_ultimate_trial(user)
+ end
+
+ def render_two_factor_auth_recovery_settings_check
+ end
+
+ def show_suggest_popover?
+ !user_dismissed?(SUGGEST_POPOVER_DISMISSED)
+ end
+
+ def show_feature_flags_new_version?
+ !user_dismissed?(FEATURE_FLAGS_NEW_VERSION)
+ end
+
+ def show_unfinished_tag_cleanup_callout?
+ !user_dismissed?(UNFINISHED_TAG_CLEANUP_CALLOUT)
+ end
+
+ def show_registration_enabled_user_callout?
+ !Gitlab.com? &&
+ current_user&.admin? &&
+ signup_enabled? &&
+ !user_dismissed?(REGISTRATION_ENABLED_CALLOUT)
+ end
+
+ def dismiss_two_factor_auth_recovery_settings_check
+ end
+
+ def show_security_newsletter_user_callout?
+ current_user&.admin? &&
+ !user_dismissed?(SECURITY_NEWSLETTER_CALLOUT)
+ end
+
+ private
+
+ def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
+ return false unless current_user
+
+ current_user.dismissed_callout?(feature_name: feature_name, ignore_dismissal_earlier_than: ignore_dismissal_earlier_than)
+ end
+ end
+end
+
+Users::CalloutsHelper.prepend_mod
diff --git a/app/helpers/users/group_callouts_helper.rb b/app/helpers/users/group_callouts_helper.rb
new file mode 100644
index 00000000000..b66c7f9f821
--- /dev/null
+++ b/app/helpers/users/group_callouts_helper.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Users
+ module GroupCalloutsHelper
+ INVITE_MEMBERS_BANNER = 'invite_members_banner'
+
+ def show_invite_banner?(group)
+ Ability.allowed?(current_user, :admin_group, group) &&
+ !just_created? &&
+ !user_dismissed_for_group(INVITE_MEMBERS_BANNER, group) &&
+ !multiple_members?(group)
+ end
+
+ private
+
+ 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)
+ end
+
+ def just_created?
+ flash[:notice]&.include?('successfully created')
+ end
+
+ def multiple_members?(group)
+ group.member_count > 1 || group.members_with_parents.count > 1
+ end
+ end
+end
diff --git a/app/helpers/version_check_helper.rb b/app/helpers/version_check_helper.rb
index f8d7264d4cc..7875b9e4a28 100644
--- a/app/helpers/version_check_helper.rb
+++ b/app/helpers/version_check_helper.rb
@@ -6,7 +6,7 @@ module VersionCheckHelper
return unless Gitlab::CurrentSettings.version_check_enabled
return if User.single_user&.requires_usage_stats_consent?
- image_tag VersionCheck.url, class: 'js-version-status-badge'
+ image_tag VersionCheck.image_url, class: 'js-version-status-badge'
end
def link_to_version
diff --git a/app/helpers/x509_helper.rb b/app/helpers/x509_helper.rb
index 4afc5643af4..1a9dbefceef 100644
--- a/app/helpers/x509_helper.rb
+++ b/app/helpers/x509_helper.rb
@@ -18,6 +18,6 @@ module X509Helper
end
def x509_signature?(sig)
- sig.is_a?(X509CommitSignature) || sig.is_a?(Gitlab::X509::Signature)
+ sig.is_a?(CommitSignatures::X509CommitSignature) || sig.is_a?(Gitlab::X509::Signature)
end
end