summaryrefslogtreecommitdiff
path: root/app/helpers
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-06-18 11:18:50 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-06-18 11:18:50 +0000
commit8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781 (patch)
treea77e7fe7a93de11213032ed4ab1f33a3db51b738 /app/helpers
parent00b35af3db1abfe813a778f643dad221aad51fca (diff)
downloadgitlab-ce-8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781.tar.gz
Add latest changes from gitlab-org/gitlab@13-1-stable-ee
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/active_sessions_helper.rb2
-rw-r--r--app/helpers/application_helper.rb3
-rw-r--r--app/helpers/application_settings_helper.rb14
-rw-r--r--app/helpers/auto_devops_helper.rb2
-rw-r--r--app/helpers/clusters_helper.rb24
-rw-r--r--app/helpers/environments_helper.rb15
-rw-r--r--app/helpers/events_helper.rb2
-rw-r--r--app/helpers/gitlab_routing_helper.rb29
-rw-r--r--app/helpers/issuables_helper.rb5
-rw-r--r--app/helpers/issues_helper.rb39
-rw-r--r--app/helpers/markup_helper.rb6
-rw-r--r--app/helpers/namespaces_helper.rb41
-rw-r--r--app/helpers/notes_helper.rb23
-rw-r--r--app/helpers/notifications_helper.rb2
-rw-r--r--app/helpers/numbers_helper.rb5
-rw-r--r--app/helpers/page_layout_helper.rb10
-rw-r--r--app/helpers/projects/alert_management_helper.rb2
-rw-r--r--app/helpers/projects_helper.rb51
-rw-r--r--app/helpers/search_helper.rb107
-rw-r--r--app/helpers/services_helper.rb22
-rw-r--r--app/helpers/subscribable_banner_helper.rb9
-rw-r--r--app/helpers/timeboxes_helper.rb (renamed from app/helpers/milestones_helper.rb)39
-rw-r--r--app/helpers/timeboxes_routing_helper.rb (renamed from app/helpers/milestones_routing_helper.rb)4
-rw-r--r--app/helpers/todos_helper.rb14
-rw-r--r--app/helpers/visibility_level_helper.rb11
-rw-r--r--app/helpers/wiki_helper.rb51
26 files changed, 292 insertions, 240 deletions
diff --git a/app/helpers/active_sessions_helper.rb b/app/helpers/active_sessions_helper.rb
index 84aa1160f12..8fb23f99cb3 100644
--- a/app/helpers/active_sessions_helper.rb
+++ b/app/helpers/active_sessions_helper.rb
@@ -20,6 +20,6 @@ module ActiveSessionsHelper
'monitor-o'
end
- sprite_icon(icon_name, size: 16, css_class: 'prepend-top-2')
+ sprite_icon(icon_name, size: 16, css_class: 'gl-mt-2')
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 2df33073a89..bdfdf5a69b3 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -103,7 +103,7 @@ module ApplicationHelper
page: body_data_page,
page_type_id: controller.params[:id],
find_file: find_file_path,
- group: "#{@group&.path}"
+ group: @group&.path
}.merge(project_data)
end
@@ -113,6 +113,7 @@ module ApplicationHelper
{
project_id: @project.id,
project: @project.path,
+ group: @project.group&.path,
namespace_id: @project.namespace&.id
}
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index b9f0e3582df..e709d15a946 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -26,6 +26,17 @@ module ApplicationSettingsHelper
end
end
+ def storage_weights
+ ApplicationSetting.repository_storages_weighted_attributes.map do |attribute|
+ storage = attribute.to_s.delete_prefix('repository_storages_weighted_')
+ {
+ name: attribute,
+ label: storage,
+ value: @application_setting.repository_storages_weighted[storage] || 0
+ }
+ end
+ end
+
def all_protocols_enabled?
Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
end
@@ -228,6 +239,7 @@ module ApplicationSettingsHelper
:import_sources,
:max_artifacts_size,
:max_attachment_size,
+ :max_import_size,
:max_pages_size,
:metrics_method_call_threshold,
:minimum_password_length,
@@ -261,6 +273,8 @@ module ApplicationSettingsHelper
:sourcegraph_enabled,
:sourcegraph_url,
:sourcegraph_public_only,
+ :spam_check_endpoint_enabled,
+ :spam_check_endpoint_url,
:terminal_max_session_time,
:terms,
:throttle_authenticated_api_enabled,
diff --git a/app/helpers/auto_devops_helper.rb b/app/helpers/auto_devops_helper.rb
index 0f0d5350df6..0f14680607e 100644
--- a/app/helpers/auto_devops_helper.rb
+++ b/app/helpers/auto_devops_helper.rb
@@ -2,7 +2,7 @@
module AutoDevopsHelper
def show_auto_devops_callout?(project)
- Feature.get(:auto_devops_banner_disabled).off? &&
+ Feature.disabled?(:auto_devops_banner_disabled) &&
show_callout?('auto_devops_settings_dismissed') &&
can?(current_user, :admin_pipeline, project) &&
project.has_auto_devops_implicitly_disabled? &&
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index 39aaf242231..1204f882707 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -17,15 +17,23 @@ module ClustersHelper
end
end
+ def js_clusters_list_data(path = nil)
+ {
+ endpoint: path,
+ img_tags: {
+ aws: { path: image_path('illustrations/logos/amazon_eks.svg'), text: s_('ClusterIntegration|Amazon EKS') },
+ default: { path: image_path('illustrations/logos/kubernetes.svg'), text: _('Kubernetes Cluster') },
+ gcp: { path: image_path('illustrations/logos/google_gke.svg'), text: s_('ClusterIntegration|Google GKE') }
+ }
+ }
+ end
+
+ # This method is depreciated and will be removed when associated HAML files are moved to JavaScript
def provider_icon(provider = nil)
- case provider
- when 'aws'
- image_tag 'illustrations/logos/amazon_eks.svg', alt: s_('ClusterIntegration|Amazon EKS'), class: 'gl-h-full'
- when 'gcp'
- image_tag 'illustrations/logos/google_gke.svg', alt: s_('ClusterIntegration|Google GKE'), class: 'gl-h-full'
- else
- image_tag 'illustrations/logos/kubernetes.svg', alt: _('Kubernetes Cluster'), class: 'gl-h-full'
- end
+ img_data = js_clusters_list_data.dig(:img_tags, provider&.to_sym) ||
+ js_clusters_list_data.dig(:img_tags, :default)
+
+ image_tag img_data[:path], alt: img_data[:text], class: 'gl-h-full'
end
def render_gcp_signup_offer
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index e7b561af3da..41a255434af 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -60,7 +60,8 @@ module EnvironmentsHelper
'custom-metrics-path' => project_prometheus_metrics_path(project),
'validate-query-path' => validate_query_project_prometheus_metrics_path(project),
'custom-metrics-available' => "#{custom_metrics_available?(project)}",
- 'prometheus-alerts-available' => "#{can?(current_user, :read_prometheus_alerts, project)}"
+ 'prometheus-alerts-available' => "#{can?(current_user, :read_prometheus_alerts, project)}",
+ 'dashboard-timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase
}
end
@@ -68,10 +69,11 @@ module EnvironmentsHelper
return {} unless environment
{
- 'current-environment-name' => environment.name,
- 'has-metrics' => "#{environment.has_metrics?}",
- 'prometheus-status' => "#{environment.prometheus_status}",
- 'environment-state' => "#{environment.state}"
+ 'metrics-dashboard-base-path' => environment_metrics_path(environment),
+ 'current-environment-name' => environment.name,
+ 'has-metrics' => "#{environment.has_metrics?}",
+ 'prometheus-status' => "#{environment.prometheus_status}",
+ 'environment-state' => "#{environment.state}"
}
end
@@ -94,7 +96,8 @@ module EnvironmentsHelper
'empty-loading-svg-path' => image_path('illustrations/monitoring/loading.svg'),
'empty-no-data-svg-path' => image_path('illustrations/monitoring/no_data.svg'),
'empty-no-data-small-svg-path' => image_path('illustrations/chart-empty-state-small.svg'),
- 'empty-unable-to-connect-svg-path' => image_path('illustrations/monitoring/unable_to_connect.svg')
+ 'empty-unable-to-connect-svg-path' => image_path('illustrations/monitoring/unable_to_connect.svg'),
+ 'custom-dashboard-base-path' => Metrics::Dashboard::CustomDashboardService::DASHBOARD_ROOT
}
end
end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index e93aeba6dfd..c1f343edd10 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -188,7 +188,7 @@ module EventsHelper
end
def event_wiki_page_target_url(event)
- project_wiki_url(event.project, event.target.canonical_slug)
+ project_wiki_url(event.project, event.target&.canonical_slug || Wiki::HOMEPAGE)
end
def event_note_title_html(event)
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index 4474534045b..8a9380f4771 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -162,8 +162,8 @@ module GitlabRoutingHelper
# 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)
- expose_fast_artifacts_path(project, job, :download)
+ 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)
@@ -176,8 +176,13 @@ module GitlabRoutingHelper
expose_fast_artifacts_path(project, job, :browse)
end
- def expose_fast_artifacts_path(project, job, action)
+ 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
@@ -240,6 +245,14 @@ module GitlabRoutingHelper
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)
@@ -298,6 +311,16 @@ module GitlabRoutingHelper
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
+
private
def snippet_query_params(snippet, *args)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 1ce99652463..a848c814742 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -205,9 +205,9 @@ module IssuablesHelper
author_output
end
- output << content_tag(:span, (issuable_first_contribution_icon if issuable.first_contribution?), class: 'has-tooltip prepend-left-4', title: _('1st contribution!'))
+ output << content_tag(:span, (issuable_first_contribution_icon if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!'))
- output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-sm-none d-md-inline-block prepend-left-8")
+ output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-sm-none d-md-inline-block gl-ml-3")
output << content_tag(:span, (issuable.task_status_short if issuable.tasks?), id: "task_status_short", class: "d-md-none")
output.join.html_safe
@@ -276,6 +276,7 @@ module IssuablesHelper
canUpdate: can?(current_user, :"update_#{issuable.to_ability_name}", issuable),
canDestroy: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable),
issuableRef: issuable.to_reference,
+ issuableStatus: issuable.state,
markdownPreviewPath: preview_markdown_path(parent),
markdownDocsPath: help_page_path('user/markdown'),
lockVersion: issuable.lock_version,
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 39edfeea81e..244b97c7196 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -9,40 +9,6 @@ module IssuesHelper
classes.join(' ')
end
- def url_for_issue(issue_iid, project = @project, options = {})
- return '' if project.nil?
-
- url =
- if options[:internal]
- url_for_internal_issue(issue_iid, project, options)
- else
- url_for_tracker_issue(issue_iid, project, options)
- end
-
- # Ensure we return a valid URL to prevent possible XSS.
- URI.parse(url).to_s
- rescue URI::InvalidURIError
- ''
- end
-
- def url_for_tracker_issue(issue_iid, project, options)
- if options[:only_path]
- project.issues_tracker.issue_path(issue_iid)
- else
- project.issues_tracker.issue_url(issue_iid)
- end
- end
-
- def url_for_internal_issue(issue_iid, project = @project, options = {})
- helpers = Gitlab::Routing.url_helpers
-
- if options[:only_path]
- helpers.namespace_project_issue_path(namespace_id: project.namespace, project_id: project, id: issue_iid)
- else
- helpers.namespace_project_issue_url(namespace_id: project.namespace, project_id: project, id: issue_iid)
- end
- end
-
def status_box_class(item)
if item.try(:expired?)
'status-box-expired'
@@ -168,11 +134,6 @@ module IssuesHelper
def show_moved_service_desk_issue_warning?(issue)
false
end
-
- # Required for Banzai::Filter::IssueReferenceFilter
- module_function :url_for_issue
- module_function :url_for_internal_issue
- module_function :url_for_tracker_issue
end
IssuesHelper.prepend_if_ee('EE::IssuesHelper')
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index 4f66356c27e..7ab2b33de8c 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -129,8 +129,8 @@ module MarkupHelper
context.merge!(
pipeline: :wiki,
project: @project,
- project_wiki: @project_wiki,
- repository: @project_wiki.repository,
+ wiki: @wiki,
+ repository: @wiki.repository,
page_slug: wiki_page.slug,
issuable_state_filter_enabled: true
)
@@ -300,7 +300,7 @@ module MarkupHelper
# RepositoryLinkFilter and UploadLinkFilter
commit: @commit,
- project_wiki: @project_wiki,
+ wiki: @wiki,
ref: @ref,
requested_path: @path
)
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index 228dc2cc27f..b9f8d81bc4e 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -56,6 +56,45 @@ module NamespacesHelper
namespaces_options(selected, options)
end
+ def namespace_storage_alert(namespace)
+ return {} if current_user.nil?
+
+ payload = Namespaces::CheckStorageSizeService.new(namespace, current_user).execute.payload
+
+ return {} if payload.empty?
+
+ alert_level = payload[:alert_level]
+ root_namespace = payload[:root_namespace]
+
+ return {} if cookies["hide_storage_limit_alert_#{root_namespace.id}_#{alert_level}"] == 'true'
+
+ payload
+ end
+
+ def namespace_storage_alert_style(alert_level)
+ if alert_level == :error || alert_level == :alert
+ 'danger'
+ else
+ alert_level.to_s
+ end
+ end
+
+ def namespace_storage_alert_icon(alert_level)
+ if alert_level == :error || alert_level == :alert
+ 'error'
+ elsif alert_level == :info
+ 'information-o'
+ else
+ alert_level.to_s
+ end
+ end
+
+ def namespace_storage_usage_link(namespace)
+ # The usage quota page is only available in EE. This will be changed in
+ # the future, see https://gitlab.com/gitlab-org/gitlab/-/issues/220042.
+ nil
+ end
+
private
# Many importers create a temporary Group, so use the real
@@ -89,4 +128,4 @@ module NamespacesHelper
end
end
-NamespacesHelper.include_if_ee('EE::NamespacesHelper')
+NamespacesHelper.prepend_if_ee('EE::NamespacesHelper')
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index acf9f8c5b5b..782f1d3e759 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -3,6 +3,13 @@
module NotesHelper
MAX_PRERENDERED_NOTES = 10
+ def note_target_title(note)
+ # The design title is already present in `Event#note_target_reference`.
+ return if note.nil? || note.for_design?
+
+ note.title
+ end
+
def note_target_fields(note)
if note.noteable
hidden_field_tag(:target_type, note.noteable.class.name.underscore) +
@@ -54,8 +61,8 @@ module NotesHelper
class: 'add-diff-note js-add-diff-note-button',
type: 'submit', name: 'button',
data: diff_view_line_data(line_code, position, line_type),
- title: 'Add a comment to this line' do
- icon('comment-o')
+ title: _('Add a comment to this line') do
+ sprite_icon('comment', size: 12)
end
end
@@ -162,7 +169,7 @@ module NotesHelper
end
def notes_data(issuable)
- {
+ data = {
discussionsPath: discussions_path(issuable),
registerPath: new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'),
newSessionPath: new_session_path(:user, redirect_to_referer: 'yes'),
@@ -174,6 +181,16 @@ module NotesHelper
prerenderedNotesCount: issuable.capped_notes_count(MAX_PRERENDERED_NOTES),
lastFetchedAt: Time.now.to_i
}
+
+ if issuable.is_a?(MergeRequest)
+ data.merge!(
+ draftsPath: project_merge_request_drafts_path(@project, issuable),
+ draftsPublishPath: publish_project_merge_request_drafts_path(@project, issuable),
+ draftsDiscardPath: discard_project_merge_request_drafts_path(@project, issuable)
+ )
+ end
+
+ data
end
def discussion_resolved_intro(discussion)
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 8fd277564df..68dfd008921 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -122,6 +122,6 @@ module NotificationsHelper
end
def notification_event_disabled?(event)
- event == :fixed_pipeline && Feature.disabled?(:ci_pipeline_fixed_notifications)
+ event == :fixed_pipeline && !Gitlab::Ci::Features.pipeline_fixed_notifications?
end
end
diff --git a/app/helpers/numbers_helper.rb b/app/helpers/numbers_helper.rb
index 3c0b11c4d32..38d3f90dd55 100644
--- a/app/helpers/numbers_helper.rb
+++ b/app/helpers/numbers_helper.rb
@@ -1,15 +1,14 @@
# frozen_string_literal: true
module NumbersHelper
- # rubocop: disable CodeReuse/ActiveRecord
def limited_counter_with_delimiter(resource, **options)
limit = options.fetch(:limit, 1000).to_i
- count = resource.limit(limit + 1).count(:all)
+ count = resource.page.total_count_with_limit(:all, limit: limit)
+
if count > limit
number_with_delimiter(count - 1, options) + '+'
else
number_with_delimiter(count, options)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 46e2c9ce56e..a44760e85ca 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -104,6 +104,16 @@ module PageLayoutHelper
end
end
+ # This helper ensures there is always a default `Gitlab::SearchContext` available
+ # to all controller that use the application layout.
+ def search_context
+ strong_memoize(:search_context) do
+ next super if defined?(super)
+
+ Gitlab::SearchContext::Builder.new(controller.view_context).build!
+ end
+ end
+
def fluid_layout
current_user && current_user.layout == "fluid"
end
diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb
index af86ef715c2..bc585899591 100644
--- a/app/helpers/projects/alert_management_helper.rb
+++ b/app/helpers/projects/alert_management_helper.rb
@@ -15,7 +15,7 @@ module Projects::AlertManagementHelper
{
'alert-id' => alert_id,
'project-path' => project.full_path,
- 'new-issue-path' => new_project_issue_path(project)
+ 'project-issues-path' => project_issues_path(project)
}
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index d743ea6aeea..bda9a69d71f 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -284,8 +284,8 @@ module ProjectsHelper
"xcode://clone?repo=#{CGI.escape(default_url_to_repo(project))}"
end
- def link_to_bfg
- link_to 'BFG', 'https://rtyley.github.io/bfg-repo-cleaner/', target: '_blank', rel: 'noopener noreferrer'
+ def link_to_filter_repo
+ link_to 'git filter-repo', 'https://github.com/newren/git-filter-repo', target: '_blank', rel: 'noopener noreferrer'
end
def explore_projects_tab?
@@ -367,6 +367,10 @@ module ProjectsHelper
@project.metrics_setting_external_dashboard_url
end
+ def metrics_dashboard_timezone
+ @project.metrics_setting_dashboard_timezone
+ end
+
def grafana_integration_url
@project.grafana_integration&.grafana_url
end
@@ -410,7 +414,7 @@ module ProjectsHelper
nav_tabs << :pipelines
end
- if can?(current_user, :read_environment, project) || can?(current_user, :read_cluster, project)
+ if can_view_operations_tab?(current_user, project)
nav_tabs << :operations
end
@@ -438,22 +442,29 @@ module ProjectsHelper
def tab_ability_map
{
- environments: :read_environment,
- milestones: :read_milestone,
- snippets: :read_snippet,
- settings: :admin_project,
- builds: :read_build,
- clusters: :read_cluster,
- serverless: :read_cluster,
- error_tracking: :read_sentry_issue,
- alert_management: :read_alert_management_alert,
- labels: :read_label,
- issues: :read_issue,
- project_members: :read_project_member,
- wiki: :read_wiki
+ environments: :read_environment,
+ metrics_dashboards: :metrics_dashboard,
+ milestones: :read_milestone,
+ snippets: :read_snippet,
+ settings: :admin_project,
+ builds: :read_build,
+ clusters: :read_cluster,
+ serverless: :read_cluster,
+ error_tracking: :read_sentry_issue,
+ alert_management: :read_alert_management_alert,
+ labels: :read_label,
+ issues: :read_issue,
+ project_members: :read_project_member,
+ wiki: :read_wiki
}
end
+ def can_view_operations_tab?(current_user, project)
+ [:read_environment, :read_cluster, :metrics_dashboard].any? do |ability|
+ can?(current_user, ability, project)
+ end
+ end
+
def search_tab_ability_map
@search_tab_ability_map ||= tab_ability_map.merge(
blobs: :download_code,
@@ -533,11 +544,6 @@ module ProjectsHelper
end
end
- def project_wiki_path_with_version(proj, page, version, is_newest)
- url_params = is_newest ? {} : { version_id: version }
- project_wiki_path(proj, page, url_params)
- end
-
def project_status_css_class(status)
case status
when "started"
@@ -670,7 +676,6 @@ module ProjectsHelper
def sidebar_settings_paths
%w[
projects#edit
- project_members#index
integrations#show
services#edit
hooks#index
@@ -729,7 +734,7 @@ module ProjectsHelper
end
def native_code_navigation_enabled?(project)
- Feature.enabled?(:code_navigation, project)
+ Feature.enabled?(:code_navigation, project, default_enabled: true)
end
def show_visibility_confirm_modal?(project)
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 5ad65c59a2e..4e3b6aad8cc 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -3,28 +3,6 @@
module SearchHelper
SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets].freeze
- def search_autocomplete_opts(term)
- return unless current_user
-
- resources_results = [
- groups_autocomplete(term),
- projects_autocomplete(term)
- ].flatten
-
- search_pattern = Regexp.new(Regexp.escape(term), "i")
-
- generic_results = project_autocomplete + default_autocomplete + help_autocomplete
- generic_results.concat(default_autocomplete_admin) if current_user.admin?
- generic_results.select! { |result| result[:label] =~ search_pattern }
-
- [
- resources_results,
- generic_results
- ].flatten.uniq do |item|
- item[:label]
- end
- end
-
def search_entries_info(collection, scope, term)
return if collection.to_a.empty?
@@ -95,91 +73,6 @@ module SearchHelper
private
- # Autocomplete results for various settings pages
- def default_autocomplete
- [
- { category: "Settings", label: _("User settings"), url: profile_path },
- { category: "Settings", label: _("SSH Keys"), url: profile_keys_path },
- { category: "Settings", label: _("Dashboard"), url: root_path }
- ]
- end
-
- # Autocomplete results for settings pages, for admins
- def default_autocomplete_admin
- [
- { category: "Settings", label: _("Admin Section"), url: admin_root_path }
- ]
- end
-
- # Autocomplete results for internal help pages
- def help_autocomplete
- [
- { category: "Help", label: _("API Help"), url: help_page_path("api/README") },
- { 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: _("System Hooks Help"), url: help_page_path("system_hooks/system_hooks") },
- { category: "Help", label: _("Webhooks Help"), url: help_page_path("user/project/integrations/webhooks") },
- { category: "Help", label: _("Workflow Help"), url: help_page_path("workflow/README") }
- ]
- end
-
- # Autocomplete results for the current project, if it's defined
- def project_autocomplete
- if @project && @project.repository.root_ref
- ref = @ref || @project.repository.root_ref
-
- [
- { category: "In this project", label: _("Files"), url: project_tree_path(@project, ref) },
- { category: "In this project", label: _("Commits"), url: project_commits_path(@project, ref) },
- { category: "In this project", label: _("Network"), url: project_network_path(@project, ref) },
- { category: "In this project", label: _("Graph"), url: project_graph_path(@project, ref) },
- { category: "In this project", label: _("Issues"), url: project_issues_path(@project) },
- { category: "In this project", label: _("Merge Requests"), url: project_merge_requests_path(@project) },
- { category: "In this project", label: _("Milestones"), url: project_milestones_path(@project) },
- { category: "In this project", label: _("Snippets"), url: project_snippets_path(@project) },
- { category: "In this project", label: _("Members"), url: project_project_members_path(@project) },
- { category: "In this project", label: _("Wiki"), url: project_wikis_path(@project) }
- ]
- else
- []
- end
- end
-
- # Autocomplete results for the current user's groups
- # rubocop: disable CodeReuse/ActiveRecord
- def groups_autocomplete(term, limit = 5)
- current_user.authorized_groups.order_id_desc.search(term).limit(limit).map do |group|
- {
- category: "Groups",
- id: group.id,
- label: "#{search_result_sanitize(group.full_name)}",
- url: group_path(group),
- avatar_url: group.avatar_url || ''
- }
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # Autocomplete results for the current user's projects
- # rubocop: disable CodeReuse/ActiveRecord
- def projects_autocomplete(term, limit = 5)
- current_user.authorized_projects.order_id_desc.search_by_title(term)
- .sorted_by_stars_desc.non_archived.limit(limit).map do |p|
- {
- category: "Projects",
- id: p.id,
- value: "#{search_result_sanitize(p.name)}",
- label: "#{search_result_sanitize(p.full_name)}",
- url: project_path(p),
- avatar_url: p.avatar_url || ''
- }
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
def search_result_sanitize(str)
Sanitize.clean(str)
end
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index b13cc93436f..fe839b92ba6 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -98,6 +98,28 @@ module ServicesHelper
end
end
+ def integration_form_refactor?
+ Feature.enabled?(:integration_form_refactor, @project)
+ end
+
+ def trigger_events_for_service
+ return [] unless integration_form_refactor?
+
+ ServiceEventSerializer.new(service: @service).represent(@service.configurable_events).to_json
+ end
+
+ def fields_for_service
+ return [] unless integration_form_refactor?
+
+ ServiceFieldSerializer.new(service: @service).represent(@service.global_fields).to_json
+ end
+
+ def show_service_trigger_events?
+ return false if @service.is_a?(JiraService) || integration_form_refactor?
+
+ @service.configurable_events.present?
+ end
+
extend self
end
diff --git a/app/helpers/subscribable_banner_helper.rb b/app/helpers/subscribable_banner_helper.rb
new file mode 100644
index 00000000000..c9d4370f8ad
--- /dev/null
+++ b/app/helpers/subscribable_banner_helper.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module SubscribableBannerHelper
+ # Overridden in EE
+ def display_subscription_banner!
+ end
+end
+
+SubscribableBannerHelper.prepend_if_ee('EE::SubscribableBannerHelper')
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/timeboxes_helper.rb
index df1ee54c5ac..0bffdba7349 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/timeboxes_helper.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module MilestonesHelper
+module TimeboxesHelper
include EntityDateHelper
include Gitlab::Utils::StrongMemoize
@@ -209,30 +209,27 @@ module MilestonesHelper
end
end
- def milestone_date_range(milestone)
- if milestone.start_date && milestone.due_date
- "#{milestone.start_date.to_s(:medium)}–#{milestone.due_date.to_s(:medium)}"
- elsif milestone.due_date
- if milestone.due_date.past?
- _("expired on %{milestone_due_date}") % { milestone_due_date: milestone.due_date.strftime('%b %-d, %Y') }
+ def timebox_date_range(timebox)
+ if timebox.start_date && timebox.due_date
+ "#{timebox.start_date.to_s(:medium)}–#{timebox.due_date.to_s(:medium)}"
+ elsif timebox.due_date
+ if timebox.due_date.past?
+ _("expired on %{timebox_due_date}") % { timebox_due_date: timebox.due_date.to_s(:medium) }
else
- _("expires on %{milestone_due_date}") % { milestone_due_date: milestone.due_date.strftime('%b %-d, %Y') }
+ _("expires on %{timebox_due_date}") % { timebox_due_date: timebox.due_date.to_s(:medium) }
end
- elsif milestone.start_date
- if milestone.start_date.past?
- _("started on %{milestone_start_date}") % { milestone_start_date: milestone.start_date.strftime('%b %-d, %Y') }
+ elsif timebox.start_date
+ if timebox.start_date.past?
+ _("started on %{timebox_start_date}") % { timebox_start_date: timebox.start_date.to_s(:medium) }
else
- _("starts on %{milestone_start_date}") % { milestone_start_date: milestone.start_date.strftime('%b %-d, %Y') }
+ _("starts on %{timebox_start_date}") % { timebox_start_date: timebox.start_date.to_s(:medium) }
end
end
end
+ alias_method :milestone_date_range, :timebox_date_range
def milestone_tab_path(milestone, tab)
- if milestone.global_milestone?
- url_for(action: tab, title: milestone.title, format: :json)
- else
- url_for(action: tab, format: :json)
- end
+ url_for(action: tab, format: :json)
end
def update_milestone_path(milestone, params = {})
@@ -246,11 +243,7 @@ module MilestonesHelper
def group_milestone_route(milestone, params = {})
params = nil if params.empty?
- if milestone.legacy_group_milestone?
- group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: params)
- else
- group_milestone_path(milestone.group, milestone.iid, milestone: params)
- end
+ group_milestone_path(milestone.group, milestone.iid, milestone: params)
end
def group_or_project_milestone_path(milestone)
@@ -306,4 +299,4 @@ module MilestonesHelper
end
end
-MilestonesHelper.prepend_if_ee('EE::MilestonesHelper')
+TimeboxesHelper.prepend_if_ee('EE::TimeboxesHelper')
diff --git a/app/helpers/milestones_routing_helper.rb b/app/helpers/timeboxes_routing_helper.rb
index a49b561533a..6fb5a1a3185 100644
--- a/app/helpers/milestones_routing_helper.rb
+++ b/app/helpers/timeboxes_routing_helper.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module MilestonesRoutingHelper
+module TimeboxesRoutingHelper
def milestone_path(milestone, *args)
if milestone.group_milestone?
group_milestone_path(milestone.group, milestone, *args)
@@ -17,3 +17,5 @@ module MilestonesRoutingHelper
end
end
end
+
+TimeboxesRoutingHelper.prepend_if_ee('EE::TimeboxesRoutingHelper')
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index 41f39c7e798..2b4f2f11d1e 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -37,11 +37,12 @@ module TodosHelper
end
def todo_target_title(todo)
- if todo.target
- "\"#{todo.target.title}\""
- else
- ""
- end
+ # Design To Dos' filenames are displayed in `#todo_target_link` (see `Design#to_reference`),
+ # so to avoid displaying duplicate filenames in the To Do list for designs,
+ # we return an empty string here.
+ return "" if todo.target.blank? || todo.for_design?
+
+ "\"#{todo.target.title}\""
end
def todo_parent_path(todo)
@@ -54,6 +55,7 @@ module TodosHelper
def todo_target_type_name(todo)
return _('design') if todo.for_design?
+ return _('alert') if todo.for_alert?
todo.target_type.titleize.downcase
end
@@ -67,6 +69,8 @@ module TodosHelper
project_commit_path(todo.project, todo.target, path_options)
elsif todo.for_design?
todos_design_path(todo, path_options)
+ elsif todo.for_alert?
+ details_project_alert_management_path(todo.project, todo.target)
else
path = [todo.resource_parent, todo.target]
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index d62839cf037..304b58d232a 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -167,6 +167,17 @@ module VisibilityLevelHelper
[requested_level, max_allowed_visibility_level(form_model)].min
end
+ def available_visibility_levels(form_model)
+ Gitlab::VisibilityLevel.values.reject do |level|
+ disallowed_visibility_level?(form_model, level) ||
+ restricted_visibility_levels.include?(level)
+ end
+ end
+
+ def snippets_selected_visibility_level(visibility_levels, selected)
+ visibility_levels.find { |level| level == selected } || visibility_levels.min
+ end
+
def multiple_visibility_levels_restricted?
restricted_visibility_levels.many? # rubocop: disable CodeReuse/ActiveRecord
end
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index dd8fde2a697..3c983606b73 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -22,7 +22,7 @@ module WikiHelper
page_slug_split
.map do |dir_or_page|
current_slug = "#{current_slug}#{dir_or_page}/"
- add_to_breadcrumb_dropdown link_to(WikiPage.unhyphenize(dir_or_page).capitalize, project_wiki_path(@project, current_slug)), location: :after
+ add_to_breadcrumb_dropdown link_to(WikiPage.unhyphenize(dir_or_page).capitalize, wiki_page_path(@wiki, current_slug)), location: :after
end
end
@@ -32,7 +32,7 @@ module WikiHelper
content_tag(:div, class: 'alert alert-danger') do
case error
when WikiPage::PageChangedError
- page_link = link_to s_("WikiPageConflictMessage|the page"), project_wiki_path(@project, @page), target: "_blank"
+ page_link = link_to s_("WikiPageConflictMessage|the page"), wiki_page_path(@wiki, @page), target: "_blank"
concat(
(s_("WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs.") % { page_link: page_link }).html_safe
)
@@ -45,26 +45,63 @@ module WikiHelper
end
def wiki_attachment_upload_url
- expose_url(api_v4_projects_wikis_attachments_path(id: @project.id))
+ expose_url(api_v4_projects_wikis_attachments_path(id: @wiki.container.id))
end
- def wiki_sort_controls(project, sort, direction)
- sort ||= ProjectWiki::TITLE_ORDER
+ def wiki_sort_controls(wiki, sort, direction)
+ sort ||= Wiki::TITLE_ORDER
link_class = 'btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort'
reversed_direction = direction == 'desc' ? 'asc' : 'desc'
icon_class = direction == 'desc' ? 'highest' : 'lowest'
- link_to(project_wikis_pages_path(project, sort: sort, direction: reversed_direction),
+ link_to(wiki_path(wiki, action: :pages, sort: sort, direction: reversed_direction),
type: 'button', class: link_class, title: _('Sort direction')) do
sprite_icon("sort-#{icon_class}", size: 16)
end
end
def wiki_sort_title(key)
- if key == ProjectWiki::CREATED_AT_ORDER
+ if key == Wiki::CREATED_AT_ORDER
s_("Wiki|Created date")
else
s_("Wiki|Title")
end
end
+
+ def wiki_empty_state_messages(wiki)
+ case wiki.container
+ when Project
+ {
+ writable: {
+ title: s_('WikiEmpty|The wiki lets you write documentation for your project'),
+ body: s_("WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on.")
+ },
+ issuable: {
+ title: s_('WikiEmpty|This project has no wiki pages'),
+ body: s_('WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}.')
+ },
+ readonly: {
+ title: s_('WikiEmpty|This project has no wiki pages'),
+ body: s_('WikiEmpty|You must be a project member in order to add wiki pages.')
+ }
+ }
+ when Group
+ {
+ writable: {
+ title: s_('WikiEmpty|The wiki lets you write documentation for your group'),
+ body: s_("WikiEmpty|A wiki is where you can store all the details about your group. This can include why you've created it, its principles, how to use it, and so on.")
+ },
+ issuable: {
+ title: s_('WikiEmpty|This group has no wiki pages'),
+ body: s_('WikiEmptyIssueMessage|You must be a group member in order to add wiki pages. If you have suggestions for how to improve the wiki for this group, consider opening an issue in the %{issues_link}.')
+ },
+ readonly: {
+ title: s_('WikiEmpty|This group has no wiki pages'),
+ body: s_('WikiEmpty|You must be a group member in order to add wiki pages.')
+ }
+ }
+ else
+ raise NotImplementedError, "Unknown wiki container type #{wiki.container.class.name}"
+ end
+ end
end