From 3cccd102ba543e02725d247893729e5c73b38295 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 20 Apr 2022 10:00:54 +0000 Subject: Add latest changes from gitlab-org/gitlab@14-10-stable-ee --- app/helpers/admin/background_migrations_helper.rb | 10 ++-- app/helpers/application_settings_helper.rb | 59 +++++++++--------- app/helpers/auth_helper.rb | 1 + app/helpers/boards_helper.rb | 30 +++++----- app/helpers/broadcast_messages_helper.rb | 22 ++----- app/helpers/button_helper.rb | 2 +- app/helpers/ci/jobs_helper.rb | 4 +- app/helpers/ci/pipeline_editor_helper.rb | 4 +- app/helpers/ci/pipelines_helper.rb | 6 ++ app/helpers/ci/runners_helper.rb | 30 +++++----- app/helpers/clusters_helper.rb | 1 + app/helpers/colors_helper.rb | 23 ++++++++ app/helpers/commits_helper.rb | 4 +- app/helpers/diff_helper.rb | 69 ++++++++-------------- app/helpers/emails_helper.rb | 17 ++++++ app/helpers/environment_helper.rb | 2 +- app/helpers/environments_helper.rb | 2 +- app/helpers/external_link_helper.rb | 2 +- app/helpers/groups/group_members_helper.rb | 32 +++++++--- app/helpers/ide_helper.rb | 8 ++- app/helpers/invite_members_helper.rb | 3 + app/helpers/issuables_helper.rb | 2 +- app/helpers/issues_helper.rb | 12 ++-- app/helpers/merge_requests_helper.rb | 6 +- app/helpers/namespaces_helper.rb | 9 +++ app/helpers/packages_helper.rb | 2 +- app/helpers/preferences_helper.rb | 16 +++++ app/helpers/projects/alert_management_helper.rb | 5 +- app/helpers/projects/pipeline_helper.rb | 16 +++++ app/helpers/projects/project_members_helper.rb | 6 +- .../projects/security/configuration_helper.rb | 4 ++ app/helpers/projects_helper.rb | 20 ++++--- app/helpers/routing/projects_helper.rb | 4 -- app/helpers/routing/pseudonymization_helper.rb | 4 ++ app/helpers/search_helper.rb | 19 +++--- app/helpers/snippets_helper.rb | 4 +- app/helpers/sorting_helper.rb | 17 ++++-- app/helpers/submodule_helper.rb | 2 +- app/helpers/timeboxes_helper.rb | 15 ----- app/helpers/users/callouts_helper.rb | 5 ++ app/helpers/users/group_callouts_helper.rb | 2 + app/helpers/wiki_helper.rb | 14 +++++ app/helpers/workhorse_helper.rb | 4 +- 43 files changed, 315 insertions(+), 204 deletions(-) create mode 100644 app/helpers/colors_helper.rb create mode 100644 app/helpers/projects/pipeline_helper.rb (limited to 'app/helpers') diff --git a/app/helpers/admin/background_migrations_helper.rb b/app/helpers/admin/background_migrations_helper.rb index 6516ea27b2c..79bb13810bb 100644 --- a/app/helpers/admin/background_migrations_helper.rb +++ b/app/helpers/admin/background_migrations_helper.rb @@ -4,13 +4,13 @@ module Admin module BackgroundMigrationsHelper def batched_migration_status_badge_variant(migration) variants = { - 'active' => :info, - 'paused' => :warning, - 'failed' => :danger, - 'finished' => :success + active: :info, + paused: :warning, + failed: :danger, + finished: :success } - variants[migration.status] + variants[migration.status_name] end # The extra logic here is needed because total_tuple_count is just diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index a9c13b2fdeb..57e08eeb4f4 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -37,9 +37,15 @@ module ApplicationSettingsHelper end def storage_weights - Gitlab.config.repositories.storages.keys.each_with_object(OpenStruct.new) do |storage, weights| - weights[storage.to_sym] = @application_setting.repository_storages_weighted[storage] || 0 + # Instead of using a `Struct` we could wrap this into an object. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/358419 + weights = Struct.new(*Gitlab.config.repositories.storages.keys.map(&:to_sym)) + + values = Gitlab.config.repositories.storages.keys.map do |storage| + @application_setting.repository_storages_weighted[storage] || 0 end + + weights.new(*values) end def all_protocols_enabled? @@ -63,39 +69,31 @@ module ApplicationSettingsHelper end end - # Return a group of checkboxes that use Bootstrap's button plugin for a - # toggle button effect. - def restricted_level_checkboxes(help_block_id, checkbox_name, options = {}) + def restricted_level_checkboxes(form) Gitlab::VisibilityLevel.values.map do |level| checked = restricted_visibility_levels(true).include?(level) - css_class = checked ? 'active' : '' - tag_name = "application_setting_visibility_level_#{level}" - - label_tag(tag_name, class: css_class) do - check_box_tag(checkbox_name, level, checked, - autocomplete: 'off', - 'aria-describedby' => help_block_id, - 'class' => options[:class], - id: tag_name) + visibility_level_icon(level) + visibility_level_label(level) - end + + form.gitlab_ui_checkbox_component( + :restricted_visibility_levels, + "#{visibility_level_icon(level)} #{visibility_level_label(level)}".html_safe, + checkbox_options: { checked: checked, multiple: true, autocomplete: 'off' }, + checked_value: level, + unchecked_value: nil + ) end end - # Return a group of checkboxes that use Bootstrap's button plugin for a - # toggle button effect. - def import_sources_checkboxes(help_block_id, options = {}) + def import_sources_checkboxes(form) Gitlab::ImportSources.options.map do |name, source| checked = @application_setting.import_sources.include?(source) - css_class = checked ? 'active' : '' - checkbox_name = 'application_setting[import_sources][]' - - label_tag(name, class: css_class) do - check_box_tag(checkbox_name, source, checked, - autocomplete: 'off', - 'aria-describedby' => help_block_id, - 'class' => options[:class], - id: name.tr(' ', '_')) + name - end + + form.gitlab_ui_checkbox_component( + :import_sources, + name, + checkbox_options: { checked: checked, multiple: true, autocomplete: 'off' }, + checked_value: source, + unchecked_value: nil + ) end end @@ -223,6 +221,7 @@ module ApplicationSettingsHelper :default_project_visibility, :default_projects_limit, :default_snippet_visibility, + :delete_inactive_projects, :disable_feed_token, :disabled_oauth_sign_in_sources, :domain_denylist, @@ -266,7 +265,6 @@ module ApplicationSettingsHelper :help_page_text, :hide_third_party_offers, :home_page_url, - :housekeeping_bitmaps_enabled, :housekeeping_enabled, :housekeeping_full_repack_period, :housekeeping_gc_period, @@ -274,6 +272,9 @@ module ApplicationSettingsHelper :html_emails_enabled, :import_sources, :in_product_marketing_emails_enabled, + :inactive_projects_delete_after_months, + :inactive_projects_min_size_mb, + :inactive_projects_send_warning_email_after_months, :invisible_captcha_enabled, :max_artifacts_size, :max_attachment_size, diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index ba6c0380edf..6ac4a12bcd5 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -2,6 +2,7 @@ module AuthHelper PROVIDERS_WITH_ICONS = %w( + alicloud atlassian_oauth2 auth0 authentiq diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb index 28cd61e10d9..f849f36bf84 100644 --- a/app/helpers/boards_helper.rb +++ b/app/helpers/boards_helper.rb @@ -16,6 +16,7 @@ module BoardsHelper bulk_update_path: @bulk_issues_path, can_update: can_update?.to_s, can_admin_list: can_admin_list?.to_s, + can_admin_board: can_admin_board?.to_s, time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s, parent: current_board_parent.model_name.param_key, group_id: group_id, @@ -23,7 +24,11 @@ module BoardsHelper labels_fetch_path: labels_fetch_path, labels_manage_path: labels_manage_path, releases_fetch_path: releases_fetch_path, - board_type: board.to_type + board_type: board.to_type, + has_scope: board.scoped?.to_s, + has_missing_boards: has_missing_boards?.to_s, + multiple_boards_available: multiple_boards_available?.to_s, + board_base_url: board_base_url } end @@ -85,6 +90,11 @@ module BoardsHelper current_board_parent.multiple_issue_boards_available? end + # Boards are hidden when extra boards were created but the license does not allow multiple boards + def has_missing_boards? + !multiple_boards_available? && current_board_parent.boards.size > 1 + end + def current_board_path(board) @current_board_path ||= if board.group_board? group_board_path(current_board_parent, board) @@ -109,22 +119,12 @@ module BoardsHelper can?(current_user, :admin_issue_board_list, current_board_parent) end - def can_admin_issue? - can?(current_user, :admin_issue, current_board_parent) + def can_admin_board? + can?(current_user, :admin_issue_board, current_board_parent) end - def board_list_data - include_descendant_groups = @group&.present? - - { - toggle: "dropdown", - list_labels_path: labels_filter_path_with_defaults(only_group_labels: true, include_ancestor_groups: true), - labels: labels_filter_path_with_defaults(only_group_labels: true, include_descendant_groups: include_descendant_groups), - labels_endpoint: @labels_endpoint, - namespace_path: @namespace_path, - project_path: @project&.path, - group_path: @group&.path - } + def can_admin_issue? + can?(current_user, :admin_issue, current_board_parent) end def serializer diff --git a/app/helpers/broadcast_messages_helper.rb b/app/helpers/broadcast_messages_helper.rb index dda834ee2c5..b138e9aeb0c 100644 --- a/app/helpers/broadcast_messages_helper.rb +++ b/app/helpers/broadcast_messages_helper.rb @@ -25,23 +25,7 @@ module BroadcastMessagesHelper def broadcast_message(message, opts = {}) return unless message.present? - render "shared/broadcast_message", { message: message, opts: opts } - end - - def broadcast_message_style(broadcast_message) - return '' if broadcast_message.notification? - - style = [] - - if broadcast_message.color.present? - style << "background-color: #{broadcast_message.color}" - end - - if broadcast_message.font.present? - style << "color: #{broadcast_message.font}" - end - - style.join('; ') + render "shared/broadcast_message", { message: message, **opts } end def broadcast_message_status(broadcast_message) @@ -70,6 +54,10 @@ module BroadcastMessagesHelper BroadcastMessage.broadcast_types.keys.map { |w| [w.humanize, w] } end + def broadcast_theme_options + BroadcastMessage.themes.keys + end + def target_access_level_options BroadcastMessage::ALLOWED_TARGET_ACCESS_LEVELS.map do |access_level| [Gitlab::Access.human_access(access_level), access_level] diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb index 4ec95dc8bd7..c47aef24367 100644 --- a/app/helpers/button_helper.rb +++ b/app/helpers/button_helper.rb @@ -20,7 +20,7 @@ module ButtonHelper # # See http://clipboardjs.com/#usage def clipboard_button(data = {}) - css_class = data[:class] || 'btn-clipboard btn-transparent' + css_class = data[:class] || 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm' title = data[:title] || _('Copy') button_text = data[:button_text] || nil hide_tooltip = data[:hide_tooltip] || false diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb index 14e52b120f3..6d63151769f 100644 --- a/app/helpers/ci/jobs_helper.rb +++ b/app/helpers/ci/jobs_helper.rb @@ -6,8 +6,8 @@ module Ci { "endpoint" => project_job_path(@project, @build, format: :json), "project_path" => @project.full_path, - "artifact_help_url" => help_page_path('user/gitlab_com/index.html', anchor: 'gitlab-cicd'), - "deployment_help_url" => help_page_path('user/project/clusters/deploy_to_cluster.html', anchor: 'troubleshooting'), + "artifact_help_url" => help_page_path('user/gitlab_com/index.md', anchor: 'gitlab-cicd'), + "deployment_help_url" => help_page_path('user/project/clusters/deploy_to_cluster.md', anchor: 'troubleshooting'), "runner_settings_url" => project_runners_path(@build.project, anchor: 'js-runners-settings'), "page_path" => project_job_path(@project, @build), "build_status" => @build.status, diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb index 3f0379b1baa..18557afcb99 100644 --- a/app/helpers/ci/pipeline_editor_helper.rb +++ b/app/helpers/ci/pipeline_editor_helper.rb @@ -21,8 +21,8 @@ module Ci "default-branch" => project.default_branch_or_main, "empty-state-illustration-path" => image_path('illustrations/empty-state/empty-dag-md.svg'), "initial-branch-name" => initial_branch, - "lint-help-page-path" => help_page_path('ci/lint', anchor: 'validate-basic-logic-and-syntax'), - "lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available'), + "lint-help-page-path" => help_page_path('ci/lint', anchor: 'check-cicd-syntax'), + "lint-unavailable-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'configuration-validation-currently-not-available-message'), "needs-help-page-path" => help_page_path('ci/yaml/index', anchor: 'needs'), "new-merge-request-path" => namespace_project_new_merge_request_path, "pipeline_etag" => latest_commit ? graphql_etag_pipeline_sha_path(commit_sha) : '', diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb index 8d2f83409be..70d2a4fafd1 100644 --- a/app/helpers/ci/pipelines_helper.rb +++ b/app/helpers/ci/pipelines_helper.rb @@ -106,6 +106,12 @@ module Ci e.candidate { data[:any_runners_available] = project.active_runners.exists?.to_s } end + experiment(:ios_specific_templates, actor: current_user, project: project, sticky_to: project) do |e| + e.candidate do + data[:registration_token] = project.runners_token if can?(current_user, :register_project_runners, project) + end + end + data end diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb index f84b42209da..0e8b6fa6d25 100644 --- a/app/helpers/ci/runners_helper.rb +++ b/app/helpers/ci/runners_helper.rb @@ -6,7 +6,7 @@ module Ci def runner_status_icon(runner, size: 16, icon_class: '') status = runner.status - active = runner.active + contacted_at = runner.contacted_at title = '' icon = 'warning-solid' @@ -14,22 +14,20 @@ module Ci case status when :online - if active - title = s_("Runners|Runner is online, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) } - icon = 'status-active' - span_class = 'gl-text-green-500' - else - title = s_("Runners|Runner is paused, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) } - icon = 'status-paused' - span_class = 'gl-text-gray-600' - end + title = s_("Runners|Runner is online; last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(contacted_at) } + icon = 'status-active' + span_class = 'gl-text-green-500' when :not_connected, :never_contacted - title = s_("Runners|New runner, has not contacted yet") + title = s_("Runners|Runner has never contacted this instance") icon = 'warning-solid' when :offline - title = s_("Runners|Runner is offline, last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(runner.contacted_at) } + title = s_("Runners|Runner is offline; last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(contacted_at) } icon = 'status-failed' span_class = 'gl-text-red-500' + when :stale + # runner may have contacted (or not) and be stale: consider both cases. + title = contacted_at ? s_("Runners|Runner is stale; last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(contacted_at) } : s_("Runners|Runner is stale; it has never contacted this instance") + icon = 'warning-solid' end content_tag(:span, class: span_class, title: title, data: { toggle: 'tooltip', container: 'body', testid: 'runner_status_icon', qa_selector: "runner_status_#{status}_content" }) do @@ -65,7 +63,9 @@ module Ci # Runner install help page is external, located at # https://gitlab.com/gitlab-org/gitlab-runner runner_install_help_page: 'https://docs.gitlab.com/runner/install/', - registration_token: Gitlab::CurrentSettings.runners_registration_token + registration_token: Gitlab::CurrentSettings.runners_registration_token, + online_contact_timeout_secs: ::Ci::Runner::ONLINE_CONTACT_TIMEOUT.to_i, + stale_timeout_secs: ::Ci::Runner::STALE_TIMEOUT.to_i } end @@ -85,7 +85,9 @@ module Ci registration_token: group.runners_token, group_id: group.id, group_full_path: group.full_path, - runner_install_help_page: 'https://docs.gitlab.com/runner/install/' + runner_install_help_page: 'https://docs.gitlab.com/runner/install/', + online_contact_timeout_secs: ::Ci::Runner::ONLINE_CONTACT_TIMEOUT.to_i, + stale_timeout_secs: ::Ci::Runner::STALE_TIMEOUT.to_i } end diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb index 959dac1254e..fe057fb3412 100644 --- a/app/helpers/clusters_helper.rb +++ b/app/helpers/clusters_helper.rb @@ -19,6 +19,7 @@ module ClustersHelper empty_state_help_text: clusterable.empty_state_help_text, new_cluster_path: clusterable.new_path, add_cluster_path: clusterable.connect_path, + new_cluster_docs_path: clusterable.new_cluster_docs_path, can_add_cluster: clusterable.can_add_cluster?.to_s, can_admin_cluster: clusterable.can_admin_cluster?.to_s, display_cluster_agents: display_cluster_agents?(clusterable).to_s, diff --git a/app/helpers/colors_helper.rb b/app/helpers/colors_helper.rb new file mode 100644 index 00000000000..bc72122220a --- /dev/null +++ b/app/helpers/colors_helper.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module ColorsHelper + HEX_COLOR_PATTERN = /\A\#(?:[0-9A-Fa-f]{3}){1,2}\Z/.freeze + + def hex_color_to_rgb_array(hex_color) + raise ArgumentError, "invalid hex color `#{hex_color}`" unless hex_color =~ HEX_COLOR_PATTERN + + hex_color.length == 7 ? hex_color[1, 7].scan(/.{2}/).map(&:hex) : hex_color[1, 4].scan(/./).map { |v| (v * 2).hex } + end + + def rgb_array_to_hex_color(rgb_array) + raise ArgumentError, "invalid RGB array `#{rgb_array}`" unless rgb_array_valid?(rgb_array) + + "##{rgb_array.map{ "%02x" % _1 }.join}" + end + + private + + def rgb_array_valid?(rgb_array) + rgb_array.is_a?(Array) && rgb_array.length == 3 && rgb_array.all?{ _1 >= 0 && _1 <= 255 } + end +end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index c78e906e052..3c3179f6fbe 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -135,9 +135,9 @@ module CommitsHelper %w(btn gpg-status-box) + Array(additional_classes) end - def conditionally_paginate_diff_files(diffs, paginate:, per:) + def conditionally_paginate_diff_files(diffs, paginate:, page:, per:) if paginate - Kaminari.paginate_array(diffs.diff_files.to_a).page(params[:page]).per(per) + Kaminari.paginate_array(diffs.diff_files.to_a).page(page).per(per) else diffs.diff_files end diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 100d5c0281c..522593dd487 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -60,6 +60,18 @@ module DiffHelper html.join.html_safe end + def diff_nomappinginraw_line(line, first_line_num_class, second_line_num_class, content_line_class) + css_class = '' + css_class = 'old' if line.type == 'old-nomappinginraw' + css_class = 'new' if line.type == 'new-nomappinginraw' + + html = [content_tag(:td, '', class: [*first_line_num_class, css_class])] + html << content_tag(:td, '', class: [*second_line_num_class, css_class]) if second_line_num_class + html << content_tag(:td, diff_line_content(line.rich_text), class: [*content_line_class, 'nomappinginraw', css_class]) + + html.join.html_safe + end + def diff_line_content(line) if line.blank? " ".html_safe @@ -74,7 +86,7 @@ module DiffHelper end def diff_link_number(line_type, match, text) - line_type == match || text == 0 ? " " : text + line_type == match ? " " : text end def parallel_diff_discussions(left, right, diff_file) @@ -167,26 +179,20 @@ module DiffHelper } end - def editable_diff?(diff_file) - !diff_file.deleted_file? && @merge_request && @merge_request.source_project - end - - def diff_file_changed_icon(diff_file) - if diff_file.deleted_file? - "file-deletion" - elsif diff_file.new_file? - "file-addition" - else - "file-modified" - end + def diff_file_stats_data(diff_file) + old_blob = diff_file.old_blob + new_blob = diff_file.new_blob + { + old_size: old_blob&.size, + new_size: new_blob&.size, + added_lines: diff_file.added_lines, + removed_lines: diff_file.removed_lines, + viewer_name: diff_file.viewer.partial_name + } end - def diff_file_changed_icon_color(diff_file) - if diff_file.deleted_file? - "danger" - elsif diff_file.new_file? - "success" - end + def editable_diff?(diff_file) + !diff_file.deleted_file? && @merge_request && @merge_request.source_project end def render_overflow_warning?(diffs_collection) @@ -248,23 +254,6 @@ module DiffHelper toggle_whitespace_link(url, options) end - def diff_files_data(diff_files) - diffs_map = diff_files.map do |f| - { - href: "##{hexdigest(f.file_path)}", - title: f.new_path, - name: f.file_path, - path: diff_file_path_text(f), - icon: diff_file_changed_icon(f), - iconColor: "#{diff_file_changed_icon_color(f)}", - added: f.added_lines, - removed: f.removed_lines - } - end - - diffs_map.to_json - end - def hide_whitespace? params[:w] == '1' end @@ -278,14 +267,6 @@ module DiffHelper link_to "#{hide_whitespace? ? 'Show' : 'Hide'} whitespace changes", url, class: options[:class] end - def diff_file_path_text(diff_file, max: 60) - path = diff_file.new_path - - return path unless path.size > max && max > 3 - - "...#{path[-(max - 3)..]}" - end - def code_navigation_path(diffs) Gitlab::CodeNavigationPath.new(merge_request.project, merge_request.diff_head_sha) end diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index b804efb9561..79b04ae0e2b 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -206,6 +206,23 @@ module EmailsHelper end end + def new_email_address_added_text(email) + _('A new email address has been added to your GitLab account: %{email}') % { email: email } + end + + def remove_email_address_text(format: nil) + url = profile_emails_url + + case format + when :html + settings_link_to = generate_link(_('email address settings'), url).html_safe + _("If you want to remove this email address, visit the %{settings_link_to} page.").html_safe % { settings_link_to: settings_link_to } + else + _('If you want to remove this email address, visit %{profile_link}') % + { profile_link: url } + end + end + def admin_changed_password_text(format: nil) url = Gitlab.config.gitlab.url diff --git a/app/helpers/environment_helper.rb b/app/helpers/environment_helper.rb index 1f0bf46097d..b6997b6fb70 100644 --- a/app/helpers/environment_helper.rb +++ b/app/helpers/environment_helper.rb @@ -77,7 +77,7 @@ module EnvironmentHelper can_destroy_environment: can_destroy_environment?(environment), can_stop_environment: can?(current_user, :stop_environment, environment), can_admin_environment: can?(current_user, :admin_environment, project), - environment_metrics_path: environment_metrics_path(environment), + environment_metrics_path: project_metrics_dashboard_path(project, environment: environment), environments_fetch_path: project_environments_path(project, format: :json), environment_edit_path: edit_project_environment_path(project, environment), environment_stop_path: stop_project_environment_path(project, environment), diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb index 1894aba7dc0..3b60bda8605 100644 --- a/app/helpers/environments_helper.rb +++ b/app/helpers/environments_helper.rb @@ -92,7 +92,7 @@ module EnvironmentsHelper return path if request.path.include?(path) end - environment_metrics_path(environment) + project_metrics_dashboard_path(project, environment: environment) end def project_and_environment_metrics_data(project, environment) diff --git a/app/helpers/external_link_helper.rb b/app/helpers/external_link_helper.rb index c951d0daf96..53dacfe0566 100644 --- a/app/helpers/external_link_helper.rb +++ b/app/helpers/external_link_helper.rb @@ -5,7 +5,7 @@ module ExternalLinkHelper def external_link(body, url, options = {}) link = link_to url, { target: '_blank', rel: 'noopener noreferrer' }.merge(options) do - "#{body}#{sprite_icon('external-link', css_class: 'gl-ml-1')}".html_safe + "#{body}#{sprite_icon('external-link', css_class: 'gl-ml-2')}".html_safe end sanitize(link, tags: %w(a svg use), attributes: %w(target rel data-testid class href).concat(options.stringify_keys.keys)) end diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb index a719d80a1a1..80ab303357b 100644 --- a/app/helpers/groups/group_members_helper.rb +++ b/app/helpers/groups/group_members_helper.rb @@ -9,10 +9,10 @@ module Groups::GroupMembersHelper { multiple: true, class: 'input-clamp qa-member-select-field ', scope: :all, email_user: true } end - def group_members_app_data(group, members:, invited:, access_requests:) + def group_members_app_data(group, members:, invited:, access_requests:, include_relations:, search:) { user: group_members_list_data(group, members, { param_name: :page, params: { invited_members_page: nil, search_invited: nil } }), - group: group_group_links_list_data(group), + group: group_group_links_list_data(group, include_relations, search), invite: group_members_list_data(group, invited.nil? ? [] : invited, { param_name: :invited_members_page, params: { page: nil } }), access_request: group_members_list_data(group, access_requests.nil? ? [] : access_requests), source_id: group.id, @@ -26,8 +26,8 @@ module Groups::GroupMembersHelper MemberSerializer.new.represent(members, { current_user: current_user, group: group, source: group }) end - def group_group_links_serialized(group_links) - GroupLink::GroupGroupLinkSerializer.new.represent(group_links, { current_user: current_user }) + def group_group_links_serialized(group, group_links) + GroupLink::GroupGroupLinkSerializer.new.represent(group_links, { current_user: current_user, source: group }) end # Overridden in `ee/app/helpers/ee/groups/group_members_helper.rb` @@ -39,11 +39,29 @@ module Groups::GroupMembersHelper } end - def group_group_links_list_data(group) - group_links = group.shared_with_group_links + def group_group_links(group, include_relations) + group_links = case include_relations + when [:direct] + group.shared_with_group_links + when [:inherited] + group.shared_with_group_links.of_ancestors + else + group.shared_with_group_links.of_ancestors_and_self + end + + group_links.distinct_on_shared_with_group_id_with_group_access + end + + def group_group_links_list_data(group, include_relations, search) + if ::Feature.enabled?(:group_member_inherited_group, group, default_enabled: :yaml) + group_links = group_group_links(group, include_relations) + group_links = group_links.search(search) if search + else + group_links = group.shared_with_group_links + end { - members: group_group_links_serialized(group_links), + members: group_group_links_serialized(group, group_links), pagination: members_pagination_data(group_links), member_path: group_group_link_path(group, ':id') } diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb index bd1571f3956..4b463b9971d 100644 --- a/app/helpers/ide_helper.rb +++ b/app/helpers/ide_helper.rb @@ -20,7 +20,11 @@ module IdeHelper 'fork-info' => @fork_info&.to_json, 'project' => convert_to_project_entity_json(@project), 'enable-environments-guidance' => enable_environments_guidance?.to_s, - 'preview-markdown-path' => @project && preview_markdown_path(@project) + 'preview-markdown-path' => @project && preview_markdown_path(@project), + 'web-terminal-svg-path' => image_path('illustrations/web-ide_promotion.svg'), + 'web-terminal-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'interactive-web-terminals-for-the-web-ide'), + 'web-terminal-config-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'web-ide-configuration-file'), + 'web-terminal-runners-help-path' => help_page_path('user/project/web_ide/index.md', anchor: 'runner-configuration') } end @@ -44,5 +48,3 @@ module IdeHelper current_user.dismissed_callout?(feature_name: 'web_ide_ci_environments_guidance') end end - -::IdeHelper.prepend_mod_with('IdeHelper') diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb index a2dde29e25d..a682d2712be 100644 --- a/app/helpers/invite_members_helper.rb +++ b/app/helpers/invite_members_helper.rb @@ -36,6 +36,7 @@ module InviteMembersHelper def common_invite_group_modal_data(source, member_class, is_project) { id: source.id, + root_id: source.root_ancestor&.id, name: source.name, default_access_level: Gitlab::Access::GUEST, invalid_groups: source.related_group_ids, @@ -45,9 +46,11 @@ module InviteMembersHelper } end + # Overridden in EE def common_invite_modal_dataset(source) dataset = { id: source.id, + root_id: source.root_ancestor&.id, name: source.name, default_access_level: Gitlab::Access::GUEST } diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index ec1f8ca5f00..98eca3785e7 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -233,7 +233,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, - markdownPreviewPath: preview_markdown_path(parent), + markdownPreviewPath: preview_markdown_path(parent, target_type: issuable.model_name, target_id: issuable.iid), markdownDocsPath: help_page_path('user/markdown'), lockVersion: issuable.lock_version, issuableTemplateNamesPath: template_names_path(parent, issuable), diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 298162fe970..c8c9ea32184 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -91,7 +91,7 @@ module IssuesHelper if !can?(current_user, :award_emoji, awardable) "disabled" elsif current_user && awards.find { |a| a.user_id == current_user.id } - "active" + "selected" else "" end @@ -239,15 +239,19 @@ module IssuesHelper ) end + def issues_form_data(project) + { + new_issue_path: new_project_issue_path(project) + } + end + # Overridden in EE def scoped_labels_available?(parent) false end def award_emoji_issue_api_path(issue) - if Feature.enabled?(:improved_emoji_picker, issue.project, default_enabled: :yaml) - api_v4_projects_issues_award_emoji_path(id: issue.project.id, issue_iid: issue.iid) - end + api_v4_projects_issues_award_emoji_path(id: issue.project.id, issue_iid: issue.iid) end end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 84a3802c72c..2d93813d5ee 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -185,7 +185,7 @@ module MergeRequestsHelper endpoint_metadata: @endpoint_metadata_url, endpoint_batch: diffs_batch_project_json_merge_request_path(project, merge_request, 'json', params), endpoint_coverage: @coverage_path, - help_page_path: help_page_path('user/discussions/index.md', anchor: 'suggest-changes'), + help_page_path: help_page_path('user/project/merge_requests/reviews/suggestions.md'), current_user_data: @current_user_data, update_current_user_path: @update_current_user_path, project_path: project_path(merge_request.project), @@ -203,9 +203,7 @@ module MergeRequestsHelper end def award_emoji_merge_request_api_path(merge_request) - if Feature.enabled?(:improved_emoji_picker, merge_request.project, default_enabled: :yaml) - api_v4_projects_merge_requests_award_emoji_path(id: merge_request.project.id, merge_request_iid: merge_request.iid) - end + api_v4_projects_merge_requests_award_emoji_path(id: merge_request.project.id, merge_request_iid: merge_request.iid) end private diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index 64b58d28fc9..cf386ee398a 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -88,6 +88,15 @@ module NamespacesHelper }.to_json end + def pipeline_usage_quota_app_data(namespace) + { + namespace_actual_plan_name: namespace.actual_plan_name, + namespace_path: namespace.full_path, + namespace_id: namespace.id, + page_size: page_size + } + end + private # Many importers create a temporary Group, so use the real diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb index 01075862618..20d40626449 100644 --- a/app/helpers/packages_helper.rb +++ b/app/helpers/packages_helper.rb @@ -46,7 +46,7 @@ module PackagesHelper ::Gitlab::Tracking.event(category, event_name.to_s, **args) end - def show_cleanup_policy_on_alert(project) + def show_cleanup_policy_link(project) Gitlab.com? && Gitlab.config.registry.enabled && project.feature_available?(:container_registry, current_user) && diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb index 6a8c39b5b15..39a57e786ed 100644 --- a/app/helpers/preferences_helper.rb +++ b/app/helpers/preferences_helper.rb @@ -82,6 +82,22 @@ module PreferencesHelper Gitlab::TabWidth.css_class_for_user(current_user) end + def user_diffs_colors + { + deletion: current_user&.diffs_deletion_color.presence, + addition: current_user&.diffs_addition_color.presence + }.compact + end + + def custom_diff_color_classes + return if request.path == profile_preferences_path + + classes = [] + classes << 'diff-custom-addition-color' if current_user&.diffs_addition_color.presence + classes << 'diff-custom-deletion-color' if current_user&.diffs_deletion_color.presence + classes + end + def language_choices options_for_select( selectable_locales_with_translation_level.sort, diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb index e03f2ae78bf..f21538fd3fb 100644 --- a/app/helpers/projects/alert_management_helper.rb +++ b/app/helpers/projects/alert_management_helper.rb @@ -15,13 +15,14 @@ module Projects::AlertManagementHelper } end - def alert_management_detail_data(project, alert_id) + def alert_management_detail_data(current_user, project, alert_id) { 'alert-id' => alert_id, 'project-path' => project.full_path, 'project-id' => project.id, 'project-issues-path' => project_issues_path(project), - 'page' => 'OPERATIONS' + 'page' => 'OPERATIONS', + 'can-update' => can?(current_user, :update_alert_management_alert, project).to_s } end diff --git a/app/helpers/projects/pipeline_helper.rb b/app/helpers/projects/pipeline_helper.rb new file mode 100644 index 00000000000..185632a49b5 --- /dev/null +++ b/app/helpers/projects/pipeline_helper.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Projects + module PipelineHelper + def js_pipeline_tabs_data(project, pipeline) + { + can_generate_codequality_reports: pipeline.can_generate_codequality_reports?.to_json, + graphql_resource_etag: graphql_etag_pipeline_path(pipeline), + metrics_path: namespace_project_ci_prometheus_metrics_histograms_path(namespace_id: project.namespace, project_id: project, format: :json), + pipeline_project_path: project.full_path + } + end + end +end + +Projects::PipelineHelper.prepend_mod diff --git a/app/helpers/projects/project_members_helper.rb b/app/helpers/projects/project_members_helper.rb index 514737b1417..980c8ca6b80 100644 --- a/app/helpers/projects/project_members_helper.rb +++ b/app/helpers/projects/project_members_helper.rb @@ -18,8 +18,8 @@ module Projects::ProjectMembersHelper MemberSerializer.new.represent(members, { current_user: current_user, group: project.group, source: project }) end - def project_group_links_serialized(group_links) - GroupLink::ProjectGroupLinkSerializer.new.represent(group_links, { current_user: current_user }) + def project_group_links_serialized(project, group_links) + GroupLink::ProjectGroupLinkSerializer.new.represent(group_links, { current_user: current_user, source: project }) end def project_members_list_data(project, members, pagination = {}) @@ -32,7 +32,7 @@ module Projects::ProjectMembersHelper def project_group_links_list_data(project, group_links) { - members: project_group_links_serialized(group_links), + members: project_group_links_serialized(project, group_links), pagination: members_pagination_data(group_links), member_path: project_group_link_path(project, ':id') } diff --git a/app/helpers/projects/security/configuration_helper.rb b/app/helpers/projects/security/configuration_helper.rb index 8281b1f8522..efc77550c90 100644 --- a/app/helpers/projects/security/configuration_helper.rb +++ b/app/helpers/projects/security/configuration_helper.rb @@ -6,6 +6,10 @@ module Projects def security_upgrade_path "https://#{ApplicationHelper.promo_host}/pricing/" end + + def vulnerability_training_docs_path + help_page_path('user/application_security/vulnerabilities/index', anchor: 'enable-security-training-for-vulnerabilities') + end end end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 8a75f545a32..21c7a54670c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -420,6 +420,14 @@ module ProjectsHelper project.path_with_namespace end + def able_to_see_issues?(project, user) + project.issues_enabled? && can?(user, :read_issue, project) + end + + def able_to_see_merge_requests?(project, user) + project.merge_requests_enabled? && can?(user, :read_merge_request, project) + end + def fork_button_disabled_tooltip(project) return unless current_user @@ -627,7 +635,9 @@ module ProjectsHelper end def can_show_last_commit_in_list?(project) - can?(current_user, :read_cross_project) && project.commit + can?(current_user, :read_cross_project) && + can?(current_user, :read_commit_status, project) && + project.commit end def pages_https_only_disabled? @@ -640,14 +650,6 @@ module ProjectsHelper "You must enable HTTPS for all your domains first" end - def pages_https_only_label_class - if pages_https_only_disabled? - "list-label disabled" - else - "list-label" - end - end - def filter_starrer_path(options = {}) options = params.slice(:sort).merge(options).permit! "#{request.path}?#{options.to_param}" diff --git a/app/helpers/routing/projects_helper.rb b/app/helpers/routing/projects_helper.rb index fb000b29739..859070d59ec 100644 --- a/app/helpers/routing/projects_helper.rb +++ b/app/helpers/routing/projects_helper.rb @@ -18,10 +18,6 @@ module Routing project_environment_path(environment.project, environment, *args) end - def environment_metrics_path(environment, *args) - metrics_project_environment_path(environment.project, environment, *args) - end - def environment_delete_path(environment, *args) expose_path(api_v4_projects_environments_path(id: environment.project.id, environment_id: environment.id)) end diff --git a/app/helpers/routing/pseudonymization_helper.rb b/app/helpers/routing/pseudonymization_helper.rb index f1fafd563ce..3e5d4ee21c0 100644 --- a/app/helpers/routing/pseudonymization_helper.rb +++ b/app/helpers/routing/pseudonymization_helper.rb @@ -5,7 +5,11 @@ module Routing class MaskHelper QUERY_PARAMS_TO_NOT_MASK = %w[ scope + severity + sortBy + sortDesc state + tab ].freeze def initialize(request_object, group, project) diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 5b596c328d1..f8bfc74b344 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -260,6 +260,7 @@ module SearchHelper { category: "Groups", id: group.id, + value: "#{search_result_sanitize(group.name)}", label: "#{search_result_sanitize(group.full_name)}", url: group_path(group), avatar_url: group.avatar_url || '' @@ -311,7 +312,9 @@ module SearchHelper id: mr.id, label: search_result_sanitize(mr.title), url: merge_request_path(mr), - avatar_url: mr.project.avatar_url || '' + avatar_url: mr.project.avatar_url || '', + project_id: mr.target_project_id, + project_name: mr.target_project.name } end end @@ -325,7 +328,9 @@ module SearchHelper id: i.id, label: search_result_sanitize(i.title), url: issue_path(i), - avatar_url: i.project.avatar_url || '' + avatar_url: i.project.avatar_url || '', + project_id: i.project_id, + project_name: i.project.name } end end @@ -436,11 +441,11 @@ module SearchHelper end def show_user_search_tab? - if @project - project_search_tabs?(:members) - else - can?(current_user, :read_users_list) - end + return project_search_tabs?(:members) if @project + return false unless can?(current_user, :read_users_list) + return true if @group + + Feature.enabled?(:global_search_users_tab, current_user, type: :ops, default_enabled: :yaml) end def issuable_state_to_badge_class(issuable) diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb index ca90d1e13c1..78b204fefe9 100644 --- a/app/helpers/snippets_helper.rb +++ b/app/helpers/snippets_helper.rb @@ -77,8 +77,6 @@ module SnippetsHelper end def project_snippets_award_api_path(snippet) - if Feature.enabled?(:improved_emoji_picker, snippet.project, default_enabled: :yaml) - api_v4_projects_snippets_award_emoji_path(id: snippet.project.id, snippet_id: snippet.id) - end + api_v4_projects_snippets_award_emoji_path(id: snippet.project.id, snippet_id: snippet.id) end end diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 4db14d5cc4d..b4ad9db815d 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -134,14 +134,14 @@ module SortingHelper ) end - def milestone_sort_options_hash + def milestones_sort_options_hash { - 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_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_start_date_soon => sort_title_start_date_soon + sort_value_name => sort_title_name_asc, + sort_value_name_desc => sort_title_name_desc } end @@ -186,6 +186,13 @@ module SortingHelper } end + def runners_sort_options_hash + { + sort_value_created_date => sort_title_created_date, + sort_value_contacted_date => sort_title_contacted_date + } + end + def starrers_sort_options_hash { sort_value_name => sort_title_name, diff --git a/app/helpers/submodule_helper.rb b/app/helpers/submodule_helper.rb index d3af6a00181..2942765a108 100644 --- a/app/helpers/submodule_helper.rb +++ b/app/helpers/submodule_helper.rb @@ -30,7 +30,7 @@ module SubmoduleHelper end end - namespace.sub!(%r{\A/}, '') + namespace.delete_prefix!('/') project.rstrip! project.delete_suffix!('.git') diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb index eca40572735..c81fbcbfd11 100644 --- a/app/helpers/timeboxes_helper.rb +++ b/app/helpers/timeboxes_helper.rb @@ -63,21 +63,6 @@ module TimeboxesHelper issues.size end - # Returns count of milestones for different states - # Uses explicit hash keys as the 'opened' state URL params differs from the db value - # and we need to add the total - # rubocop: disable CodeReuse/ActiveRecord - def milestone_counts(milestones) - counts = milestones.reorder(nil).group(:state).count - - { - opened: counts['active'] || 0, - closed: counts['closed'] || 0, - all: counts.values.sum || 0 - } - end - # rubocop: enable CodeReuse/ActiveRecord - def milestone_progress_tooltip_text(milestone) has_issues = milestone.total_issues_count > 0 diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb index 87c8bf5cb28..b8231b02ac1 100644 --- a/app/helpers/users/callouts_helper.rb +++ b/app/helpers/users/callouts_helper.rb @@ -9,6 +9,7 @@ module Users FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version' REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout' UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout' + MINUTE_LIMIT_BANNER = 'minute_limit_banner' SECURITY_NEWSLETTER_CALLOUT = 'security_newsletter_callout' REGISTRATION_ENABLED_CALLOUT_ALLOWED_CONTROLLER_PATHS = [/^root/, /^dashboard\S*/, /^admin\S*/].freeze @@ -60,6 +61,10 @@ module Users !user_dismissed?(SECURITY_NEWSLETTER_CALLOUT) end + def minute_limit_banner_dismissed? + user_dismissed?(MINUTE_LIMIT_BANNER) + end + private def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil) diff --git a/app/helpers/users/group_callouts_helper.rb b/app/helpers/users/group_callouts_helper.rb index 0aa4eb89499..9a9fce4d7e3 100644 --- a/app/helpers/users/group_callouts_helper.rb +++ b/app/helpers/users/group_callouts_helper.rb @@ -31,3 +31,5 @@ module Users end end end + +Users::GroupCalloutsHelper.prepend_mod diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb index ba876f6cb65..02ea3c1b010 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -134,6 +134,20 @@ module WikiHelper current_user&.can?(:admin_project, container) && !container.has_confluence? end + + def wiki_page_render_api_endpoint(page) + expose_path(api_v4_projects_wikis_path(wiki_page_render_api_endpoint_params(page))) + end + + def wiki_markup_hash_by_name_id + Wiki::VALID_USER_MARKUPS.map { |key, value| { value[:name] => key } }.reduce({}, :merge) + end + + private + + def wiki_page_render_api_endpoint_params(page) + { id: page.container.id, slug: ERB::Util.url_encode(page.slug), params: { version: page.version.id } } + end end WikiHelper.prepend_mod_with('WikiHelper') diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb index 2460c956bb6..f1ddc2e902e 100644 --- a/app/helpers/workhorse_helper.rb +++ b/app/helpers/workhorse_helper.rb @@ -35,9 +35,11 @@ module WorkhorseHelper head :ok end - # Send an entry from artifacts through Workhorse + # Send an entry from artifacts through Workhorse and set safe content type def send_artifacts_entry(file, entry) headers.store(*Gitlab::Workhorse.send_artifacts_entry(file, entry)) + headers.store(*Gitlab::Workhorse.detect_content_type) + head :ok end -- cgit v1.2.3