Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
commit43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch)
treedceebdc68925362117480a5d672bcff122fb625b /app/presenters
parent20c84b99005abd1c82101dfeff264ac50d2df211 (diff)
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'app/presenters')
-rw-r--r--app/presenters/README.md12
-rw-r--r--app/presenters/ci/build_presenter.rb4
-rw-r--r--app/presenters/ci/build_runner_presenter.rb6
-rw-r--r--app/presenters/ci/pipeline_presenter.rb1
-rw-r--r--app/presenters/commit_presenter.rb4
-rw-r--r--app/presenters/event_presenter.rb2
-rw-r--r--app/presenters/label_presenter.rb18
-rw-r--r--app/presenters/merge_request_presenter.rb20
-rw-r--r--app/presenters/ml/candidate_details_presenter.rb88
-rw-r--r--app/presenters/ml/candidates_csv_presenter.rb49
-rw-r--r--app/presenters/packages/npm/package_presenter.rb85
-rw-r--r--app/presenters/pages_domain_presenter.rb7
-rw-r--r--app/presenters/project_presenter.rb262
-rw-r--r--app/presenters/search_service_presenter.rb3
-rw-r--r--app/presenters/snippet_blob_presenter.rb8
15 files changed, 332 insertions, 237 deletions
diff --git a/app/presenters/README.md b/app/presenters/README.md
index e2461580107..5b600e8f2b2 100644
--- a/app/presenters/README.md
+++ b/app/presenters/README.md
@@ -165,15 +165,15 @@ however, there is a risk that it accidentally overrides important logic.
For example, [this production incident](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5498)
was caused by [including `ActionView::Helpers::UrlHelper` in a presenter](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69537/diffs#4b581cff00ef3cc9780efd23682af383de302e7d_3_3).
-The `tag` accesor in `Ci::Build` was accidentally overridden by `ActionView::Helpers::TagHelper#tag`,
-and as a conseuqence, a wrong `tag` value was persited into database.
+The `tag` accessor in `Ci::Build` was accidentally overridden by `ActionView::Helpers::TagHelper#tag`,
+and as a consequence, a wrong `tag` value was persisted into database.
-Starting from GitLab 14.4, we validate the presenters (specifically all of the subclasses of `Gitlab::View::Presenter::Delegated`)
+Starting from GitLab 14.4, we [validate](../../lib/gitlab/utils/delegator_override/validator.rb) the presenters (specifically all of the subclasses of `Gitlab::View::Presenter::Delegated`)
that they do not accidentally override core/backend logic. In such case, a pipeline in merge requests fails with an error message,
here is an example:
```plaintext
-We've detected that a presetner is overriding a specific method(s) on a subject model.
+We've detected that a presenter is overriding a specific method(s) on a subject model.
There is a risk that it accidentally modifies the backend/core logic that leads to production incident.
Please follow https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/presenters/README.md#validate-accidental-overrides
to resolve this error with caution.
@@ -193,7 +193,7 @@ Here are the potential solutions:
### How to use the `Gitlab::Utils::DelegatorOverride` validator
-If a presenter class inhertis from `Gitlab::View::Presenter::Delegated`,
+If a presenter class inherits from `Gitlab::View::Presenter::Delegated`,
you should define what object class is presented:
```ruby
@@ -201,7 +201,7 @@ class WebHookLogPresenter < Gitlab::View::Presenter::Delegated
presents ::WebHookLog, as: :web_hook_log # This defines that the presenter presents `WebHookLog` Active Record model.
```
-These presenters are validated not to accidentaly override the methods in the presented object.
+These presenters are validated not to accidentally override the methods in the presented object.
You can run the validation locally with:
```shell
diff --git a/app/presenters/ci/build_presenter.rb b/app/presenters/ci/build_presenter.rb
index 513fcd90cf8..b89e8db334d 100644
--- a/app/presenters/ci/build_presenter.rb
+++ b/app/presenters/ci/build_presenter.rb
@@ -27,6 +27,10 @@ module Ci
scheduled? && scheduled_at && [0, scheduled_at - Time.now].max
end
+ def failure_message
+ callout_failure_message if build.failed?
+ end
+
private
def tooltip_for_badge(status)
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index 9a586a1733f..79c1946f3d2 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -34,9 +34,7 @@ module Ci
def runner_variables
variables
- .sort_and_expand_all(keep_undefined: true,
- expand_file_refs: false,
- expand_raw_refs: false)
+ .sort_and_expand_all(keep_undefined: true, expand_file_refs: false, expand_raw_refs: false)
.to_runner_variables
end
@@ -58,7 +56,7 @@ module Ci
# rubocop: disable CodeReuse/ActiveRecord
def all_dependencies
dependencies = super
- ActiveRecord::Associations::Preloader.new.preload(dependencies, :job_artifacts_archive)
+ ActiveRecord::Associations::Preloader.new(records: dependencies, associations: :job_artifacts_archive).call
dependencies
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index aa0cd476191..8c9ff49b0e7 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -13,7 +13,6 @@ module Ci
config_error: 'The pipeline failed due to an error on the CI/CD configuration file.',
external_validation_failure: 'The external pipeline validation failed.',
user_not_verified: 'The pipeline failed due to the user not being verified',
- activity_limit_exceeded: 'The pipeline activity limit was exceeded.',
size_limit_exceeded: 'The pipeline size limit was exceeded.',
job_activity_limit_exceeded: 'The pipeline job activity limit was exceeded.',
deployments_limit_exceeded: 'The pipeline deployments limit was exceeded.',
diff --git a/app/presenters/commit_presenter.rb b/app/presenters/commit_presenter.rb
index 2cb88179845..2879326ff8a 100644
--- a/app/presenters/commit_presenter.rb
+++ b/app/presenters/commit_presenter.rb
@@ -25,6 +25,10 @@ class CommitPresenter < Gitlab::View::Presenter::Delegated
commit.pipelines.any?
end
+ def tags_for_display
+ commit.referenced_by&.map { |tag_name| Gitlab::Git.ref_name(tag_name) }
+ end
+
def signature_html
return unless commit.has_signature?
diff --git a/app/presenters/event_presenter.rb b/app/presenters/event_presenter.rb
index 2f2fb1aa3ba..a098db7fbbc 100644
--- a/app/presenters/event_presenter.rb
+++ b/app/presenters/event_presenter.rb
@@ -9,7 +9,7 @@ class EventPresenter < Gitlab::View::Presenter::Delegated
@visible_to_user_cache = ActiveSupport::Cache::MemoryStore.new
end
- # Caching `visible_to_user?` method in the presenter beause it might be called multiple times.
+ # Caching `visible_to_user?` method in the presenter because it might be called multiple times.
delegator_override :visible_to_user?
def visible_to_user?(user = nil)
@visible_to_user_cache.fetch(user&.id) { super(user) }
diff --git a/app/presenters/label_presenter.rb b/app/presenters/label_presenter.rb
index e60cdf4088c..56d986a9c23 100644
--- a/app/presenters/label_presenter.rb
+++ b/app/presenters/label_presenter.rb
@@ -27,14 +27,18 @@ class LabelPresenter < Gitlab::View::Presenter::Delegated
def filter_path(type: :issue)
case context_subject
when Group
- send("#{type.to_s.pluralize}_group_path", # rubocop:disable GitlabSecurity/PublicSend
- context_subject,
- label_name: [label.name])
+ send( # rubocop:disable GitlabSecurity/PublicSend
+ "#{type.to_s.pluralize}_group_path",
+ context_subject,
+ label_name: [label.name]
+ )
when Project
- send("namespace_project_#{type.to_s.pluralize}_path", # rubocop:disable GitlabSecurity/PublicSend
- context_subject.namespace,
- context_subject,
- label_name: [label.name])
+ send( # rubocop:disable GitlabSecurity/PublicSend
+ "namespace_project_#{type.to_s.pluralize}_path",
+ context_subject.namespace,
+ context_subject,
+ label_name: [label.name]
+ )
end
end
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 353e0fad6fb..12f4b0496e4 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -57,9 +57,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
notice_now: edit_in_new_fork_notice_now
}
- project_forks_path(merge_request.project,
- namespace_key: current_user.namespace.id,
- continue: continue_params)
+ project_forks_path(merge_request.project, namespace_key: current_user.namespace.id, continue: continue_params)
end
end
@@ -71,9 +69,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
notice_now: edit_in_new_fork_notice_now
}
- project_forks_path(project,
- namespace_key: current_user.namespace.id,
- continue: continue_params)
+ project_forks_path(project, namespace_key: current_user.namespace.id, continue: continue_params)
end
end
@@ -155,12 +151,12 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
def assign_to_closing_issues_count
# rubocop: disable CodeReuse/ServiceClass
- issues = MergeRequests::AssignIssuesService.new(project: project,
- current_user: current_user,
- params: {
- merge_request: merge_request,
- closes_issues: closing_issues
- }).assignable_issues
+ issues = MergeRequests::AssignIssuesService.new(
+ project: project,
+ current_user: current_user,
+ params: { merge_request: merge_request, closes_issues: closing_issues }
+ ).assignable_issues
+
issues.count
# rubocop: enable CodeReuse/ServiceClass
end
diff --git a/app/presenters/ml/candidate_details_presenter.rb b/app/presenters/ml/candidate_details_presenter.rb
new file mode 100644
index 00000000000..58ec2aee471
--- /dev/null
+++ b/app/presenters/ml/candidate_details_presenter.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+module Ml
+ class CandidateDetailsPresenter
+ include Rails.application.routes.url_helpers
+
+ def initialize(candidate)
+ @candidate = candidate
+ end
+
+ def present
+ data = {
+ candidate: {
+ info: {
+ iid: candidate.iid,
+ eid: candidate.eid,
+ path_to_artifact: link_to_artifact,
+ experiment_name: candidate.experiment.name,
+ path_to_experiment: link_to_experiment,
+ path: link_to_details,
+ status: candidate.status,
+ ci_job: job_info
+ },
+ params: candidate.params,
+ metrics: candidate.latest_metrics,
+ metadata: candidate.metadata
+ }
+ }
+
+ Gitlab::Json.generate(data)
+ end
+
+ private
+
+ attr_reader :candidate
+
+ def job_info
+ return unless candidate.from_ci?
+
+ build = candidate.ci_build
+
+ {
+ path: project_job_path(build.project, build),
+ name: build.name,
+ **user_info(build.user) || {},
+ **mr_info(build.pipeline.merge_request) || {}
+ }
+ end
+
+ def user_info(user)
+ return unless user
+
+ {
+ user: {
+ path: user_path(user),
+ username: user.username
+ }
+ }
+ end
+
+ def mr_info(mr)
+ return unless mr
+
+ {
+ merge_request: {
+ path: project_merge_request_path(mr.project, mr),
+ title: mr.title
+ }
+ }
+ end
+
+ def link_to_artifact
+ artifact = candidate.artifact
+
+ return unless artifact.present?
+
+ project_package_path(candidate.project, artifact)
+ end
+
+ def link_to_details
+ project_ml_candidate_path(candidate.project, candidate.iid)
+ end
+
+ def link_to_experiment
+ project_ml_experiment_path(candidate.project, candidate.experiment.iid)
+ end
+ end
+end
diff --git a/app/presenters/ml/candidates_csv_presenter.rb b/app/presenters/ml/candidates_csv_presenter.rb
new file mode 100644
index 00000000000..8e2baf6bd28
--- /dev/null
+++ b/app/presenters/ml/candidates_csv_presenter.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Ml
+ class CandidatesCsvPresenter
+ CANDIDATE_ASSOCIATIONS = [:latest_metrics, :params, :experiment].freeze
+ # This file size limit is mainly to avoid the generation to hog resources from the server. The value is arbitrary
+ # can be update once we have better insight into usage.
+ TARGET_FILESIZE = 2.megabytes
+
+ def initialize(candidates)
+ @candidates = candidates
+ end
+
+ def present
+ CsvBuilder.new(@candidates, headers, CANDIDATE_ASSOCIATIONS).render(TARGET_FILESIZE)
+ end
+
+ private
+
+ def headers
+ metric_names = columns_names(&:metrics)
+ param_names = columns_names(&:params)
+
+ candidate_to_metrics = @candidates.to_h do |candidate|
+ [candidate.id, candidate.latest_metrics.to_h { |m| [m.name, m.value] }]
+ end
+
+ candidate_to_params = @candidates.to_h do |candidate|
+ [candidate.id, candidate.params.to_h { |m| [m.name, m.value] }]
+ end
+
+ {
+ project_id: 'project_id',
+ experiment_iid: ->(c) { c.experiment.iid },
+ candidate_iid: 'internal_id',
+ name: 'name',
+ external_id: 'eid',
+ start_time: 'start_time',
+ end_time: 'end_time',
+ **param_names.index_with { |name| ->(c) { candidate_to_params.dig(c.id, name) } },
+ **metric_names.index_with { |name| ->(c) { candidate_to_metrics.dig(c.id, name) } }
+ }
+ end
+
+ def columns_names(&selector)
+ @candidates.flat_map(&selector).map(&:name).uniq
+ end
+ end
+end
diff --git a/app/presenters/packages/npm/package_presenter.rb b/app/presenters/packages/npm/package_presenter.rb
index 57bdd373309..42f61182ab8 100644
--- a/app/presenters/packages/npm/package_presenter.rb
+++ b/app/presenters/packages/npm/package_presenter.rb
@@ -3,94 +3,25 @@
module Packages
module Npm
class PackagePresenter
- include API::Helpers::RelatedResourcesHelpers
-
- # Allowed fields are those defined in the abbreviated form
- # defined here: https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-version-object
- # except: name, version, dist, dependencies and xDependencies. Those are generated by this presenter.
- PACKAGE_JSON_ALLOWED_FIELDS = %w[deprecated bin directories dist engines _hasShrinkwrap].freeze
-
- attr_reader :name, :packages
+ def initialize(metadata)
+ @metadata = metadata
+ end
- def initialize(name, packages)
- @name = name
- @packages = packages
+ def name
+ metadata[:name]
end
def versions
- package_versions = {}
-
- packages.each_batch do |relation|
- batched_packages = relation.including_dependency_links
- .preload_files
- .preload_npm_metadatum
-
- batched_packages.each do |package|
- package_file = package.installable_package_files.last
-
- next unless package_file
-
- package_versions[package.version] = build_package_version(package, package_file)
- end
- end
-
- package_versions
+ metadata[:versions]
end
def dist_tags
- build_package_tags.tap { |t| t["latest"] ||= sorted_versions.last }
+ metadata[:dist_tags]
end
private
- def build_package_tags
- package_tags.to_h { |tag| [tag.name, tag.package.version] }
- end
-
- def build_package_version(package, package_file)
- abbreviated_package_json(package).merge(
- name: package.name,
- version: package.version,
- dist: {
- shasum: package_file.file_sha1,
- tarball: tarball_url(package, package_file)
- }
- ).tap do |package_version|
- package_version.merge!(build_package_dependencies(package))
- end
- end
-
- def tarball_url(package, package_file)
- expose_url "#{api_v4_projects_path(id: package.project_id)}" \
- "/packages/npm/#{package.name}" \
- "/-/#{package_file.file_name}"
- end
-
- def build_package_dependencies(package)
- dependencies = Hash.new { |h, key| h[key] = {} }
-
- package.dependency_links.each do |dependency_link|
- dependency = dependency_link.dependency
- dependencies[dependency_link.dependency_type][dependency.name] = dependency.version_pattern
- end
-
- dependencies
- end
-
- def sorted_versions
- versions = packages.pluck_versions.compact
- VersionSorter.sort(versions)
- end
-
- def package_tags
- Packages::Tag.for_package_ids(packages.last_of_each_version_ids)
- .preload_package
- end
-
- def abbreviated_package_json(package)
- json = package.npm_metadatum&.package_json || {}
- json.slice(*PACKAGE_JSON_ALLOWED_FIELDS)
- end
+ attr_reader :metadata
end
end
end
diff --git a/app/presenters/pages_domain_presenter.rb b/app/presenters/pages_domain_presenter.rb
index d730608cc27..49322ad6b43 100644
--- a/app/presenters/pages_domain_presenter.rb
+++ b/app/presenters/pages_domain_presenter.rb
@@ -13,4 +13,11 @@ class PagesDomainPresenter < Gitlab::View::Presenter::Delegated
::Gitlab::LetsEncrypt.enabled? && auto_ssl_failed
end
+
+ def user_defined_certificate?
+ persisted? &&
+ certificate.present? &&
+ certificate_user_provided? &&
+ errors[:certificate].blank?
+ end
end
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 392a2fcd390..856eba5aadc 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -99,11 +99,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
def contribution_guide_path
if project && contribution_guide = repository.contribution_guide
- project_blob_path(
- project,
- tree_join(project.default_branch,
- contribution_guide.name)
- )
+ project_blob_path(project, tree_join(project.default_branch, contribution_guide.name))
end
end
@@ -166,14 +162,16 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
def storage_anchor_data
can_show_quota = can?(current_user, :admin_project, project) && !empty_repo?
- AnchorData.new(true,
- statistic_icon('disk') +
- _('%{strong_start}%{human_size}%{strong_end} Project Storage').html_safe % {
- human_size: storage_counter(statistics.storage_size),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- can_show_quota ? project_usage_quotas_path(project) : nil)
+ AnchorData.new(
+ true,
+ statistic_icon('disk') +
+ _('%{strong_start}%{human_size}%{strong_end} Project Storage').html_safe % {
+ human_size: storage_counter(statistics.storage_size),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ can_show_quota ? project_usage_quotas_path(project) : nil
+ )
end
def releases_anchor_data
@@ -182,14 +180,16 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
releases_count = project.releases.count
return if releases_count < 1
- AnchorData.new(true,
- statistic_icon('deployments') +
- n_('%{strong_start}%{release_count}%{strong_end} Release', '%{strong_start}%{release_count}%{strong_end} Releases', releases_count).html_safe % {
- release_count: number_with_delimiter(releases_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- project_releases_path(project))
+ AnchorData.new(
+ true,
+ statistic_icon('rocket-launch') +
+ n_('%{strong_start}%{release_count}%{strong_end} Release', '%{strong_start}%{release_count}%{strong_end} Releases', releases_count).html_safe % {
+ release_count: number_with_delimiter(releases_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ project_releases_path(project)
+ )
end
def environments_anchor_data
@@ -198,67 +198,76 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
environments_count = project.environments.available.count
return if environments_count == 0
- AnchorData.new(true,
- statistic_icon('environment') +
- n_('%{strong_start}%{count}%{strong_end} Environment', '%{strong_start}%{count}%{strong_end} Environments', environments_count).html_safe % {
- count: number_with_delimiter(environments_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- project_environments_path(project))
+ AnchorData.new(
+ true,
+ statistic_icon('environment') +
+ n_('%{strong_start}%{count}%{strong_end} Environment', '%{strong_start}%{count}%{strong_end} Environments', environments_count).html_safe % {
+ count: number_with_delimiter(environments_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ project_environments_path(project)
+ )
end
def commits_anchor_data
- AnchorData.new(true,
- statistic_icon('commit') +
- n_('%{strong_start}%{commit_count}%{strong_end} Commit', '%{strong_start}%{commit_count}%{strong_end} Commits', statistics.commit_count).html_safe % {
- commit_count: number_with_delimiter(statistics.commit_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- empty_repo? ? nil : project_commits_path(project, default_branch_or_main))
+ AnchorData.new(
+ true,
+ statistic_icon('commit') +
+ n_('%{strong_start}%{commit_count}%{strong_end} Commit', '%{strong_start}%{commit_count}%{strong_end} Commits', statistics.commit_count).html_safe % {
+ commit_count: number_with_delimiter(statistics.commit_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ empty_repo? ? nil : project_commits_path(project, default_branch_or_main)
+ )
end
def branches_anchor_data
- AnchorData.new(true,
- statistic_icon('branch') +
- n_('%{strong_start}%{branch_count}%{strong_end} Branch', '%{strong_start}%{branch_count}%{strong_end} Branches', repository.branch_count).html_safe % {
- branch_count: number_with_delimiter(repository.branch_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- empty_repo? ? nil : project_branches_path(project))
+ AnchorData.new(
+ true,
+ statistic_icon('branch') +
+ n_('%{strong_start}%{branch_count}%{strong_end} Branch', '%{strong_start}%{branch_count}%{strong_end} Branches', repository.branch_count).html_safe % {
+ branch_count: number_with_delimiter(repository.branch_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ empty_repo? ? nil : project_branches_path(project)
+ )
end
def tags_anchor_data
- AnchorData.new(true,
- statistic_icon('label') +
- n_('%{strong_start}%{tag_count}%{strong_end} Tag', '%{strong_start}%{tag_count}%{strong_end} Tags', repository.tag_count).html_safe % {
- tag_count: number_with_delimiter(repository.tag_count),
- strong_start: '<strong class="project-stat-value">'.html_safe,
- strong_end: '</strong>'.html_safe
- },
- empty_repo? ? nil : project_tags_path(project))
+ AnchorData.new(
+ true,
+ statistic_icon('label') +
+ n_('%{strong_start}%{tag_count}%{strong_end} Tag', '%{strong_start}%{tag_count}%{strong_end} Tags', repository.tag_count).html_safe % {
+ tag_count: number_with_delimiter(repository.tag_count),
+ strong_start: '<strong class="project-stat-value">'.html_safe,
+ strong_end: '</strong>'.html_safe
+ },
+ empty_repo? ? nil : project_tags_path(project)
+ )
end
def upload_anchor_data
strong_memoize(:upload_anchor_data) do
next unless can_current_user_push_to_default_branch?
- AnchorData.new(false,
- statistic_icon('upload') + _('Upload file'),
- '#modal-upload-blob',
- 'js-upload-file-trigger',
- nil,
- nil,
- {
- 'target_branch' => default_branch_or_main,
- 'original_branch' => default_branch_or_main,
- 'can_push_code' => 'true',
- 'path' => project_create_blob_path(project, default_branch_or_main),
- 'project_path' => project.full_path
- }
- )
+ AnchorData.new(
+ false,
+ statistic_icon('upload') + _('Upload file'),
+ '#modal-upload-blob',
+ 'js-upload-file-trigger',
+ nil,
+ nil,
+ {
+ 'target_branch' => default_branch_or_main,
+ 'original_branch' => default_branch_or_main,
+ 'can_push_code' => 'true',
+ 'path' => project_create_blob_path(project, default_branch_or_main),
+ 'project_path' => project.full_path
+ }
+ )
end
end
@@ -266,37 +275,38 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if can_current_user_push_to_default_branch?
new_file_path = empty_repo? ? ide_edit_path(project, default_branch_or_main) : project_new_blob_path(project, default_branch_or_main)
- AnchorData.new(false,
- statistic_icon + _('New file'),
- new_file_path,
- 'btn-dashed')
+ AnchorData.new(false, statistic_icon + _('New file'), new_file_path, 'btn-dashed')
end
end
def readme_anchor_data
if can_current_user_push_to_default_branch? && readme_path.nil?
- AnchorData.new(false,
- statistic_icon + _('Add README'),
- empty_repo? ? add_readme_ide_path : add_readme_path)
+ AnchorData.new(false, statistic_icon + _('Add README'), empty_repo? ? add_readme_ide_path : add_readme_path)
elsif readme_path
- AnchorData.new(false,
- statistic_icon('doc-text') + _('README'),
- default_view != 'readme' ? readme_path : '#readme',
- 'btn-default',
- 'doc-text')
+ AnchorData.new(
+ false,
+ statistic_icon('doc-text') + _('README'),
+ default_view != 'readme' ? readme_path : '#readme',
+ 'btn-default',
+ 'doc-text'
+ )
end
end
def changelog_anchor_data
if can_current_user_push_to_default_branch? && repository.changelog.blank?
- AnchorData.new(false,
- statistic_icon + _('Add CHANGELOG'),
- empty_repo? ? add_changelog_ide_path : add_changelog_path)
+ AnchorData.new(
+ false,
+ statistic_icon + _('Add CHANGELOG'),
+ empty_repo? ? add_changelog_ide_path : add_changelog_path
+ )
elsif repository.changelog.present?
- AnchorData.new(false,
- statistic_icon('doc-text') + _('CHANGELOG'),
- changelog_path,
- 'btn-default')
+ AnchorData.new(
+ false,
+ statistic_icon('doc-text') + _('CHANGELOG'),
+ changelog_path,
+ 'btn-default'
+ )
end
end
@@ -304,29 +314,37 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
icon = statistic_icon('scale')
if repository.license_blob.present?
- AnchorData.new(false,
- icon + content_tag(:span, license_short_name, class: 'project-stat-value'),
- license_path,
- 'btn-default',
- nil,
- 'license')
+ AnchorData.new(
+ false,
+ icon + content_tag(:span, license_short_name, class: 'project-stat-value'),
+ license_path,
+ 'btn-default',
+ nil,
+ 'license'
+ )
elsif can_current_user_push_to_default_branch?
- AnchorData.new(false,
- content_tag(:span, statistic_icon + _('Add LICENSE'), class: 'add-license-link d-flex'),
- empty_repo? ? add_license_ide_path : add_license_path)
+ AnchorData.new(
+ false,
+ content_tag(:span, statistic_icon + _('Add LICENSE'), class: 'add-license-link d-flex'),
+ empty_repo? ? add_license_ide_path : add_license_path
+ )
end
end
def contribution_guide_anchor_data
if can_current_user_push_to_default_branch? && repository.contribution_guide.blank?
- AnchorData.new(false,
- statistic_icon + _('Add CONTRIBUTING'),
- empty_repo? ? add_contribution_guide_ide_path : add_contribution_guide_path)
+ AnchorData.new(
+ false,
+ statistic_icon + _('Add CONTRIBUTING'),
+ empty_repo? ? add_contribution_guide_ide_path : add_contribution_guide_path
+ )
elsif repository.contribution_guide.present?
- AnchorData.new(false,
- statistic_icon('doc-text') + _('CONTRIBUTING'),
- contribution_guide_path,
- 'btn-default')
+ AnchorData.new(
+ false,
+ statistic_icon('doc-text') + _('CONTRIBUTING'),
+ contribution_guide_path,
+ 'btn-default'
+ )
end
end
@@ -335,35 +353,32 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if current_user && can?(current_user, :admin_pipeline, project) && repository.gitlab_ci_yml.blank? && !show_auto_devops_callout
if auto_devops_enabled?
- AnchorData.new(false,
- statistic_icon('settings') + _('Auto DevOps enabled'),
- project_settings_ci_cd_path(project, anchor: 'autodevops-settings'),
- 'btn-default')
+ AnchorData.new(
+ false,
+ statistic_icon('settings') + _('Auto DevOps enabled'),
+ project_settings_ci_cd_path(project, anchor: 'autodevops-settings'),
+ 'btn-default'
+ )
else
- AnchorData.new(false,
- statistic_icon + _('Enable Auto DevOps'),
- project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
+ AnchorData.new(
+ false,
+ statistic_icon + _('Enable Auto DevOps'),
+ project_settings_ci_cd_path(project, anchor: 'autodevops-settings')
+ )
end
elsif auto_devops_enabled?
- AnchorData.new(false,
- _('Auto DevOps enabled'),
- nil)
+ AnchorData.new(false, _('Auto DevOps enabled'), nil)
end
end
def kubernetes_cluster_anchor_data
if can_instantiate_cluster?
if clusters.empty?
- AnchorData.new(false,
- statistic_icon + _('Add Kubernetes cluster'),
- project_clusters_path(project))
+ AnchorData.new(false, statistic_icon + _('Add Kubernetes cluster'), project_clusters_path(project))
else
cluster_link = clusters.count == 1 ? project_cluster_path(project, clusters.first) : project_clusters_path(project)
- AnchorData.new(false,
- _('Kubernetes'),
- cluster_link,
- 'btn-default')
+ AnchorData.new(false, _('Kubernetes'), cluster_link, 'btn-default')
end
end
end
@@ -372,14 +387,9 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
return unless can_view_pipeline_editor?(project)
if cicd_missing?
- AnchorData.new(false,
- statistic_icon + _('Set up CI/CD'),
- project_ci_pipeline_editor_path(project))
+ AnchorData.new(false, statistic_icon + _('Set up CI/CD'), project_ci_pipeline_editor_path(project))
elsif repository.gitlab_ci_yml.present?
- AnchorData.new(false,
- statistic_icon('doc-text') + _('CI/CD configuration'),
- project_ci_pipeline_editor_path(project),
- 'btn-default')
+ AnchorData.new(false, statistic_icon('doc-text') + _('CI/CD configuration'), project_ci_pipeline_editor_path(project), 'btn-default')
end
end
diff --git a/app/presenters/search_service_presenter.rb b/app/presenters/search_service_presenter.rb
index d7d959217b0..91e67c379c4 100644
--- a/app/presenters/search_service_presenter.rb
+++ b/app/presenters/search_service_presenter.rb
@@ -2,6 +2,7 @@
class SearchServicePresenter < Gitlab::View::Presenter::Delegated
include RendersCommits
+ include RendersProjectsList
presents ::SearchService, as: :search_service
@@ -28,6 +29,8 @@ class SearchServicePresenter < Gitlab::View::Presenter::Delegated
objects.respond_to?(:eager_load) ? objects.eager_load(:status) : objects # rubocop:disable CodeReuse/ActiveRecord
when 'commits'
prepare_commits_for_rendering(objects)
+ when 'projects'
+ prepare_projects_for_rendering(objects)
else
objects
end
diff --git a/app/presenters/snippet_blob_presenter.rb b/app/presenters/snippet_blob_presenter.rb
index 2e5d3ae21d9..84e98e18e32 100644
--- a/app/presenters/snippet_blob_presenter.rb
+++ b/app/presenters/snippet_blob_presenter.rb
@@ -40,9 +40,11 @@ class SnippetBlobPresenter < BlobPresenter
end
def render_rich_partial
- renderer.render("projects/blob/viewers/_#{blob.rich_viewer.partial_name}",
- locals: { viewer: blob.rich_viewer, blob: blob, blob_raw_path: raw_path, blob_raw_url: raw_url, parent_dir_raw_path: raw_directory },
- layout: false)
+ renderer.render(
+ "projects/blob/viewers/_#{blob.rich_viewer.partial_name}",
+ locals: { viewer: blob.rich_viewer, blob: blob, blob_raw_path: raw_path, blob_raw_url: raw_url, parent_dir_raw_path: raw_directory },
+ layout: false
+ )
end
def renderer