summaryrefslogtreecommitdiff
path: root/app/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/analytics/navbar_helper.rb43
-rw-r--r--app/helpers/appearances_helper.rb3
-rw-r--r--app/helpers/application_helper.rb34
-rw-r--r--app/helpers/application_settings_helper.rb17
-rw-r--r--app/helpers/auth_helper.rb31
-rw-r--r--app/helpers/avatars_helper.rb13
-rw-r--r--app/helpers/award_emoji_helper.rb2
-rw-r--r--app/helpers/blob_helper.rb4
-rw-r--r--app/helpers/boards_helper.rb8
-rw-r--r--app/helpers/branches_helper.rb2
-rw-r--r--app/helpers/button_helper.rb2
-rw-r--r--app/helpers/ci/jobs_helper.rb5
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb12
-rw-r--r--app/helpers/ci/pipelines_helper.rb3
-rw-r--r--app/helpers/ci/runners_helper.rb2
-rw-r--r--app/helpers/commits_helper.rb23
-rw-r--r--app/helpers/dashboard_helper.rb2
-rw-r--r--app/helpers/dev_ops_report_helper.rb74
-rw-r--r--app/helpers/diff_helper.rb6
-rw-r--r--app/helpers/emails_helper.rb2
-rw-r--r--app/helpers/environments_helper.rb11
-rw-r--r--app/helpers/events_helper.rb4
-rw-r--r--app/helpers/export_helper.rb2
-rw-r--r--app/helpers/feature_flags_helper.rb2
-rw-r--r--app/helpers/form_helper.rb2
-rw-r--r--app/helpers/gitlab_routing_helper.rb16
-rw-r--r--app/helpers/graph_helper.rb2
-rw-r--r--app/helpers/groups/group_members_helper.rb34
-rw-r--r--app/helpers/groups_helper.rb48
-rw-r--r--app/helpers/hooks_helper.rb2
-rw-r--r--app/helpers/ide_helper.rb17
-rw-r--r--app/helpers/in_product_marketing_helper.rb379
-rw-r--r--app/helpers/invite_members_helper.rb33
-rw-r--r--app/helpers/issuables_helper.rb20
-rw-r--r--app/helpers/issues_helper.rb29
-rw-r--r--app/helpers/kerberos_spnego_helper.rb2
-rw-r--r--app/helpers/labels_helper.rb2
-rw-r--r--app/helpers/learn_gitlab_helper.rb66
-rw-r--r--app/helpers/markup_helper.rb2
-rw-r--r--app/helpers/members_helper.rb10
-rw-r--r--app/helpers/merge_requests_helper.rb12
-rw-r--r--app/helpers/mirror_helper.rb2
-rw-r--r--app/helpers/namespace_storage_limit_alert_helper.rb2
-rw-r--r--app/helpers/namespaces_helper.rb11
-rw-r--r--app/helpers/nav/top_nav_helper.rb243
-rw-r--r--app/helpers/nav_helper.rb12
-rw-r--r--app/helpers/notes_helper.rb2
-rw-r--r--app/helpers/notify_helper.rb2
-rw-r--r--app/helpers/operations_helper.rb2
-rw-r--r--app/helpers/page_layout_helper.rb1
-rw-r--r--app/helpers/preferences_helper.rb20
-rw-r--r--app/helpers/profiles_helper.rb2
-rw-r--r--app/helpers/projects/alert_management_helper.rb5
-rw-r--r--app/helpers/projects/incidents_helper.rb2
-rw-r--r--app/helpers/projects/project_members_helper.rb32
-rw-r--r--app/helpers/projects/security/configuration_helper.rb2
-rw-r--r--app/helpers/projects_helper.rb182
-rw-r--r--app/helpers/registrations_helper.rb12
-rw-r--r--app/helpers/releases_helper.rb2
-rw-r--r--app/helpers/search_helper.rb4
-rw-r--r--app/helpers/selects_helper.rb2
-rw-r--r--app/helpers/services_helper.rb12
-rw-r--r--app/helpers/sidebars_helper.rb8
-rw-r--r--app/helpers/snippets_helper.rb6
-rw-r--r--app/helpers/sorting_helper.rb2
-rw-r--r--app/helpers/sorting_titles_values_helper.rb2
-rw-r--r--app/helpers/ssh_keys_helper.rb5
-rw-r--r--app/helpers/subscribable_banner_helper.rb2
-rw-r--r--app/helpers/system_note_helper.rb4
-rw-r--r--app/helpers/time_zone_helper.rb2
-rw-r--r--app/helpers/timeboxes_helper.rb2
-rw-r--r--app/helpers/timeboxes_routing_helper.rb2
-rw-r--r--app/helpers/todos_helper.rb8
-rw-r--r--app/helpers/tree_helper.rb2
-rw-r--r--app/helpers/user_callouts_helper.rb4
-rw-r--r--app/helpers/users_helper.rb50
-rw-r--r--app/helpers/version_check_helper.rb14
-rw-r--r--app/helpers/webpack_helper.rb22
-rw-r--r--app/helpers/whats_new_helper.rb29
-rw-r--r--app/helpers/wiki_helper.rb2
-rw-r--r--app/helpers/x509_helper.rb2
81 files changed, 895 insertions, 810 deletions
diff --git a/app/helpers/analytics/navbar_helper.rb b/app/helpers/analytics/navbar_helper.rb
index 33a5028cdf1..091571ff15a 100644
--- a/app/helpers/analytics/navbar_helper.rb
+++ b/app/helpers/analytics/navbar_helper.rb
@@ -13,14 +13,6 @@ module Analytics
end
end
- def project_analytics_navbar_links(project, current_user)
- [
- cycle_analytics_navbar_link(project, current_user),
- repository_analytics_navbar_link(project, current_user),
- ci_cd_analytics_navbar_link(project, current_user)
- ].compact
- end
-
def group_analytics_navbar_links(group, current_user)
[]
end
@@ -30,40 +22,7 @@ module Analytics
def navbar_sub_item(args)
NavbarSubItem.new(**args)
end
-
- def cycle_analytics_navbar_link(project, current_user)
- return unless project_nav_tab?(:cycle_analytics)
-
- navbar_sub_item(
- title: _('Value Stream'),
- path: 'cycle_analytics#show',
- link: project_cycle_analytics_path(project),
- link_to_options: { class: 'shortcuts-project-cycle-analytics' }
- )
- end
-
- def repository_analytics_navbar_link(project, current_user)
- return if project.empty_repo?
-
- navbar_sub_item(
- title: _('Repository'),
- path: 'graphs#charts',
- link: charts_project_graph_path(project, current_ref),
- link_to_options: { class: 'shortcuts-repository-charts' }
- )
- end
-
- def ci_cd_analytics_navbar_link(project, current_user)
- return unless project_nav_tab?(:pipelines)
- return unless project.feature_available?(:builds, current_user) || !project.empty_repo?
-
- navbar_sub_item(
- title: _('CI/CD'),
- path: 'pipelines#charts',
- link: charts_project_pipelines_path(project)
- )
- end
end
end
-Analytics::NavbarHelper.prepend_if_ee('EE::Analytics::NavbarHelper')
+Analytics::NavbarHelper.prepend_mod_with('Analytics::NavbarHelper')
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index 65feea4f6e0..60e37c96f61 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -83,5 +83,4 @@ module AppearancesHelper
end
end
-AppearancesHelper.prepend_if_ee('EE::AppearancesHelper')
-AppearancesHelper.prepend_if_jh('JH::AppearancesHelper')
+AppearancesHelper.prepend_mod
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a2ef2f1207c..2e15b3f22c2 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -72,7 +72,7 @@ module ApplicationHelper
else
'Never'
end
- rescue
+ rescue StandardError
'Never'
end
@@ -382,15 +382,26 @@ module ApplicationHelper
def autocomplete_data_sources(object, noteable_type)
return {} unless object && noteable_type
- {
- members: members_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
- issues: issues_project_autocomplete_sources_path(object),
- mergeRequests: merge_requests_project_autocomplete_sources_path(object),
- labels: labels_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
- milestones: milestones_project_autocomplete_sources_path(object),
- commands: commands_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
- snippets: snippets_project_autocomplete_sources_path(object)
- }
+ if object.is_a?(Group)
+ {
+ members: members_group_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
+ issues: issues_group_autocomplete_sources_path(object),
+ mergeRequests: merge_requests_group_autocomplete_sources_path(object),
+ labels: labels_group_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
+ milestones: milestones_group_autocomplete_sources_path(object),
+ commands: commands_group_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id])
+ }
+ else
+ {
+ members: members_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
+ issues: issues_project_autocomplete_sources_path(object),
+ mergeRequests: merge_requests_project_autocomplete_sources_path(object),
+ labels: labels_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
+ milestones: milestones_project_autocomplete_sources_path(object),
+ commands: commands_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
+ snippets: snippets_project_autocomplete_sources_path(object)
+ }
+ end
end
def asset_to_string(name)
@@ -409,5 +420,4 @@ module ApplicationHelper
end
end
-ApplicationHelper.prepend_if_ee('EE::ApplicationHelper')
-ApplicationHelper.prepend_if_jh('JH::ApplicationHelper')
+ApplicationHelper.prepend_mod
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 504ebb5606e..0e3dff27da9 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -233,6 +233,7 @@ module ApplicationSettingsHelper
:external_pipeline_validation_service_token,
:external_pipeline_validation_service_url,
:first_day_of_week,
+ :floc_enabled,
:force_pages_access_control,
:gitaly_timeout_default,
:gitaly_timeout_medium,
@@ -302,6 +303,7 @@ module ApplicationSettingsHelper
:sourcegraph_public_only,
:spam_check_endpoint_enabled,
:spam_check_endpoint_url,
+ :spam_check_api_key,
:terminal_max_session_time,
:terms,
:throttle_authenticated_api_enabled,
@@ -310,9 +312,15 @@ module ApplicationSettingsHelper
:throttle_authenticated_web_enabled,
:throttle_authenticated_web_period_in_seconds,
:throttle_authenticated_web_requests_per_period,
+ :throttle_authenticated_packages_api_enabled,
+ :throttle_authenticated_packages_api_period_in_seconds,
+ :throttle_authenticated_packages_api_requests_per_period,
:throttle_unauthenticated_enabled,
:throttle_unauthenticated_period_in_seconds,
:throttle_unauthenticated_requests_per_period,
+ :throttle_unauthenticated_packages_api_enabled,
+ :throttle_unauthenticated_packages_api_period_in_seconds,
+ :throttle_unauthenticated_packages_api_requests_per_period,
:throttle_protected_paths_enabled,
:throttle_protected_paths_period_in_seconds,
:throttle_protected_paths_requests_per_period,
@@ -358,7 +366,8 @@ module ApplicationSettingsHelper
:rate_limiting_response_text,
:container_registry_expiration_policies_worker_capacity,
:container_registry_cleanup_tags_service_max_list_size,
- :keep_latest_artifact
+ :keep_latest_artifact,
+ :whats_new_variant
]
end
@@ -387,7 +396,7 @@ module ApplicationSettingsHelper
end
def integration_expanded?(substring)
- @application_setting.errors.any? { |k| k.to_s.start_with?(substring) }
+ @application_setting.errors.messages.any? { |k, _| k.to_s.start_with?(substring) }
end
def instance_clusters_enabled?
@@ -429,8 +438,8 @@ module ApplicationSettingsHelper
end
end
-ApplicationSettingsHelper.prepend_if_ee('EE::ApplicationSettingsHelper')
+ApplicationSettingsHelper.prepend_mod_with('ApplicationSettingsHelper')
# The methods in `EE::ApplicationSettingsHelper` should be available as both
# instance and class methods.
-ApplicationSettingsHelper.extend_if_ee('EE::ApplicationSettingsHelper')
+ApplicationSettingsHelper.extend_mod_with('ApplicationSettingsHelper')
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index cacf9c7ad0b..a0c3a6f2f52 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -16,7 +16,7 @@ module AuthHelper
twitter
).freeze
LDAP_PROVIDER = /\Aldap/.freeze
- TRIAL_REGISTRATION_PROVIDERS = %w(google_oauth2 github).freeze
+ POPULAR_PROVIDERS = %w(google_oauth2 github).freeze
def ldap_enabled?
Gitlab::Auth::Ldap::Config.enabled?
@@ -116,19 +116,12 @@ module AuthHelper
providers = button_based_providers.map(&:to_s) - disabled_providers
providers.sort_by do |provider|
- case provider
- when 'google_oauth2'
- 0
- when 'github'
- 1
- else
- 2
- end
+ POPULAR_PROVIDERS.index(provider) || POPULAR_PROVIDERS.length
end
end
- def trial_enabled_button_based_providers
- enabled_button_based_providers & TRIAL_REGISTRATION_PROVIDERS
+ def popular_enabled_button_based_providers
+ enabled_button_based_providers & POPULAR_PROVIDERS
end
def button_based_providers_enabled?
@@ -176,11 +169,23 @@ module AuthHelper
!current_user
end
+ def auth_app_owner_text(owner)
+ return unless owner
+
+ if owner.is_a?(Group)
+ group_link = link_to(owner.name, group_path(owner))
+ _("This application was created for group %{group_link}.").html_safe % { group_link: group_link }
+ else
+ user_link = link_to(owner.name, user_path(owner))
+ _("This application was created by %{user_link}.").html_safe % { user_link: user_link }
+ end
+ end
+
extend self
end
-AuthHelper.prepend_if_ee('EE::AuthHelper')
+AuthHelper.prepend_mod_with('AuthHelper')
# The methods added in EE should be available as both class and instance
# methods, just like the methods provided by `AuthHelper` itself.
-AuthHelper.extend_if_ee('EE::AuthHelper')
+AuthHelper.extend_mod_with('AuthHelper')
diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb
index 09f91f350bd..4cfa1528d9b 100644
--- a/app/helpers/avatars_helper.rb
+++ b/app/helpers/avatars_helper.rb
@@ -98,6 +98,14 @@ module AvatarsHelper
end
end
+ def avatar_without_link(resource, options = {})
+ if resource.is_a?(User)
+ user_avatar_without_link(options.merge(user: resource))
+ elsif resource.is_a?(Group)
+ group_icon(resource, options.merge(class: 'avatar'))
+ end
+ end
+
private
def avatar_icon_by_user_email_or_gravatar(email, size, scale, only_path:)
@@ -136,11 +144,12 @@ module AvatarsHelper
def source_identicon(source, options = {})
bg_key = (source.id % 7) + 1
+ size_class = "s#{options[:size]}" if options[:size]
options[:class] =
- [*options[:class], "identicon bg#{bg_key}"].join(' ')
+ [*options[:class], "identicon bg#{bg_key}", size_class].compact.join(' ')
- content_tag(:div, class: options[:class].strip) do
+ content_tag(:span, class: options[:class].strip) do
source.name[0, 1].upcase
end
end
diff --git a/app/helpers/award_emoji_helper.rb b/app/helpers/award_emoji_helper.rb
index af9ab93d459..196415bb363 100644
--- a/app/helpers/award_emoji_helper.rb
+++ b/app/helpers/award_emoji_helper.rb
@@ -17,4 +17,4 @@ module AwardEmojiHelper
end
end
-AwardEmojiHelper.prepend_if_ee('EE::AwardEmojiHelper')
+AwardEmojiHelper.prepend_mod_with('AwardEmojiHelper')
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 3144686bba9..dfd6de3f1d5 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -206,10 +206,6 @@ module BlobHelper
@gitlab_ci_ymls ||= TemplateFinder.all_template_names(project, :gitlab_ci_ymls)
end
- def gitlab_ci_syntax_ymls(project)
- @gitlab_ci_syntax_ymls ||= TemplateFinder.all_template_names(project, :gitlab_ci_syntax_ymls)
- end
-
def metrics_dashboard_ymls(project)
@metrics_dashboard_ymls ||= TemplateFinder.all_template_names(project, :metrics_dashboard_ymls)
end
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index 49963d14934..f72f8bfd151 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -10,7 +10,7 @@ module BoardsHelper
boards_endpoint: @boards_endpoint,
lists_endpoint: board_lists_path(board),
board_id: board.id,
- disabled: (!can?(current_user, :create_non_backlog_issues, board)).to_s,
+ disabled: board.disabled_for?(current_user).to_s,
root_path: root_path,
full_path: full_path,
bulk_update_path: @bulk_issues_path,
@@ -89,6 +89,10 @@ module BoardsHelper
@current_board_parent ||= @group || @project
end
+ def current_board_namespace
+ @current_board_namespace = board.group_board? ? @group : @project.namespace
+ end
+
def can_update?
can?(current_user, :admin_issue, board)
end
@@ -136,4 +140,4 @@ module BoardsHelper
end
end
-BoardsHelper.prepend_if_ee('EE::BoardsHelper')
+BoardsHelper.prepend_mod_with('BoardsHelper')
diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb
index 8f87cd5bfe0..a500a695029 100644
--- a/app/helpers/branches_helper.rb
+++ b/app/helpers/branches_helper.rb
@@ -22,4 +22,4 @@ module BranchesHelper
end
end
-BranchesHelper.prepend_if_ee('EE::BranchesHelper')
+BranchesHelper.prepend_mod_with('BranchesHelper')
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index 1b00f583b55..27d6ee57d8b 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -100,4 +100,4 @@ module ButtonHelper
end
end
-ButtonHelper.prepend_if_ee('EE::ButtonHelper')
+ButtonHelper.prepend_mod_with('ButtonHelper')
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index a0d169c1358..23f2a082a68 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -15,7 +15,8 @@ module Ci
"build_stage" => @build.stage,
"log_state" => '',
"build_options" => javascript_build_options,
- "retry_outdated_job_docs_url" => help_page_path('ci/pipelines/settings', anchor: 'retry-outdated-jobs')
+ "retry_outdated_job_docs_url" => help_page_path('ci/pipelines/settings', anchor: 'retry-outdated-jobs'),
+ "code_quality_help_url" => help_page_path('user/project/merge_requests/code_quality', anchor: 'troubleshooting')
}
end
@@ -36,4 +37,4 @@ module Ci
end
end
-Ci::JobsHelper.prepend_if_ee('::EE::Ci::JobsHelper')
+Ci::JobsHelper.prepend_mod_with('Ci::JobsHelper')
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index ceb18d90c92..8c8ee2d4d0f 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -9,21 +9,29 @@ module Ci
end
def js_pipeline_editor_data(project)
+ commit_sha = project.commit ? project.commit.sha : ''
{
"ci-config-path": project.ci_config_path_or_default,
- "commit-sha" => project.commit ? project.commit.sha : '',
+ "ci-examples-help-page-path" => help_page_path('ci/examples/README'),
+ "ci-help-page-path" => help_page_path('ci/README'),
+ "commit-sha" => commit_sha,
"default-branch" => project.default_branch,
"empty-state-illustration-path" => image_path('illustrations/empty-state/empty-dag-md.svg'),
"initial-branch-name": params[:branch_name],
"lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'),
+ "needs-help-page-path" => help_page_path('ci/yaml/README', anchor: 'needs'),
"new-merge-request-path" => namespace_project_new_merge_request_path,
+ "pipeline_etag" => project.commit ? graphql_etag_pipeline_sha_path(commit_sha) : '',
+ "pipeline-page-path" => project_pipelines_path(project),
"project-path" => project.path,
"project-full-path" => project.full_path,
"project-namespace" => project.namespace.full_path,
+ "runner-help-page-path" => help_page_path('ci/runners/README'),
+ "total-branches" => project.repository.branches.length,
"yml-help-page-path" => help_page_path('ci/yaml/README')
}
end
end
end
-Ci::PipelineEditorHelper.prepend_if_ee('EE::Ci::PipelineEditorHelper')
+Ci::PipelineEditorHelper.prepend_mod_with('Ci::PipelineEditorHelper')
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index cabb43f45fd..f42cd53ae3a 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -50,10 +50,9 @@ module Ci
{ name: 'Gradle', logo: image_path('illustrations/logos/gradle.svg') },
{ name: 'Grails', logo: image_path('illustrations/logos/grails.svg') },
{ name: 'dotNET', logo: image_path('illustrations/logos/dotnet.svg') },
- { name: 'Rails', logo: image_path('illustrations/logos/rails.svg') },
{ name: 'Julia', logo: image_path('illustrations/logos/julia.svg') },
{ name: 'Laravel', logo: image_path('illustrations/logos/laravel.svg') },
- { name: 'Latex', logo: image_path('illustrations/logos/latex.svg') },
+ { name: 'LaTeX', logo: image_path('illustrations/logos/latex.svg') },
{ name: 'Maven', logo: image_path('illustrations/logos/maven.svg') },
{ name: 'Mono', logo: image_path('illustrations/logos/mono.svg') },
{ name: 'Nodejs', logo: image_path('illustrations/logos/node_js.svg') },
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index 82347053d6f..550fa4de2c5 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -75,4 +75,4 @@ module Ci
end
end
-Ci::RunnersHelper.prepend_if_ee('EE::Ci::RunnersHelper')
+Ci::RunnersHelper.prepend_mod_with('Ci::RunnersHelper')
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index e7a81eb5629..9b952ad127e 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -128,7 +128,7 @@ module CommitsHelper
%w(btn gpg-status-box) + Array(additional_classes)
end
- def conditionally_paginate_diff_files(diffs, paginate:, per: Projects::CommitController::COMMIT_DIFFS_PER_PAGE)
+ def conditionally_paginate_diff_files(diffs, paginate:, per:)
if paginate
Kaminari.paginate_array(diffs.diff_files.to_a).page(params[:page]).per(per)
else
@@ -148,6 +148,27 @@ module CommitsHelper
end
end
+ # This is used to calculate a cache key for the app/views/projects/commits/_commit.html.haml
+ # partial. It takes some of the same parameters as used in the partial and will hash the
+ # current pipeline status.
+ #
+ # This includes a keyed hash for values that can be nil, to prevent invalid cache entries
+ # being served if the order should change in future.
+ def commit_partial_cache_key(commit, ref:, merge_request:, request:)
+ [
+ commit,
+ commit.author,
+ ref,
+ {
+ merge_request: merge_request,
+ pipeline_status: commit.status_for(ref),
+ xhr: request.xhr?,
+ controller: controller.controller_path,
+ path: @path # referred to in #link_to_browse_code
+ }
+ ]
+ end
+
protected
# Private: Returns a link to a person. If the person has a matching user and
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index 08f357916b5..95bbf2eff41 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -66,4 +66,4 @@ module DashboardHelper
end
end
-DashboardHelper.prepend_if_ee('EE::DashboardHelper')
+DashboardHelper.prepend_mod_with('DashboardHelper')
diff --git a/app/helpers/dev_ops_report_helper.rb b/app/helpers/dev_ops_report_helper.rb
index ab7e56fc1a2..c2200a4c3da 100644
--- a/app/helpers/dev_ops_report_helper.rb
+++ b/app/helpers/dev_ops_report_helper.rb
@@ -1,18 +1,80 @@
# frozen_string_literal: true
module DevOpsReportHelper
+ def devops_score_metrics(metric)
+ return {} if metric.blank?
+
+ {
+ averageScore: average_score_data(metric),
+ cards: devops_score_card_data(metric),
+ createdAt: metric.created_at.strftime('%Y-%m-%d %H:%M')
+ }
+ end
+
+ private
+
+ def format_score(score)
+ precision = score < 1 ? 2 : 1
+ number_with_precision(score, precision: precision)
+ end
+
def score_level(score)
if score < 33.33
- 'low'
+ {
+ label: s_('DevopsReport|Low'),
+ variant: 'muted'
+ }
elsif score < 66.66
- 'average'
+ {
+ label: s_('DevopsReport|Moderate'),
+ variant: 'neutral'
+ }
else
- 'high'
+ {
+ label: s_('DevopsReport|High'),
+ variant: 'success'
+ }
end
end
- def format_score(score)
- precision = score < 1 ? 2 : 1
- number_with_precision(score, precision: precision)
+ def average_score_level(score)
+ if score < 33.33
+ {
+ label: s_('DevopsReport|Low'),
+ variant: 'danger',
+ icon: 'status-failed'
+ }
+ elsif score < 66.66
+ {
+ label: s_('DevopsReport|Moderate'),
+ variant: 'warning',
+ icon: 'status-alert'
+ }
+ else
+ {
+ label: s_('DevopsReport|High'),
+ variant: 'success',
+ icon: 'status_success_solid'
+ }
+ end
+ end
+
+ def average_score_data(metric)
+ {
+ value: format_score(metric.average_percentage_score),
+ scoreLevel: average_score_level(metric.average_percentage_score)
+ }
+ end
+
+ def devops_score_card_data(metric)
+ metric.cards.map do |card|
+ {
+ title: "#{card.title} #{card.description}",
+ usage: format_score(card.instance_score),
+ leadInstance: format_score(card.leader_score),
+ score: format_score(card.percentage_score),
+ scoreLevel: score_level(card.percentage_score)
+ }
+ end
end
end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 7bf3cb6230b..e430b0f402b 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -23,14 +23,16 @@ module DiffHelper
end
end
+ def show_only_context_commits?
+ !!params[:only_context_commits] || @merge_request&.commits&.empty?
+ end
+
def diff_options
options = { ignore_whitespace_change: hide_whitespace?, expanded: diffs_expanded? }
if action_name == 'diff_for_path'
options[:expanded] = true
options[:paths] = params.values_at(:old_path, :new_path)
- elsif action_name == 'show'
- options[:include_context_commits] = true unless @project.context_commits_enabled?
end
options
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index b58ff21b257..0b1bdb68e50 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -298,4 +298,4 @@ module EmailsHelper
end
end
-EmailsHelper.prepend_if_ee('EE::EmailsHelper')
+EmailsHelper.prepend_mod_with('EmailsHelper')
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 7f0c59f65a0..594c6fedef1 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -34,7 +34,7 @@ module EnvironmentsHelper
def environment_logs_data(project, environment)
{
"environment_name": environment.name,
- "environments_path": project_environments_path(project, format: :json),
+ "environments_path": api_v4_projects_environments_path(id: project.id),
"environment_id": environment.id,
"cluster_applications_documentation_path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'),
"clusters_path": project_clusters_path(project, format: :json)
@@ -62,7 +62,8 @@ module EnvironmentsHelper
'validate_query_path' => validate_query_project_prometheus_metrics_path(project),
'custom_metrics_available' => "#{custom_metrics_available?(project)}",
'prometheus_alerts_available' => "#{can?(current_user, :read_prometheus_alerts, project)}",
- 'dashboard_timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase
+ 'dashboard_timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase,
+ 'has_managed_prometheus' => has_managed_prometheus?(project).to_s
}
end
@@ -78,6 +79,10 @@ module EnvironmentsHelper
}
end
+ def has_managed_prometheus?(project)
+ project.prometheus_service&.prometheus_available? == true
+ end
+
def metrics_dashboard_base_path(environment, project)
# This is needed to support our transition from environment scoped metric paths to project scoped.
if project
@@ -117,4 +122,4 @@ module EnvironmentsHelper
end
end
-EnvironmentsHelper.prepend_if_ee('::EE::EnvironmentsHelper')
+EnvironmentsHelper.prepend_mod_with('EnvironmentsHelper')
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 6b3abb4274e..03c3ee3363d 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -228,7 +228,7 @@ module EventsHelper
def event_commit_title(message)
message ||= ''
(message.split("\n").first || "").truncate(70)
- rescue
+ rescue StandardError
"--broken encoding"
end
@@ -290,4 +290,4 @@ module EventsHelper
end
end
-EventsHelper.prepend_if_ee('EE::EventsHelper')
+EventsHelper.prepend_mod_with('EventsHelper')
diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb
index 38a4f7f1b4b..92d06471384 100644
--- a/app/helpers/export_helper.rb
+++ b/app/helpers/export_helper.rb
@@ -25,4 +25,4 @@ module ExportHelper
end
end
-ExportHelper.prepend_if_ee('EE::ExportHelper')
+ExportHelper.prepend_mod_with('ExportHelper')
diff --git a/app/helpers/feature_flags_helper.rb b/app/helpers/feature_flags_helper.rb
index e50191a471f..2b8804bc07e 100644
--- a/app/helpers/feature_flags_helper.rb
+++ b/app/helpers/feature_flags_helper.rb
@@ -16,4 +16,4 @@ module FeatureFlagsHelper
end
end
-FeatureFlagsHelper.prepend_if_ee('::EE::FeatureFlagsHelper')
+FeatureFlagsHelper.prepend_mod_with('FeatureFlagsHelper')
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index d0276c91316..cf3e99eee49 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -131,4 +131,4 @@ module FormHelper
end
end
-FormHelper.prepend_if_ee('::EE::FormHelper')
+FormHelper.prepend_mod_with('FormHelper')
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index 48af4793fb0..0a684d92eb1 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -166,6 +166,16 @@ module GitlabRoutingHelper
resend_invite_group_group_member_path(group_member.source, group_member)
end
+ # Members
+ def source_members_url(member)
+ case member.source_type
+ when 'Namespace'
+ group_group_members_url(member.source)
+ when 'Project'
+ project_project_members_url(member.source)
+ end
+ end
+
# Artifacts
# Rails path generators are slow because they need to do large regex comparisons
@@ -354,6 +364,10 @@ module GitlabRoutingHelper
[api_graphql_path, "pipelines/id/#{pipeline.id}"].join(':')
end
+ def graphql_etag_pipeline_sha_path(sha)
+ [api_graphql_path, "pipelines/sha/#{sha}"].join(':')
+ end
+
private
def snippet_query_params(snippet, *args)
@@ -370,4 +384,4 @@ module GitlabRoutingHelper
end
end
-GitlabRoutingHelper.include_if_ee('EE::GitlabRoutingHelper')
+GitlabRoutingHelper.include_mod_with('GitlabRoutingHelper')
diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb
index bcbc67957eb..3a94f7d47c2 100644
--- a/app/helpers/graph_helper.rb
+++ b/app/helpers/graph_helper.rb
@@ -28,4 +28,4 @@ module GraphHelper
end
end
-GraphHelper.prepend_if_ee('EE::GraphHelper')
+GraphHelper.prepend_mod_with('GraphHelper')
diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb
index 3e7d6febabf..79191616c8f 100644
--- a/app/helpers/groups/group_members_helper.rb
+++ b/app/helpers/groups/group_members_helper.rb
@@ -13,31 +13,45 @@ module Groups::GroupMembersHelper
render 'shared/members/invite_member', submit_url: group_group_members_path(group), access_levels: group.access_level_roles, default_access_level: default_access_level
end
- def group_group_links_data_json(group_links)
- GroupLink::GroupGroupLinkSerializer.new.represent(group_links, { current_user: current_user }).to_json
+ def group_members_list_data_json(group, members, pagination = {})
+ group_members_list_data(group, members, pagination).to_json
end
- def members_data_json(group, members)
- MemberSerializer.new.represent(members, { current_user: current_user, group: group, source: group }).to_json
+ def group_group_links_list_data_json(group)
+ group_group_links_list_data(group).to_json
+ end
+
+ private
+
+ def group_members_serialized(group, members)
+ MemberSerializer.new.represent(members, { current_user: current_user, group: group, source: group })
+ end
+
+ def group_group_links_serialized(group_links)
+ GroupLink::GroupGroupLinkSerializer.new.represent(group_links, { current_user: current_user })
end
# Overridden in `ee/app/helpers/ee/groups/group_members_helper.rb`
- def group_members_list_data_attributes(group, members)
+ def group_members_list_data(group, members, pagination)
{
- members: members_data_json(group, members),
+ members: group_members_serialized(group, members),
+ pagination: members_pagination_data(members, pagination),
member_path: group_group_member_path(group, ':id'),
source_id: group.id,
- can_manage_members: can?(current_user, :admin_group_member, group).to_s
+ can_manage_members: can?(current_user, :admin_group_member, group)
}
end
- def group_group_links_list_data_attributes(group)
+ def group_group_links_list_data(group)
+ group_links = group.shared_with_group_links
+
{
- members: group_group_links_data_json(group.shared_with_group_links),
+ members: group_group_links_serialized(group_links),
+ pagination: members_pagination_data(group_links),
member_path: group_group_link_path(group, ':id'),
source_id: group.id
}
end
end
-Groups::GroupMembersHelper.prepend_if_ee('EE::Groups::GroupMembersHelper')
+Groups::GroupMembersHelper.prepend_mod_with('Groups::GroupMembersHelper')
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 5ce23baa226..8f647a49a64 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -7,7 +7,11 @@ module GroupsHelper
groups#details
groups#activity
groups#subgroups
- ]
+ ].tap do |paths|
+ break paths if Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+
+ paths.concat(['labels#index', 'group_members#index'])
+ end
end
def group_settings_nav_link_paths
@@ -25,7 +29,9 @@ module GroupsHelper
applications#index
applications#show
applications#edit
- packages_and_registries#index
+ packages_and_registries#show
+ groups/runners#show
+ groups/runners#edit
]
end
@@ -36,6 +42,14 @@ module GroupsHelper
]
end
+ def group_information_title(group)
+ if Feature.enabled?(:sidebar_refactor, current_user)
+ group.subgroup? ? _('Subgroup information') : _('Group information')
+ else
+ group.subgroup? ? _('Subgroup overview') : _('Group overview')
+ end
+ end
+
def group_container_registry_nav?
Gitlab.config.registry.enabled &&
can?(current_user, :read_container_image, @group)
@@ -113,9 +127,7 @@ module GroupsHelper
@has_group_title = true
full_title = []
- ancestors = group.ancestors.with_route
-
- ancestors.reverse_each.with_index do |parent, index|
+ sorted_ancestors(group).with_route.reverse_each.with_index do |parent, index|
if index > 0
add_to_breadcrumb_dropdown(group_title_link(parent, hidable: false, show_avatar: true, for_dropdown: true), location: :before)
else
@@ -141,9 +153,9 @@ module GroupsHelper
def projects_lfs_status(group)
lfs_status =
if group.lfs_enabled?
- group.projects.select(&:lfs_enabled?).size
+ group.projects.count(&:lfs_enabled?)
else
- group.projects.reject(&:lfs_enabled?).size
+ group.projects.count { |project| !project.lfs_enabled? }
end
size = group.projects.size
@@ -206,10 +218,9 @@ module GroupsHelper
end
def show_invite_banner?(group)
- Feature.enabled?(:invite_your_teammates_banner_a, group) &&
- can?(current_user, :admin_group, group) &&
- !just_created? &&
- !multiple_members?(group)
+ can?(current_user, :admin_group, group) &&
+ !just_created? &&
+ !multiple_members?(group)
end
def render_setting_to_allow_project_access_token_creation?(group)
@@ -231,7 +242,7 @@ module GroupsHelper
end
def multiple_members?(group)
- group.member_count > 1
+ group.member_count > 1 || group.members_with_parents.count > 1
end
def get_group_sidebar_links
@@ -285,11 +296,20 @@ module GroupsHelper
end
def oldest_consecutively_locked_ancestor(group)
- group.ancestors.find do |group|
+ sorted_ancestors(group).find do |group|
!group.has_parent? || !group.parent.share_with_group_lock?
end
end
+ # Ancestors sorted by hierarchy depth in bottom-top order.
+ def sorted_ancestors(group)
+ if group.root_ancestor.use_traversal_ids?
+ group.ancestors(hierarchy_order: :asc)
+ else
+ group.ancestors
+ end
+ end
+
def default_help
s_("GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually.")
end
@@ -327,4 +347,4 @@ module GroupsHelper
end
end
-GroupsHelper.prepend_if_ee('EE::GroupsHelper')
+GroupsHelper.prepend_mod_with('GroupsHelper')
diff --git a/app/helpers/hooks_helper.rb b/app/helpers/hooks_helper.rb
index 9466a37ed93..2725d28c47c 100644
--- a/app/helpers/hooks_helper.rb
+++ b/app/helpers/hooks_helper.rb
@@ -38,4 +38,4 @@ module HooksHelper
end
end
-HooksHelper.prepend_if_ee('EE::HooksHelper')
+HooksHelper.prepend_mod_with('HooksHelper')
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index 61d8d0f779d..d1c84bd4141 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -17,7 +17,8 @@ module IdeHelper
'file-path' => @path,
'merge-request' => @merge_request,
'fork-info' => @fork_info&.to_json,
- 'project' => convert_to_project_entity_json(@project)
+ 'project' => convert_to_project_entity_json(@project),
+ 'enable-environments-guidance' => enable_environments_guidance?.to_s
}
end
@@ -28,6 +29,18 @@ module IdeHelper
API::Entities::Project.represent(project).to_json
end
+
+ def enable_environments_guidance?
+ experiment(:in_product_guidance_environments_webide, project: @project) do |e|
+ e.try { !has_dismissed_ide_environments_callout? }
+
+ e.run
+ end
+ end
+
+ def has_dismissed_ide_environments_callout?
+ current_user.dismissed_callout?(feature_name: 'web_ide_ci_environments_guidance')
+ end
end
-::IdeHelper.prepend_if_ee('::EE::IdeHelper')
+::IdeHelper.prepend_mod_with('IdeHelper')
diff --git a/app/helpers/in_product_marketing_helper.rb b/app/helpers/in_product_marketing_helper.rb
index 9e59a04d709..09546f251f9 100644
--- a/app/helpers/in_product_marketing_helper.rb
+++ b/app/helpers/in_product_marketing_helper.rb
@@ -1,381 +1,12 @@
# frozen_string_literal: true
module InProductMarketingHelper
- def subject_line(track, series)
- {
- create: [
- s_('InProductMarketing|Create a project in GitLab in 5 minutes'),
- s_('InProductMarketing|Import your project and code from GitHub, Bitbucket and others'),
- s_('InProductMarketing|Understand repository mirroring')
- ],
- verify: [
- s_('InProductMarketing|Feel the need for speed?'),
- s_('InProductMarketing|3 ways to dive into GitLab CI/CD'),
- s_('InProductMarketing|Explore the power of GitLab CI/CD')
- ],
- trial: [
- s_('InProductMarketing|Go farther with GitLab'),
- s_('InProductMarketing|Automated security scans directly within GitLab'),
- s_('InProductMarketing|Take your source code management to the next level')
- ],
- team: [
- s_('InProductMarketing|Working in GitLab = more efficient'),
- s_("InProductMarketing|Multiple owners, confusing workstreams? We've got you covered"),
- s_('InProductMarketing|Your teams can be more efficient')
- ]
- }[track][series]
- end
-
- def in_product_marketing_logo(track, series)
- inline_image_link('mailers/in_product_marketing', "#{track}-#{series}.png", { width: '150', style: 'width: 150px;' })
- end
-
- def about_link(folder, image, width)
- link_to inline_image_link(folder, image, { width: width, style: "width: #{width}px;", alt: s_('InProductMarketing|go to about.gitlab.com') }), 'https://about.gitlab.com/'
- end
-
- def in_product_marketing_tagline(track, series)
- {
- create: [
- s_('InProductMarketing|Get started today'),
- s_('InProductMarketing|Get our import guides'),
- s_('InProductMarketing|Need an alternative to importing?')
- ],
- verify: [
- s_('InProductMarketing|Use GitLab CI/CD'),
- s_('InProductMarketing|Test, create, deploy'),
- s_('InProductMarketing|Are your runners ready?')
- ],
- trial: [
- s_('InProductMarketing|Start a free trial of GitLab Ultimate – no CC required'),
- s_('InProductMarketing|Improve app security with a 30-day trial'),
- s_('InProductMarketing|Start with a GitLab Ultimate free trial')
- ],
- team: [
- s_('InProductMarketing|Invite your colleagues to join in less than one minute'),
- s_('InProductMarketing|Get your team set up on GitLab'),
- nil
- ]
- }[track][series]
- end
-
- def in_product_marketing_title(track, series)
- {
- create: [
- s_('InProductMarketing|Take your first steps with GitLab'),
- s_('InProductMarketing|Start by importing your projects'),
- s_('InProductMarketing|How (and why) mirroring makes sense')
- ],
- verify: [
- s_('InProductMarketing|Rapid development, simplified'),
- s_('InProductMarketing|Get started with GitLab CI/CD'),
- s_('InProductMarketing|Launch GitLab CI/CD in 20 minutes or less')
- ],
- trial: [
- s_('InProductMarketing|Give us one minute...'),
- s_("InProductMarketing|Security that's integrated into your development lifecycle"),
- s_('InProductMarketing|Improve code quality and streamline reviews')
- ],
- team: [
- s_('InProductMarketing|Team work makes the dream work'),
- s_('InProductMarketing|*GitLab*, noun: a synonym for efficient teams'),
- s_('InProductMarketing|Find out how your teams are really doing')
- ]
- }[track][series]
- end
-
- def in_product_marketing_subtitle(track, series)
- {
- create: [
- s_('InProductMarketing|Dig in and create a project and a repo'),
- s_("InProductMarketing|Here's what you need to know"),
- s_('InProductMarketing|Try it out')
- ],
- verify: [
- s_('InProductMarketing|How to build and test faster'),
- s_('InProductMarketing|Explore the options'),
- s_('InProductMarketing|Follow our steps')
- ],
- trial: [
- s_('InProductMarketing|...and you can get a free trial of GitLab Ultimate'),
- s_('InProductMarketing|Try GitLab Ultimate for free'),
- s_('InProductMarketing|Better code in less time')
- ],
- team: [
- s_('InProductMarketing|Actually, GitLab makes the team work (better)'),
- s_('InProductMarketing|Our tool brings all the things together'),
- s_("InProductMarketing|It's all in the stats")
- ]
- }[track][series]
- end
-
- def in_product_marketing_body_line1(track, series, format: nil)
- {
- create: [
- s_("InProductMarketing|To understand and get the most out of GitLab, start at the beginning and %{project_link}. In GitLab, repositories are part of a project, so after you've created your project you can go ahead and %{repo_link}.") % { project_link: project_link(format), repo_link: repo_link(format) },
- s_("InProductMarketing|Making the switch? It's easier than you think to import your projects into GitLab. Move %{github_link}, or import something %{bitbucket_link}.") % { github_link: github_link(format), bitbucket_link: bitbucket_link(format) },
- s_("InProductMarketing|Sometimes you're not ready to make a full transition to a new tool. If you're not ready to fully commit, %{mirroring_link} gives you a safe way to try out GitLab in parallel with your current tool.") % { mirroring_link: mirroring_link(format) }
- ],
- verify: [
- s_("InProductMarketing|Tired of wrestling with disparate tool chains, information silos and inefficient processes? GitLab's CI/CD is built on a DevOps platform with source code management, planning, monitoring and more ready to go. Find out %{ci_link}.") % { ci_link: ci_link(format) },
- s_("InProductMarketing|GitLab's CI/CD makes software development easier. Don't believe us? Here are three ways you can take it for a fast (and satisfying) test drive:"),
- s_("InProductMarketing|Get going with CI/CD quickly using our %{quick_start_link}. Start with an available runner and then create a CI .yml file – it's really that easy.") % { quick_start_link: quick_start_link(format) }
- ],
- trial: [
- [
- s_("InProductMarketing|GitLab's premium tiers are designed to make you, your team and your application more efficient and more secure with features including but not limited to:"),
- list([
- s_('InProductMarketing|%{strong_start}Company wide portfolio management%{strong_end} — including multi-level epics, scoped labels').html_safe % strong_options(format),
- s_('InProductMarketing|%{strong_start}Multiple approval roles%{strong_end} — including code owners and required merge approvals').html_safe % strong_options(format),
- s_('InProductMarketing|%{strong_start}Advanced application security%{strong_end} — including SAST, DAST scanning, FUZZ testing, dependency scanning, license compliance, secrete detection').html_safe % strong_options(format),
- s_('InProductMarketing|%{strong_start}Executive level insights%{strong_end} — including reporting on productivity, tasks by type, days to completion, value stream').html_safe % strong_options(format)
- ], format)
- ].join("\n"),
- s_('InProductMarketing|GitLab provides static application security testing (SAST), dynamic application security testing (DAST), container scanning, and dependency scanning to help you deliver secure applications along with license compliance.'),
- s_('InProductMarketing|By enabling code owners and required merge approvals the right person will review the right MR. This is a win-win: cleaner code and a more efficient review process.')
- ],
- team: [
- [
- s_('InProductMarketing|Did you know teams that use GitLab are far more efficient?'),
- list([
- s_('InProductMarketing|Goldman Sachs went from 1 build every two weeks to thousands of builds a day'),
- s_('InProductMarketing|Ticketmaster decreased their CI build time by 15X')
- ], format)
- ].join("\n"),
- s_("InProductMarketing|We know a thing or two about efficiency and we don't want to keep that to ourselves. Sign up for a free trial of GitLab Ultimate and your teams will be on it from day one."),
- [
- s_('InProductMarketing|Stop wondering and use GitLab to answer questions like:'),
- list([
- s_('InProductMarketing|How long does it take us to close issues/MRs by types like feature requests, bugs, tech debt, security?'),
- s_('InProductMarketing|How many days does it take our team to complete various tasks?'),
- s_('InProductMarketing|What does our value stream timeline look like from product to development to review and production?')
- ], format)
- ].join("\n")
- ]
- }[track][series]
- end
-
- def in_product_marketing_body_line2(track, series, format: nil)
- {
- create: [
- s_("InProductMarketing|That's all it takes to get going with GitLab, but if you're new to working with Git, check out our %{basics_link} for helpful tips and tricks for getting started.") % { basics_link: basics_link(format) },
- s_("InProductMarketing|Have a different instance you'd like to import? Here's our %{import_link}.") % { import_link: import_link(format) },
- s_("InProductMarketing|It's also possible to simply %{external_repo_link} in order to take advantage of GitLab's CI/CD.") % { external_repo_link: external_repo_link(format) }
- ],
- verify: [
- nil,
- list([
- s_('InProductMarketing|Start by %{performance_link}').html_safe % { performance_link: performance_link(format) },
- s_('InProductMarketing|Move on to easily creating a Pages website %{ci_template_link}').html_safe % { ci_template_link: ci_template_link(format) },
- s_('InProductMarketing|And finally %{deploy_link} a Python application.').html_safe % { deploy_link: deploy_link(format) }
- ], format),
- nil
- ],
- trial: [
- s_('InProductMarketing|Start a GitLab Ultimate trial today in less than one minute, no credit card required.'),
- s_('InProductMarketing|Get started today with a 30-day GitLab Ultimate trial, no credit card required.'),
- s_('InProductMarketing|Code owners and required merge approvals are part of the paid tiers of GitLab. You can start a free 30-day trial of GitLab Ultimate and enable these features in less than 5 minutes with no credit card required.')
- ],
- team: [
- s_('InProductMarketing|Invite your colleagues and start shipping code faster.'),
- s_("InProductMarketing|Streamline code review, know at a glance who's unavailable, communicate in comments or in email and integrate with Slack so everyone's on the same page."),
- s_('InProductMarketing|When your team is on GitLab these answers are a click away.')
- ]
- }[track][series]
- end
-
- def cta_link(track, series, group, format: nil)
- case format
- when :html
- link_to in_product_marketing_cta_text(track, series), group_email_campaigns_url(group, track: track, series: series), target: '_blank', rel: 'noopener noreferrer'
- else
- [in_product_marketing_cta_text(track, series), group_email_campaigns_url(group, track: track, series: series)].join(' >> ')
- end
- end
-
- def in_product_marketing_progress(track, series, format: nil)
- if Gitlab.com?
- s_('InProductMarketing|This is email %{series} of 3 in the %{track} series.') % { series: series + 1, track: track.to_s.humanize }
- else
- s_('InProductMarketing|This is email %{series} of 3 in the %{track} series. To disable notification emails sent by your local GitLab instance, either contact your administrator or %{unsubscribe_link}.') % { series: series + 1, track: track.to_s.humanize, unsubscribe_link: unsubscribe_link(format) }
- end
- end
-
- def footer_links(format: nil)
- links = [
- [s_('InProductMarketing|Blog'), 'https://about.gitlab.com/blog'],
- [s_('InProductMarketing|Twitter'), 'https://twitter.com/gitlab'],
- [s_('InProductMarketing|Facebook'), 'https://www.facebook.com/gitlab'],
- [s_('InProductMarketing|YouTube'), 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg']
- ]
- case format
- when :html
- links.map do |text, link|
- link_to(text, link)
- end
- else
- '| ' + links.map do |text, link|
- [text, link].join(' ')
- end.join("\n| ")
- end
- end
-
- def address(format: nil)
- s_('InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA').html_safe % strong_options(format)
- end
-
- def unsubscribe(track, series, format: nil)
- parts = Gitlab.com? ? unsubscribe_com(format) : unsubscribe_self_managed(track, series, format)
-
- case format
- when :html
- parts.join(' ')
- else
- parts.join("\n" + ' ' * 16)
- end
- end
-
- private
-
- def unsubscribe_com(format)
- [
- s_('InProductMarketing|If you no longer wish to receive marketing emails from us,'),
- s_('InProductMarketing|you may %{unsubscribe_link} at any time.') % { unsubscribe_link: unsubscribe_link(format) }
- ]
- end
-
- def unsubscribe_self_managed(track, series, format)
- [
- s_('InProductMarketing|To opt out of these onboarding emails, %{unsubscribe_link}.') % { unsubscribe_link: unsubscribe_link(format) },
- s_("InProductMarketing|If you don't want to receive marketing emails directly from GitLab, %{marketing_preference_link}.") % { marketing_preference_link: marketing_preference_link(track, series, format) }
- ]
- end
-
- def in_product_marketing_cta_text(track, series)
- {
- create: [
- s_('InProductMarketing|Create your first project!'),
- s_('InProductMarketing|Master the art of importing!'),
- s_('InProductMarketing|Understand your project options')
- ],
- verify: [
- s_('InProductMarketing|Get to know GitLab CI/CD'),
- s_('InProductMarketing|Try it yourself'),
- s_('InProductMarketing|Explore GitLab CI/CD')
- ],
- trial: [
- s_('InProductMarketing|Start a trial'),
- s_('InProductMarketing|Beef up your security'),
- s_('InProductMarketing|Start your trial now!')
- ],
- team: [
- s_('InProductMarketing|Invite your colleagues today'),
- s_('InProductMarketing|Invite your team in less than 60 seconds'),
- s_('InProductMarketing|Invite your team now')
- ]
- }[track][series]
- end
-
- def project_link(format)
- link(s_('InProductMarketing|create a project'), help_page_url('gitlab-basics/create-project'), format)
- end
-
- def repo_link(format)
- link(s_('InProductMarketing|set up a repo'), help_page_url('user/project/repository/index', anchor: 'create-a-repository'), format)
- end
-
- def github_link(format)
- link(s_('InProductMarketing|GitHub Enterprise projects to GitLab'), help_page_url('integration/github'), format)
- end
-
- def bitbucket_link(format)
- link(s_('InProductMarketing|from Bitbucket'), help_page_url('user/project/import/bitbucket_server'), format)
- end
-
- def mirroring_link(format)
- link(s_('InProductMarketing|repository mirroring'), help_page_url('user/project/repository/repository_mirroring'), format)
- end
-
- def ci_link(format)
- link(s_('InProductMarketing|how easy it is to get started'), help_page_url('ci/README'), format)
- end
-
- def performance_link(format)
- link(s_('InProductMarketing|testing browser performance'), help_page_url('user/project/merge_requests/browser_performance_testing'), format)
- end
-
- def ci_template_link(format)
- link(s_('InProductMarketing|using a CI/CD template'), help_page_url('user/project/pages/getting_started/pages_ci_cd_template'), format)
- end
-
- def deploy_link(format)
- link(s_('InProductMarketing|test and deploy'), help_page_url('ci/examples/test-and-deploy-python-application-to-heroku'), format)
- end
-
- def quick_start_link(format)
- link(s_('InProductMarketing|quick start guide'), help_page_url('ci/quick_start/README'), format)
- end
-
- def basics_link(format)
- link(s_('InProductMarketing|Git basics'), help_page_url('gitlab-basics/README'), format)
- end
-
- def import_link(format)
- link(s_('InProductMarketing|comprehensive guide'), help_page_url('user/project/import/index'), format)
- end
-
- def external_repo_link(format)
- link(s_('InProductMarketing|connect an external repository'), new_project_url(anchor: 'cicd_for_external_repo'), format)
- end
-
- def unsubscribe_link(format)
- unsubscribe_url = Gitlab.com? ? '%tag_unsubscribe_url%' : profile_notifications_url
-
- link(s_('InProductMarketing|unsubscribe'), unsubscribe_url, format)
- end
-
- def marketing_preference_link(track, series, format)
- params = {
- utm_source: 'SM',
- utm_medium: 'email',
- utm_campaign: 'onboarding',
- utm_term: "#{track}_#{series}"
- }
-
- preference_link = "https://about.gitlab.com/company/preference-center/?#{params.to_query}"
-
- link(s_('InProductMarketing|update your preferences'), preference_link, format)
- end
-
- def link(text, link, format)
- case format
- when :html
- link_to text, link
- else
- "#{text} (#{link})"
- end
- end
-
- def list(array, format)
- case format
- when :html
- tag.ul { array.map { |item| concat tag.li item} }
- else
- '- ' + array.join("\n- ")
- end
- end
-
- def strong_options(format)
- case format
- when :html
- { strong_start: '<b>'.html_safe, strong_end: '</b>'.html_safe }
- else
- { strong_start: '', strong_end: '' }
- end
+ def inline_image_link(image, options)
+ attachments.inline[image] = File.read(Rails.root.join("app/assets/images", image))
+ image_tag attachments[image].url, **options
end
- def inline_image_link(folder, image, options)
- attachments.inline[image] = File.read(Rails.root.join("app/assets/images", folder, image))
- image_tag attachments[image].url, **options
+ def about_link(image, width)
+ link_to inline_image_link(image, { width: width, style: "width: #{width}px;", alt: s_('InProductMarketing|go to about.gitlab.com') }), 'https://about.gitlab.com/'
end
end
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index 62d83ebe79e..889c058cb21 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -3,12 +3,12 @@
module InviteMembersHelper
include Gitlab::Utils::StrongMemoize
- def can_invite_members_for_group?(group)
- Feature.enabled?(:invite_members_group_modal, group) && can?(current_user, :admin_group_member, group)
+ def can_invite_members_for_project?(project)
+ Feature.enabled?(:invite_members_group_modal, project.group) && can_manage_project_members?(project)
end
- def can_invite_members_for_project?(project)
- Feature.enabled?(:invite_members_group_modal, project.group) && can_import_members?
+ def can_invite_group_for_project?(project)
+ Feature.enabled?(:invite_members_group_modal, project.group) && project.allowed_to_share_with_group?
end
def directly_invite_members?
@@ -17,20 +17,6 @@ module InviteMembersHelper
end
end
- def indirectly_invite_members?
- strong_memoize(:indirectly_invite_members) do
- experiment_enabled?(:invite_members_version_b) && !can_import_members?
- end
- end
-
- def show_invite_members_track_event
- if directly_invite_members?
- 'show_invite_members'
- elsif indirectly_invite_members?
- 'show_invite_members_version_b'
- end
- end
-
def invite_group_members?(group)
experiment_enabled?(:invite_members_empty_group_version_a) && Ability.allowed?(current_user, :admin_group_member, group)
end
@@ -46,6 +32,17 @@ module InviteMembersHelper
end
end
+ def invite_accepted_notice(member)
+ case member.source
+ when Project
+ _("You have been granted %{member_human_access} access to project %{name}.") %
+ { member_human_access: member.human_access, name: member.source.name }
+ when Group
+ _("You have been granted %{member_human_access} access to group %{name}.") %
+ { member_human_access: member.human_access, name: member.source.name }
+ end
+ end
+
private
def invite_members_url(form_model)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 8ebc773bb25..c662dabe453 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -199,7 +199,7 @@ module IssuablesHelper
count = issuables_count_for_state(issuable_type, state)
if count != -1
- html << " " << content_tag(:span, number_with_delimiter(count), class: 'badge badge-pill')
+ html << " " << content_tag(:span, number_with_delimiter(count), class: 'badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm')
end
html.html_safe
@@ -332,6 +332,18 @@ module IssuablesHelper
end
end
+ def state_name_with_icon(issuable)
+ if issuable.is_a?(MergeRequest) && issuable.merged?
+ [_("Merged"), "git-merge"]
+ elsif issuable.is_a?(MergeRequest) && issuable.closed?
+ [_("Closed"), "close"]
+ elsif issuable.closed?
+ [_("Closed"), "mobile-issue-close"]
+ else
+ [_("Open"), "issue-open-m"]
+ end
+ end
+
private
def sidebar_gutter_collapsed?
@@ -386,11 +398,11 @@ module IssuablesHelper
rootPath: root_path,
fullPath: issuable[:project_full_path],
iid: issuable[:iid],
+ id: issuable[:id],
severity: issuable[:severity],
timeTrackingLimitToHours: Gitlab::CurrentSettings.time_tracking_limit_to_hours,
createNoteEmail: issuable[:create_note_email],
- issuableType: issuable[:type],
- projectMembersPath: project_project_members_path(@project, sort: :access_level_desc)
+ issuableType: issuable[:type]
}
end
@@ -414,4 +426,4 @@ module IssuablesHelper
end
end
-IssuablesHelper.prepend_if_ee('EE::IssuablesHelper')
+IssuablesHelper.prepend_mod_with('IssuablesHelper')
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 0a83e707412..1449725fb2b 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -9,6 +9,22 @@ module IssuesHelper
classes.join(' ')
end
+ def issue_manual_ordering_class
+ is_sorting_by_relative_position = @sort == 'relative_position'
+
+ if is_sorting_by_relative_position && !issue_repositioning_disabled?
+ "manual-ordering"
+ end
+ end
+
+ def issue_repositioning_disabled?
+ if @group
+ @group.root_ancestor.issue_repositioning_disabled?
+ elsif @project
+ @project.root_namespace.issue_repositioning_disabled?
+ end
+ end
+
def status_box_class(item)
if item.try(:expired?)
'status-box-expired'
@@ -165,23 +181,32 @@ module IssuesHelper
def issues_list_data(project, current_user, finder)
{
+ autocomplete_users_path: autocomplete_users_path(active: true, current_user: true, project_id: project.id, format: :json),
+ autocomplete_award_emojis_path: autocomplete_award_emojis_path,
calendar_path: url_for(safe_params.merge(calendar_url_options)),
can_bulk_update: can?(current_user, :admin_issue, project).to_s,
can_edit: can?(current_user, :admin_project, project).to_s,
can_import_issues: can?(current_user, :import_issues, @project).to_s,
email: current_user&.notification_email,
+ emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'),
empty_state_svg_path: image_path('illustrations/issues.svg'),
endpoint: expose_path(api_v4_projects_issues_path(id: project.id)),
export_csv_path: export_csv_project_issues_path(project),
- full_path: project.full_path,
has_issues: project_issues(project).exists?.to_s,
import_csv_issues_path: import_csv_namespace_project_issues_path,
+ initial_email: project.new_issuable_address(current_user, 'issue'),
is_signed_in: current_user.present?.to_s,
issues_path: project_issues_path(project),
jira_integration_path: help_page_url('user/project/integrations/jira', anchor: 'view-jira-issues'),
+ markdown_help_path: help_page_path('user/markdown'),
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
new_issue_path: new_project_issue_path(project, issue: { assignee_id: finder.assignee.try(:id), milestone_id: finder.milestones.first.try(:id) }),
project_import_jira_path: project_import_jira_path(project),
+ project_labels_path: project_labels_path(project, include_ancestor_groups: true, format: :json),
+ project_milestones_path: project_milestones_path(project, format: :json),
+ project_path: project.full_path,
+ quick_actions_help_path: help_page_path('user/project/quick_actions'),
+ reset_path: new_issuable_address_project_path(project, issuable_type: 'issue'),
rss_path: url_for(safe_params.merge(rss_url_options)),
show_new_issue_link: show_new_issue_link?(project).to_s,
sign_in_path: new_user_session_path
@@ -200,4 +225,4 @@ module IssuesHelper
end
end
-IssuesHelper.prepend_if_ee('EE::IssuesHelper')
+IssuesHelper.prepend_mod_with('IssuesHelper')
diff --git a/app/helpers/kerberos_spnego_helper.rb b/app/helpers/kerberos_spnego_helper.rb
index ed09ed755fe..0f6812bc31b 100644
--- a/app/helpers/kerberos_spnego_helper.rb
+++ b/app/helpers/kerberos_spnego_helper.rb
@@ -10,4 +10,4 @@ module KerberosSpnegoHelper
end
end
-KerberosSpnegoHelper.prepend_if_ee('EE::KerberosSpnegoHelper')
+KerberosSpnegoHelper.prepend_mod_with('KerberosSpnegoHelper')
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index cfc4075100b..2150729cb2a 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -275,4 +275,4 @@ module LabelsHelper
end
end
-LabelsHelper.prepend_if_ee('EE::LabelsHelper')
+LabelsHelper.prepend_mod_with('LabelsHelper')
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
index 81896fb9fa4..a3a8a275f67 100644
--- a/app/helpers/learn_gitlab_helper.rb
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -3,11 +3,21 @@
module LearnGitlabHelper
def learn_gitlab_experiment_enabled?(project)
return false unless current_user
- return false unless experiment_enabled_for_user?
+ return false unless continous_onboarding_experiment_enabled_for_user?
learn_gitlab_onboarding_available?(project)
end
+ def learn_gitlab_experiment_tracking_category
+ return unless current_user
+
+ if Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_a, subject: current_user)
+ Gitlab::Experimentation.get_experiment(:learn_gitlab_a).tracking_category
+ elsif Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_b, subject: current_user)
+ Gitlab::Experimentation.get_experiment(:learn_gitlab_b).tracking_category
+ end
+ end
+
def onboarding_actions_data(project)
attributes = onboarding_progress(project).attributes.symbolize_keys
@@ -21,42 +31,42 @@ module LearnGitlabHelper
end
end
- private
+ def continous_onboarding_experiment_enabled_for_user?
+ Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_a, subject: current_user) ||
+ Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_b, subject: current_user)
+ end
- ACTION_ISSUE_IDS = {
- issue_created: 4,
- git_write: 6,
- pipeline_created: 7,
- merge_request_created: 9,
- user_added: 8,
- trial_started: 2,
- required_mr_approvals_enabled: 11,
- code_owners_enabled: 10
- }.freeze
-
- ACTION_DOC_URLS = {
- security_scan_enabled: 'https://docs.gitlab.com/ee/user/application_security/security_dashboard/#gitlab-security-dashboard-security-center-and-vulnerability-reports'
- }.freeze
+ def onboarding_sections_data
+ {
+ workspace: {
+ svg: image_path("learn_gitlab/section_workspace.svg")
+ },
+ plan: {
+ svg: image_path("learn_gitlab/section_plan.svg")
+ },
+ deploy: {
+ svg: image_path("learn_gitlab/section_deploy.svg")
+ }
+ }
+ end
+
+ def learn_gitlab_onboarding_available?(project)
+ OnboardingProgress.onboarding?(project.namespace) &&
+ LearnGitlab::Project.new(current_user).available?
+ end
+
+ private
def action_urls
- ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) }.merge(ACTION_DOC_URLS)
+ LearnGitlab::Onboarding::ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) }
+ .merge(LearnGitlab::Onboarding::ACTION_DOC_URLS)
end
def learn_gitlab_project
- @learn_gitlab_project ||= LearnGitlab.new(current_user).project
+ @learn_gitlab_project ||= LearnGitlab::Project.new(current_user).project
end
def onboarding_progress(project)
OnboardingProgress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord
end
-
- def experiment_enabled_for_user?
- Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_a, subject: current_user) ||
- Gitlab::Experimentation.in_experiment_group?(:learn_gitlab_b, subject: current_user)
- end
-
- def learn_gitlab_onboarding_available?(project)
- OnboardingProgress.onboarding?(project.namespace) &&
- LearnGitlab.new(current_user).available?
- end
end
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index ad206d0e5b5..05a55a09271 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -318,4 +318,4 @@ module MarkupHelper
extend self
end
-MarkupHelper.prepend_if_ee('EE::MarkupHelper')
+MarkupHelper.prepend_mod_with('MarkupHelper')
diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb
index 5dc636ad996..d3db5d24207 100644
--- a/app/helpers/members_helper.rb
+++ b/app/helpers/members_helper.rb
@@ -65,4 +65,14 @@ module MembersHelper
'group and any subresources'
end
+
+ def members_pagination_data(members, pagination = {})
+ {
+ current_page: members.respond_to?(:current_page) ? members.current_page : nil,
+ per_page: members.respond_to?(:limit_value) ? members.limit_value : nil,
+ total_items: members.respond_to?(:total_count) ? members.total_count : members.count,
+ param_name: pagination[:param_name] || nil,
+ params: pagination[:params] || {}
+ }
+ end
end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index df7fcb0f3da..514f5fafd65 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -29,16 +29,6 @@ module MergeRequestsHelper
classes.join(' ')
end
- def state_name_with_icon(merge_request)
- if merge_request.merged?
- [_("Merged"), "git-merge"]
- elsif merge_request.closed?
- [_("Closed"), "close"]
- else
- [_("Open"), "issue-open-m"]
- end
- end
-
def merge_path_description(merge_request, separator)
if merge_request.for_fork?
"Project:Branches: #{@merge_request.source_project_path}:#{@merge_request.source_branch} #{separator} #{@merge_request.target_project.full_path}:#{@merge_request.target_branch}"
@@ -223,4 +213,4 @@ module MergeRequestsHelper
end
end
-MergeRequestsHelper.prepend_if_ee('EE::MergeRequestsHelper')
+MergeRequestsHelper.prepend_mod_with('MergeRequestsHelper')
diff --git a/app/helpers/mirror_helper.rb b/app/helpers/mirror_helper.rb
index 9d23ab87b98..3dfd30f07db 100644
--- a/app/helpers/mirror_helper.rb
+++ b/app/helpers/mirror_helper.rb
@@ -17,4 +17,4 @@ module MirrorHelper
end
end
-MirrorHelper.prepend_if_ee('EE::MirrorHelper')
+MirrorHelper.prepend_mod_with('MirrorHelper')
diff --git a/app/helpers/namespace_storage_limit_alert_helper.rb b/app/helpers/namespace_storage_limit_alert_helper.rb
index d7174c38254..ed11f89a7dd 100644
--- a/app/helpers/namespace_storage_limit_alert_helper.rb
+++ b/app/helpers/namespace_storage_limit_alert_helper.rb
@@ -6,4 +6,4 @@ module NamespaceStorageLimitAlertHelper
end
end
-NamespaceStorageLimitAlertHelper.prepend_if_ee('EE::NamespaceStorageLimitAlertHelper')
+NamespaceStorageLimitAlertHelper.prepend_mod_with('NamespaceStorageLimitAlertHelper')
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index a4521541bf9..39a8f506ba2 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -83,6 +83,15 @@ module NamespacesHelper
}
end
+ def cascading_namespace_setting_locked?(attribute, group, **args)
+ return false if group.nil?
+
+ method_name = "#{attribute}_locked?"
+ return false unless group.namespace_settings.respond_to?(method_name)
+
+ group.namespace_settings.public_send(method_name, **args) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
private
# Many importers create a temporary Group, so use the real
@@ -116,4 +125,4 @@ module NamespacesHelper
end
end
-NamespacesHelper.prepend_if_ee('EE::NamespacesHelper')
+NamespacesHelper.prepend_mod_with('NamespacesHelper')
diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb
new file mode 100644
index 00000000000..159b7ca87f9
--- /dev/null
+++ b/app/helpers/nav/top_nav_helper.rb
@@ -0,0 +1,243 @@
+# frozen_string_literal: true
+
+module Nav
+ module TopNavHelper
+ PROJECTS_VIEW = :projects
+ GROUPS_VIEW = :groups
+
+ def top_nav_view_model(project:, group:)
+ builder = ::Gitlab::Nav::TopNavViewModelBuilder.new
+
+ if current_user
+ build_view_model(builder: builder, project: project, group: group)
+ else
+ build_anonymous_view_model(builder: builder)
+ end
+
+ builder.build
+ end
+
+ private
+
+ def build_anonymous_view_model(builder:)
+ # These come from `app/views/layouts/nav/_explore.html.ham`
+ if explore_nav_link?(:projects)
+ builder.add_primary_menu_item(
+ **projects_menu_item_attrs.merge(
+ {
+ active: active_nav_link?(path: %w[dashboard#show root#show projects#trending projects#starred projects#index]),
+ href: explore_root_path
+ })
+ )
+ end
+
+ if explore_nav_link?(:groups)
+ builder.add_primary_menu_item(
+ **groups_menu_item_attrs.merge(
+ {
+ active: active_nav_link?(controller: [:groups, 'groups/milestones', 'groups/group_members']),
+ href: explore_groups_path
+ })
+ )
+ end
+
+ if explore_nav_link?(:snippets)
+ builder.add_primary_menu_item(
+ **snippets_menu_item_attrs.merge(
+ {
+ active: active_nav_link?(controller: :snippets),
+ href: explore_snippets_path
+ })
+ )
+ end
+ end
+
+ def build_view_model(builder:, project:, group:)
+ # These come from `app/views/layouts/nav/_dashboard.html.haml`
+ if dashboard_nav_link?(:projects)
+ current_item = project ? current_project(project: project) : {}
+
+ builder.add_primary_menu_item(
+ **projects_menu_item_attrs.merge({
+ active: 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_event: "click_dropdown", track_experiment: "new_repo" },
+ view: PROJECTS_VIEW
+ })
+ )
+ builder.add_view(PROJECTS_VIEW, container_view_props(namespace: 'projects', current_item: current_item, submenu: projects_submenu))
+ end
+
+ if dashboard_nav_link?(:groups)
+ current_item = group ? current_group(group: group) : {}
+
+ builder.add_primary_menu_item(
+ **groups_menu_item_attrs.merge({
+ active: active_nav_link?(path: %w[dashboard/groups explore/groups]),
+ css_class: 'qa-groups-dropdown',
+ data: { track_label: "groups_dropdown", track_event: "click_dropdown" },
+ view: GROUPS_VIEW
+ })
+ )
+ builder.add_view(GROUPS_VIEW, container_view_props(namespace: 'groups', current_item: current_item, submenu: groups_submenu))
+ end
+
+ if dashboard_nav_link?(:milestones)
+ builder.add_primary_menu_item(
+ id: 'milestones',
+ title: 'Milestones',
+ active: active_nav_link?(controller: 'dashboard/milestones'),
+ icon: 'clock',
+ data: { qa_selector: 'milestones_link' },
+ href: dashboard_milestones_path
+ )
+ end
+
+ if dashboard_nav_link?(:snippets)
+ builder.add_primary_menu_item(
+ **snippets_menu_item_attrs.merge({
+ active: active_nav_link?(controller: 'dashboard/snippets'),
+ data: { qa_selector: 'snippets_link' },
+ href: dashboard_snippets_path
+ })
+ )
+ end
+
+ if dashboard_nav_link?(:activity)
+ builder.add_primary_menu_item(
+ id: 'activity',
+ title: 'Activity',
+ active: active_nav_link?(path: 'dashboard#activity'),
+ icon: 'history',
+ data: { qa_selector: 'activity_link' },
+ href: activity_dashboard_path
+ )
+ end
+
+ # Using admin? is generally discouraged because it does not check for
+ # "admin_mode". In this case we are migrating code and check both, so
+ # we should be good.
+ # rubocop: disable Cop/UserAdmin
+ if current_user&.admin?
+ builder.add_secondary_menu_item(
+ id: 'admin',
+ title: _('Admin'),
+ active: active_nav_link?(controller: 'admin/dashboard'),
+ icon: 'admin',
+ css_class: 'qa-admin-area-link',
+ href: admin_root_path
+ )
+ end
+
+ if Gitlab::CurrentSettings.admin_mode
+ if header_link?(:admin_mode)
+ builder.add_secondary_menu_item(
+ id: 'leave_admin_mode',
+ title: _('Leave Admin Mode'),
+ active: active_nav_link?(controller: 'admin/sessions'),
+ icon: 'lock-open',
+ href: destroy_admin_session_path,
+ method: :post
+ )
+ elsif current_user.admin?
+ builder.add_secondary_menu_item(
+ id: 'enter_admin_mode',
+ title: _('Enter Admin Mode'),
+ active: active_nav_link?(controller: 'admin/sessions'),
+ icon: 'lock',
+ href: new_admin_session_path
+ )
+ end
+ end
+ # rubocop: enable Cop/UserAdmin
+
+ if Gitlab::Sherlock.enabled?
+ builder.add_secondary_menu_item(
+ id: 'sherlock',
+ title: _('Sherlock Transactions'),
+ icon: 'admin',
+ href: sherlock_transactions_path
+ )
+ end
+ end
+
+ def projects_menu_item_attrs
+ {
+ id: 'project',
+ title: _('Projects'),
+ icon: 'project'
+ }
+ end
+
+ def groups_menu_item_attrs
+ {
+ id: 'groups',
+ title: 'Groups',
+ icon: 'group'
+ }
+ end
+
+ def snippets_menu_item_attrs
+ {
+ id: 'snippets',
+ title: _('Snippets'),
+ icon: 'snippet'
+ }
+ end
+
+ def container_view_props(namespace:, current_item:, submenu:)
+ {
+ namespace: namespace,
+ currentUserName: current_user&.username,
+ currentItem: current_item,
+ linksPrimary: submenu[:primary],
+ linksSecondary: submenu[:secondary]
+ }
+ end
+
+ def current_project(project:)
+ return {} unless project.persisted?
+
+ {
+ id: project.id,
+ name: project.name,
+ namespace: project.full_name,
+ webUrl: project_path(project),
+ avatarUrl: project.avatar_url
+ }
+ end
+
+ def current_group(group:)
+ return {} unless group.persisted?
+
+ {
+ id: group.id,
+ name: group.name,
+ namespace: group.full_name,
+ webUrl: group_path(group),
+ avatarUrl: group.avatar_url
+ }
+ end
+
+ def projects_submenu
+ # These project links come from `app/views/layouts/nav/projects_dropdown/_show.html.haml`
+ builder = ::Gitlab::Nav::TopNavMenuBuilder.new
+ builder.add_primary_menu_item(id: 'your', title: _('Your projects'), href: dashboard_projects_path)
+ builder.add_primary_menu_item(id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path)
+ builder.add_primary_menu_item(id: 'explore', title: _('Explore projects'), href: explore_root_path)
+ builder.add_secondary_menu_item(id: 'create', title: _('Create new project'), href: new_project_path)
+ builder.build
+ end
+
+ def groups_submenu
+ # These group links come from `app/views/layouts/nav/groups_dropdown/_show.html.haml`
+ builder = ::Gitlab::Nav::TopNavMenuBuilder.new
+ builder.add_primary_menu_item(id: 'your', title: _('Your groups'), href: dashboard_groups_path)
+ builder.add_primary_menu_item(id: 'explore', title: _('Explore groups'), href: explore_groups_path)
+ builder.add_secondary_menu_item(id: 'create', title: _('Create group'), href: new_group_path(anchor: 'create-group-pane'))
+ builder.build
+ end
+ end
+end
+
+Nav::TopNavHelper.prepend_mod
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index db144f63f92..aab1a44bdfb 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -12,6 +12,7 @@ module NavHelper
def page_with_sidebar_class
class_name = page_gutter_class
class_name << 'page-with-contextual-sidebar' if defined?(@left_sidebar) && @left_sidebar
+ class_name << 'sidebar-refactoring' if Feature.enabled?(:sidebar_refactor, current_user)
class_name << 'page-with-icon-sidebar' if collapsed_sidebar? && @left_sidebar
class_name -= ['right-sidebar-expanded'] if defined?(@right_sidebar) && !@right_sidebar
@@ -68,7 +69,14 @@ module NavHelper
end
def group_issues_sub_menu_items
- %w(groups#issues labels#index milestones#index boards#index boards#show)
+ %w[
+ groups#issues
+ milestones#index
+ boards#index
+ boards#show
+ ].tap do |paths|
+ paths << 'labels#index' if Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ end
end
private
@@ -100,4 +108,4 @@ module NavHelper
end
end
-NavHelper.prepend_if_ee('EE::NavHelper')
+NavHelper.prepend_mod_with('NavHelper')
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 62580124c0f..fff7e5d1c7f 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -215,4 +215,4 @@ module NotesHelper
end
end
-NotesHelper.prepend_if_ee('EE::NotesHelper')
+NotesHelper.prepend_mod_with('NotesHelper')
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
index 03da679cfdd..38c98776fdf 100644
--- a/app/helpers/notify_helper.rb
+++ b/app/helpers/notify_helper.rb
@@ -18,7 +18,7 @@ module NotifyHelper
when "Developer"
s_("InviteEmail|As a developer, you have full access to projects, so you can take an idea from concept to production.")
when "Maintainer"
- s_("InviteEmail|As a maintainer, you have full access to projects. You can push commits to master and deploy to production.")
+ s_("InviteEmail|As a maintainer, you have full access to projects. You can push commits to the default branch and deploy to production.")
when "Owner"
s_("InviteEmail|As an owner, you have full access to projects and can manage access to the group, including inviting new members.")
when "Minimal Access"
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index 51f4304911b..df07baa2d03 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -44,4 +44,4 @@ module OperationsHelper
end
end
-OperationsHelper.prepend_if_ee('EE::OperationsHelper')
+OperationsHelper.prepend_mod_with('OperationsHelper')
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 6997c8cffda..2729951d685 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -162,7 +162,6 @@ module PageLayoutHelper
default_properties = {
current_emoji: '',
current_message: '',
- can_set_user_availability: Feature.enabled?(:set_user_availability_status, user, default_enabled: :yaml),
default_emoji: UserStatus::DEFAULT_EMOJI
}
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index add6e1eaf6f..d851ed3db8f 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -4,8 +4,8 @@
module PreferencesHelper
def layout_choices
[
- ['Fixed', :fixed],
- ['Fluid', :fluid]
+ ['Fixed', :fixed],
+ ['Fluid', :fluid]
]
end
@@ -76,7 +76,7 @@ module PreferencesHelper
def language_choices
options_for_select(
- Gitlab::I18n.selectable_locales.map(&:reverse).sort,
+ selectable_locales_with_translation_level.sort,
current_user.preferred_language
)
end
@@ -107,6 +107,18 @@ module PreferencesHelper
def default_first_day_of_week
first_day_of_week_choices.rassoc(Gitlab::CurrentSettings.first_day_of_week).first
end
+
+ def selectable_locales_with_translation_level
+ Gitlab::I18n.selectable_locales.map do |code, language|
+ [
+ s_("i18n|%{language} (%{percent_translated}%% translated)") % {
+ language: language,
+ percent_translated: Gitlab::I18n.percentage_translated_for(code)
+ },
+ code
+ ]
+ end
+ end
end
-PreferencesHelper.prepend_if_ee('EE::PreferencesHelper')
+PreferencesHelper.prepend_mod_with('PreferencesHelper')
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 3219620de71..f6ed567c9ea 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -51,4 +51,4 @@ module ProfilesHelper
end
end
-ProfilesHelper.prepend_ee_mod
+ProfilesHelper.prepend_mod
diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb
index b705258f133..b46e3eb3bc3 100644
--- a/app/helpers/projects/alert_management_helper.rb
+++ b/app/helpers/projects/alert_management_helper.rb
@@ -10,6 +10,7 @@ module Projects::AlertManagementHelper
'empty-alert-svg-path' => image_path('illustrations/alert-management-empty-state.svg'),
'user-can-enable-alert-management' => can?(current_user, :admin_operations, project).to_s,
'alert-management-enabled' => alert_management_enabled?(project).to_s,
+ 'has-managed-prometheus' => has_managed_prometheus?(project).to_s,
'text-query': params[:search],
'assignee-username-query': params[:assignee_username]
}
@@ -27,6 +28,10 @@ module Projects::AlertManagementHelper
private
+ def has_managed_prometheus?(project)
+ project.prometheus_service&.prometheus_available? == true
+ end
+
def alert_management_enabled?(project)
!!(
project.alert_management_alerts.any? ||
diff --git a/app/helpers/projects/incidents_helper.rb b/app/helpers/projects/incidents_helper.rb
index 63504cb55b9..dde2980817f 100644
--- a/app/helpers/projects/incidents_helper.rb
+++ b/app/helpers/projects/incidents_helper.rb
@@ -16,4 +16,4 @@ module Projects::IncidentsHelper
end
end
-Projects::IncidentsHelper.prepend_if_ee('EE::Projects::IncidentsHelper')
+Projects::IncidentsHelper.prepend_mod_with('Projects::IncidentsHelper')
diff --git a/app/helpers/projects/project_members_helper.rb b/app/helpers/projects/project_members_helper.rb
index 662afbcfd25..fa68bbad135 100644
--- a/app/helpers/projects/project_members_helper.rb
+++ b/app/helpers/projects/project_members_helper.rb
@@ -27,29 +27,41 @@ module Projects::ProjectMembersHelper
project.group.has_owner?(current_user)
end
- def project_group_links_data_json(group_links)
- GroupLink::ProjectGroupLinkSerializer.new.represent(group_links, { current_user: current_user }).to_json
+ def project_members_list_data_json(project, members, pagination = {})
+ project_members_list_data(project, members, pagination).to_json
end
- def project_members_data_json(project, members)
- MemberSerializer.new.represent(members, { current_user: current_user, group: project.group, source: project }).to_json
+ def project_group_links_list_data_json(project, group_links)
+ project_group_links_list_data(project, group_links).to_json
end
- def project_members_list_data_attributes(project, members)
+ private
+
+ def project_members_serialized(project, members)
+ MemberSerializer.new.represent(members, { current_user: current_user, group: project.group, source: project })
+ end
+
+ def project_group_links_serialized(group_links)
+ GroupLink::ProjectGroupLinkSerializer.new.represent(group_links, { current_user: current_user })
+ end
+
+ def project_members_list_data(project, members, pagination)
{
- members: project_members_data_json(project, members),
+ members: project_members_serialized(project, members),
+ pagination: members_pagination_data(members, pagination),
member_path: project_project_member_path(project, ':id'),
source_id: project.id,
- can_manage_members: can_manage_project_members?(project).to_s
+ can_manage_members: can_manage_project_members?(project)
}
end
- def project_group_links_list_data_attributes(project, group_links)
+ def project_group_links_list_data(project, group_links)
{
- members: project_group_links_data_json(group_links),
+ members: project_group_links_serialized(group_links),
+ pagination: members_pagination_data(group_links),
member_path: project_group_link_path(project, ':id'),
source_id: project.id,
- can_manage_members: can_manage_project_members?(project).to_s
+ can_manage_members: can_manage_project_members?(project)
}
end
end
diff --git a/app/helpers/projects/security/configuration_helper.rb b/app/helpers/projects/security/configuration_helper.rb
index 265d46cbc41..dee106ab3ae 100644
--- a/app/helpers/projects/security/configuration_helper.rb
+++ b/app/helpers/projects/security/configuration_helper.rb
@@ -10,4 +10,4 @@ module Projects
end
end
-::Projects::Security::ConfigurationHelper.prepend_if_ee('::EE::Projects::Security::ConfigurationHelper')
+::Projects::Security::ConfigurationHelper.prepend_mod_with('Projects::Security::ConfigurationHelper')
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 4be6cd4276b..f2a50ce1325 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -125,34 +125,12 @@ module ProjectsHelper
project.fork_source if project.fork_source && can?(current_user, :read_project, project.fork_source)
end
- def project_nav_tabs
- @nav_tabs ||= get_project_nav_tabs(@project, current_user)
- end
-
def project_search_tabs?(tab)
abilities = Array(search_tab_ability_map[tab])
abilities.any? { |ability| can?(current_user, ability, @project) }
end
- def project_nav_tab?(name)
- project_nav_tabs.include? name
- end
-
- def any_project_nav_tab?(tabs)
- tabs.any? { |tab| project_nav_tab?(tab) }
- end
-
- def project_for_deploy_key(deploy_key)
- if deploy_key.has_access_to?(@project)
- @project
- else
- deploy_key.projects.find do |project|
- can?(current_user, :read_project, project)
- end
- end
- end
-
def can_change_visibility_level?(project, current_user)
can?(current_user, :change_visibility_level, project)
end
@@ -285,10 +263,6 @@ module ProjectsHelper
!disabled && !compact_mode
end
- def settings_operations_available?
- !@project.archived? && can?(current_user, :admin_operations, @project)
- end
-
def error_tracking_setting_project_json
setting = @project.error_tracking_setting
@@ -378,89 +352,6 @@ module ProjectsHelper
private
- def can_read_security_configuration?(project, current_user)
- can?(current_user, :access_security_and_compliance, project) &&
- can?(current_user, :read_security_configuration, project)
- end
-
- def get_project_security_nav_tabs(project, current_user)
- if can_read_security_configuration?(project, current_user)
- [:security_and_compliance, :security_configuration]
- else
- []
- end
- end
-
- # rubocop:disable Metrics/CyclomaticComplexity
- def get_project_nav_tabs(project, current_user)
- nav_tabs = [:home]
-
- unless project.empty_repo?
- nav_tabs += [:files, :commits, :network, :graphs, :forks] if can?(current_user, :download_code, project)
- nav_tabs << :releases if can?(current_user, :read_release, project)
- end
-
- nav_tabs += get_project_security_nav_tabs(project, current_user)
-
- if project.repo_exists? && can?(current_user, :read_merge_request, project)
- nav_tabs << :merge_requests
- end
-
- if Gitlab.config.registry.enabled && can?(current_user, :read_container_image, project)
- nav_tabs << :container_registry
- end
-
- if Feature.enabled?(:infrastructure_registry_page)
- nav_tabs << :infrastructure_registry
- end
-
- # Pipelines feature is tied to presence of builds
- if can?(current_user, :read_build, project)
- nav_tabs << :pipelines
- end
-
- if can_view_operations_tab?(current_user, project)
- nav_tabs << :operations
- end
-
- if can_view_product_analytics?(current_user, project)
- nav_tabs << :product_analytics
- end
-
- tab_ability_map.each do |tab, ability|
- if can?(current_user, ability, project)
- nav_tabs << tab
- end
- end
-
- apply_external_nav_tabs(nav_tabs, project)
-
- nav_tabs += package_nav_tabs(project, current_user)
-
- nav_tabs << :learn_gitlab if learn_gitlab_experiment_enabled?(project)
-
- nav_tabs
- end
- # rubocop:enable Metrics/CyclomaticComplexity
-
- def package_nav_tabs(project, current_user)
- [].tap do |tabs|
- if ::Gitlab.config.packages.enabled && can?(current_user, :read_package, project)
- tabs << :packages
- end
- end
- end
-
- def apply_external_nav_tabs(nav_tabs, project)
- nav_tabs << :external_issue_tracker if project.external_issue_tracker
- nav_tabs << :external_wiki if project.external_wiki
-
- if project.has_confluence?
- nav_tabs.delete(:wiki)
- nav_tabs << :confluence
- end
- end
-
def tab_ability_map
{
cycle_analytics: :read_cycle_analytics,
@@ -485,32 +376,6 @@ module ProjectsHelper
}
end
- def view_operations_tab_ability
- [
- :metrics_dashboard,
- :read_alert_management_alert,
- :read_environment,
- :read_issue,
- :read_sentry_issue,
- :read_cluster,
- :read_feature_flag,
- :read_terraform_state
- ]
- end
-
- def can_view_operations_tab?(current_user, project)
- return false unless project.feature_available?(:operations, current_user)
-
- view_operations_tab_ability.any? do |ability|
- can?(current_user, ability, project)
- end
- end
-
- def can_view_product_analytics?(current_user, project)
- Feature.enabled?(:product_analytics, project) &&
- can?(current_user, :read_product_analytics, project)
- end
-
def search_tab_ability_map
@search_tab_ability_map ||= tab_ability_map.merge(
blobs: :download_code,
@@ -578,14 +443,6 @@ module ProjectsHelper
end
end
- def sidebar_operations_link_path(project = @project)
- if can?(current_user, :read_environment, project)
- metrics_project_environments_path(project)
- else
- project_feature_flags_path(project)
- end
- end
-
def project_last_activity(project)
if project.last_activity_at
time_ago_with_tooltip(project.last_activity_at, placement: 'bottom', html_class: 'last_activity_time_ago')
@@ -723,29 +580,6 @@ module ProjectsHelper
"#{request.path}?#{options.to_param}"
end
- def sidebar_security_configuration_paths
- %w[
- projects/security/configuration#show
- ]
- end
-
- def sidebar_settings_paths
- %w[
- projects#edit
- integrations#show
- services#edit
- hooks#index
- hooks#edit
- access_tokens#index
- hook_logs#show
- repository#show
- ci_cd#show
- operations#show
- badges#index
- pages#show
- ]
- end
-
def sidebar_operations_paths
%w[
environments
@@ -766,10 +600,6 @@ module ProjectsHelper
]
end
- def sidebar_security_paths
- %w[projects/security/configuration#show]
- end
-
def user_can_see_auto_devops_implicitly_enabled_banner?(project, user)
Ability.allowed?(user, :admin_project, project) &&
project.has_auto_devops_implicitly_enabled? &&
@@ -782,6 +612,16 @@ module ProjectsHelper
end
def settings_container_registry_expiration_policy_available?(project)
+ Feature.disabled?(:sidebar_refactor, current_user) &&
+ can_destroy_container_registry_image?(current_user, project)
+ end
+
+ def settings_packages_and_registries_enabled?(project)
+ Feature.enabled?(:sidebar_refactor, current_user) &&
+ can_destroy_container_registry_image?(current_user, project)
+ end
+
+ def can_destroy_container_registry_image?(current_user, project)
Gitlab.config.registry.enabled &&
can?(current_user, :destroy_container_image, project)
end
@@ -811,4 +651,4 @@ module ProjectsHelper
end
end
-ProjectsHelper.prepend_if_ee('EE::ProjectsHelper')
+ProjectsHelper.prepend_mod_with('ProjectsHelper')
diff --git a/app/helpers/registrations_helper.rb b/app/helpers/registrations_helper.rb
new file mode 100644
index 00000000000..79f0a66f995
--- /dev/null
+++ b/app/helpers/registrations_helper.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module RegistrationsHelper
+ def social_signin_enabled?
+ ::Gitlab.dev_env_or_com? &&
+ omniauth_enabled? &&
+ devise_mapping.omniauthable? &&
+ button_based_providers_enabled?
+ end
+end
+
+RegistrationsHelper.prepend_mod_with('RegistrationsHelper')
diff --git a/app/helpers/releases_helper.rb b/app/helpers/releases_helper.rb
index d9851564585..de9288121c4 100644
--- a/app/helpers/releases_helper.rb
+++ b/app/helpers/releases_helper.rb
@@ -72,4 +72,4 @@ module ReleasesHelper
end
end
-ReleasesHelper.prepend_if_ee('EE::ReleasesHelper')
+ReleasesHelper.prepend_mod_with('ReleasesHelper')
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 2568917bafc..1f4c98d6f28 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -310,7 +310,7 @@ module SearchHelper
link_to search_path(search_params) do
concat label
concat ' '
- concat content_tag(:span, count, class: ['badge badge-pill', badge_class], data: badge_data)
+ concat content_tag(:span, count, class: ['badge badge-pill gl-badge badge-muted sm', badge_class], data: badge_data)
end
end
end
@@ -431,4 +431,4 @@ module SearchHelper
end
end
-SearchHelper.prepend_if_ee('EE::SearchHelper')
+SearchHelper.prepend_mod_with('SearchHelper')
diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb
index 4d0f9e530fb..88aff31af54 100644
--- a/app/helpers/selects_helper.rb
+++ b/app/helpers/selects_helper.rb
@@ -91,4 +91,4 @@ module SelectsHelper
end
end
-SelectsHelper.prepend_if_ee('EE::SelectsHelper')
+SelectsHelper.prepend_mod_with('SelectsHelper')
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index ffa09cb12fb..3d3ab3a6972 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -153,9 +153,9 @@ module ServicesHelper
private
def integration_level(integration)
- if integration.instance
+ if integration.instance_level?
'instance'
- elsif integration.group_id
+ elsif integration.group_level?
'group'
else
'project'
@@ -172,10 +172,14 @@ module ServicesHelper
name: integration.to_param
}
end
+
+ def show_service_templates_nav_link?
+ Feature.disabled?(:disable_service_templates, type: :development, default_enabled: :yaml)
+ end
end
-ServicesHelper.prepend_if_ee('EE::ServicesHelper')
+ServicesHelper.prepend_mod_with('ServicesHelper')
# The methods in `EE::ServicesHelper` should be available as both instance and
# class methods.
-ServicesHelper.extend_if_ee('EE::ServicesHelper')
+ServicesHelper.extend_mod_with('ServicesHelper')
diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb
index 31dfe21671a..0fc306a3f2e 100644
--- a/app/helpers/sidebars_helper.rb
+++ b/app/helpers/sidebars_helper.rb
@@ -39,7 +39,13 @@ module SidebarsHelper
current_user: user,
container: project,
learn_gitlab_experiment_enabled: learn_gitlab_experiment_enabled?(project),
- current_ref: current_ref
+ learn_gitlab_experiment_tracking_category: learn_gitlab_experiment_tracking_category,
+ current_ref: current_ref,
+ jira_issues_integration: project_jira_issues_integration?,
+ can_view_pipeline_editor: can_view_pipeline_editor?(project),
+ show_cluster_hint: show_gke_cluster_integration_callout?(project)
}
end
end
+
+SidebarsHelper.prepend_mod_with('SidebarsHelper')
diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb
index f4af7a5a350..84eb0405c01 100644
--- a/app/helpers/snippets_helper.rb
+++ b/app/helpers/snippets_helper.rb
@@ -72,4 +72,10 @@ module SnippetsHelper
concat(file_count)
end
end
+
+ def project_snippets_award_api_path(snippet)
+ if Feature.enabled?(:improved_emoji_picker, snippet.project, default_enabled: :yaml)
+ api_v4_projects_snippets_award_emoji_path(id: snippet.project.id, snippet_id: snippet.id)
+ end
+ end
end
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 974ec046bbb..0bb9e9e9bdd 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -301,4 +301,4 @@ module SortingHelper
end
end
-SortingHelper.prepend_if_ee('::EE::SortingHelper')
+SortingHelper.prepend_mod_with('SortingHelper')
diff --git a/app/helpers/sorting_titles_values_helper.rb b/app/helpers/sorting_titles_values_helper.rb
index 651a6437479..28d70f1db45 100644
--- a/app/helpers/sorting_titles_values_helper.rb
+++ b/app/helpers/sorting_titles_values_helper.rb
@@ -328,4 +328,4 @@ module SortingTitlesValuesHelper
end
end
-SortingHelper.include_if_ee('::EE::SortingTitlesValuesHelper')
+SortingHelper.include_mod_with('SortingTitlesValuesHelper')
diff --git a/app/helpers/ssh_keys_helper.rb b/app/helpers/ssh_keys_helper.rb
index 381db893943..f5a9bea482b 100644
--- a/app/helpers/ssh_keys_helper.rb
+++ b/app/helpers/ssh_keys_helper.rb
@@ -12,7 +12,10 @@ module SshKeysHelper
message: _('This action cannot be undone, and will permanently delete the %{key} SSH key') % { key: key.title },
okVariant: 'danger',
okTitle: _('Delete')
- }
+ },
+ toggle: 'tooltip',
+ placement: 'top',
+ container: 'body'
}
end
end
diff --git a/app/helpers/subscribable_banner_helper.rb b/app/helpers/subscribable_banner_helper.rb
index c9d4370f8ad..d9251fb3f21 100644
--- a/app/helpers/subscribable_banner_helper.rb
+++ b/app/helpers/subscribable_banner_helper.rb
@@ -6,4 +6,4 @@ module SubscribableBannerHelper
end
end
-SubscribableBannerHelper.prepend_if_ee('EE::SubscribableBannerHelper')
+SubscribableBannerHelper.prepend_mod_with('SubscribableBannerHelper')
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 85e644967ea..521423fbb94 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -54,8 +54,8 @@ module SystemNoteHelper
extend self
end
-SystemNoteHelper.prepend_if_ee('EE::SystemNoteHelper')
+SystemNoteHelper.prepend_mod_with('SystemNoteHelper')
# The methods in `EE::SystemNoteHelper` should be available as both instance and
# class methods.
-SystemNoteHelper.extend_if_ee('EE::SystemNoteHelper')
+SystemNoteHelper.extend_mod_with('SystemNoteHelper')
diff --git a/app/helpers/time_zone_helper.rb b/app/helpers/time_zone_helper.rb
index 00f65b72c8e..fe045182c96 100644
--- a/app/helpers/time_zone_helper.rb
+++ b/app/helpers/time_zone_helper.rb
@@ -18,7 +18,7 @@ module TimeZoneHelper
def timezone_data(format: :short)
attrs = TIME_ZONE_FORMAT_ATTRS.fetch(format) do
valid_formats = TIME_ZONE_FORMAT_ATTRS.keys.map { |k| ":#{k}"}.join(", ")
- raise ArgumentError.new("Invalid format :#{format}. Valid formats are #{valid_formats}.")
+ raise ArgumentError, "Invalid format :#{format}. Valid formats are #{valid_formats}."
end
ActiveSupport::TimeZone.all.map do |timezone|
diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb
index e034a985b50..0993e210f42 100644
--- a/app/helpers/timeboxes_helper.rb
+++ b/app/helpers/timeboxes_helper.rb
@@ -288,4 +288,4 @@ module TimeboxesHelper
end
end
-TimeboxesHelper.prepend_if_ee('EE::TimeboxesHelper')
+TimeboxesHelper.prepend_mod_with('TimeboxesHelper')
diff --git a/app/helpers/timeboxes_routing_helper.rb b/app/helpers/timeboxes_routing_helper.rb
index 6fb5a1a3185..6a5bef74dc9 100644
--- a/app/helpers/timeboxes_routing_helper.rb
+++ b/app/helpers/timeboxes_routing_helper.rb
@@ -18,4 +18,4 @@ module TimeboxesRoutingHelper
end
end
-TimeboxesRoutingHelper.prepend_if_ee('EE::TimeboxesRoutingHelper')
+TimeboxesRoutingHelper.prepend_mod_with('TimeboxesRoutingHelper')
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index e9a0fef06c4..e9dc271dbdd 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -110,10 +110,8 @@ module TodosHelper
'alert'
end
- content_tag(:span, nil, class: 'target-status') do
- content_tag(:span, nil, class: "status-box status-box-#{type}-#{todo.target.state.to_s.dasherize}") do
- todo.target.state.to_s.capitalize
- end
+ tag.span class: "gl-my-0 gl-px-2 status-box status-box-#{type}-#{todo.target.state.to_s.dasherize}" do
+ todo.target.state.to_s.capitalize
end
end
@@ -232,4 +230,4 @@ module TodosHelper
end
end
-TodosHelper.prepend_if_ee('EE::TodosHelper')
+TodosHelper.prepend_mod_with('TodosHelper')
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index b795851ba30..54c03d3d966 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -205,4 +205,4 @@ module TreeHelper
end
end
-TreeHelper.prepend_if_ee('::EE::TreeHelper')
+TreeHelper.prepend_mod_with('TreeHelper')
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index 7a90984cd77..23db3be631c 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -44,7 +44,7 @@ module UserCalloutsHelper
def show_service_templates_deprecated_callout?
!Gitlab.com? &&
current_user&.admin? &&
- Service.for_template.active.exists? &&
+ Integration.for_template.active.exists? &&
!user_dismissed?(SERVICE_TEMPLATES_DEPRECATED_CALLOUT)
end
@@ -80,4 +80,4 @@ module UserCalloutsHelper
end
end
-UserCalloutsHelper.prepend_if_ee('EE::UserCalloutsHelper')
+UserCalloutsHelper.prepend_mod_with('UserCalloutsHelper')
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 1979426f844..c1d05c2d3cf 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -100,7 +100,7 @@ module UsersHelper
badges << blocked_user_badge(user) if user.blocked?
badges << { text: s_('AdminUsers|Admin'), variant: 'success' } if user.admin?
badges << { text: s_('AdminUsers|External'), variant: 'secondary' } if user.external?
- badges << { text: s_("AdminUsers|It's you!"), variant: nil } if current_user == user
+ badges << { text: s_("AdminUsers|It's you!"), variant: 'muted' } if current_user == user
end
end
@@ -162,6 +162,49 @@ module UsersHelper
header + list
end
+ def user_ban_data(user)
+ {
+ path: ban_admin_user_path(user),
+ method: 'put',
+ modal_attributes: {
+ title: s_('AdminUsers|Ban user %{username}?') % { username: sanitize_name(user.name) },
+ message: s_('AdminUsers|You can unban their account in the future. Their data remains intact.'),
+ okVariant: 'warning',
+ okTitle: s_('AdminUsers|Ban')
+ }.to_json
+ }
+ end
+
+ def user_unban_data(user)
+ {
+ path: unban_admin_user_path(user),
+ method: 'put',
+ modal_attributes: {
+ title: s_('AdminUsers|Unban %{username}?') % { username: sanitize_name(user.name) },
+ message: s_('AdminUsers|You ban their account in the future if necessary.'),
+ okVariant: 'info',
+ okTitle: s_('AdminUsers|Unban')
+ }.to_json
+ }
+ end
+
+ def user_ban_effects
+ header = tag.p s_('AdminUsers|Banning the user has the following effects:')
+
+ list = tag.ul do
+ concat tag.li s_('AdminUsers|User will be blocked')
+ end
+
+ link_start = '<a href="%{url}" target="_blank">'.html_safe % { url: help_page_path("user/admin_area/moderate_users", anchor: "ban-a-user") }
+ info = tag.p s_('AdminUsers|Learn more about %{link_start}banned users.%{link_end}').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+
+ header + list + info
+ end
+
+ def ban_feature_available?
+ Feature.enabled?(:ban_user_feature_flag)
+ end
+
def user_deactivation_data(user, message)
{
path: deactivate_admin_user_path(user),
@@ -235,6 +278,9 @@ module UsersHelper
pending_approval_badge = { text: s_('AdminUsers|Pending approval'), variant: 'info' }
return pending_approval_badge if user.blocked_pending_approval?
+ banned_badge = { text: s_('AdminUsers|Banned'), variant: 'danger' }
+ return banned_badge if user.banned?
+
{ text: s_('AdminUsers|Blocked'), variant: 'danger' }
end
@@ -322,4 +368,4 @@ module UsersHelper
end
end
-UsersHelper.prepend_if_ee('EE::UsersHelper')
+UsersHelper.prepend_mod_with('UsersHelper')
diff --git a/app/helpers/version_check_helper.rb b/app/helpers/version_check_helper.rb
index bac3c99e3e5..6f94c241914 100644
--- a/app/helpers/version_check_helper.rb
+++ b/app/helpers/version_check_helper.rb
@@ -11,16 +11,24 @@ module VersionCheckHelper
def link_to_version
if Gitlab.pre_release?
- commit_link = link_to(Gitlab.revision, Gitlab::COM_URL + namespace_project_commits_path('gitlab-org', source_code_project, Gitlab.revision))
+ commit_link = link_to(Gitlab.revision, source_host_url + namespace_project_commits_path(source_code_group, source_code_project, Gitlab.revision))
[Gitlab::VERSION, content_tag(:small, commit_link)].join(' ').html_safe
else
- link_to Gitlab::VERSION, Gitlab::COM_URL + namespace_project_tag_path('gitlab-org', source_code_project, "v#{Gitlab::VERSION}")
+ link_to Gitlab::VERSION, source_host_url + namespace_project_tag_path(source_code_group, source_code_project, "v#{Gitlab::VERSION}")
end
end
+ def source_host_url
+ Gitlab::COM_URL
+ end
+
+ def source_code_group
+ 'gitlab-org'
+ end
+
def source_code_project
'gitlab-foss'
end
end
-VersionCheckHelper.prepend_if_ee('EE::VersionCheckHelper')
+VersionCheckHelper.prepend_mod
diff --git a/app/helpers/webpack_helper.rb b/app/helpers/webpack_helper.rb
index 170e3c45a21..0d27e07f172 100644
--- a/app/helpers/webpack_helper.rb
+++ b/app/helpers/webpack_helper.rb
@@ -1,10 +1,32 @@
# frozen_string_literal: true
module WebpackHelper
+ def prefetch_link_tag(source)
+ href = asset_path(source)
+
+ link_tag = tag.link(rel: 'prefetch', href: href)
+
+ early_hints_link = "<#{href}>; rel=prefetch"
+
+ request.send_early_hints("Link" => early_hints_link)
+
+ link_tag
+ end
+
def webpack_bundle_tag(bundle)
javascript_include_tag(*webpack_entrypoint_paths(bundle))
end
+ def webpack_preload_asset_tag(asset, options = {})
+ path = Gitlab::Webpack::Manifest.asset_paths(asset).first
+
+ if options.delete(:prefetch)
+ prefetch_link_tag(path)
+ else
+ preload_link_tag(path, options)
+ end
+ end
+
def webpack_controller_bundle_tags
chunks = []
diff --git a/app/helpers/whats_new_helper.rb b/app/helpers/whats_new_helper.rb
index 9362ae1491f..5fca00c5dce 100644
--- a/app/helpers/whats_new_helper.rb
+++ b/app/helpers/whats_new_helper.rb
@@ -10,6 +10,33 @@ module WhatsNewHelper
end
def display_whats_new?
- Gitlab.dev_env_org_or_com? || user_signed_in?
+ (Gitlab.dev_env_org_or_com? || user_signed_in?) &&
+ !Gitlab::CurrentSettings.current_application_settings.whats_new_variant_disabled?
+ end
+
+ def whats_new_variants
+ ApplicationSetting.whats_new_variants
+ end
+
+ def whats_new_variants_label(variant)
+ case variant
+ when 'all_tiers'
+ _("Enable What's new: All tiers")
+ when 'current_tier'
+ _("Enable What's new: Current tier only")
+ when 'disabled'
+ _("Disable What's new")
+ end
+ end
+
+ def whats_new_variants_description(variant)
+ case variant
+ when 'all_tiers'
+ _("What's new presents new features from all tiers to help you keep track of all new features.")
+ when 'current_tier'
+ _("What's new presents new features for your current subscription tier, while hiding new features not available to your subscription tier.")
+ when 'disabled'
+ _("What's new is disabled and can no longer be viewed.")
+ end
end
end
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index c2a5ff40852..1b0d1254dc8 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -136,4 +136,4 @@ module WikiHelper
end
end
-WikiHelper.prepend_if_ee('EE::WikiHelper')
+WikiHelper.prepend_mod_with('WikiHelper')
diff --git a/app/helpers/x509_helper.rb b/app/helpers/x509_helper.rb
index 009635fb629..4afc5643af4 100644
--- a/app/helpers/x509_helper.rb
+++ b/app/helpers/x509_helper.rb
@@ -13,7 +13,7 @@ module X509Helper
end
subjects
- rescue
+ rescue StandardError
{}
end