diff options
Diffstat (limited to 'app/helpers')
32 files changed, 254 insertions, 173 deletions
diff --git a/app/helpers/analytics/navbar_helper.rb b/app/helpers/analytics/navbar_helper.rb index bc0b5e7c74f..33a5028cdf1 100644 --- a/app/helpers/analytics/navbar_helper.rb +++ b/app/helpers/analytics/navbar_helper.rb @@ -58,7 +58,7 @@ module Analytics return unless project.feature_available?(:builds, current_user) || !project.empty_repo? navbar_sub_item( - title: _('CI / CD'), + title: _('CI/CD'), path: 'pipelines#charts', link: charts_project_pipelines_path(project) ) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 30ae535b06f..085fbfd08da 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -37,13 +37,8 @@ module ApplicationSettingsHelper 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 - } + Gitlab.config.repositories.storages.keys.each_with_object(OpenStruct.new) do |storage, weights| + weights[storage.to_sym] = @application_setting.repository_storages_weighted[storage] || 0 end end @@ -107,15 +102,20 @@ module ApplicationSettingsHelper def oauth_providers_checkboxes button_based_providers.map do |source| disabled = @application_setting.disabled_oauth_sign_in_sources.include?(source.to_s) - css_class = ['btn'] - css_class << 'active' unless disabled - checkbox_name = 'application_setting[enabled_oauth_sign_in_sources][]' name = Gitlab::Auth::OAuth::Provider.label_for(source) - - label_tag(checkbox_name, class: css_class.join(' ')) do - check_box_tag(checkbox_name, source, !disabled, - autocomplete: 'off', - id: name.tr(' ', '_')) + name + checkbox_name = 'application_setting[enabled_oauth_sign_in_sources][]' + checkbox_id = "application_setting_enabled_oauth_sign_in_sources_#{name.parameterize(separator: '_')}" + + content_tag :div, class: 'form-check' do + check_box_tag( + checkbox_name, + source, + !disabled, + autocomplete: 'off', + id: checkbox_id, + class: 'form-check-input' + ) + + label_tag(checkbox_id, name, class: 'form-check-label') end end end @@ -252,6 +252,7 @@ module ApplicationSettingsHelper :housekeeping_incremental_repack_period, :html_emails_enabled, :import_sources, + :in_product_marketing_emails_enabled, :invisible_captcha_enabled, :max_artifacts_size, :max_attachment_size, diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index 24c1d224c89..cacf9c7ad0b 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -1,8 +1,22 @@ # frozen_string_literal: true module AuthHelper - PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq salesforce atlassian_oauth2 openid_connect).freeze + PROVIDERS_WITH_ICONS = %w( + atlassian_oauth2 + authentiq + azure_activedirectory_v2 + azure_oauth2 + bitbucket + facebook + github + gitlab + google_oauth2 + openid_connect + salesforce + twitter + ).freeze LDAP_PROVIDER = /\Aldap/.freeze + TRIAL_REGISTRATION_PROVIDERS = %w(google_oauth2 github).freeze def ldap_enabled? Gitlab::Auth::Ldap::Config.enabled? @@ -113,8 +127,8 @@ module AuthHelper end end - def experiment_enabled_button_based_providers - enabled_button_based_providers & %w(google_oauth2 github).freeze + def trial_enabled_button_based_providers + enabled_button_based_providers & TRIAL_REGISTRATION_PROVIDERS end def button_based_providers_enabled? @@ -125,11 +139,11 @@ module AuthHelper label = label_for_provider(provider) if provider_has_custom_icon?(provider) - image_tag(icon_for_provider(provider), alt: label, title: "Sign in with #{label}") + image_tag(icon_for_provider(provider), alt: label, title: "Sign in with #{label}", class: "gl-button-icon") elsif provider_has_builtin_icon?(provider) file_name = "#{provider.to_s.split('_').first}_#{size}.png" - image_tag("auth_buttons/#{file_name}", alt: label, title: "Sign in with #{label}") + image_tag("auth_buttons/#{file_name}", alt: label, title: "Sign in with #{label}", class: "gl-button-icon") else label end diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb index 5457f96d506..8d22bda279f 100644 --- a/app/helpers/avatars_helper.rb +++ b/app/helpers/avatars_helper.rb @@ -22,11 +22,14 @@ module AvatarsHelper end def avatar_icon_for_email(email = nil, size = nil, scale = 2, only_path: true) - user = User.find_by_any_email(email) - if user - avatar_icon_for_user(user, size, scale, only_path: only_path) + return gravatar_icon(email, size, scale) if email.nil? + + if Feature.enabled?(:avatar_cache_for_email, @current_user, type: :development) + Gitlab::AvatarCache.by_email(email, size, scale, only_path) do + avatar_icon_by_user_email_or_gravatar(email, size, scale, only_path: only_path) + end else - gravatar_icon(email, size, scale) + avatar_icon_by_user_email_or_gravatar(email, size, scale, only_path: only_path) end end @@ -101,19 +104,23 @@ module AvatarsHelper private - def user_avatar_url_for(only_path: true, **options) - return options[:url] if options[:url] - - email = options[:user_email] - user = options.key?(:user) ? options[:user] : User.find_by_any_email(email) + def avatar_icon_by_user_email_or_gravatar(email, size, scale, only_path:) + user = User.find_by_any_email(email) if user - avatar_icon_for_user(user, options[:size], only_path: only_path) + avatar_icon_for_user(user, size, scale, only_path: only_path) else - gravatar_icon(email, options[:size]) + gravatar_icon(email, size, scale) end end + def user_avatar_url_for(only_path: true, **options) + return options[:url] if options[:url] + return avatar_icon_for_user(options[:user], options[:size], only_path: only_path) if options[:user] + + avatar_icon_for_email(options[:user_email], options[:size], only_path: only_path) + end + def source_icon(source, options = {}) avatar_url = source.try(:avatar_url) diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 28a947a6ca1..41bbd0fddd5 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -235,7 +235,9 @@ module BlobHelper def copy_blob_source_button(blob) return unless blob.rendered_as_text?(ignore_errors: false) - clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}'] > pre", class: "btn gl-button btn-default btn-icon js-copy-blob-source-btn", title: _("Copy file contents")) + content_tag(:span, class: 'btn-group has-tooltip js-copy-blob-source-btn-tooltip') do + clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}'] > pre", class: "btn gl-button btn-default btn-icon js-copy-blob-source-btn", hide_tooltip: true) + end end def open_raw_blob_button(blob) diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb index 73e7476b55d..b8c2255ab7e 100644 --- a/app/helpers/boards_helper.rb +++ b/app/helpers/boards_helper.rb @@ -18,7 +18,7 @@ module BoardsHelper time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s, recent_boards_endpoint: recent_boards_path, parent: current_board_parent.model_name.param_key, - group_id: @group&.id, + group_id: group_id, labels_filter_base_path: build_issue_link_base, labels_fetch_path: labels_fetch_path, labels_manage_path: labels_manage_path, @@ -26,6 +26,12 @@ module BoardsHelper } end + def group_id + return @group.id if board.group_board? + + @project&.group&.id + end + def full_path if board.group_board? @group.full_path diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb index 3f48b2687b9..a71b0f4a83a 100644 --- a/app/helpers/ci/pipeline_editor_helper.rb +++ b/app/helpers/ci/pipeline_editor_helper.rb @@ -5,8 +5,7 @@ module Ci include ChecksCollaboration def can_view_pipeline_editor?(project) - can_collaborate_with_project?(project) && - Gitlab::Ci::Features.ci_pipeline_editor_page_enabled?(project) + can_collaborate_with_project?(project) end end end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index f5c75d62097..93776503dd6 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -105,7 +105,7 @@ module CommitsHelper tooltip = _("Browse Directory") end - link_to url, class: "btn gl-button btn-default has-tooltip", title: tooltip, data: { container: "body" } do + link_to url, class: "btn gl-button btn-default btn-icon has-tooltip", title: tooltip, data: { container: "body" } do sprite_icon('folder-open') end end @@ -127,13 +127,23 @@ module CommitsHelper end def conditionally_paginate_diff_files(diffs, paginate:, per: Projects::CommitController::COMMIT_DIFFS_PER_PAGE) - if paginate && Feature.enabled?(:paginate_commit_view, @project, type: :development) + if paginate Kaminari.paginate_array(diffs.diff_files.to_a).page(params[:page]).per(per) else diffs.diff_files end end + def cherry_pick_projects_data(project) + target_projects(project).map do |project| + { + id: project.id.to_s, + name: project.full_path, + refsUrl: refs_project_path(project) + } + end + end + protected # Private: Returns a link to a person. If the person has a matching user and diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb index 9ece8b0bc5b..b07baf59114 100644 --- a/app/helpers/compare_helper.rb +++ b/app/helpers/compare_helper.rb @@ -1,22 +1,47 @@ # frozen_string_literal: true module CompareHelper - def create_mr_button?(from = params[:from], to = params[:to], project = @project) + def create_mr_button?(from: params[:from], to: params[:to], source_project: @project, target_project: @target_project) from.present? && to.present? && from != to && - can?(current_user, :create_merge_request_from, project) && - project.repository.branch_exists?(from) && - project.repository.branch_exists?(to) + can?(current_user, :create_merge_request_from, source_project) && + can?(current_user, :create_merge_request_in, target_project) && + target_project.repository.branch_exists?(from) && + source_project.repository.branch_exists?(to) end - def create_mr_path(from = params[:from], to = params[:to], project = @project) + def create_mr_path(from: params[:from], to: params[:to], source_project: @project, target_project: @target_project) project_new_merge_request_path( - project, + target_project, merge_request: { + source_project_id: source_project.id, source_branch: to, + target_project_id: target_project.id, target_branch: from } ) end + + def target_projects(source_project) + MergeRequestTargetProjectFinder + .new(current_user: current_user, source_project: source_project, project_feature: :repository) + .execute(include_routes: true) + end + + def project_compare_selector_data(project, merge_request, params) + { + project_compare_index_path: project_compare_index_path(project), + refs_project_path: refs_project_path(project), + params_from: params[:from], + params_to: params[:to], + project_merge_request_path: merge_request.present? ? project_merge_request_path(project, merge_request) : '', + create_mr_path: create_mr_button? ? create_mr_path : '' + }.tap do |data| + if Feature.enabled?(:compare_repo_dropdown, project, default_enabled: :yaml) + data[:project_to] = { id: project.id, name: project.full_path }.to_json + data[:projects_from] = target_projects(project).map { |project| { id: project.id, name: project.full_path } }.to_json + end + end + end end diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 233a8260036..10c7b4032cf 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -4,8 +4,8 @@ module DiffHelper def mark_inline_diffs(old_line, new_line) old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_line, new_line).inline_diffs - marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs, mode: :deletion) - marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs, mode: :addition) + marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs) + marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs) [marked_old_line, marked_new_line] end @@ -232,7 +232,7 @@ module DiffHelper # Always use HTML to handle case where JSON diff rendered this button params_copy.delete(:format) - link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn gl-button active' : 'btn gl-button'), data: { view_type: name } do + link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn gl-button btn-default selected' : 'btn gl-button btn-default'), data: { view_type: name } do title end end diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index 7ae00a70671..6dcdc018a20 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -347,6 +347,11 @@ module GitlabRoutingHelper Gitlab::UrlBuilder.wiki_page_url(wiki, page, only_path: true, **options) end + # GraphQL ETag routes + def graphql_etag_pipeline_path(pipeline) + [api_graphql_path, "pipelines/id/#{pipeline.id}"].join(':') + end + private def snippet_query_params(snippet, *args) diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index eeeffb7b3ae..62f0c68b0c8 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -63,7 +63,7 @@ module GroupsHelper end def group_open_issues_count(group) - if Feature.enabled?(:cached_sidebar_open_issues_count, group) + if Feature.enabled?(:cached_sidebar_open_issues_count, group, default_enabled: :yaml) cached_open_group_issues_count(group) else number_with_delimiter(group_issues_count(state: 'opened')) @@ -99,6 +99,12 @@ module GroupsHelper .count end + def group_dependency_proxy_url(group) + # The namespace path can include uppercase letters, which + # Docker doesn't allow. The proxy expects it to be downcased. + "#{group_url(group).downcase}#{DependencyProxy::URL_SUFFIX}" + end + def group_icon_url(group, options = {}) if group.is_a?(String) group = Group.find_by_full_path(group) diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb index 93f5ca7258d..5f0d513ba35 100644 --- a/app/helpers/ide_helper.rb +++ b/app/helpers/ide_helper.rb @@ -3,18 +3,31 @@ module IdeHelper def ide_data { - "empty-state-svg-path" => image_path('illustrations/multi_file_editor_empty.svg'), - "no-changes-state-svg-path" => image_path('illustrations/multi-editor_no_changes_empty.svg'), - "committed-state-svg-path" => image_path('illustrations/multi-editor_all_changes_committed_empty.svg'), - "pipelines-empty-state-svg-path": image_path('illustrations/pipelines_empty.svg'), - "promotion-svg-path": image_path('illustrations/web-ide_promotion.svg'), - "ci-help-page-path" => help_page_path('ci/quick_start/README'), - "web-ide-help-page-path" => help_page_path('user/project/web_ide/index.md'), - "clientside-preview-enabled": Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?.to_s, - "render-whitespace-in-code": current_user.render_whitespace_in_code.to_s, - "codesandbox-bundler-url": Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url + 'empty-state-svg-path' => image_path('illustrations/multi_file_editor_empty.svg'), + 'no-changes-state-svg-path' => image_path('illustrations/multi-editor_no_changes_empty.svg'), + 'committed-state-svg-path' => image_path('illustrations/multi-editor_all_changes_committed_empty.svg'), + 'pipelines-empty-state-svg-path': image_path('illustrations/pipelines_empty.svg'), + 'promotion-svg-path': image_path('illustrations/web-ide_promotion.svg'), + 'ci-help-page-path' => help_page_path('ci/quick_start/README'), + 'web-ide-help-page-path' => help_page_path('user/project/web_ide/index.md'), + 'clientside-preview-enabled': Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?.to_s, + 'render-whitespace-in-code': current_user.render_whitespace_in_code.to_s, + 'codesandbox-bundler-url': Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url, + 'branch-name' => @branch, + 'file-path' => @path, + 'merge-request' => @merge_request, + 'forked-project' => convert_to_project_entity_json(@forked_project), + 'project' => convert_to_project_entity_json(@project) } end + + private + + def convert_to_project_entity_json(project) + return unless project + + API::Entities::Project.represent(project).to_json + end end ::IdeHelper.prepend_if_ee('::EE::IdeHelper') diff --git a/app/helpers/in_product_marketing_helper.rb b/app/helpers/in_product_marketing_helper.rb index a0e533d3fb8..061404e989d 100644 --- a/app/helpers/in_product_marketing_helper.rb +++ b/app/helpers/in_product_marketing_helper.rb @@ -47,7 +47,7 @@ module InProductMarketingHelper s_('InProductMarketing|Are your runners ready?') ], trial: [ - s_('InProductMarketing|Start a free trial of GitLab Gold – no CC required'), + s_('InProductMarketing|Start a free trial of GitLab Ultimate – no CC required'), s_('InProductMarketing|Improve app security with a 30-day trial'), s_('InProductMarketing|Start with a GitLab Gold free trial') ], @@ -343,7 +343,7 @@ module InProductMarketingHelper end end - def inline_image_link(folder, image, **options) + def inline_image_link(folder, image, options) attachments.inline[image] = File.read(Rails.root.join("app/assets/images", folder, image)) image_tag attachments[image].url, **options end diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb index 889365e39de..62d83ebe79e 100644 --- a/app/helpers/invite_members_helper.rb +++ b/app/helpers/invite_members_helper.rb @@ -13,7 +13,7 @@ module InviteMembersHelper def directly_invite_members? strong_memoize(:directly_invite_members) do - experiment_enabled?(:invite_members_version_a) && can_import_members? + can_import_members? end end @@ -23,6 +23,14 @@ module InviteMembersHelper end end + def show_invite_members_track_event + if directly_invite_members? + 'show_invite_members' + elsif indirectly_invite_members? + 'show_invite_members_version_b' + end + end + def invite_group_members?(group) experiment_enabled?(:invite_members_empty_group_version_a) && Ability.allowed?(current_user, :admin_group_member, group) end diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb index 110b3954900..5f69098de56 100644 --- a/app/helpers/issuables_description_templates_helper.rb +++ b/app/helpers/issuables_description_templates_helper.rb @@ -5,7 +5,8 @@ module IssuablesDescriptionTemplatesHelper include GitlabRoutingHelper def template_dropdown_tag(issuable, &block) - title = selected_template(issuable) || "Choose a template" + selected_template = selected_template(issuable) + title = selected_template || "Choose a template" options = { toggle_class: 'js-issuable-selector', title: title, @@ -15,7 +16,7 @@ module IssuablesDescriptionTemplatesHelper data: { data: issuable_templates(ref_project, issuable.to_ability_name), field_name: 'issuable_template', - selected: selected_template(issuable), + selected: selected_template, project_id: ref_project.id } } @@ -28,15 +29,21 @@ module IssuablesDescriptionTemplatesHelper def issuable_templates(project, issuable_type) @template_types ||= {} @template_types[project.id] ||= {} - @template_types[project.id][issuable_type] ||= TemplateFinder.all_template_names_array(project, issuable_type.pluralize) + @template_types[project.id][issuable_type] ||= TemplateFinder.all_template_names_hash_or_array(project, issuable_type) end def issuable_templates_names(issuable) - issuable_templates(ref_project, issuable.to_ability_name).map { |template| template[:name] } + all_templates = issuable_templates(ref_project, issuable.to_ability_name) + + if ref_project.inherited_issuable_templates_enabled? + all_templates.values.flatten.map { |tpl| tpl[:name] if tpl[:project_id] == ref_project.id }.compact.uniq + else + all_templates.map { |template| template[:name] } + end end def selected_template(issuable) - params[:issuable_template] if issuable_templates(ref_project, issuable.to_ability_name).any? { |template| template[:name] == params[:issuable_template] } + params[:issuable_template] if issuable_templates_names(issuable).any? { |tmpl_name| tmpl_name == params[:issuable_template] } end def template_names_path(parent, issuable) diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 41e9f61cf9f..639a54fa9ec 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -151,7 +151,7 @@ module IssuablesHelper def issuable_meta(issuable, project) output = [] - output << "Opened #{time_ago_with_tooltip(issuable.created_at)} by ".html_safe + output << "Created #{time_ago_with_tooltip(issuable.created_at)} by ".html_safe if issuable.is_a?(Issue) && issuable.service_desk_reply_to output << "#{html_escape(issuable.service_desk_reply_to)} via " @@ -388,7 +388,8 @@ module IssuablesHelper iid: issuable[:iid], severity: issuable[:severity], timeTrackingLimitToHours: Gitlab::CurrentSettings.time_tracking_limit_to_hours, - createNoteEmail: issuable[:create_note_email] + createNoteEmail: issuable[:create_note_email], + issuableType: issuable[:type] } end diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb index 080883fd594..76a7f785df6 100644 --- a/app/helpers/jira_connect_helper.rb +++ b/app/helpers/jira_connect_helper.rb @@ -1,13 +1,7 @@ # frozen_string_literal: true module JiraConnectHelper - def new_jira_connect_ui? - Feature.enabled?(:new_jira_connect_ui, type: :development, default_enabled: :yaml) - end - def jira_connect_app_data(subscriptions) - return {} unless new_jira_connect_ui? - skip_groups = subscriptions.map(&:namespace_id) { diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb index e72a9c83fc9..f50c1e52bed 100644 --- a/app/helpers/learn_gitlab_helper.rb +++ b/app/helpers/learn_gitlab_helper.rb @@ -15,7 +15,8 @@ module LearnGitlabHelper [ action, url: url, - completed: attributes[OnboardingProgress.column_name(action)].present? + completed: attributes[OnboardingProgress.column_name(action)].present?, + svg: image_path("learn_gitlab/#{action}.svg") ] end.to_h end @@ -23,13 +24,13 @@ module LearnGitlabHelper private ACTION_ISSUE_IDS = { - git_write: 2, - pipeline_created: 4, - merge_request_created: 6, - user_added: 7, - trial_started: 13, - required_mr_approvals_enabled: 15, - code_owners_enabled: 16 + git_write: 6, + pipeline_created: 7, + merge_request_created: 9, + user_added: 8, + trial_started: 2, + required_mr_approvals_enabled: 11, + code_owners_enabled: 10 }.freeze ACTION_DOC_URLS = { diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index ff1305f8cc5..7a798c83b7e 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -174,6 +174,18 @@ module MergeRequestsHelper end end + def reviewers_label(merge_request, include_value: true) + reviewers = merge_request.reviewers + reviewer_label = 'Reviewer'.pluralize(reviewers.count) + + if include_value + sanitized_list = sanitize_name(reviewers.map(&:name).to_sentence) + "#{reviewer_label}: #{sanitized_list}" + else + reviewer_label + end + end + private def review_requested_merge_requests_count diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 729585be84a..9db28b54fe9 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -72,52 +72,6 @@ module NotificationsHelper end end - def notification_list_item(level, setting) - title = notification_title(level) - - data = { - notification_level: level, - notification_title: title - } - - content_tag(:li, role: "menuitem") do - link_to '#', class: "update-notification #{('is-active' if setting.level == level)}", data: data do - link_output = content_tag(:strong, title, class: 'dropdown-menu-inner-title') - link_output << content_tag(:span, notification_description(level), class: 'dropdown-menu-inner-content') - end - end - end - - # Identifier to trigger individually dropdowns and custom settings modals in the same view - def notifications_menu_identifier(type, notification_setting) - "#{type}-#{notification_setting.user_id}-#{notification_setting.source_id}-#{notification_setting.source_type}" - end - - # Create hidden field to send notification setting source to controller - def hidden_setting_source_input(notification_setting) - return unless notification_setting.source_type - - hidden_field_tag "#{notification_setting.source_type.downcase}_id", notification_setting.source_id - end - - def notification_event_name(event) - # All values from NotificationSetting.email_events - case event - when :success_pipeline - s_('NotificationEvent|Successful pipeline') - else - event_name = "NotificationEvent|#{event.to_s.humanize}" - s_(event_name) - end - end - - def notification_setting_icon(notification_setting = nil) - sprite_icon( - !notification_setting.present? || notification_setting.disabled? ? "notifications-off" : "notifications", - css_class: "icon notifications-icon js-notifications-icon" - ) - end - def show_unsubscribe_title?(noteable) can?(current_user, "read_#{noteable.to_ability_name}".to_sym, noteable) end diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb index c2a77abb9c9..12bc509466e 100644 --- a/app/helpers/preferences_helper.rb +++ b/app/helpers/preferences_helper.rb @@ -29,6 +29,7 @@ module PreferencesHelper stars: _("Starred Projects"), project_activity: _("Your Projects' Activity"), starred_project_activity: _("Starred Projects' Activity"), + followed_user_activity: _("Followed Users' Activity"), groups: _("Your Groups"), todos: _("Your To-Do List"), issues: _("Assigned Issues"), diff --git a/app/helpers/projects/project_members_helper.rb b/app/helpers/projects/project_members_helper.rb index 99c1b742da4..662afbcfd25 100644 --- a/app/helpers/projects/project_members_helper.rb +++ b/app/helpers/projects/project_members_helper.rb @@ -40,7 +40,7 @@ module Projects::ProjectMembersHelper members: project_members_data_json(project, members), member_path: project_project_member_path(project, ':id'), source_id: project.id, - can_manage_members: can_manage_project_members?(project) + can_manage_members: can_manage_project_members?(project).to_s } end @@ -49,7 +49,7 @@ module Projects::ProjectMembersHelper members: project_group_links_data_json(group_links), member_path: project_group_link_path(project, ':id'), source_id: project.id, - can_manage_members: can_manage_project_members?(project) + can_manage_members: can_manage_project_members?(project).to_s } end end diff --git a/app/helpers/projects/security/configuration_helper.rb b/app/helpers/projects/security/configuration_helper.rb new file mode 100644 index 00000000000..265d46cbc41 --- /dev/null +++ b/app/helpers/projects/security/configuration_helper.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Projects + module Security + module ConfigurationHelper + def security_upgrade_path + 'https://about.gitlab.com/pricing/' + end + end + end +end + +::Projects::Security::ConfigurationHelper.prepend_if_ee('::EE::Projects::Security::ConfigurationHelper') diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index f5cd89d96b4..6c17039a5d9 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -379,8 +379,8 @@ module ProjectsHelper private def can_read_security_configuration?(project, current_user) - ::Feature.enabled?(:secure_security_and_compliance_configuration_page_on_ce, @subject, default_enabled: :yaml) && - can?(current_user, :read_security_configuration, project) + can?(current_user, :access_security_and_compliance, project) && + can?(current_user, :read_security_configuration, project) end def get_project_security_nav_tabs(project, current_user) @@ -646,7 +646,8 @@ module ProjectsHelper metricsDashboardAccessLevel: feature.metrics_dashboard_access_level, operationsAccessLevel: feature.operations_access_level, showDefaultAwardEmojis: project.show_default_award_emojis?, - allowEditingCommitMessages: project.allow_editing_commit_messages? + allowEditingCommitMessages: project.allow_editing_commit_messages?, + securityAndComplianceAccessLevel: project.security_and_compliance_access_level } end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index a7acc0cd7db..86012352c8b 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -360,33 +360,31 @@ module SearchHelper end end + def search_md_sanitize(source) + search_sanitize(markdown(search_truncate(source))) + end + + def simple_search_highlight_and_truncate(text, phrase, options = {}) + highlight(search_sanitize(search_truncate(text)), phrase.split, options) + end + # Sanitize a HTML field for search display. Most tags are stripped out and the # maximum length is set to 200 characters. - def search_md_sanitize(source) - source = Truncato.truncate( + def search_truncate(source) + Truncato.truncate( source, count_tags: false, count_tail: false, + filtered_tags: %w(img), max_length: 200 ) + end - html = markdown(source) - + def search_sanitize(html) # Truncato's filtered_tags and filtered_attributes are not quite the same sanitize(html, tags: %w(a p ol ul li pre code)) end - def simple_search_highlight_and_truncate(text, phrase, options = {}) - text = Truncato.truncate( - text, - count_tags: false, - count_tail: false, - max_length: options.delete(:length) { 200 } - ) - - highlight(text, phrase.split, options) - end - # _search_highlight is used in EE override def highlight_and_truncate_issuable(issuable, search_term, _search_highlight) return unless issuable.description.present? @@ -406,7 +404,7 @@ module SearchHelper # Closed is considered "danger" for MR so we need to handle separately if issuable.is_a?(::MergeRequest) if issuable.merged? - :primary + :info elsif issuable.closed? :danger else diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb index 1be7e240c1a..36f4fced147 100644 --- a/app/helpers/snippets_helper.rb +++ b/app/helpers/snippets_helper.rb @@ -68,4 +68,18 @@ module SnippetsHelper title: 'Download', rel: 'noopener noreferrer') end + + def snippet_file_count(snippet) + file_count = snippet.statistics&.file_count + + return unless file_count&.nonzero? + + tooltip = n_('%d file', '%d files', file_count) % file_count + + tag.span(class: 'file_count', title: tooltip, data: { toggle: 'tooltip', container: 'body' }) do + concat(sprite_icon('documents', css_class: 'gl-vertical-align-middle')) + concat(' ') + concat(file_count) + end + end end diff --git a/app/helpers/stat_anchors_helper.rb b/app/helpers/stat_anchors_helper.rb index 1e8e6371284..d9429f28be7 100644 --- a/app/helpers/stat_anchors_helper.rb +++ b/app/helpers/stat_anchors_helper.rb @@ -5,13 +5,14 @@ module StatAnchorsHelper {}.tap do |attrs| attrs[:class] = %w(nav-link gl-display-flex gl-align-items-center) << extra_classes(anchor) attrs[:itemprop] = anchor.itemprop if anchor.itemprop + attrs[:data] = anchor.data if anchor.data end end private def button_attribute(anchor) - "btn-#{anchor.class_modifier || 'dashed'}" + anchor.class_modifier || 'btn-dashed' end def extra_classes(anchor) diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb index f55a6c3c9e5..6a242d000ae 100644 --- a/app/helpers/user_callouts_helper.rb +++ b/app/helpers/user_callouts_helper.rb @@ -31,7 +31,7 @@ module UserCalloutsHelper render 'shared/flash_user_callout', flash_type: flash_type, message: message, feature_name: feature_name end - def render_dashboard_gold_trial(user) + def render_dashboard_ultimate_trial(user) end def render_account_recovery_regular_check diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb index 696f29164fd..b49bd33a30b 100644 --- a/app/helpers/visibility_level_helper.rb +++ b/app/helpers/visibility_level_helper.rb @@ -35,9 +35,7 @@ module VisibilityLevelHelper end def visibility_level_label(level) - # The visibility level can be: - # 'VisibilityLevel|Private', 'VisibilityLevel|Internal', 'VisibilityLevel|Public' - s_(Project.visibility_levels.key(level)) + Project.visibility_levels.key(level) end def restricted_visibility_levels(show_all = false) diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb index 786081ca815..3f82cf893a0 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -50,24 +50,6 @@ module WikiHelper end end - def wiki_page_errors(error) - return unless error - - content_tag(:div, class: 'alert alert-danger') do - case error - when WikiPage::PageChangedError - 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 - ) - when WikiPage::PageRenameError - s_("WikiEdit|There is already a page with the same title in that path.") - else - error.message - end - end - end - def wiki_attachment_upload_url case @wiki.container when Project diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb index f74b53d68a1..28dd1b00292 100644 --- a/app/helpers/workhorse_helper.rb +++ b/app/helpers/workhorse_helper.rb @@ -7,7 +7,7 @@ module WorkhorseHelper def send_git_blob(repository, blob, inline: true) headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob)) - headers['Content-Disposition'] = inline ? 'inline' : 'attachment' + headers['Content-Disposition'] = inline ? 'inline' : content_disposition_attachment(repository.project, blob.name) # If enabled, this will override the values set above workhorse_set_content_type! @@ -48,4 +48,12 @@ module WorkhorseHelper def workhorse_set_content_type! headers[Gitlab::Workhorse::DETECT_HEADER] = "true" end + + def content_disposition_attachment(project, filename) + if Feature.enabled?(:attachment_with_filename, project, default_enabled: :yaml) + ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: filename) + else + 'attachment' + end + end end |