summaryrefslogtreecommitdiff
path: root/app/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/application_settings_helper.rb43
-rw-r--r--app/helpers/avatars_helper.rb25
-rw-r--r--app/helpers/boards_helper.rb2
-rw-r--r--app/helpers/breadcrumbs_helper.rb8
-rw-r--r--app/helpers/ci_status_helper.rb24
-rw-r--r--app/helpers/compare_helper.rb4
-rw-r--r--app/helpers/diff_helper.rb16
-rw-r--r--app/helpers/events_helper.rb20
-rw-r--r--app/helpers/gitlab_routing_helper.rb6
-rw-r--r--app/helpers/groups_helper.rb9
-rw-r--r--app/helpers/icons_helper.rb4
-rw-r--r--app/helpers/instance_configuration_helper.rb18
-rw-r--r--app/helpers/issuables_helper.rb71
-rw-r--r--app/helpers/lazy_image_tag_helper.rb1
-rw-r--r--app/helpers/markup_helper.rb2
-rw-r--r--app/helpers/merge_requests_helper.rb3
-rw-r--r--app/helpers/nav_helper.rb8
-rw-r--r--app/helpers/notes_helper.rb4
-rw-r--r--app/helpers/numbers_helper.rb11
-rw-r--r--app/helpers/page_layout_helper.rb2
-rw-r--r--app/helpers/preferences_helper.rb3
-rw-r--r--app/helpers/projects_helper.rb53
-rw-r--r--app/helpers/sorting_helper.rb315
-rw-r--r--app/helpers/storage_health_helper.rb5
-rw-r--r--app/helpers/system_note_helper.rb4
26 files changed, 422 insertions, 243 deletions
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 8d02d5de5c3..4754a67450f 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -309,4 +309,8 @@ module ApplicationHelper
def show_new_repo?
cookies["new_repo"] == "true" && body_data_page != 'projects:show'
end
+
+ def locale_path
+ asset_path("locale/#{Gitlab::I18n.locale}/app.js")
+ end
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 7bd34df5c95..cd1ecaadb85 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -108,6 +108,43 @@ module ApplicationSettingsHelper
options_for_select(Sidekiq::Queue.all.map(&:name), @application_setting.sidekiq_throttling_queues)
end
+ def circuitbreaker_failure_count_help_text
+ health_link = link_to(s_('AdminHealthPageLink|health page'), admin_health_check_path)
+ api_link = link_to(s_('CircuitBreakerApiLink|circuitbreaker api'), help_page_path("api/repository_storage_health"))
+ message = _("The number of failures of after which GitLab will completely "\
+ "prevent access to the storage. The number of failures can be "\
+ "reset in the admin interface: %{link_to_health_page} or using "\
+ "the %{api_documentation_link}.")
+ message = message % { link_to_health_page: health_link, api_documentation_link: api_link }
+
+ message.html_safe
+ end
+
+ def circuitbreaker_access_retries_help_text
+ _('The number of attempts GitLab will make to access a storage.')
+ end
+
+ def circuitbreaker_backoff_threshold_help_text
+ _("The number of failures after which GitLab will start temporarily "\
+ "disabling access to a storage shard on a host")
+ end
+
+ def circuitbreaker_failure_wait_time_help_text
+ _("When access to a storage fails. GitLab will prevent access to the "\
+ "storage for the time specified here. This allows the filesystem to "\
+ "recover. Repositories on failing shards are temporarly unavailable")
+ end
+
+ def circuitbreaker_failure_reset_time_help_text
+ _("The time in seconds GitLab will keep failure information. When no "\
+ "failures occur during this time, information about the mount is reset.")
+ end
+
+ def circuitbreaker_storage_timeout_help_text
+ _("The time in seconds GitLab will try to access storage. After this time a "\
+ "timeout error will be raised.")
+ end
+
def visible_attributes
[
:admin_notification_email,
@@ -116,6 +153,12 @@ module ApplicationSettingsHelper
:akismet_api_key,
:akismet_enabled,
:auto_devops_enabled,
+ :circuitbreaker_access_retries,
+ :circuitbreaker_backoff_threshold,
+ :circuitbreaker_failure_count_threshold,
+ :circuitbreaker_failure_reset_time,
+ :circuitbreaker_failure_wait_time,
+ :circuitbreaker_storage_timeout,
:clientside_sentry_dsn,
:clientside_sentry_enabled,
:container_registry_token_expire_delay,
diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb
index a4c226a6aad..be11d453898 100644
--- a/app/helpers/avatars_helper.rb
+++ b/app/helpers/avatars_helper.rb
@@ -13,22 +13,29 @@ module AvatarsHelper
user_name = options[:user].try(:name) || options[:user_name]
avatar_url = options[:url] || avatar_icon(options[:user] || options[:user_email], avatar_size)
has_tooltip = options[:has_tooltip].nil? ? true : options[:has_tooltip]
- data_attributes = {}
+ data_attributes = options[:data] || {}
css_class = %W[avatar s#{avatar_size}].push(*options[:css_class])
if has_tooltip
css_class.push('has-tooltip')
- data_attributes = { container: 'body' }
+ data_attributes[:container] = 'body'
end
- image_tag(
- avatar_url,
+ if options[:lazy]
+ css_class << 'lazy'
+ data_attributes[:src] = avatar_url
+ avatar_url = LazyImageTagHelper.placeholder_image
+ end
+
+ image_options = {
+ alt: "#{user_name}'s avatar",
+ src: avatar_url,
+ data: data_attributes,
class: css_class,
- alt: "#{user_name}'s avatar",
- title: user_name,
- data: data_attributes,
- lazy: true
- )
+ title: user_name
+ }
+
+ tag(:img, image_options)
end
def user_avatar(options = {})
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index 62ac208f16a..7112c6ee470 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -79,6 +79,6 @@ module BoardsHelper
end
def boards_link_text
- _("Board")
+ s_("IssueBoards|Board")
end
end
diff --git a/app/helpers/breadcrumbs_helper.rb b/app/helpers/breadcrumbs_helper.rb
index ee1b7ed083e..e88fe6bcd7e 100644
--- a/app/helpers/breadcrumbs_helper.rb
+++ b/app/helpers/breadcrumbs_helper.rb
@@ -10,11 +10,7 @@ module BreadcrumbsHelper
def breadcrumb_title_link
return @breadcrumb_link if @breadcrumb_link
- if controller.available_action?(:index)
- url_for(action: "index")
- else
- request.path
- end
+ request.path
end
def breadcrumb_title(title)
@@ -25,7 +21,7 @@ module BreadcrumbsHelper
def breadcrumb_list_item(link)
content_tag "li" do
- link + icon("angle-right", class: "breadcrumbs-list-angle")
+ link + sprite_icon("angle-right", size: 8, css_class: "breadcrumbs-list-angle")
end
end
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index 8022547a6ad..4dd573c61f1 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -63,34 +63,34 @@ module CiStatusHelper
def ci_icon_for_status(status)
if detailed_status?(status)
- return custom_icon(status.icon)
+ return sprite_icon(status.icon)
end
icon_name =
case status
when 'success'
- 'icon_status_success'
+ 'status_success'
when 'success_with_warnings'
- 'icon_status_warning'
+ 'status_warning'
when 'failed'
- 'icon_status_failed'
+ 'status_failed'
when 'pending'
- 'icon_status_pending'
+ 'status_pending'
when 'running'
- 'icon_status_running'
+ 'status_running'
when 'play'
- 'icon_play'
+ 'play'
when 'created'
- 'icon_status_created'
+ 'status_created'
when 'skipped'
- 'icon_status_skipped'
+ 'status_skipped'
when 'manual'
- 'icon_status_manual'
+ 'status_manual'
else
- 'icon_status_canceled'
+ 'status_canceled'
end
- custom_icon(icon_name)
+ sprite_icon(icon_name, size: 16)
end
def pipeline_status_cache_key(pipeline_status)
diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb
index 2c28dd81c87..8bf96c0905f 100644
--- a/app/helpers/compare_helper.rb
+++ b/app/helpers/compare_helper.rb
@@ -4,8 +4,8 @@ module CompareHelper
to.present? &&
from != to &&
can?(current_user, :create_merge_request, project) &&
- project.repository.branch_names.include?(from) &&
- project.repository.branch_names.include?(to)
+ project.repository.branch_exists?(from) &&
+ project.repository.branch_exists?(to)
end
def create_mr_path(from = params[:from], to = params[:to], project = @project)
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 28f591a4e22..4e4a66e8a02 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -33,19 +33,21 @@ module DiffHelper
end
def diff_match_line(old_pos, new_pos, text: '', view: :inline, bottom: false)
- content = content_tag :td, text, class: "line_content match #{view == :inline ? '' : view}"
- cls = ['diff-line-num', 'unfold', 'js-unfold']
- cls << 'js-unfold-bottom' if bottom
+ content_line_class = %w[line_content match]
+ content_line_class << 'parallel' if view == :parallel
+
+ line_num_class = %w[diff-line-num unfold js-unfold]
+ line_num_class << 'js-unfold-bottom' if bottom
html = ''
if old_pos
- html << content_tag(:td, '...', class: cls + ['old_line'], data: { linenumber: old_pos })
- html << content unless view == :inline
+ html << content_tag(:td, '...', class: [*line_num_class, 'old_line'], data: { linenumber: old_pos })
+ html << content_tag(:td, text, class: [*content_line_class, 'left-side']) if view == :parallel
end
if new_pos
- html << content_tag(:td, '...', class: cls + ['new_line'], data: { linenumber: new_pos })
- html << content
+ html << content_tag(:td, '...', class: [*line_num_class, 'new_line'], data: { linenumber: new_pos })
+ html << content_tag(:td, text, class: [*content_line_class, ('right-side' if view == :parallel)])
end
html.html_safe
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index b331693c789..fd88e0d794a 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -1,13 +1,15 @@
module EventsHelper
ICON_NAMES_BY_EVENT_TYPE = {
- 'pushed to' => 'icon_commit',
- 'pushed new' => 'icon_commit',
- 'created' => 'icon_status_open',
- 'opened' => 'icon_status_open',
- 'closed' => 'icon_status_closed',
- 'accepted' => 'icon_code_fork',
- 'commented on' => 'icon_comment_o',
- 'deleted' => 'icon_trash_o'
+ 'pushed to' => 'commit',
+ 'pushed new' => 'commit',
+ 'created' => 'status_open',
+ 'opened' => 'status_open',
+ 'closed' => 'status_closed',
+ 'accepted' => 'fork',
+ 'commented on' => 'comment',
+ 'deleted' => 'remove',
+ 'imported' => 'import',
+ 'joined' => 'users'
}.freeze
def link_to_author(event, self_added: false)
@@ -197,7 +199,7 @@ module EventsHelper
def icon_for_event(note)
icon_name = ICON_NAMES_BY_EVENT_TYPE[note]
- custom_icon(icon_name) if icon_name
+ sprite_icon(icon_name) if icon_name
end
def icon_for_profile_event(event)
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index d4a91e533c1..a77aa0ad2cc 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -71,11 +71,13 @@ module GitlabRoutingHelper
project_commit_url(entity.project, entity.sha, *args)
end
- def preview_markdown_path(project, *args)
+ def preview_markdown_path(parent, *args)
+ return group_preview_markdown_path(parent) if parent.is_a?(Group)
+
if @snippet.is_a?(PersonalSnippet)
preview_markdown_snippets_path
else
- preview_markdown_project_path(project, *args)
+ preview_markdown_project_path(parent, *args)
end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 82bceddf1f0..676c1d1988b 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -7,7 +7,12 @@ module GroupsHelper
can?(current_user, :change_share_with_group_lock, group)
end
- def group_icon(group)
+ def group_icon(group, options = {})
+ img_path = group_icon_url(group, options)
+ image_tag img_path, options
+ end
+
+ def group_icon_url(group, options = {})
if group.is_a?(String)
group = Group.find_by_full_path(group)
end
@@ -89,7 +94,7 @@ module GroupsHelper
link_to(group_path(group), class: "group-path #{'breadcrumb-item-text' unless for_dropdown} js-breadcrumb-item-text #{'hidable' if hidable}") do
output =
if (group.try(:avatar_url) || show_avatar) && !Rails.env.test?
- image_tag(group_icon(group), class: "avatar-tile", width: 15, height: 15)
+ group_icon(group, class: "avatar-tile", width: 15, height: 15)
else
""
end
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index 08e6443bd0f..ec779c1c447 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -24,9 +24,9 @@ module IconsHelper
end
def sprite_icon(icon_name, size: nil, css_class: nil)
- css_classes = size ? "s#{size}" : nil
+ css_classes = size ? "s#{size}" : ""
css_classes << " #{css_class}" unless css_class.blank?
- content_tag(:svg, content_tag(:use, "", { "xlink:href" => "#{image_path('icons.svg')}##{icon_name}" } ), class: css_classes)
+ content_tag(:svg, content_tag(:use, "", { "xlink:href" => "#{image_path('icons.svg')}##{icon_name}" } ), class: css_classes.empty? ? nil : css_classes)
end
def audit_icon(names, options = {})
diff --git a/app/helpers/instance_configuration_helper.rb b/app/helpers/instance_configuration_helper.rb
new file mode 100644
index 00000000000..cee319f20bc
--- /dev/null
+++ b/app/helpers/instance_configuration_helper.rb
@@ -0,0 +1,18 @@
+module InstanceConfigurationHelper
+ def instance_configuration_cell_html(value, &block)
+ return '-' unless value.to_s.presence
+
+ block_given? ? yield(value) : value
+ end
+
+ def instance_configuration_host(host)
+ @instance_configuration_host ||= instance_configuration_cell_html(host).capitalize
+ end
+
+ # Value must be in bytes
+ def instance_configuration_human_size_cell(value)
+ instance_configuration_cell_html(value) do |v|
+ number_to_human_size(v, strip_insignificant_zeros: true, significant: false)
+ end
+ end
+end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index df390dd5aab..85407e38532 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -33,15 +33,17 @@ module IssuablesHelper
end
def serialize_issuable(issuable)
- case issuable
- when Issue
- IssueSerializer.new(current_user: current_user, project: issuable.project).represent(issuable).to_json
- when MergeRequest
- MergeRequestSerializer
- .new(current_user: current_user, project: issuable.project)
- .represent(issuable)
- .to_json
- end
+ serializer_klass = case issuable
+ when Issue
+ IssueSerializer
+ when MergeRequest
+ MergeRequestSerializer
+ end
+
+ serializer_klass
+ .new(current_user: current_user, project: issuable.project)
+ .represent(issuable)
+ .to_json
end
def template_dropdown_tag(issuable, &block)
@@ -209,15 +211,13 @@ module IssuablesHelper
def issuable_initial_data(issuable)
data = {
- endpoint: project_issue_path(@project, issuable),
- canUpdate: can?(current_user, :update_issue, issuable),
- canDestroy: can?(current_user, :destroy_issue, issuable),
+ endpoint: issuable_path(issuable),
+ canUpdate: can?(current_user, :"update_#{issuable.to_ability_name}", issuable),
+ canDestroy: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable),
issuableRef: issuable.to_reference,
- markdownPreviewPath: preview_markdown_path(@project),
+ markdownPreviewPath: preview_markdown_path(parent),
markdownDocsPath: help_page_path('user/markdown'),
issuableTemplates: issuable_templates(issuable),
- projectPath: ref_project.path,
- projectNamespace: ref_project.namespace.full_path,
initialTitleHtml: markdown_field(issuable, :title),
initialTitleText: issuable.title,
initialDescriptionHtml: markdown_field(issuable, :description),
@@ -225,6 +225,12 @@ module IssuablesHelper
initialTaskStatus: issuable.task_status
}
+ if parent.is_a?(Group)
+ data[:groupPath] = parent.path
+ else
+ data.merge!(projectPath: ref_project.path, projectNamespace: ref_project.namespace.full_path)
+ end
+
data.merge!(updated_at_by(issuable))
data.to_json
@@ -248,16 +254,20 @@ module IssuablesHelper
Gitlab::IssuablesCountForState.new(finder)[state]
end
- def close_issuable_url(issuable)
- issuable_url(issuable, close_reopen_params(issuable, :close))
+ def close_issuable_path(issuable)
+ issuable_path(issuable, close_reopen_params(issuable, :close))
end
- def reopen_issuable_url(issuable)
- issuable_url(issuable, close_reopen_params(issuable, :reopen))
+ def reopen_issuable_path(issuable)
+ issuable_path(issuable, close_reopen_params(issuable, :reopen))
end
- def close_reopen_issuable_url(issuable, should_inverse = false)
- issuable.closed? ^ should_inverse ? reopen_issuable_url(issuable) : close_issuable_url(issuable)
+ def close_reopen_issuable_path(issuable, should_inverse = false)
+ issuable.closed? ^ should_inverse ? reopen_issuable_path(issuable) : close_issuable_path(issuable)
+ end
+
+ def issuable_path(issuable, *options)
+ polymorphic_path(issuable, *options)
end
def issuable_url(issuable, *options)
@@ -305,20 +315,12 @@ module IssuablesHelper
@issuable_templates ||=
case issuable
when Issue
- issue_template_names
+ ref_project.repository.issue_template_names
when MergeRequest
- merge_request_template_names
+ ref_project.repository.merge_request_template_names
end
end
- def merge_request_template_names
- @merge_request_templates ||= Gitlab::Template::MergeRequestTemplate.dropdown_names(ref_project)
- end
-
- def issue_template_names
- @issue_templates ||= Gitlab::Template::IssueTemplate.dropdown_names(ref_project)
- end
-
def selected_template(issuable)
params[:issuable_template] if issuable_templates(issuable).any? { |template| template[:name] == params[:issuable_template] }
end
@@ -356,7 +358,8 @@ module IssuablesHelper
def issuable_sidebar_options(issuable, can_edit_issuable)
{
- endpoint: "#{issuable_json_path(issuable)}?basic=true",
+ endpoint: "#{issuable_json_path(issuable)}?serializer=sidebar",
+ toggleSubscriptionEndpoint: toggle_subscription_path(issuable),
moveIssueEndpoint: move_namespace_project_issue_path(namespace_id: issuable.project.namespace.to_param, project_id: issuable.project, id: issuable),
projectsAutocompleteEndpoint: autocomplete_projects_path(project_id: @project.id),
editable: can_edit_issuable,
@@ -365,4 +368,8 @@ module IssuablesHelper
fullPath: @project.full_path
}
end
+
+ def parent
+ @project || @group
+ end
end
diff --git a/app/helpers/lazy_image_tag_helper.rb b/app/helpers/lazy_image_tag_helper.rb
index 2c5619ac41b..603b9438e35 100644
--- a/app/helpers/lazy_image_tag_helper.rb
+++ b/app/helpers/lazy_image_tag_helper.rb
@@ -10,6 +10,7 @@ module LazyImageTagHelper
unless options.delete(:lazy) == false
options[:data] ||= {}
options[:data][:src] = path_to_image(source)
+
options[:class] ||= ""
options[:class] << " lazy"
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index 46bced00c72..420622399f3 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -218,7 +218,7 @@ module MarkupHelper
data: data,
title: options[:title],
aria: { label: options[:title] } do
- icon(options[:icon])
+ sprite_icon(options[:icon])
end
end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index c31023f2d9a..5b2c58d193d 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -73,7 +73,8 @@ module MergeRequestsHelper
end
def target_projects(project)
- [project, project.default_merge_request_target].uniq
+ MergeRequestTargetProjectFinder.new(current_user: current_user, source_project: project)
+ .execute
end
def merge_request_button_visibility(merge_request, closed)
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index a23a43c9f43..8ada746b244 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -1,7 +1,7 @@
module NavHelper
def page_with_sidebar_class
class_name = page_gutter_class
- class_name << 'page-with-new-sidebar' if defined?(@left_sidebar) && @left_sidebar
+ class_name << 'page-with-contextual-sidebar' if defined?(@left_sidebar) && @left_sidebar
class_name << 'page-with-icon-sidebar' if collapsed_sidebar? && @left_sidebar
class_name
@@ -19,11 +19,7 @@ module NavHelper
end
elsif current_path?('jobs#show')
%w[page-gutter build-sidebar right-sidebar-expanded]
- elsif current_path?('wikis#show') ||
- current_path?('wikis#edit') ||
- current_path?('wikis#update') ||
- current_path?('wikis#history') ||
- current_path?('wikis#git_access')
+ elsif current_controller?('wikis') && current_action?('show', 'create', 'edit', 'update', 'history', 'git_access')
%w[page-gutter wiki-sidebar right-sidebar-expanded]
else
[]
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index ce028195e51..c219aa3d6a9 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -130,8 +130,12 @@ module NotesHelper
end
def can_create_note?
+ issuable = @issue || @merge_request
+
if @snippet.is_a?(PersonalSnippet)
can?(current_user, :comment_personal_snippet, @snippet)
+ elsif issuable
+ can?(current_user, :create_note, issuable)
else
can?(current_user, :create_note, @project)
end
diff --git a/app/helpers/numbers_helper.rb b/app/helpers/numbers_helper.rb
new file mode 100644
index 00000000000..45bd3606076
--- /dev/null
+++ b/app/helpers/numbers_helper.rb
@@ -0,0 +1,11 @@
+module NumbersHelper
+ def limited_counter_with_delimiter(resource, **options)
+ limit = options.fetch(:limit, 1000).to_i
+ count = resource.limit(limit + 1).count(:all)
+ if count > limit
+ number_with_delimiter(count - 1, options) + '+'
+ else
+ number_with_delimiter(count, options)
+ end
+ end
+end
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 5946c475835..18b9bf214a3 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -9,7 +9,7 @@ module PageLayoutHelper
end
# Segments are seperated by middot
- @page_title.join(" \u00b7 ")
+ @page_title.join(" ยท ")
end
# Define or get a description for the current page
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 0d7347ed30d..8e822ed0ea2 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -36,7 +36,8 @@ module PreferencesHelper
def project_view_choices
[
['Files and Readme (default)', :files],
- ['Activity', :activity]
+ ['Activity', :activity],
+ ['Readme', :readme]
]
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index ddeff490d3a..f48d47953e4 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -15,17 +15,38 @@ module ProjectsHelper
end
def link_to_member_avatar(author, opts = {})
- default_opts = { size: 16 }
+ default_opts = { size: 16, lazy_load: false }
opts = default_opts.merge(opts)
classes = %W[avatar avatar-inline s#{opts[:size]}]
classes << opts[:avatar_class] if opts[:avatar_class]
- image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: classes, alt: '')
+ avatar = avatar_icon(author, opts[:size])
+ src = opts[:lazy_load] ? nil : avatar
+
+ image_tag(src, width: opts[:size], class: classes, alt: '', "data-src" => avatar)
+ end
+
+ def author_content_tag(author, opts = {})
+ default_opts = { author_class: 'author', tooltip: false, by_username: false }
+ opts = default_opts.merge(opts)
+
+ has_tooltip = !opts[:by_username] && opts[:tooltip]
+
+ username = opts[:by_username] ? author.to_reference : author.name
+ name_tag_options = { class: [opts[:author_class]] }
+
+ if has_tooltip
+ name_tag_options[:title] = author.to_reference
+ name_tag_options[:data] = { placement: 'top' }
+ name_tag_options[:class] << 'has-tooltip'
+ end
+
+ content_tag(:span, sanitize(username), name_tag_options)
end
def link_to_member(project, author, opts = {}, &block)
- default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name", tooltip: false }
+ default_opts = { avatar: true, name: true, title: ":name" }
opts = default_opts.merge(opts)
return "(deleted)" unless author
@@ -36,12 +57,7 @@ module ProjectsHelper
author_html << link_to_member_avatar(author, opts) if opts[:avatar]
# Build name span tag
- if opts[:by_username]
- author_html << content_tag(:span, sanitize("@#{author.username}"), class: opts[:author_class]) if opts[:name]
- else
- tooltip_data = { placement: 'top' }
- author_html << content_tag(:span, sanitize(author.name), class: [opts[:author_class], ('has-tooltip' if opts[:tooltip])], title: (author.to_reference if opts[:tooltip]), data: (tooltip_data if opts[:tooltip])) if opts[:name]
- end
+ author_html << author_content_tag(author, opts) if opts[:name]
author_html << capture(&block) if block
@@ -94,7 +110,15 @@ module ProjectsHelper
def remove_fork_project_message(project)
_("You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?") %
- { forked_from_project: @project.forked_from_project.name_with_namespace }
+ { forked_from_project: fork_source_name(project) }
+ end
+
+ def fork_source_name(project)
+ if @project.fork_source
+ @project.fork_source.full_name
+ else
+ @project.fork_network&.deleted_root_project_name
+ end
end
def project_nav_tabs
@@ -124,8 +148,8 @@ module ProjectsHelper
def can_change_visibility_level?(project, current_user)
return false unless can?(current_user, :change_visibility_level, project)
- if project.forked?
- project.forked_from_project.visibility_level > Gitlab::VisibilityLevel::PRIVATE
+ if project.fork_source
+ project.fork_source.visibility_level > Gitlab::VisibilityLevel::PRIVATE
else
true
end
@@ -239,8 +263,8 @@ module ProjectsHelper
end
end
- def has_projects_or_name?(projects, params)
- !!(params[:name] || any_projects?(projects))
+ def show_projects?(projects, params)
+ !!(params[:personal] || params[:name] || any_projects?(projects))
end
private
@@ -290,6 +314,7 @@ module ProjectsHelper
snippets: :read_project_snippet,
settings: :admin_project,
builds: :read_build,
+ clusters: :read_cluster,
labels: :read_label,
issues: :read_issue,
project_members: :read_project_member,
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index c4a73bedbcd..b05eb93b465 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -1,34 +1,38 @@
module SortingHelper
def sort_options_hash
{
- sort_value_name => sort_title_name,
- sort_value_name_desc => sort_title_name_desc,
- sort_value_recently_updated => sort_title_recently_updated,
- sort_value_oldest_updated => sort_title_oldest_updated,
+ sort_value_created_date => sort_title_created_date,
+ sort_value_downvotes => sort_title_downvotes,
+ sort_value_due_date => sort_title_due_date,
+ sort_value_due_date_later => sort_title_due_date_later,
+ sort_value_due_date_soon => sort_title_due_date_soon,
+ sort_value_label_priority => sort_title_label_priority,
+ sort_value_largest_group => sort_title_largest_group,
+ sort_value_largest_repo => sort_title_largest_repo,
+ sort_value_milestone => sort_title_milestone,
+ sort_value_milestone_later => sort_title_milestone_later,
+ sort_value_milestone_soon => sort_title_milestone_soon,
+ sort_value_name => sort_title_name,
+ sort_value_name_desc => sort_title_name_desc,
+ sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_oldest_signin => sort_title_oldest_signin,
+ sort_value_oldest_updated => sort_title_oldest_updated,
sort_value_recently_created => sort_title_recently_created,
- sort_value_oldest_created => sort_title_oldest_created,
- sort_value_milestone_soon => sort_title_milestone_soon,
- sort_value_milestone_later => sort_title_milestone_later,
- sort_value_due_date_soon => sort_title_due_date_soon,
- sort_value_due_date_later => sort_title_due_date_later,
- sort_value_largest_repo => sort_title_largest_repo,
- sort_value_largest_group => sort_title_largest_group,
- sort_value_recently_signin => sort_title_recently_signin,
- sort_value_oldest_signin => sort_title_oldest_signin,
- sort_value_downvotes => sort_title_downvotes,
- sort_value_upvotes => sort_title_upvotes,
- sort_value_priority => sort_title_priority,
- sort_value_label_priority => sort_title_label_priority
+ sort_value_recently_signin => sort_title_recently_signin,
+ sort_value_recently_updated => sort_title_recently_updated,
+ sort_value_popularity => sort_title_popularity,
+ sort_value_priority => sort_title_priority,
+ sort_value_upvotes => sort_title_upvotes
}
end
def projects_sort_options_hash
options = {
- sort_value_name => sort_title_name,
- sort_value_latest_activity => sort_title_latest_activity,
- sort_value_oldest_activity => sort_title_oldest_activity,
- sort_value_recently_created => sort_title_recently_created,
- sort_value_oldest_created => sort_title_oldest_created
+ sort_value_latest_activity => sort_title_latest_activity,
+ sort_value_name => sort_title_name,
+ sort_value_oldest_activity => sort_title_oldest_activity,
+ sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_recently_created => sort_title_recently_created
}
if current_controller?('admin/projects')
@@ -38,162 +42,187 @@ module SortingHelper
options
end
+ def groups_sort_options_hash
+ options = {
+ sort_value_recently_created => sort_title_recently_created,
+ sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_recently_updated => sort_title_recently_updated,
+ sort_value_oldest_updated => sort_title_oldest_updated
+ }
+
+ options
+ end
+
def member_sort_options_hash
{
- sort_value_access_level_asc => sort_title_access_level_asc,
+ 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_oldest_joined => sort_title_oldest_joined,
- sort_value_name => sort_title_name_asc,
- sort_value_name_desc => sort_title_name_desc,
- sort_value_recently_signin => sort_title_recently_signin,
- sort_value_oldest_signin => sort_title_oldest_signin
+ 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 milestone_sort_options_hash
{
- sort_value_name => sort_title_name_asc,
- sort_value_name_desc => sort_title_name_desc,
- sort_value_due_date_soon => sort_title_due_date_soon,
- sort_value_due_date_later => sort_title_due_date_later,
- sort_value_start_date_soon => sort_title_start_date_soon,
- sort_value_start_date_later => sort_title_start_date_later
+ sort_value_name => sort_title_name_asc,
+ sort_value_name_desc => sort_title_name_desc,
+ sort_value_due_date_later => sort_title_due_date_later,
+ sort_value_due_date_soon => sort_title_due_date_soon,
+ sort_value_start_date_later => sort_title_start_date_later,
+ sort_value_start_date_soon => sort_title_start_date_soon
}
end
def branches_sort_options_hash
{
- sort_value_name => sort_title_name,
- sort_value_recently_updated => sort_title_recently_updated,
- sort_value_oldest_updated => sort_title_oldest_updated
+ sort_value_name => sort_title_name,
+ sort_value_oldest_updated => sort_title_oldest_updated,
+ sort_value_recently_updated => sort_title_recently_updated
}
end
def tags_sort_options_hash
{
- sort_value_name => sort_title_name,
- sort_value_recently_updated => sort_title_recently_updated,
- sort_value_oldest_updated => sort_title_oldest_updated
+ sort_value_name => sort_title_name,
+ sort_value_oldest_updated => sort_title_oldest_updated,
+ sort_value_recently_updated => sort_title_recently_updated
}
end
- def sort_title_priority
- s_('SortOptions|Priority')
+ def sortable_item(item, path, sorted_by)
+ link_to item, path, class: sorted_by == item ? 'is-active' : ''
end
- def sort_title_label_priority
- s_('SortOptions|Label priority')
+ # Titles.
+ def sort_title_access_level_asc
+ s_('SortOptions|Access level, ascending')
end
- def sort_title_oldest_updated
- s_('SortOptions|Oldest updated')
+ def sort_title_access_level_desc
+ s_('SortOptions|Access level, descending')
end
- def sort_title_recently_updated
- s_('SortOptions|Last updated')
+ def sort_title_created_date
+ s_('SortOptions|Created date')
end
- def sort_title_oldest_activity
- s_('SortOptions|Oldest updated')
+ def sort_title_downvotes
+ s_('SortOptions|Least popular')
end
- def sort_title_latest_activity
- s_('SortOptions|Last updated')
+ def sort_title_due_date
+ s_('SortOptions|Due date')
end
- def sort_title_oldest_created
- s_('SortOptions|Oldest created')
+ def sort_title_due_date_later
+ s_('SortOptions|Due later')
end
- def sort_title_recently_created
- s_('SortOptions|Last created')
+ def sort_title_due_date_soon
+ s_('SortOptions|Due soon')
end
- def sort_title_milestone_soon
- s_('SortOptions|Milestone due soon')
+ def sort_title_label_priority
+ s_('SortOptions|Label priority')
end
- def sort_title_milestone_later
- s_('SortOptions|Milestone due later')
+ def sort_title_largest_group
+ s_('SortOptions|Largest group')
end
- def sort_title_due_date_soon
- s_('SortOptions|Due soon')
+ def sort_title_largest_repo
+ s_('SortOptions|Largest repository')
end
- def sort_title_due_date_later
- s_('SortOptions|Due later')
+ def sort_title_last_joined
+ s_('SortOptions|Last joined')
end
- def sort_title_start_date_soon
- s_('SortOptions|Start soon')
+ def sort_title_latest_activity
+ s_('SortOptions|Last updated')
end
- def sort_title_start_date_later
- s_('SortOptions|Start later')
+ def sort_title_milestone
+ s_('SortOptions|Milestone')
+ end
+
+ def sort_title_milestone_later
+ s_('SortOptions|Milestone due later')
+ end
+
+ def sort_title_milestone_soon
+ s_('SortOptions|Milestone due soon')
end
def sort_title_name
s_('SortOptions|Name')
end
- def sort_title_largest_repo
- s_('SortOptions|Largest repository')
+ def sort_title_name_asc
+ s_('SortOptions|Name, ascending')
end
- def sort_title_largest_group
- s_('SortOptions|Largest group')
+ def sort_title_name_desc
+ s_('SortOptions|Name, descending')
end
- def sort_title_recently_signin
- s_('SortOptions|Recent sign in')
+ def sort_title_oldest_activity
+ s_('SortOptions|Oldest updated')
end
- def sort_title_oldest_signin
- s_('SortOptions|Oldest sign in')
+ def sort_title_oldest_created
+ s_('SortOptions|Oldest created')
end
- def sort_title_downvotes
- s_('SortOptions|Least popular')
+ def sort_title_oldest_joined
+ s_('SortOptions|Oldest joined')
end
- def sort_title_upvotes
- s_('SortOptions|Most popular')
+ def sort_title_oldest_signin
+ s_('SortOptions|Oldest sign in')
end
- def sort_title_last_joined
- s_('SortOptions|Last joined')
+ def sort_title_oldest_updated
+ s_('SortOptions|Oldest updated')
end
- def sort_title_oldest_joined
- s_('SortOptions|Oldest joined')
+ def sort_title_popularity
+ s_('SortOptions|Popularity')
end
- def sort_title_access_level_asc
- s_('SortOptions|Access level, ascending')
+ def sort_title_priority
+ s_('SortOptions|Priority')
end
- def sort_title_access_level_desc
- s_('SortOptions|Access level, descending')
+ def sort_title_recently_created
+ s_('SortOptions|Last created')
end
- def sort_title_name_asc
- s_('SortOptions|Name, ascending')
+ def sort_title_recently_signin
+ s_('SortOptions|Recent sign in')
end
- def sort_title_name_desc
- s_('SortOptions|Name, descending')
+ def sort_title_recently_updated
+ s_('SortOptions|Last updated')
end
- def sort_value_last_joined
- 'last_joined'
+ def sort_title_start_date_later
+ s_('SortOptions|Start later')
end
- def sort_value_oldest_joined
- 'oldest_joined'
+ def sort_title_start_date_soon
+ s_('SortOptions|Start soon')
end
+ def sort_title_upvotes
+ s_('SortOptions|Most popular')
+ end
+
+ # Values.
def sort_value_access_level_asc
'access_level_asc'
end
@@ -202,88 +231,112 @@ module SortingHelper
'access_level_desc'
end
- def sort_value_name_desc
- 'name_desc'
+ def sort_value_created_date
+ 'created_date'
end
- def sort_value_priority
- 'priority'
+ def sort_value_downvotes
+ 'downvotes_desc'
+ end
+
+ def sort_value_due_date
+ 'due_date'
+ end
+
+ def sort_value_due_date_later
+ 'due_date_desc'
+ end
+
+ def sort_value_due_date_soon
+ 'due_date_asc'
end
def sort_value_label_priority
'label_priority'
end
- def sort_value_oldest_updated
- 'updated_asc'
+ def sort_value_largest_group
+ 'storage_size_desc'
end
- def sort_value_recently_updated
- 'updated_desc'
+ def sort_value_largest_repo
+ 'storage_size_desc'
end
- def sort_value_oldest_activity
- 'latest_activity_asc'
+ def sort_value_last_joined
+ 'last_joined'
end
def sort_value_latest_activity
'latest_activity_desc'
end
- def sort_value_oldest_created
- 'created_asc'
+ def sort_value_milestone
+ 'milestone'
end
- def sort_value_recently_created
- 'created_desc'
+ def sort_value_milestone_later
+ 'milestone_due_desc'
end
def sort_value_milestone_soon
'milestone_due_asc'
end
- def sort_value_milestone_later
- 'milestone_due_desc'
+ def sort_value_name
+ 'name_asc'
end
- def sort_value_due_date_soon
- 'due_date_asc'
+ def sort_value_name_desc
+ 'name_desc'
end
- def sort_value_due_date_later
- 'due_date_desc'
+ def sort_value_oldest_activity
+ 'latest_activity_asc'
end
- def sort_value_start_date_soon
- 'start_date_asc'
+ def sort_value_oldest_created
+ 'created_asc'
end
- def sort_value_start_date_later
- 'start_date_desc'
+ def sort_value_oldest_signin
+ 'oldest_sign_in'
end
- def sort_value_name
- 'name_asc'
+ def sort_value_oldest_joined
+ 'oldest_joined'
end
- def sort_value_largest_repo
- 'storage_size_desc'
+ def sort_value_oldest_updated
+ 'updated_asc'
end
- def sort_value_largest_group
- 'storage_size_desc'
+ def sort_value_popularity
+ 'popularity'
+ end
+
+ def sort_value_priority
+ 'priority'
+ end
+
+ def sort_value_recently_created
+ 'created_desc'
end
def sort_value_recently_signin
'recent_sign_in'
end
- def sort_value_oldest_signin
- 'oldest_sign_in'
+ def sort_value_recently_updated
+ 'updated_desc'
end
- def sort_value_downvotes
- 'downvotes_desc'
+ def sort_value_start_date_later
+ 'start_date_desc'
+ end
+
+ def sort_value_start_date_soon
+ 'start_date_asc'
end
def sort_value_upvotes
diff --git a/app/helpers/storage_health_helper.rb b/app/helpers/storage_health_helper.rb
index 544c9efb845..4d2180f7eee 100644
--- a/app/helpers/storage_health_helper.rb
+++ b/app/helpers/storage_health_helper.rb
@@ -16,17 +16,16 @@ module StorageHealthHelper
def message_for_circuit_breaker(circuit_breaker)
maximum_failures = circuit_breaker.failure_count_threshold
current_failures = circuit_breaker.failure_count
- permanently_broken = circuit_breaker.circuit_broken? && current_failures >= maximum_failures
translation_params = { number_of_failures: current_failures,
maximum_failures: maximum_failures,
number_of_seconds: circuit_breaker.failure_wait_time }
- if permanently_broken
+ if circuit_breaker.circuit_broken?
s_("%{number_of_failures} of %{maximum_failures} failures. GitLab will not "\
"retry automatically. Reset storage information when the problem is "\
"resolved.") % translation_params
- elsif circuit_breaker.circuit_broken?
+ elsif circuit_breaker.backing_off?
_("%{number_of_failures} of %{maximum_failures} failures. GitLab will "\
"block access for %{number_of_seconds} seconds.") % translation_params
else
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index d7eaf6ce24d..00fe67d6ffb 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -19,7 +19,9 @@ module SystemNoteHelper
'discussion' => 'comment',
'moved' => 'arrow-right',
'outdated' => 'pencil',
- 'duplicate' => 'issue-duplicate'
+ 'duplicate' => 'issue-duplicate',
+ 'locked' => 'lock',
+ 'unlocked' => 'lock-open'
}.freeze
def system_note_icon_name(note)