summaryrefslogtreecommitdiff
path: root/app/helpers
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 09:55:51 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 09:55:51 +0000
commite8d2c2579383897a1dd7f9debd359abe8ae8373d (patch)
treec42be41678c2586d49a75cabce89322082698334 /app/helpers
parentfc845b37ec3a90aaa719975f607740c22ba6a113 (diff)
downloadgitlab-ce-e8d2c2579383897a1dd7f9debd359abe8ae8373d.tar.gz
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/admin/user_actions_helper.rb17
-rw-r--r--app/helpers/analytics/unique_visits_helper.rb30
-rw-r--r--app/helpers/application_helper.rb2
-rw-r--r--app/helpers/application_settings_helper.rb7
-rw-r--r--app/helpers/auto_devops_helper.rb2
-rw-r--r--app/helpers/blob_helper.rb4
-rw-r--r--app/helpers/ci/jobs_helper.rb1
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb16
-rw-r--r--app/helpers/ci/pipelines_helper.rb68
-rw-r--r--app/helpers/ci/variables_helper.rb2
-rw-r--r--app/helpers/clusters_helper.rb6
-rw-r--r--app/helpers/commits_helper.rb8
-rw-r--r--app/helpers/custom_metrics_helper.rb2
-rw-r--r--app/helpers/diff_helper.rb10
-rw-r--r--app/helpers/environments_helper.rb2
-rw-r--r--app/helpers/events_helper.rb3
-rw-r--r--app/helpers/gitlab_routing_helper.rb381
-rw-r--r--app/helpers/groups_helper.rb18
-rw-r--r--app/helpers/integrations_helper.rb (renamed from app/helpers/services_helper.rb)117
-rw-r--r--app/helpers/issuables_helper.rb9
-rw-r--r--app/helpers/issues_helper.rb3
-rw-r--r--app/helpers/namespaces_helper.rb4
-rw-r--r--app/helpers/nav/new_dropdown_helper.rb15
-rw-r--r--app/helpers/nav/top_nav_helper.rb4
-rw-r--r--app/helpers/nav_helper.rb6
-rw-r--r--app/helpers/operations_helper.rb13
-rw-r--r--app/helpers/packages_helper.rb27
-rw-r--r--app/helpers/personal_access_tokens_helper.rb7
-rw-r--r--app/helpers/projects/alert_management_helper.rb4
-rw-r--r--app/helpers/projects_helper.rb22
-rw-r--r--app/helpers/registrations_helper.rb7
-rw-r--r--app/helpers/releases_helper.rb23
-rw-r--r--app/helpers/routing/artifacts_helper.rb49
-rw-r--r--app/helpers/routing/graphql_helper.rb13
-rw-r--r--app/helpers/routing/groups/members_helper.rb31
-rw-r--r--app/helpers/routing/members_helper.rb14
-rw-r--r--app/helpers/routing/pipeline_schedules_helper.rb29
-rw-r--r--app/helpers/routing/projects/members_helper.rb31
-rw-r--r--app/helpers/routing/projects_helper.rb85
-rw-r--r--app/helpers/routing/snippets_helper.rb144
-rw-r--r--app/helpers/routing/wiki_helper.rb13
-rw-r--r--app/helpers/search_helper.rb21
-rw-r--r--app/helpers/sessions_helper.rb9
-rw-r--r--app/helpers/sidebars_helper.rb74
-rw-r--r--app/helpers/sorting_helper.rb21
-rw-r--r--app/helpers/sorting_titles_values_helper.rb56
-rw-r--r--app/helpers/tracking_helper.rb2
-rw-r--r--app/helpers/user_callouts_helper.rb2
-rw-r--r--app/helpers/users_helper.rb147
-rw-r--r--app/helpers/whats_new_helper.rb6
50 files changed, 821 insertions, 766 deletions
diff --git a/app/helpers/admin/user_actions_helper.rb b/app/helpers/admin/user_actions_helper.rb
index cd520a75b44..5719d8f5ffd 100644
--- a/app/helpers/admin/user_actions_helper.rb
+++ b/app/helpers/admin/user_actions_helper.rb
@@ -15,6 +15,7 @@ module Admin
deactivate_actions
unlock_actions
delete_actions
+ ban_actions
@actions
end
@@ -28,7 +29,7 @@ module Admin
@actions << 'approve'
@actions << 'reject'
elsif @user.blocked?
- @actions << 'unblock'
+ @actions << 'unblock' unless @user.banned?
else
@actions << 'block'
end
@@ -52,5 +53,19 @@ module Admin
@actions << 'delete'
@actions << 'delete_with_contributions'
end
+
+ def ban_actions
+ return unless ban_feature_available?
+ return if @user.internal?
+
+ if @user.banned?
+ @actions << 'unban'
+ return
+ end
+
+ unless @user.blocked?
+ @actions << 'ban'
+ end
+ end
end
end
diff --git a/app/helpers/analytics/unique_visits_helper.rb b/app/helpers/analytics/unique_visits_helper.rb
deleted file mode 100644
index 4aa8907f578..00000000000
--- a/app/helpers/analytics/unique_visits_helper.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Analytics
- module UniqueVisitsHelper
- extend ActiveSupport::Concern
-
- def visitor_id
- return cookies[:visitor_id] if cookies[:visitor_id].present?
- return unless current_user
-
- uuid = SecureRandom.uuid
- cookies[:visitor_id] = { value: uuid, expires: 24.months }
- uuid
- end
-
- def track_visit(target_id)
- return unless visitor_id
-
- Gitlab::Analytics::UniqueVisits.new.track_visit(target_id, values: visitor_id)
- end
-
- class_methods do
- def track_unique_visits(controller_actions, target_id:)
- after_action only: controller_actions, if: -> { request.format.html? && request.headers['DNT'] != '1' } do
- track_visit(target_id)
- end
- end
- end
- end
-end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 2e15b3f22c2..1304bcb1c7e 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -285,7 +285,7 @@ module ApplicationHelper
def page_class
class_names = []
class_names << 'issue-boards-page gl-overflow-auto' if current_controller?(:boards)
- class_names << 'epic-boards-page' if current_controller?(:epic_boards)
+ class_names << 'epic-boards-page gl-overflow-auto' if current_controller?(:epic_boards)
class_names << 'environment-logs-page' if current_controller?(:logs)
class_names << 'with-performance-bar' if performance_bar_enabled?
class_names << system_message_class
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index efdad22fa54..a3df566e4b3 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -331,6 +331,7 @@ module ApplicationSettingsHelper
:unique_ips_limit_per_user,
:unique_ips_limit_time_window,
:usage_ping_enabled,
+ :usage_ping_features_enabled,
:user_default_external,
:user_show_add_ssh_key_message,
:user_default_internal_regex,
@@ -343,6 +344,8 @@ module ApplicationSettingsHelper
:commit_email_hostname,
:protected_ci_variables,
:local_markdown_version,
+ :mailgun_signing_key,
+ :mailgun_events_enabled,
:snowplow_collector_hostname,
:snowplow_cookie_domain,
:snowplow_enabled,
@@ -437,6 +440,10 @@ module ApplicationSettingsHelper
Feature.enabled?(:help_page_documentation_redirect)
end
+ def valid_runner_registrars
+ Gitlab::CurrentSettings.valid_runner_registrars
+ end
+
def signup_enabled?
!!Gitlab::CurrentSettings.signup_enabled
end
diff --git a/app/helpers/auto_devops_helper.rb b/app/helpers/auto_devops_helper.rb
index c27f5d4ebce..91a335cd504 100644
--- a/app/helpers/auto_devops_helper.rb
+++ b/app/helpers/auto_devops_helper.rb
@@ -7,7 +7,7 @@ module AutoDevopsHelper
can?(current_user, :admin_pipeline, project) &&
project.has_auto_devops_implicitly_disabled? &&
!project.repository.gitlab_ci_yml &&
- !project.ci_service
+ !project.ci_integration
end
def badge_for_auto_devops_scope(auto_devops_receiver)
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index dfd6de3f1d5..eccd0e7a34c 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -65,7 +65,7 @@ module BlobHelper
return unless blob = readable_blob(options, path, project, ref)
common_classes = "btn gl-button btn-confirm js-edit-blob gl-ml-3 #{options[:extra_class]}"
- data = { track_event: 'click_edit', track_label: 'Edit' }
+ data = { track_action: 'click_edit', track_label: 'edit' }
if Feature.enabled?(:web_ide_primary_edit, project.group)
common_classes += " btn-inverted"
@@ -85,7 +85,7 @@ module BlobHelper
return unless blob
common_classes = 'btn gl-button btn-confirm ide-edit-button gl-ml-3'
- data = { track_event: 'click_edit_ide', track_label: 'Web IDE' }
+ data = { track_action: 'click_edit_ide', track_label: 'web_ide' }
unless Feature.enabled?(:web_ide_primary_edit, project.group)
common_classes += " btn-inverted"
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index 23f2a082a68..882302f05ad 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -9,7 +9,6 @@ module Ci
"artifact_help_url" => help_page_path('user/gitlab_com/index.html', anchor: 'gitlab-cicd'),
"deployment_help_url" => help_page_path('user/project/clusters/index.html', anchor: 'troubleshooting'),
"runner_settings_url" => project_runners_path(@build.project, anchor: 'js-runners-settings'),
- "variables_settings_url" => project_variables_path(@build.project, anchor: 'js-cicd-variables-settings'),
"page_path" => project_job_path(@project, @build),
"build_status" => @build.status,
"build_stage" => @build.stage,
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index 8c8ee2d4d0f..d441ffbb853 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -9,24 +9,26 @@ module Ci
end
def js_pipeline_editor_data(project)
- commit_sha = project.commit ? project.commit.sha : ''
+ initial_branch = params[:branch_name]
+ latest_commit = project.repository.commit(initial_branch) || project.commit
+ commit_sha = latest_commit ? latest_commit.sha : ''
{
"ci-config-path": project.ci_config_path_or_default,
- "ci-examples-help-page-path" => help_page_path('ci/examples/README'),
- "ci-help-page-path" => help_page_path('ci/README'),
+ "ci-examples-help-page-path" => help_page_path('ci/examples/index'),
+ "ci-help-page-path" => help_page_path('ci/index'),
"commit-sha" => commit_sha,
- "default-branch" => project.default_branch,
+ "default-branch" => project.default_branch_or_main,
"empty-state-illustration-path" => image_path('illustrations/empty-state/empty-dag-md.svg'),
- "initial-branch-name": params[:branch_name],
+ "initial-branch-name" => initial_branch,
"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_etag" => latest_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'),
+ "runner-help-page-path" => help_page_path('ci/runners/index'),
"total-branches" => project.repository.branches.length,
"yml-help-page-path" => help_page_path('ci/yaml/README')
}
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index f42cd53ae3a..6be46b40023 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -30,42 +30,40 @@ module Ci
project.has_ci? && project.builds_enabled?
end
- # This list of templates is for the pipeline_empty_state_templates experiment
- # and will be cleaned up with https://gitlab.com/gitlab-org/gitlab/-/issues/326299
- def experiment_suggested_ci_templates
+ def suggested_ci_templates
[
- { name: 'Android', logo: image_path('illustrations/logos/android.svg') },
- { name: 'Bash', logo: image_path('illustrations/logos/bash.svg') },
- { name: 'C++', logo: image_path('illustrations/logos/c_plus_plus.svg') },
- { name: 'Clojure', logo: image_path('illustrations/logos/clojure.svg') },
- { name: 'Composer', logo: image_path('illustrations/logos/composer.svg') },
- { name: 'Crystal', logo: image_path('illustrations/logos/crystal.svg') },
- { name: 'Dart', logo: image_path('illustrations/logos/dart.svg') },
- { name: 'Django', logo: image_path('illustrations/logos/django.svg') },
- { name: 'Docker', logo: image_path('illustrations/logos/docker.svg') },
- { name: 'Elixir', logo: image_path('illustrations/logos/elixir.svg') },
- { name: 'iOS-Fastlane', logo: image_path('illustrations/logos/fastlane.svg') },
- { name: 'Flutter', logo: image_path('illustrations/logos/flutter.svg') },
- { name: 'Go', logo: image_path('illustrations/logos/go_logo.svg') },
- { 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: '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: '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') },
- { name: 'npm', logo: image_path('illustrations/logos/npm.svg') },
- { name: 'OpenShift', logo: image_path('illustrations/logos/openshift.svg') },
- { name: 'Packer', logo: image_path('illustrations/logos/packer.svg') },
- { name: 'PHP', logo: image_path('illustrations/logos/php.svg') },
- { name: 'Python', logo: image_path('illustrations/logos/python.svg') },
- { name: 'Ruby', logo: image_path('illustrations/logos/ruby.svg') },
- { name: 'Rust', logo: image_path('illustrations/logos/rust.svg') },
- { name: 'Scala', logo: image_path('illustrations/logos/scala.svg') },
- { name: 'Swift', logo: image_path('illustrations/logos/swift.svg') },
- { name: 'Terraform', logo: image_path('illustrations/logos/terraform.svg') }
+ { name: 'Android', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/android.svg') },
+ { name: 'Bash', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/bash.svg') },
+ { name: 'C++', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/c_plus_plus.svg') },
+ { name: 'Clojure', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/clojure.svg') },
+ { name: 'Composer', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/composer.svg') },
+ { name: 'Crystal', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/crystal.svg') },
+ { name: 'Dart', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/dart.svg') },
+ { name: 'Django', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/django.svg') },
+ { name: 'Docker', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/docker.svg') },
+ { name: 'Elixir', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/elixir.svg') },
+ { name: 'iOS-Fastlane', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/fastlane.svg') },
+ { name: 'Flutter', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/flutter.svg') },
+ { name: 'Go', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/go_logo.svg') },
+ { name: 'Gradle', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/gradle.svg') },
+ { name: 'Grails', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/grails.svg') },
+ { name: 'dotNET', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/dotnet.svg') },
+ { name: 'Julia', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/julia.svg') },
+ { name: 'Laravel', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/laravel.svg') },
+ { name: 'LaTeX', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/latex.svg') },
+ { name: 'Maven', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/maven.svg') },
+ { name: 'Mono', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/mono.svg') },
+ { name: 'Nodejs', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/node_js.svg') },
+ { name: 'npm', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/npm.svg') },
+ { name: 'OpenShift', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/openshift.svg') },
+ { name: 'Packer', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/packer.svg') },
+ { name: 'PHP', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/php.svg') },
+ { name: 'Python', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/python.svg') },
+ { name: 'Ruby', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/ruby.svg') },
+ { name: 'Rust', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/rust.svg') },
+ { name: 'Scala', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/scala.svg') },
+ { name: 'Swift', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/swift.svg') },
+ { name: 'Terraform', logo: image_path('illustrations/third-party-logos/ci_cd-template-logos/terraform.svg') }
]
end
diff --git a/app/helpers/ci/variables_helper.rb b/app/helpers/ci/variables_helper.rb
index b20390d58e9..84572363a8d 100644
--- a/app/helpers/ci/variables_helper.rb
+++ b/app/helpers/ci/variables_helper.rb
@@ -48,7 +48,7 @@ module Ci
end
def ci_variable_maskable_regex
- Ci::Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(/^\//, '').sub(/\/[a-z]*$/, '').gsub('\/', '/')
+ Ci::Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(%r{^/}, '').sub(%r{/[a-z]*$}, '').gsub('\/', '/')
end
end
end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index 14783882f5e..e9a75babb97 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -20,7 +20,11 @@ module ClustersHelper
{
default_branch_name: clusterable_project.default_branch,
empty_state_image: image_path('illustrations/clusters_empty.svg'),
- project_path: clusterable_project.full_path
+ project_path: clusterable_project.full_path,
+ agent_docs_url: help_page_path('user/clusters/agent/index'),
+ install_docs_url: help_page_path('administration/clusters/kas'),
+ get_started_docs_url: help_page_path('user/clusters/agent/index', anchor: 'define-a-configuration-repository'),
+ integration_docs_url: help_page_path('user/clusters/agent/index', anchor: 'get-started-with-gitops-and-the-gitlab-agent')
}
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index a7696ba4ea7..d2ac1e8f985 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -167,6 +167,14 @@ module CommitsHelper
]
end
+ DEFAULT_SHA = '0000000'
+
+ # Returns the template path for commit resources
+ # to be utilized by the client applications.
+ def commit_path_template(project)
+ project_commit_path(project, DEFAULT_SHA).sub("/#{DEFAULT_SHA}", '/$COMMIT_SHA')
+ end
+
protected
# Private: Returns a link to a person. If the person has a matching user and
diff --git a/app/helpers/custom_metrics_helper.rb b/app/helpers/custom_metrics_helper.rb
index 5ea386e268d..9fbfe377c61 100644
--- a/app/helpers/custom_metrics_helper.rb
+++ b/app/helpers/custom_metrics_helper.rb
@@ -5,7 +5,7 @@ module CustomMetricsHelper
{
'custom-metrics-path' => url_for([project, metric]),
'metric-persisted' => metric.persisted?.to_s,
- 'edit-project-service-path' => edit_project_service_path(project, PrometheusService),
+ 'edit-project-service-path' => edit_project_service_path(project, ::Integrations::Prometheus),
'validate-query-path' => validate_query_project_prometheus_metrics_path(project),
'title' => metric.title.to_s,
'query' => metric.query.to_s,
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index e430b0f402b..3aa54e3afe9 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -190,10 +190,8 @@ module DiffHelper
end
def render_overflow_warning?(diffs_collection)
- diff_files = diffs_collection.raw_diff_files
-
- diff_files.overflow?.tap do |overflown|
- log_overflow_limits(diff_files)
+ diffs_collection.overflow?.tap do |overflown|
+ log_overflow_limits(diff_files: diffs_collection.raw_diff_files, collection_overflow: overflown)
end
end
@@ -285,12 +283,12 @@ module DiffHelper
conflicts_service.conflicts.files.index_by(&:our_path)
end
- def log_overflow_limits(diff_files)
+ def log_overflow_limits(diff_files:, collection_overflow:)
if diff_files.any?(&:too_large?)
Gitlab::Metrics.add_event(:diffs_overflow_single_file_limits)
end
- Gitlab::Metrics.add_event(:diffs_overflow_collection_limits) if diff_files.overflow?
+ Gitlab::Metrics.add_event(:diffs_overflow_collection_limits) if collection_overflow
Gitlab::Metrics.add_event(:diffs_overflow_max_bytes_limits) if diff_files.overflow_max_bytes?
Gitlab::Metrics.add_event(:diffs_overflow_max_files_limits) if diff_files.overflow_max_files?
Gitlab::Metrics.add_event(:diffs_overflow_max_lines_limits) if diff_files.overflow_max_lines?
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 5927c82abe9..62060200698 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -79,7 +79,7 @@ module EnvironmentsHelper
end
def has_managed_prometheus?(project)
- project.prometheus_service&.prometheus_available? == true
+ project.prometheus_integration&.prometheus_available? == true
end
def metrics_dashboard_base_path(environment, project)
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index cd70c6f3962..4ee3acd32d2 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -240,8 +240,7 @@ module EventsHelper
DESIGN_ICONS = {
'created' => 'upload',
'updated' => 'pencil',
- 'destroyed' => ICON_NAMES_BY_EVENT_TYPE['destroyed'],
- 'archived' => 'archive'
+ 'destroyed' => ICON_NAMES_BY_EVENT_TYPE['destroyed']
}.freeze
def design_event_icon(action, size: 24)
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index 0a684d92eb1..0f835e6881e 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -7,381 +7,18 @@ module GitlabRoutingHelper
include ::ProjectsHelper
include ::ApplicationSettingsHelper
include API::Helpers::RelatedResourcesHelpers
+ include ::Routing::ProjectsHelper
+ include ::Routing::Projects::MembersHelper
+ include ::Routing::Groups::MembersHelper
+ include ::Routing::MembersHelper
+ include ::Routing::ArtifactsHelper
+ include ::Routing::PipelineSchedulesHelper
+ include ::Routing::SnippetsHelper
+ include ::Routing::WikiHelper
+ include ::Routing::GraphqlHelper
included do
Gitlab::Routing.includes_helpers(self)
end
-
- # Project
- def project_tree_path(project, ref = nil, *args)
- namespace_project_tree_path(project.namespace, project, ref || @ref || project.repository.root_ref, *args) # rubocop:disable Cop/ProjectPathHelper
- end
-
- def project_commits_path(project, ref = nil, *args)
- namespace_project_commits_path(project.namespace, project, ref || @ref || project.repository.root_ref, *args) # rubocop:disable Cop/ProjectPathHelper
- end
-
- def project_ref_path(project, ref_name, *args)
- project_commits_path(project, ref_name, *args)
- end
-
- def environment_path(environment, *args)
- project_environment_path(environment.project, environment, *args)
- end
-
- def environment_metrics_path(environment, *args)
- metrics_project_environment_path(environment.project, environment, *args)
- end
-
- def environment_delete_path(environment, *args)
- expose_path(api_v4_projects_environments_path(id: environment.project.id, environment_id: environment.id))
- end
-
- def issue_path(entity, *args)
- project_issue_path(entity.project, entity, *args)
- end
-
- def merge_request_path(entity, *args)
- project_merge_request_path(entity.project, entity, *args)
- end
-
- def pipeline_path(pipeline, *args)
- project_pipeline_path(pipeline.project, pipeline.id, *args)
- end
-
- def issue_url(entity, *args)
- project_issue_url(entity.project, entity, *args)
- end
-
- def merge_request_url(entity, *args)
- project_merge_request_url(entity.project, entity, *args)
- end
-
- def pipeline_url(pipeline, *args)
- project_pipeline_url(pipeline.project, pipeline.id, *args)
- end
-
- def pipeline_job_url(pipeline, build, *args)
- project_job_url(pipeline.project, build.id, *args)
- end
-
- def commits_url(entity, *args)
- project_commits_url(entity.project, entity.source_ref, *args)
- end
-
- def commit_url(entity, *args)
- project_commit_url(entity.project, entity.sha, *args)
- end
-
- def release_url(entity, *args)
- project_release_url(entity.project, entity, *args)
- end
-
- def preview_markdown_path(parent, *args)
- return group_preview_markdown_path(parent, *args) if parent.is_a?(Group)
-
- if @snippet.is_a?(PersonalSnippet)
- preview_markdown_snippets_path
- else
- preview_markdown_project_path(parent, *args)
- end
- end
-
- def edit_milestone_path(entity, *args)
- if entity.resource_parent.is_a?(Group)
- edit_group_milestone_path(entity.resource_parent, entity, *args)
- else
- edit_project_milestone_path(entity.resource_parent, entity, *args)
- end
- end
-
- def toggle_subscription_path(entity, *args)
- if entity.is_a?(Issue)
- toggle_subscription_project_issue_path(entity.project, entity)
- else
- toggle_subscription_project_merge_request_path(entity.project, entity)
- end
- end
-
- def toggle_award_emoji_personal_snippet_path(*args)
- toggle_award_emoji_snippet_path(*args)
- end
-
- def toggle_award_emoji_project_project_snippet_path(*args)
- toggle_award_emoji_project_snippet_path(*args)
- end
-
- def toggle_award_emoji_project_project_snippet_url(*args)
- toggle_award_emoji_project_snippet_url(*args)
- end
-
- ## Members
- def project_members_url(project, *args)
- project_project_members_url(project, *args)
- end
-
- def project_member_path(project_member, *args)
- project_project_member_path(project_member.source, project_member)
- end
-
- def request_access_project_members_path(project, *args)
- request_access_project_project_members_path(project)
- end
-
- def leave_project_members_path(project, *args)
- leave_project_project_members_path(project)
- end
-
- def approve_access_request_project_member_path(project_member, *args)
- approve_access_request_project_project_member_path(project_member.source, project_member)
- end
-
- def resend_invite_project_member_path(project_member, *args)
- resend_invite_project_project_member_path(project_member.source, project_member)
- end
-
- # Groups
-
- ## Members
- def group_members_url(group, *args)
- group_group_members_url(group, *args)
- end
-
- def group_member_path(group_member, *args)
- group_group_member_path(group_member.source, group_member)
- end
-
- def request_access_group_members_path(group, *args)
- request_access_group_group_members_path(group)
- end
-
- def leave_group_members_path(group, *args)
- leave_group_group_members_path(group)
- end
-
- def approve_access_request_group_member_path(group_member, *args)
- approve_access_request_group_group_member_path(group_member.source, group_member)
- end
-
- def resend_invite_group_member_path(group_member, *args)
- 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
- # against the arguments. We can speed this up 10x by generating the strings directly.
-
- # /*namespace_id/:project_id/-/jobs/:job_id/artifacts/download(.:format)
- def fast_download_project_job_artifacts_path(project, job, params = {})
- expose_fast_artifacts_path(project, job, :download, params)
- end
-
- # /*namespace_id/:project_id/-/jobs/:job_id/artifacts/keep(.:format)
- def fast_keep_project_job_artifacts_path(project, job)
- expose_fast_artifacts_path(project, job, :keep)
- end
-
- # /*namespace_id/:project_id/-/jobs/:job_id/artifacts/browse(/*path)
- def fast_browse_project_job_artifacts_path(project, job)
- expose_fast_artifacts_path(project, job, :browse)
- end
-
- def expose_fast_artifacts_path(project, job, action, params = {})
- path = "#{project.full_path}/-/jobs/#{job.id}/artifacts/#{action}"
-
- unless params.empty?
- path += "?#{params.to_query}"
- end
-
- Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, path)
- end
-
- def artifacts_action_path(path, project, build)
- action, path_params = path.split('/', 2)
- args = [project, build, path_params]
-
- case action
- when 'download'
- download_project_job_artifacts_path(*args)
- when 'browse'
- browse_project_job_artifacts_path(*args)
- when 'file'
- file_project_job_artifacts_path(*args)
- when 'raw'
- raw_project_job_artifacts_path(*args)
- end
- end
-
- # Pipeline Schedules
- def pipeline_schedules_path(project, *args)
- project_pipeline_schedules_path(project, *args)
- end
-
- def pipeline_schedule_path(schedule, *args)
- project = schedule.project
- project_pipeline_schedule_path(project, schedule, *args)
- end
-
- def edit_pipeline_schedule_path(schedule)
- project = schedule.project
- edit_project_pipeline_schedule_path(project, schedule)
- end
-
- def play_pipeline_schedule_path(schedule, *args)
- project = schedule.project
- play_project_pipeline_schedule_path(project, schedule, *args)
- end
-
- def take_ownership_pipeline_schedule_path(schedule, *args)
- project = schedule.project
- take_ownership_project_pipeline_schedule_path(project, schedule, *args)
- end
-
- def gitlab_snippet_path(snippet, *args)
- if snippet.is_a?(ProjectSnippet)
- project_snippet_path(snippet.project, snippet, *args)
- else
- new_args = snippet_query_params(snippet, *args)
- snippet_path(snippet, *new_args)
- end
- end
-
- def gitlab_snippet_url(snippet, *args)
- if snippet.is_a?(ProjectSnippet)
- project_snippet_url(snippet.project, snippet, *args)
- else
- new_args = snippet_query_params(snippet, *args)
- snippet_url(snippet, *new_args)
- end
- end
-
- def gitlab_dashboard_snippets_path(snippet, *args)
- if snippet.is_a?(ProjectSnippet)
- project_snippets_path(snippet.project, *args)
- else
- dashboard_snippets_path
- end
- end
-
- def gitlab_raw_snippet_path(snippet, *args)
- if snippet.is_a?(ProjectSnippet)
- raw_project_snippet_path(snippet.project, snippet, *args)
- else
- new_args = snippet_query_params(snippet, *args)
- raw_snippet_path(snippet, *new_args)
- end
- end
-
- def gitlab_raw_snippet_url(snippet, *args)
- if snippet.is_a?(ProjectSnippet)
- raw_project_snippet_url(snippet.project, snippet, *args)
- else
- new_args = snippet_query_params(snippet, *args)
- raw_snippet_url(snippet, *new_args)
- end
- end
-
- def gitlab_raw_snippet_blob_url(snippet, path, ref = nil, **options)
- params = {
- snippet_id: snippet,
- ref: ref || snippet.repository.root_ref,
- path: path
- }
-
- if snippet.is_a?(ProjectSnippet)
- project_snippet_blob_raw_url(snippet.project, **params, **options)
- else
- snippet_blob_raw_url(**params, **options)
- end
- end
-
- def gitlab_raw_snippet_blob_path(snippet, path, ref = nil, **options)
- gitlab_raw_snippet_blob_url(snippet, path, ref, only_path: true, **options)
- end
-
- def gitlab_snippet_notes_path(snippet, *args)
- new_args = snippet_query_params(snippet, *args)
- snippet_notes_path(snippet, *new_args)
- end
-
- def gitlab_snippet_notes_url(snippet, *args)
- new_args = snippet_query_params(snippet, *args)
- snippet_notes_url(snippet, *new_args)
- end
-
- def gitlab_snippet_note_path(snippet, note, *args)
- new_args = snippet_query_params(snippet, *args)
- snippet_note_path(snippet, note, *new_args)
- end
-
- def gitlab_snippet_note_url(snippet, note, *args)
- new_args = snippet_query_params(snippet, *args)
- snippet_note_url(snippet, note, *new_args)
- end
-
- def gitlab_toggle_award_emoji_snippet_note_path(snippet, note, *args)
- new_args = snippet_query_params(snippet, *args)
- toggle_award_emoji_snippet_note_path(snippet, note, *new_args)
- end
-
- def gitlab_toggle_award_emoji_snippet_note_url(snippet, note, *args)
- new_args = snippet_query_params(snippet, *args)
- toggle_award_emoji_snippet_note_url(snippet, note, *new_args)
- end
-
- def gitlab_toggle_award_emoji_snippet_path(snippet, *args)
- new_args = snippet_query_params(snippet, *args)
- toggle_award_emoji_snippet_path(snippet, *new_args)
- end
-
- def gitlab_toggle_award_emoji_snippet_url(snippet, *args)
- new_args = snippet_query_params(snippet, *args)
- toggle_award_emoji_snippet_url(snippet, *new_args)
- end
-
- # Wikis
-
- def wiki_path(wiki, **options)
- Gitlab::UrlBuilder.wiki_url(wiki, only_path: true, **options)
- end
-
- def wiki_page_path(wiki, page, **options)
- Gitlab::UrlBuilder.wiki_page_url(wiki, page, only_path: true, **options)
- end
-
- # GraphQL ETag routes
- def graphql_etag_pipeline_path(pipeline)
- [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)
- opts = case args.last
- when Hash
- args.pop
- when ActionController::Parameters
- args.pop.to_h
- else
- {}
- end
-
- args << opts
- end
end
GitlabRoutingHelper.include_mod_with('GitlabRoutingHelper')
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 26a5df321cd..400ad721b06 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -5,15 +5,9 @@ module GroupsHelper
%w[
groups#activity
groups#subgroups
- ].tap do |paths|
- extra_routes = if sidebar_refactor_disabled?
- ['groups#show', 'groups#details']
- else
- ['labels#index', 'group_members#index']
- end
-
- paths.concat(extra_routes)
- end
+ labels#index
+ group_members#index
+ ]
end
def group_settings_nav_link_paths
@@ -45,11 +39,7 @@ module GroupsHelper
end
def group_information_title(group)
- if Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
- group.subgroup? ? _('Subgroup information') : _('Group information')
- else
- group.subgroup? ? _('Subgroup overview') : _('Group overview')
- end
+ group.subgroup? ? _('Subgroup information') : _('Group information')
end
def group_container_registry_nav?
diff --git a/app/helpers/services_helper.rb b/app/helpers/integrations_helper.rb
index 83000189ab3..ab305d822e8 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/integrations_helper.rb
@@ -1,36 +1,18 @@
# frozen_string_literal: true
-module ServicesHelper
- def service_event_description(event)
- case event
- when "push", "push_events"
- s_("ProjectService|Trigger event for pushes to the repository.")
- when "tag_push", "tag_push_events"
- s_("ProjectService|Trigger event for new tags pushed to the repository.")
- when "note", "note_events"
- s_("ProjectService|Trigger event for new comments.")
- when "confidential_note", "confidential_note_events"
- s_("ProjectService|Trigger event for new comments on confidential issues.")
- when "issue", "issue_events"
- s_("ProjectService|Trigger event when an issue is created, updated, or closed.")
- when "confidential_issue", "confidential_issue_events"
- s_("ProjectService|Trigger event when a confidential issue is created, updated, or closed.")
- when "merge_request", "merge_request_events"
- s_("ProjectService|Trigger event when a merge request is created, updated, or merged.")
- when "pipeline", "pipeline_events"
- s_("ProjectService|Trigger event when a pipeline status changes.")
- when "wiki_page", "wiki_page_events"
- s_("ProjectService|Trigger event when a wiki page is created or updated.")
- when "commit", "commit_events"
- s_("ProjectService|Trigger event when a commit is created or updated.")
- when "deployment"
- s_("ProjectService|Trigger event when a deployment starts or finishes.")
- when "alert"
- s_("ProjectService|Trigger event when a new, unique alert is recorded.")
+module IntegrationsHelper
+ def integration_event_description(integration, event)
+ case integration
+ when Integrations::Jira
+ jira_integration_event_description(event)
+ when Integrations::Teamcity
+ teamcity_integration_event_description(event)
+ else
+ default_integration_event_description(event)
end
end
- def service_event_field_name(event)
+ def integration_event_field_name(event)
event = event.pluralize if %w[merge_request issue confidential_issue].include?(event)
"#{event}_events"
end
@@ -96,13 +78,13 @@ module ServicesHelper
enable_comments: integration.comment_on_event_enabled.to_s,
comment_detail: integration.comment_detail,
learn_more_path: integrations_help_page_path,
- trigger_events: trigger_events_for_service(integration),
- fields: fields_for_service(integration),
+ trigger_events: trigger_events_for_integration(integration),
+ fields: fields_for_integration(integration),
inherit_from_id: integration.inherit_from_id,
integration_level: integration_level(integration),
editable: integration.editable?.to_s,
cancel_path: scoped_integrations_path,
- can_test: integration.can_test?.to_s,
+ can_test: integration.testable?.to_s,
test_path: scoped_test_integration_path(integration),
reset_path: scoped_reset_integration_path(integration, group: group)
}
@@ -121,14 +103,6 @@ module ServicesHelper
}
end
- def trigger_events_for_service(integration)
- ServiceEventSerializer.new(service: integration).represent(integration.configurable_events).to_json
- end
-
- def fields_for_service(integration)
- ServiceFieldSerializer.new(service: integration).represent(integration.global_fields).to_json
- end
-
def integrations_help_page_path
help_page_path('user/admin_area/settings/project_integration_management')
end
@@ -152,6 +126,61 @@ module ServicesHelper
private
+ def jira_integration_event_description(event)
+ case event
+ when "merge_request", "merge_request_events"
+ s_("JiraService|Jira comments are created when an issue is referenced in a merge request.")
+ when "commit", "commit_events"
+ s_("JiraService|Jira comments are created when an issue is referenced in a commit.")
+ end
+ end
+
+ def teamcity_integration_event_description(event)
+ case event
+ when 'push', 'push_events'
+ s_('TeamcityIntegration|Trigger TeamCity CI after every push to the repository, except branch delete')
+ when 'merge_request', 'merge_request_events'
+ s_('TeamcityIntegration|Trigger TeamCity CI after a merge request has been created or updated')
+ end
+ end
+
+ def default_integration_event_description(event)
+ case event
+ when "push", "push_events"
+ s_("ProjectService|Trigger event for pushes to the repository.")
+ when "tag_push", "tag_push_events"
+ s_("ProjectService|Trigger event for new tags pushed to the repository.")
+ when "note", "note_events"
+ s_("ProjectService|Trigger event for new comments.")
+ when "confidential_note", "confidential_note_events"
+ s_("ProjectService|Trigger event for new comments on confidential issues.")
+ when "issue", "issue_events"
+ s_("ProjectService|Trigger event when an issue is created, updated, or closed.")
+ when "confidential_issue", "confidential_issue_events"
+ s_("ProjectService|Trigger event when a confidential issue is created, updated, or closed.")
+ when "merge_request", "merge_request_events"
+ s_("ProjectService|Trigger event when a merge request is created, updated, or merged.")
+ when "pipeline", "pipeline_events"
+ s_("ProjectService|Trigger event when a pipeline status changes.")
+ when "wiki_page", "wiki_page_events"
+ s_("ProjectService|Trigger event when a wiki page is created or updated.")
+ when "commit", "commit_events"
+ s_("ProjectService|Trigger event when a commit is created or updated.")
+ when "deployment"
+ s_("ProjectService|Trigger event when a deployment starts or finishes.")
+ when "alert"
+ s_("ProjectService|Trigger event when a new, unique alert is recorded.")
+ end
+ end
+
+ def trigger_events_for_integration(integration)
+ ServiceEventSerializer.new(service: integration).represent(integration.configurable_events).to_json
+ end
+
+ def fields_for_integration(integration)
+ ServiceFieldSerializer.new(service: integration).represent(integration.global_fields).to_json
+ end
+
def integration_level(integration)
if integration.instance_level?
'instance'
@@ -172,14 +201,10 @@ 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_mod_with('ServicesHelper')
+IntegrationsHelper.prepend_mod_with('IntegrationsHelper')
-# The methods in `EE::ServicesHelper` should be available as both instance and
+# The methods in `EE::IntegrationsHelper` should be available as both instance and
# class methods.
-ServicesHelper.extend_mod_with('ServicesHelper')
+IntegrationsHelper.extend_mod_with('IntegrationsHelper')
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index c40feb42eea..d8ba530f3f6 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -425,6 +425,15 @@ module IssuablesHelper
}
end
+ def sidebar_status_data(issuable_sidebar, project)
+ {
+ iid: issuable_sidebar[:iid],
+ issuable_type: issuable_sidebar[:type],
+ full_path: project.full_path,
+ can_edit: issuable_sidebar.dig(:current_user, :can_edit).to_s
+ }
+ end
+
def parent
@project || @group
end
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 7690773354f..5bedfc61d46 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -181,7 +181,6 @@ 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,
@@ -201,8 +200,6 @@ module IssuesHelper
max_attachment_size: number_to_human_size(Gitlab::CurrentSettings.max_attachment_size.megabytes),
new_issue_path: new_project_issue_path(project, issue: { 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'),
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index 39a8f506ba2..106df168080 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -56,10 +56,6 @@ module NamespacesHelper
namespaces_options(selected, **options)
end
- def cascading_namespace_settings_enabled?
- NamespaceSetting.cascading_settings_feature_enabled?
- end
-
def cascading_namespace_settings_popover_data(attribute, group, settings_path_helper)
locked_by_ancestor = group.namespace_settings.public_send("#{attribute}_locked_by_ancestor?") # rubocop:disable GitlabSecurity/PublicSend
diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb
index b952aeacb13..ff8839d68fd 100644
--- a/app/helpers/nav/new_dropdown_helper.rb
+++ b/app/helpers/nav/new_dropdown_helper.rb
@@ -21,13 +21,6 @@ module Nav
}
end
- def new_repo_experiment_text
- experiment(:new_repo, user: current_user) do |e|
- e.use { _('New project') }
- e.try { _('New project/repository') }
- end.run
- end
-
private
def group_menu_section(group)
@@ -37,9 +30,9 @@ module Nav
menu_items.push(
::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_project',
- title: new_repo_experiment_text,
+ title: _('New project/repository'),
href: new_project_path(namespace_id: group.id),
- data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
+ data: { track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
)
)
end
@@ -129,9 +122,9 @@ module Nav
menu_items.push(
::Gitlab::Nav::TopNavMenuItem.build(
id: 'general_new_project',
- title: new_repo_experiment_text,
+ title: _('New project/repository'),
href: new_project_path,
- data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
+ data: { track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
)
)
end
diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb
index b8ddb932b73..052b8339ebd 100644
--- a/app/helpers/nav/top_nav_helper.rb
+++ b/app/helpers/nav/top_nav_helper.rb
@@ -22,7 +22,7 @@ module Nav
new_view_model = new_dropdown_view_model(project: project, group: group)
- if new_view_model
+ if new_view_model && new_view_model.fetch(:menu_sections)&.any?
builder.add_view(NEW_VIEW, new_view_model)
end
@@ -98,7 +98,7 @@ module Nav
builder.add_primary_menu_item_with_shortcut(
active: nav == 'project' || active_nav_link?(path: %w[root#index projects#trending projects#starred dashboard/projects#index]),
css_class: 'qa-projects-dropdown',
- data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" },
+ data: { track_label: "projects_dropdown", track_event: "click_dropdown" },
view: PROJECTS_VIEW,
shortcut_href: dashboard_projects_path,
**projects_menu_item_attrs
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index b5171dfbebd..6c57a31f3db 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -64,7 +64,7 @@ module NavHelper
end
def admin_analytics_nav_links
- %w(dev_ops_report)
+ %w(dev_ops_report usage_trends)
end
def group_issues_sub_menu_items
@@ -73,9 +73,7 @@ module NavHelper
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
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index fb410c46128..5d2f225edcf 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -2,10 +2,11 @@
module OperationsHelper
include Gitlab::Utils::StrongMemoize
+ include IntegrationsHelper
- def prometheus_service
- strong_memoize(:prometheus_service) do
- @project.find_or_initialize_service(::PrometheusService.to_param)
+ def prometheus_integration
+ strong_memoize(:prometheus_integration) do
+ @project.find_or_initialize_integration(::Integrations::Prometheus.to_param)
end
end
@@ -14,11 +15,11 @@ module OperationsHelper
templates = setting.available_issue_templates.map { |t| { key: t.key, name: t.name } }
{
- 'prometheus_activated' => prometheus_service.manual_configuration?.to_s,
- 'prometheus_form_path' => scoped_integration_path(prometheus_service),
+ 'prometheus_activated' => prometheus_integration.manual_configuration?.to_s,
+ 'prometheus_form_path' => scoped_integration_path(prometheus_integration),
'prometheus_reset_key_path' => reset_alerting_token_project_settings_operations_path(@project),
'prometheus_authorization_key' => @project.alerting_setting&.token,
- 'prometheus_api_url' => prometheus_service.api_url,
+ 'prometheus_api_url' => prometheus_integration.api_url,
'prometheus_url' => notify_project_prometheus_alerts_url(@project, format: :json),
'alerts_setup_url' => help_page_path('operations/incident_management/integrations.md', anchor: 'configuration'),
'alerts_usage_url' => project_alert_management_index_path(@project),
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index fe41c041b4f..50984415aa5 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -57,10 +57,35 @@ module PackagesHelper
def show_cleanup_policy_on_alert(project)
Gitlab.com? &&
Gitlab.config.registry.enabled &&
- project.container_registry_enabled &&
+ project.feature_available?(:container_registry, current_user) &&
!Gitlab::CurrentSettings.container_expiration_policies_enable_historic_entries &&
Feature.enabled?(:container_expiration_policies_historic_entry, project) &&
project.container_expiration_policy.nil? &&
project.container_repositories.exists?
end
+
+ def package_details_data(project, package = nil)
+ {
+ package: package ? package_from_presenter(package) : nil,
+ can_delete: can?(current_user, :destroy_package, project).to_s,
+ svg_path: image_path('illustrations/no-packages.svg'),
+ npm_path: package_registry_instance_url(:npm),
+ npm_help_path: help_page_path('user/packages/npm_registry/index'),
+ maven_path: package_registry_project_url(project.id, :maven),
+ maven_help_path: help_page_path('user/packages/maven_repository/index'),
+ conan_path: package_registry_project_url(project.id, :conan),
+ conan_help_path: help_page_path('user/packages/conan_repository/index'),
+ nuget_path: nuget_package_registry_url(project.id),
+ nuget_help_path: help_page_path('user/packages/nuget_repository/index'),
+ pypi_path: pypi_registry_url(project.id),
+ pypi_setup_path: package_registry_project_url(project.id, :pypi),
+ pypi_help_path: help_page_path('user/packages/pypi_repository/index'),
+ composer_path: composer_registry_url(project&.group&.id),
+ composer_help_path: help_page_path('user/packages/composer_repository/index'),
+ project_name: project.name,
+ project_list_url: project_packages_path(project),
+ group_list_url: project.group ? group_packages_path(project.group) : '',
+ composer_config_repository_name: composer_config_repository_name(project.group&.id)
+ }
+ end
end
diff --git a/app/helpers/personal_access_tokens_helper.rb b/app/helpers/personal_access_tokens_helper.rb
new file mode 100644
index 00000000000..5cc8d21096f
--- /dev/null
+++ b/app/helpers/personal_access_tokens_helper.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module PersonalAccessTokensHelper
+ def personal_access_token_expiration_enforced?
+ false
+ end
+end
diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb
index b46e3eb3bc3..b50e287a509 100644
--- a/app/helpers/projects/alert_management_helper.rb
+++ b/app/helpers/projects/alert_management_helper.rb
@@ -29,13 +29,13 @@ module Projects::AlertManagementHelper
private
def has_managed_prometheus?(project)
- project.prometheus_service&.prometheus_available? == true
+ project.prometheus_integration&.prometheus_available? == true
end
def alert_management_enabled?(project)
!!(
project.alert_management_alerts.any? ||
- project.prometheus_service_active? ||
+ project.prometheus_integration_active? ||
AlertManagement::HttpIntegrationsFinder.new(project, active: true).execute.any?
)
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 8800bd0643c..752e91df9c4 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -350,6 +350,10 @@ module ProjectsHelper
nil
end
+ def show_terraform_banner?(project)
+ project.repository_languages.with_programming_language('HCL').exists? && project.terraform_states.empty?
+ end
+
private
def tab_ability_map
@@ -530,7 +534,8 @@ module ProjectsHelper
pagesAvailable: Gitlab.config.pages.enabled,
pagesAccessControlEnabled: Gitlab.config.pages.access_control,
pagesAccessControlForced: ::Gitlab::Pages.access_control_is_forced?,
- pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control')
+ pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control'),
+ issuesHelpPath: help_page_path('user/project/issues/index')
}
end
@@ -611,21 +616,6 @@ module ProjectsHelper
project.unlink_forks_upon_visibility_decrease_enabled? && project.visibility_level > Gitlab::VisibilityLevel::PRIVATE && project.forks_count > 0
end
- def settings_container_registry_expiration_policy_available?(project)
- Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml) &&
- can_destroy_container_registry_image?(current_user, project)
- end
-
- def settings_packages_and_registries_enabled?(project)
- Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml) &&
- 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
-
def build_project_breadcrumb_link(project)
project_name = simple_sanitize(project.name)
diff --git a/app/helpers/registrations_helper.rb b/app/helpers/registrations_helper.rb
index 24131e32c6c..91adc36749b 100644
--- a/app/helpers/registrations_helper.rb
+++ b/app/helpers/registrations_helper.rb
@@ -1,13 +1,6 @@
# 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
-
def signup_username_data_attributes
{
min_length: User::MIN_USERNAME_LENGTH,
diff --git a/app/helpers/releases_helper.rb b/app/helpers/releases_helper.rb
index de9288121c4..4fa61191ba5 100644
--- a/app/helpers/releases_helper.rb
+++ b/app/helpers/releases_helper.rb
@@ -4,6 +4,10 @@ module ReleasesHelper
IMAGE_PATH = 'illustrations/releases.svg'
DOCUMENTATION_PATH = 'user/project/releases/index'
+ # This needs to be kept in sync with the constant in
+ # app/assets/javascripts/releases/constants.js
+ DEFAULT_SORT = 'RELEASED_AT_DESC'
+
def illustration
image_path(IMAGE_PATH)
end
@@ -20,15 +24,24 @@ module ReleasesHelper
documentation_path: help_page
}.tap do |data|
if can?(current_user, :create_release, @project)
- data[:new_release_path] = if Feature.enabled?(:new_release_page, @project, default_enabled: true)
- new_project_release_path(@project)
- else
- new_project_tag_path(@project)
- end
+ data[:new_release_path] = new_project_release_path(@project)
end
end
end
+ # For simplicity, only optimize non-paginated requests
+ def use_startup_query_for_index_page?
+ params[:before].nil? && params[:after].nil?
+ end
+
+ def index_page_startup_query_variables
+ {
+ fullPath: @project.full_path,
+ sort: DEFAULT_SORT,
+ first: 1
+ }
+ end
+
def data_for_show_page
{
project_id: @project.id,
diff --git a/app/helpers/routing/artifacts_helper.rb b/app/helpers/routing/artifacts_helper.rb
new file mode 100644
index 00000000000..32df9098e48
--- /dev/null
+++ b/app/helpers/routing/artifacts_helper.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Routing
+ module ArtifactsHelper
+ # Rails path generators are slow because they need to do large regex comparisons
+ # against the arguments. We can speed this up 10x by generating the strings directly.
+
+ # /*namespace_id/:project_id/-/jobs/:job_id/artifacts/download(.:format)
+ def fast_download_project_job_artifacts_path(project, job, params = {})
+ expose_fast_artifacts_path(project, job, :download, params)
+ end
+
+ # /*namespace_id/:project_id/-/jobs/:job_id/artifacts/keep(.:format)
+ def fast_keep_project_job_artifacts_path(project, job)
+ expose_fast_artifacts_path(project, job, :keep)
+ end
+
+ # /*namespace_id/:project_id/-/jobs/:job_id/artifacts/browse(/*path)
+ def fast_browse_project_job_artifacts_path(project, job)
+ expose_fast_artifacts_path(project, job, :browse)
+ end
+
+ def expose_fast_artifacts_path(project, job, action, params = {})
+ path = "#{project.full_path}/-/jobs/#{job.id}/artifacts/#{action}"
+
+ unless params.empty?
+ path += "?#{params.to_query}"
+ end
+
+ Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, path)
+ end
+
+ def artifacts_action_path(path, project, build)
+ action, path_params = path.split('/', 2)
+ args = [project, build, path_params]
+
+ case action
+ when 'download'
+ download_project_job_artifacts_path(*args)
+ when 'browse'
+ browse_project_job_artifacts_path(*args)
+ when 'file'
+ file_project_job_artifacts_path(*args)
+ when 'raw'
+ raw_project_job_artifacts_path(*args)
+ end
+ end
+ end
+end
diff --git a/app/helpers/routing/graphql_helper.rb b/app/helpers/routing/graphql_helper.rb
new file mode 100644
index 00000000000..beefbb9b387
--- /dev/null
+++ b/app/helpers/routing/graphql_helper.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Routing
+ module GraphqlHelper
+ def graphql_etag_pipeline_path(pipeline)
+ [api_graphql_path, "pipelines/id/#{pipeline.id}"].join(':')
+ end
+
+ def graphql_etag_pipeline_sha_path(sha)
+ [api_graphql_path, "pipelines/sha/#{sha}"].join(':')
+ end
+ end
+end
diff --git a/app/helpers/routing/groups/members_helper.rb b/app/helpers/routing/groups/members_helper.rb
new file mode 100644
index 00000000000..eabeacff1d7
--- /dev/null
+++ b/app/helpers/routing/groups/members_helper.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Routing
+ module Groups
+ module MembersHelper
+ def group_members_url(group, *args)
+ group_group_members_url(group, *args)
+ end
+
+ def group_member_path(group_member, *args)
+ group_group_member_path(group_member.source, group_member)
+ end
+
+ def request_access_group_members_path(group, *args)
+ request_access_group_group_members_path(group)
+ end
+
+ def leave_group_members_path(group, *args)
+ leave_group_group_members_path(group)
+ end
+
+ def approve_access_request_group_member_path(group_member, *args)
+ approve_access_request_group_group_member_path(group_member.source, group_member)
+ end
+
+ def resend_invite_group_member_path(group_member, *args)
+ resend_invite_group_group_member_path(group_member.source, group_member)
+ end
+ end
+ end
+end
diff --git a/app/helpers/routing/members_helper.rb b/app/helpers/routing/members_helper.rb
new file mode 100644
index 00000000000..18f6d06ab3b
--- /dev/null
+++ b/app/helpers/routing/members_helper.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Routing
+ module MembersHelper
+ 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
+ end
+end
diff --git a/app/helpers/routing/pipeline_schedules_helper.rb b/app/helpers/routing/pipeline_schedules_helper.rb
new file mode 100644
index 00000000000..6501018a365
--- /dev/null
+++ b/app/helpers/routing/pipeline_schedules_helper.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Routing
+ module PipelineSchedulesHelper
+ def pipeline_schedules_path(project, *args)
+ project_pipeline_schedules_path(project, *args)
+ end
+
+ def pipeline_schedule_path(schedule, *args)
+ project = schedule.project
+ project_pipeline_schedule_path(project, schedule, *args)
+ end
+
+ def edit_pipeline_schedule_path(schedule)
+ project = schedule.project
+ edit_project_pipeline_schedule_path(project, schedule)
+ end
+
+ def play_pipeline_schedule_path(schedule, *args)
+ project = schedule.project
+ play_project_pipeline_schedule_path(project, schedule, *args)
+ end
+
+ def take_ownership_pipeline_schedule_path(schedule, *args)
+ project = schedule.project
+ take_ownership_project_pipeline_schedule_path(project, schedule, *args)
+ end
+ end
+end
diff --git a/app/helpers/routing/projects/members_helper.rb b/app/helpers/routing/projects/members_helper.rb
new file mode 100644
index 00000000000..72f88a1408b
--- /dev/null
+++ b/app/helpers/routing/projects/members_helper.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Routing
+ module Projects
+ module MembersHelper
+ def project_members_url(project, *args)
+ project_project_members_url(project, *args)
+ end
+
+ def project_member_path(project_member, *args)
+ project_project_member_path(project_member.source, project_member)
+ end
+
+ def request_access_project_members_path(project, *args)
+ request_access_project_project_members_path(project)
+ end
+
+ def leave_project_members_path(project, *args)
+ leave_project_project_members_path(project)
+ end
+
+ def approve_access_request_project_member_path(project_member, *args)
+ approve_access_request_project_project_member_path(project_member.source, project_member)
+ end
+
+ def resend_invite_project_member_path(project_member, *args)
+ resend_invite_project_project_member_path(project_member.source, project_member)
+ end
+ end
+ end
+end
diff --git a/app/helpers/routing/projects_helper.rb b/app/helpers/routing/projects_helper.rb
new file mode 100644
index 00000000000..fb000b29739
--- /dev/null
+++ b/app/helpers/routing/projects_helper.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module Routing
+ module ProjectsHelper
+ def project_tree_path(project, ref = nil, *args)
+ namespace_project_tree_path(project.namespace, project, ref || @ref || project.repository.root_ref, *args) # rubocop:disable Cop/ProjectPathHelper
+ end
+
+ def project_commits_path(project, ref = nil, *args)
+ namespace_project_commits_path(project.namespace, project, ref || @ref || project.repository.root_ref, *args) # rubocop:disable Cop/ProjectPathHelper
+ end
+
+ def project_ref_path(project, ref_name, *args)
+ project_commits_path(project, ref_name, *args)
+ end
+
+ def environment_path(environment, *args)
+ project_environment_path(environment.project, environment, *args)
+ end
+
+ def environment_metrics_path(environment, *args)
+ metrics_project_environment_path(environment.project, environment, *args)
+ end
+
+ def environment_delete_path(environment, *args)
+ expose_path(api_v4_projects_environments_path(id: environment.project.id, environment_id: environment.id))
+ end
+
+ def issue_path(entity, *args)
+ project_issue_path(entity.project, entity, *args)
+ end
+
+ def merge_request_path(entity, *args)
+ project_merge_request_path(entity.project, entity, *args)
+ end
+
+ def pipeline_path(pipeline, *args)
+ project_pipeline_path(pipeline.project, pipeline.id, *args)
+ end
+
+ def issue_url(entity, *args)
+ project_issue_url(entity.project, entity, *args)
+ end
+
+ def merge_request_url(entity, *args)
+ project_merge_request_url(entity.project, entity, *args)
+ end
+
+ def pipeline_url(pipeline, *args)
+ project_pipeline_url(pipeline.project, pipeline.id, *args)
+ end
+
+ def pipeline_job_url(pipeline, build, *args)
+ project_job_url(pipeline.project, build.id, *args)
+ end
+
+ def commits_url(entity, *args)
+ project_commits_url(entity.project, entity.source_ref, *args)
+ end
+
+ def commit_url(entity, *args)
+ project_commit_url(entity.project, entity.sha, *args)
+ end
+
+ def release_url(entity, *args)
+ project_release_url(entity.project, entity, *args)
+ end
+
+ def edit_milestone_path(entity, *args)
+ if entity.resource_parent.is_a?(Group)
+ edit_group_milestone_path(entity.resource_parent, entity, *args)
+ else
+ edit_project_milestone_path(entity.resource_parent, entity, *args)
+ end
+ end
+
+ def toggle_subscription_path(entity, *args)
+ if entity.is_a?(Issue)
+ toggle_subscription_project_issue_path(entity.project, entity)
+ else
+ toggle_subscription_project_merge_request_path(entity.project, entity)
+ end
+ end
+ end
+end
diff --git a/app/helpers/routing/snippets_helper.rb b/app/helpers/routing/snippets_helper.rb
new file mode 100644
index 00000000000..19450c1d033
--- /dev/null
+++ b/app/helpers/routing/snippets_helper.rb
@@ -0,0 +1,144 @@
+# frozen_string_literal: true
+
+module Routing
+ module SnippetsHelper
+ def gitlab_snippet_path(snippet, *args)
+ if snippet.is_a?(ProjectSnippet)
+ project_snippet_path(snippet.project, snippet, *args)
+ else
+ new_args = snippet_query_params(snippet, *args)
+ snippet_path(snippet, *new_args)
+ end
+ end
+
+ def gitlab_snippet_url(snippet, *args)
+ if snippet.is_a?(ProjectSnippet)
+ project_snippet_url(snippet.project, snippet, *args)
+ else
+ new_args = snippet_query_params(snippet, *args)
+ snippet_url(snippet, *new_args)
+ end
+ end
+
+ def gitlab_dashboard_snippets_path(snippet, *args)
+ if snippet.is_a?(ProjectSnippet)
+ project_snippets_path(snippet.project, *args)
+ else
+ dashboard_snippets_path
+ end
+ end
+
+ def gitlab_raw_snippet_path(snippet, *args)
+ if snippet.is_a?(ProjectSnippet)
+ raw_project_snippet_path(snippet.project, snippet, *args)
+ else
+ new_args = snippet_query_params(snippet, *args)
+ raw_snippet_path(snippet, *new_args)
+ end
+ end
+
+ def gitlab_raw_snippet_url(snippet, *args)
+ if snippet.is_a?(ProjectSnippet)
+ raw_project_snippet_url(snippet.project, snippet, *args)
+ else
+ new_args = snippet_query_params(snippet, *args)
+ raw_snippet_url(snippet, *new_args)
+ end
+ end
+
+ def gitlab_raw_snippet_blob_url(snippet, path, ref = nil, **options)
+ params = {
+ snippet_id: snippet,
+ ref: ref || snippet.default_branch,
+ path: path
+ }
+
+ if snippet.is_a?(ProjectSnippet)
+ project_snippet_blob_raw_url(snippet.project, **params, **options)
+ else
+ snippet_blob_raw_url(**params, **options)
+ end
+ end
+
+ def gitlab_raw_snippet_blob_path(snippet, path, ref = nil, **options)
+ gitlab_raw_snippet_blob_url(snippet, path, ref, only_path: true, **options)
+ end
+
+ def gitlab_snippet_notes_path(snippet, *args)
+ new_args = snippet_query_params(snippet, *args)
+ snippet_notes_path(snippet, *new_args)
+ end
+
+ def gitlab_snippet_notes_url(snippet, *args)
+ new_args = snippet_query_params(snippet, *args)
+ snippet_notes_url(snippet, *new_args)
+ end
+
+ def gitlab_snippet_note_path(snippet, note, *args)
+ new_args = snippet_query_params(snippet, *args)
+ snippet_note_path(snippet, note, *new_args)
+ end
+
+ def gitlab_snippet_note_url(snippet, note, *args)
+ new_args = snippet_query_params(snippet, *args)
+ snippet_note_url(snippet, note, *new_args)
+ end
+
+ def gitlab_toggle_award_emoji_snippet_note_path(snippet, note, *args)
+ new_args = snippet_query_params(snippet, *args)
+ toggle_award_emoji_snippet_note_path(snippet, note, *new_args)
+ end
+
+ def gitlab_toggle_award_emoji_snippet_note_url(snippet, note, *args)
+ new_args = snippet_query_params(snippet, *args)
+ toggle_award_emoji_snippet_note_url(snippet, note, *new_args)
+ end
+
+ def gitlab_toggle_award_emoji_snippet_path(snippet, *args)
+ new_args = snippet_query_params(snippet, *args)
+ toggle_award_emoji_snippet_path(snippet, *new_args)
+ end
+
+ def gitlab_toggle_award_emoji_snippet_url(snippet, *args)
+ new_args = snippet_query_params(snippet, *args)
+ toggle_award_emoji_snippet_url(snippet, *new_args)
+ end
+
+ def preview_markdown_path(parent, *args)
+ return group_preview_markdown_path(parent, *args) if parent.is_a?(Group)
+
+ if @snippet.is_a?(PersonalSnippet)
+ preview_markdown_snippets_path
+ else
+ preview_markdown_project_path(parent, *args)
+ end
+ end
+
+ def toggle_award_emoji_personal_snippet_path(*args)
+ toggle_award_emoji_snippet_path(*args)
+ end
+
+ def toggle_award_emoji_project_project_snippet_path(*args)
+ toggle_award_emoji_project_snippet_path(*args)
+ end
+
+ def toggle_award_emoji_project_project_snippet_url(*args)
+ toggle_award_emoji_project_snippet_url(*args)
+ end
+
+ private
+
+ def snippet_query_params(snippet, *args)
+ opts = case args.last
+ when Hash
+ args.pop
+ when ActionController::Parameters
+ args.pop.to_h
+ else
+ {}
+ end
+
+ args << opts
+ end
+ end
+end
diff --git a/app/helpers/routing/wiki_helper.rb b/app/helpers/routing/wiki_helper.rb
new file mode 100644
index 00000000000..95f9e87de36
--- /dev/null
+++ b/app/helpers/routing/wiki_helper.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Routing
+ module WikiHelper
+ def wiki_path(wiki, **options)
+ Gitlab::UrlBuilder.wiki_url(wiki, only_path: true, **options)
+ end
+
+ def wiki_page_path(wiki, page, **options)
+ Gitlab::UrlBuilder.wiki_page_url(wiki, page, only_path: true, **options)
+ end
+ end
+end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index e07ee22339a..ec8ed3d6e7f 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -131,7 +131,7 @@ module SearchHelper
end
def search_sort_options
- [
+ options = [
{
title: _('Created date'),
sortable: true,
@@ -149,6 +149,19 @@ module SearchHelper
}
}
]
+
+ if search_service.scope == 'issues' && Feature.enabled?(:search_sort_issues_by_popularity)
+ options << {
+ title: _('Popularity'),
+ sortable: true,
+ sortParam: {
+ asc: 'popularity_asc',
+ desc: 'popularity_desc'
+ }
+ }
+ end
+
+ options
end
private
@@ -172,12 +185,12 @@ module SearchHelper
# Autocomplete results for internal help pages
def help_autocomplete
[
- { category: "Help", label: _("API Help"), url: help_page_path("api/README") },
+ { category: "Help", label: _("API Help"), url: help_page_path("api/index") },
{ category: "Help", label: _("Markdown Help"), url: help_page_path("user/markdown") },
{ category: "Help", label: _("Permissions Help"), url: help_page_path("user/permissions") },
{ category: "Help", label: _("Public Access Help"), url: help_page_path("public_access/public_access") },
{ category: "Help", label: _("Rake Tasks Help"), url: help_page_path("raketasks/README") },
- { category: "Help", label: _("SSH Keys Help"), url: help_page_path("ssh/README") },
+ { category: "Help", label: _("SSH Keys Help"), url: help_page_path("ssh/index") },
{ category: "Help", label: _("System Hooks Help"), url: help_page_path("system_hooks/system_hooks") },
{ category: "Help", label: _("Webhooks Help"), url: help_page_path("user/project/integrations/webhooks") }
]
@@ -301,7 +314,7 @@ module SearchHelper
if @scope == scope
li_class = 'active'
- count = @search_results.formatted_count(scope)
+ count = @timeout ? 0 : @search_results.formatted_count(scope)
else
badge_class = 'js-search-count hidden'
badge_data = { url: search_count_path(search_params) }
diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb
index ef737b25bc7..117f662fec6 100644
--- a/app/helpers/sessions_helper.rb
+++ b/app/helpers/sessions_helper.rb
@@ -1,6 +1,15 @@
# frozen_string_literal: true
module SessionsHelper
+ include Gitlab::Utils::StrongMemoize
+
+ def recently_confirmed_com?
+ strong_memoize(:recently_confirmed_com) do
+ ::Gitlab.dev_env_or_com? &&
+ !!flash[:notice]&.include?(t(:confirmed, scope: [:devise, :confirmations]))
+ end
+ end
+
def unconfirmed_email?
flash[:alert] == t(:unconfirmed, scope: [:devise, :failure])
end
diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb
index 39ad8ed8a0f..77af6e37099 100644
--- a/app/helpers/sidebars_helper.rb
+++ b/app/helpers/sidebars_helper.rb
@@ -2,34 +2,75 @@
module SidebarsHelper
def sidebar_tracking_attributes_by_object(object)
+ sidebar_attributes_for_object(object).fetch(:tracking_attrs, {})
+ end
+
+ def sidebar_qa_selector(object)
+ sidebar_attributes_for_object(object).fetch(:sidebar_qa_selector, nil)
+ end
+
+ def scope_qa_menu_item(object)
+ sidebar_attributes_for_object(object).fetch(:scope_qa_menu_item, nil)
+ end
+
+ def scope_avatar_classes(object)
+ %w[avatar-container rect-avatar s32].tap do |klasses|
+ klass = sidebar_attributes_for_object(object).fetch(:scope_avatar_class, nil)
+ klasses << klass if klass
+ end
+ end
+
+ def project_sidebar_context(project, user, current_ref)
+ context_data = project_sidebar_context_data(project, user, current_ref)
+
+ Sidebars::Projects::Context.new(**context_data)
+ end
+
+ def group_sidebar_context(group, user)
+ context_data = group_sidebar_context_data(group, user)
+
+ Sidebars::Groups::Context.new(**context_data)
+ end
+
+ private
+
+ def sidebar_attributes_for_object(object)
case object
when Project
- sidebar_project_tracking_attrs
+ sidebar_project_attributes
when Group
- sidebar_group_tracking_attrs
+ sidebar_group_attributes
when User
- sidebar_user_profile_tracking_attrs
+ sidebar_user_attributes
else
{}
end
end
- def project_sidebar_context(project, user, current_ref)
- context_data = project_sidebar_context_data(project, user, current_ref)
-
- Sidebars::Projects::Context.new(**context_data)
+ def sidebar_project_attributes
+ {
+ tracking_attrs: sidebar_project_tracking_attrs,
+ sidebar_qa_selector: 'project_sidebar',
+ scope_qa_menu_item: 'Project scope',
+ scope_avatar_class: 'project_avatar'
+ }
end
- def sidebar_refactor_enabled?
- Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml)
+ def sidebar_group_attributes
+ {
+ tracking_attrs: sidebar_group_tracking_attrs,
+ sidebar_qa_selector: 'group_sidebar',
+ scope_qa_menu_item: 'Group scope',
+ scope_avatar_class: 'group_avatar'
+ }
end
- def sidebar_refactor_disabled?
- !sidebar_refactor_enabled?
+ def sidebar_user_attributes
+ {
+ tracking_attrs: sidebar_user_profile_tracking_attrs
+ }
end
- private
-
def sidebar_project_tracking_attrs
tracking_attrs('projects_side_navigation', 'render', 'projects_side_navigation')
end
@@ -54,6 +95,13 @@ module SidebarsHelper
show_cluster_hint: show_gke_cluster_integration_callout?(project)
}
end
+
+ def group_sidebar_context_data(group, user)
+ {
+ current_user: user,
+ container: group
+ }
+ end
end
SidebarsHelper.prepend_mod_with('SidebarsHelper')
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 0bb9e9e9bdd..da32dfb0b9b 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -26,6 +26,9 @@ module SortingHelper
sort_value_recently_updated => sort_title_recently_updated,
sort_value_popularity => sort_title_popularity,
sort_value_priority => sort_title_priority,
+ sort_value_merged_date => sort_title_merged_date,
+ sort_value_merged_recently => sort_title_merged_recently,
+ sort_value_merged_earlier => sort_title_merged_earlier,
sort_value_upvotes => sort_title_upvotes,
sort_value_contacted_date => sort_title_contacted_date,
sort_value_relative_position => sort_title_relative_position,
@@ -168,19 +171,6 @@ module SortingHelper
}
end
- def member_sort_options_hash
- {
- sort_value_access_level_asc => sort_title_access_level_asc,
- sort_value_access_level_desc => sort_title_access_level_desc,
- sort_value_last_joined => sort_title_last_joined,
- sort_value_name => sort_title_name_asc,
- sort_value_name_desc => sort_title_name_desc,
- sort_value_oldest_joined => sort_title_oldest_joined,
- sort_value_oldest_signin => sort_title_oldest_signin,
- sort_value_recently_signin => sort_title_recently_signin
- }
- end
-
def sortable_item(item, path, sorted_by)
link_to item, path, class: sorted_by == item ? 'is-active' : ''
end
@@ -191,6 +181,7 @@ module SortingHelper
sort_value_oldest_updated => sort_value_recently_updated,
sort_value_milestone_later => sort_value_milestone,
sort_value_due_date_later => sort_value_due_date,
+ sort_value_merged_recently => sort_value_merged_date,
sort_value_least_popular => sort_value_popularity
}
end
@@ -203,6 +194,8 @@ module SortingHelper
sort_value_milestone => sort_value_milestone_later,
sort_value_due_date => sort_value_due_date_later,
sort_value_due_date_soon => sort_value_due_date_later,
+ sort_value_merged_date => sort_value_merged_recently,
+ sort_value_merged_earlier => sort_value_merged_recently,
sort_value_popularity => sort_value_least_popular,
sort_value_most_popular => sort_value_least_popular
}.merge(issuable_sort_option_overrides)
@@ -223,7 +216,7 @@ module SortingHelper
def sort_direction_icon(sort_value)
case sort_value
- when sort_value_milestone, sort_value_due_date, /_asc\z/
+ when sort_value_milestone, sort_value_due_date, sort_value_merged_date, /_asc\z/
'sort-lowest'
else
'sort-highest'
diff --git a/app/helpers/sorting_titles_values_helper.rb b/app/helpers/sorting_titles_values_helper.rb
index 28d70f1db45..9b839f4e9bc 100644
--- a/app/helpers/sorting_titles_values_helper.rb
+++ b/app/helpers/sorting_titles_values_helper.rb
@@ -2,14 +2,6 @@
module SortingTitlesValuesHelper
# Titles.
- def sort_title_access_level_asc
- s_('SortOptions|Access level, ascending')
- end
-
- def sort_title_access_level_desc
- s_('SortOptions|Access level, descending')
- end
-
def sort_title_created_date
s_('SortOptions|Created date')
end
@@ -34,6 +26,18 @@ module SortingTitlesValuesHelper
s_('SortOptions|Label priority')
end
+ def sort_title_merged_date
+ s_('SortOptions|Merged date')
+ end
+
+ def sort_title_merged_recently
+ s_('SortOptions|Merged recently')
+ end
+
+ def sort_title_merged_earlier
+ s_('SortOptions|Merged earlier')
+ end
+
def sort_title_largest_group
s_('SortOptions|Largest group')
end
@@ -42,10 +46,6 @@ module SortingTitlesValuesHelper
s_('SortOptions|Largest repository')
end
- def sort_title_last_joined
- s_('SortOptions|Last joined')
- end
-
def sort_title_latest_activity
s_('SortOptions|Last updated')
end
@@ -82,10 +82,6 @@ module SortingTitlesValuesHelper
s_('SortOptions|Oldest created')
end
- def sort_title_oldest_joined
- s_('SortOptions|Oldest joined')
- end
-
def sort_title_oldest_signin
s_('SortOptions|Oldest sign in')
end
@@ -167,14 +163,6 @@ module SortingTitlesValuesHelper
end
# Values.
- def sort_value_access_level_asc
- 'access_level_asc'
- end
-
- def sort_value_access_level_desc
- 'access_level_desc'
- end
-
def sort_value_created_date
'created_date'
end
@@ -199,6 +187,18 @@ module SortingTitlesValuesHelper
'label_priority'
end
+ def sort_value_merged_date
+ 'merged_at'
+ end
+
+ def sort_value_merged_recently
+ 'merged_at_desc'
+ end
+
+ def sort_value_merged_earlier
+ 'merged_at_asc'
+ end
+
def sort_value_largest_group
'storage_size_desc'
end
@@ -207,10 +207,6 @@ module SortingTitlesValuesHelper
'storage_size_desc'
end
- def sort_value_last_joined
- 'last_joined'
- end
-
def sort_value_latest_activity
'latest_activity_desc'
end
@@ -247,10 +243,6 @@ module SortingTitlesValuesHelper
'oldest_sign_in'
end
- def sort_value_oldest_joined
- 'oldest_joined'
- end
-
def sort_value_oldest_updated
'updated_asc'
end
diff --git a/app/helpers/tracking_helper.rb b/app/helpers/tracking_helper.rb
index 7957038c21e..3f53bd535b2 100644
--- a/app/helpers/tracking_helper.rb
+++ b/app/helpers/tracking_helper.rb
@@ -17,6 +17,6 @@ module TrackingHelper
def tracking_enabled?
Rails.env.production? &&
- ::Gitlab::CurrentSettings.snowplow_enabled?
+ ::Gitlab::Tracking.enabled?
end
end
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index c44da915105..4e6af298fcd 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -43,7 +43,7 @@ module UserCalloutsHelper
end
def show_customize_homepage_banner?
- !user_dismissed?(CUSTOMIZE_HOMEPAGE)
+ current_user.default_dashboard? && !user_dismissed?(CUSTOMIZE_HOMEPAGE)
end
def show_feature_flags_new_version?
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index c1d05c2d3cf..93a0166f43e 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -123,130 +123,38 @@ module UsersHelper
!user.confirmed?
end
- def user_block_data(user, message)
- {
- path: block_admin_user_path(user),
- method: 'put',
- modal_attributes: {
- title: s_('AdminUsers|Block user %{username}?') % { username: sanitize_name(user.name) },
- messageHtml: message,
- okVariant: 'warning',
- okTitle: s_('AdminUsers|Block')
- }.to_json
- }
- end
-
- def user_unblock_data(user)
- {
- path: unblock_admin_user_path(user),
- method: 'put',
- modal_attributes: {
- title: s_('AdminUsers|Unblock user %{username}?') % { username: sanitize_name(user.name) },
- message: s_('AdminUsers|You can always block their account again if needed.'),
- okVariant: 'info',
- okTitle: s_('AdminUsers|Unblock')
- }.to_json
- }
- end
-
- def user_block_effects
- header = tag.p s_('AdminUsers|Blocking user has the following effects:')
-
- list = tag.ul do
- concat tag.li s_('AdminUsers|User will not be able to login')
- concat tag.li s_('AdminUsers|User will not be able to access git repositories')
- concat tag.li s_('AdminUsers|Personal projects will be left')
- concat tag.li s_('AdminUsers|Owned groups will be left')
- end
-
- 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),
- method: 'put',
- modal_attributes: {
- title: s_('AdminUsers|Deactivate user %{username}?') % { username: sanitize_name(user.name) },
- messageHtml: message,
- okVariant: 'warning',
- okTitle: s_('AdminUsers|Deactivate')
- }.to_json
- }
- end
+ def confirm_user_data(user)
+ message = if user.unconfirmed_email.present?
+ _('This user has an unconfirmed email address (%{email}). You may force a confirmation.') % { email: user.unconfirmed_email }
+ else
+ _('This user has an unconfirmed email address. You may force a confirmation.')
+ end
+
+ modal_attributes = Gitlab::Json.dump({
+ title: s_('AdminUsers|Confirm user %{username}?') % { username: sanitize_name(user.name) },
+ messageHtml: message,
+ actionPrimary: {
+ text: s_('AdminUsers|Confirm user'),
+ attributes: [{ variant: 'info', 'data-qa-selector': 'confirm_user_confirm_button' }]
+ },
+ actionSecondary: {
+ text: _('Cancel'),
+ attributes: [{ variant: 'default' }]
+ }
+ })
- def user_activation_data(user)
{
- path: activate_admin_user_path(user),
+ path: confirm_admin_user_path(user),
method: 'put',
- modal_attributes: {
- title: s_('AdminUsers|Activate user %{username}?') % { username: sanitize_name(user.name) },
- message: s_('AdminUsers|You can always deactivate their account again if needed.'),
- okVariant: 'info',
- okTitle: s_('AdminUsers|Activate')
- }.to_json
+ modal_attributes: modal_attributes,
+ qa_selector: 'confirm_user_button'
}
end
- def user_deactivation_effects
- header = tag.p s_('AdminUsers|Deactivating a user has the following effects:')
-
- list = tag.ul do
- concat tag.li s_('AdminUsers|The user will be logged out')
- concat tag.li s_('AdminUsers|The user will not be able to access git repositories')
- concat tag.li s_('AdminUsers|The user will not be able to access the API')
- concat tag.li s_('AdminUsers|The user will not receive any notifications')
- concat tag.li s_('AdminUsers|The user will not be able to use slash commands')
- concat tag.li s_('AdminUsers|When the user logs back in, their account will reactivate as a fully active account')
- concat tag.li s_('AdminUsers|Personal projects, group and user history will be left intact')
- end
-
- header + list
- end
-
def user_display_name(user)
return s_('UserProfile|Blocked user') if user.blocked?
@@ -256,6 +164,13 @@ module UsersHelper
user.name
end
+ def admin_user_actions_data_attributes(user)
+ {
+ user: Admin::UserEntity.represent(user, { current_user: current_user }).to_json,
+ paths: admin_users_paths.to_json
+ }
+ end
+
private
def admin_users_paths
@@ -270,7 +185,9 @@ module UsersHelper
unlock: unlock_admin_user_path(:id),
delete: admin_user_path(:id),
delete_with_contributions: admin_user_path(:id),
- admin_user: admin_user_path(:id)
+ admin_user: admin_user_path(:id),
+ ban: ban_admin_user_path(:id),
+ unban: unban_admin_user_path(:id)
}
end
diff --git a/app/helpers/whats_new_helper.rb b/app/helpers/whats_new_helper.rb
index 5fca00c5dce..ccccfcb930b 100644
--- a/app/helpers/whats_new_helper.rb
+++ b/app/helpers/whats_new_helper.rb
@@ -32,11 +32,11 @@ module WhatsNewHelper
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.")
+ _("Include new features from all tiers.")
when 'current_tier'
- _("What's new presents new features for your current subscription tier, while hiding new features not available to your subscription tier.")
+ _("Only include features new to your current subscription tier.")
when 'disabled'
- _("What's new is disabled and can no longer be viewed.")
+ _("%{italic_start}What's new%{italic_end} is inactive and cannot be viewed.").html_safe % { italic_start: '<i>'.html_safe, italic_end: '</i>'.html_safe }
end
end
end