diff options
Diffstat (limited to 'app/helpers')
47 files changed, 369 insertions, 390 deletions
diff --git a/app/helpers/admin/user_actions_helper.rb b/app/helpers/admin/user_actions_helper.rb index dc31c06477e..969c5d5a0b5 100644 --- a/app/helpers/admin/user_actions_helper.rb +++ b/app/helpers/admin/user_actions_helper.rb @@ -55,7 +55,6 @@ module Admin end def ban_actions - return unless ban_feature_available? return if @user.internal? if @user.banned? diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb index ab743e27603..e9465e0db22 100644 --- a/app/helpers/appearances_helper.rb +++ b/app/helpers/appearances_helper.rb @@ -4,14 +4,40 @@ module AppearancesHelper include MarkupHelper include Gitlab::Utils::StrongMemoize - def appearance_short_name - Appearance.current&.pwa_short_name.presence || _('GitLab') + def appearance_pwa_icon_path_scaled(width) + return unless Appearance::ALLOWED_PWA_ICON_SCALER_WIDTHS.include?(width) + + append_root_path((current_appearance&.pwa_icon_path_scaled(width) || "/-/pwa-icons/logo-#{width}.png")) + end + + def appearance_maskable_logo + append_root_path('/-/pwa-icons/maskable-logo.png') + end + + def append_root_path(path) + Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, path) end def brand_title current_appearance&.title.presence || default_brand_title end + def appearance_pwa_name + current_appearance&.pwa_name.presence || _('GitLab') + end + + def appearance_pwa_short_name + current_appearance&.pwa_short_name.presence || _('GitLab') + end + + def appearance_pwa_description + current_appearance&.pwa_description.presence || + _("The complete DevOps platform. " \ + "One application with endless possibilities. " \ + "Organizations rely on GitLab’s source code management, " \ + "CI/CD, security, and more to deliver software rapidly.") + end + def default_brand_title # This resides in a separate method so that EE can easily redefine it. _('GitLab Community Edition') diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f4b34044e0e..93b7c8c0b94 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -232,7 +232,7 @@ module ApplicationHelper end def support_url - Gitlab::CurrentSettings.current_application_settings.help_page_support_url.presence || "#{promo_url}/getting-help/" + Gitlab::CurrentSettings.current_application_settings.help_page_support_url.presence || "#{promo_url}/get-help/" end def instance_review_permitted? @@ -284,10 +284,6 @@ module ApplicationHelper !params.has_key?(:no_startup_css) end - def use_new_fonts? - Feature.enabled?(:new_fonts, current_user) || request.params.has_key?(:new_fonts) - end - def outdated_browser? browser.ie? end @@ -368,6 +364,12 @@ module ApplicationHelper end end + def discord_url(user) + return '' if user.discord.blank? + + "https://discord.com/users/#{user.discord}" + end + def collapsed_sidebar? cookies["sidebar_collapsed"] == "true" end diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 339938245a0..3abaae98c29 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -75,16 +75,38 @@ module ApplicationSettingsHelper end def restricted_level_checkboxes(form) - Gitlab::VisibilityLevel.values.map do |level| + restricted_visibility_levels_help_text = { + Gitlab::VisibilityLevel::PUBLIC => s_( + 'AdminSettings|If selected, only administrators are able to create public groups, projects, ' \ + 'and snippets. Also, profiles are only visible to authenticated users.' + ), + Gitlab::VisibilityLevel::INTERNAL => s_( + 'AdminSettings|If selected, only administrators are able to create internal groups, projects, and ' \ + 'snippets.' + ), + Gitlab::VisibilityLevel::PRIVATE => s_( + 'AdminSettings|If selected, only administrators are able to create private groups, projects, and ' \ + 'snippets.' + ) + } + + Gitlab::VisibilityLevel.options.map do |label, level| checked = restricted_visibility_levels(true).include?(level) 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 - ) + ) do |c| + c.label do + visibility_level_icon(level) + content_tag(:span, label, { class: 'gl-ml-2' }) + end + + c.help_text do + restricted_visibility_levels_help_text.fetch(level) + end + end end end @@ -145,6 +167,10 @@ module ApplicationSettingsHelper " using their classification label.") end + def external_authorization_allow_token_help_text + s_("ExternalAuthorization|Does not apply if service URL is specified.") + end + def external_authorization_timeout_help_text s_("ExternalAuthorization|Period GitLab waits for a response from the external "\ "service. If there is no response, access is denied. Default: 0.5 seconds.") @@ -197,6 +223,7 @@ module ApplicationSettingsHelper :allow_local_requests_from_hooks_and_services, :allow_local_requests_from_web_hooks_and_services, :allow_local_requests_from_system_hooks, + :allow_possible_spam, :dns_rebinding_protection_enabled, :archive_builds_in_human_readable, :asset_proxy_enabled, @@ -282,6 +309,7 @@ module ApplicationSettingsHelper :inactive_projects_send_warning_email_after_months, :invisible_captcha_enabled, :jira_connect_application_key, + :jira_connect_public_key_storage_enabled, :jira_connect_proxy_url, :max_artifacts_size, :max_attachment_size, @@ -383,7 +411,6 @@ module ApplicationSettingsHelper :user_default_internal_regex, :user_oauth_applications, :version_check_enabled, - :web_ide_clientside_preview_enabled, :diff_max_patch_bytes, :diff_max_files, :diff_max_lines, @@ -450,7 +477,8 @@ module ApplicationSettingsHelper :can_create_group, :bulk_import_enabled, :allow_runner_registration_token, - :user_defaults_to_private_profile + :user_defaults_to_private_profile, + :deactivation_email_additional_text ].tap do |settings| next if Gitlab.com? @@ -475,7 +503,8 @@ module ApplicationSettingsHelper :external_authorization_service_default_label, :external_authorization_service_enabled, :external_authorization_service_timeout, - :external_authorization_service_url + :external_authorization_service_url, + :allow_deploy_tokens_and_keys_with_external_authn ] end diff --git a/app/helpers/artifacts_helper.rb b/app/helpers/artifacts_helper.rb new file mode 100644 index 00000000000..df0432105d5 --- /dev/null +++ b/app/helpers/artifacts_helper.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module ArtifactsHelper + def artifacts_app_data(project) + { + project_path: project.full_path, + can_destroy_artifacts: can?(current_user, :destroy_artifacts, project).to_s, + artifacts_management_feedback_image_path: image_path('illustrations/chat-bubble-sm.svg') + } + end +end diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index c41b5923d13..e2e89c9abca 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -5,7 +5,6 @@ module AuthHelper alicloud atlassian_oauth2 auth0 - authentiq azure_activedirectory_v2 azure_oauth2 bitbucket @@ -17,7 +16,6 @@ module AuthHelper jwt openid_connect salesforce - shibboleth twitter ).freeze LDAP_PROVIDER = /\Aldap/.freeze diff --git a/app/helpers/bizible_helper.rb b/app/helpers/bizible_helper.rb index 970cc6558da..4c8d3744ced 100644 --- a/app/helpers/bizible_helper.rb +++ b/app/helpers/bizible_helper.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true module BizibleHelper - def bizible_enabled? - Feature.enabled?(:ecomm_instrumentation, type: :ops) && + def bizible_enabled?(invite_email = nil) + invite_email.blank? && + Feature.enabled?(:ecomm_instrumentation, type: :ops) && Gitlab.config.extra.has_key?('bizible') && Gitlab.config.extra.bizible.present? && Gitlab.config.extra.bizible == true diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb index c93c8dd8d76..823332c3d1d 100644 --- a/app/helpers/ci/pipelines_helper.rb +++ b/app/helpers/ci/pipelines_helper.rb @@ -101,7 +101,7 @@ module Ci has_gitlab_ci: has_gitlab_ci?(project).to_s, pipeline_editor_path: can?(current_user, :create_pipeline, project) && project_ci_pipeline_editor_path(project), suggested_ci_templates: suggested_ci_templates.to_json, - ci_runner_settings_path: project_settings_ci_cd_path(project, ci_runner_templates: true, anchor: 'js-runners-settings') + ci_runner_settings_path: project_settings_ci_cd_path(project, anchor: 'js-runners-settings') } experiment(:runners_availability_section, namespace: project.root_ancestor) do |e| diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb index ac36c867baf..41ef0bd20a8 100644 --- a/app/helpers/ci/runners_helper.rb +++ b/app/helpers/ci/runners_helper.rb @@ -63,6 +63,7 @@ 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/', + new_runner_path: new_admin_runner_path, 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, diff --git a/app/helpers/ci/variables_helper.rb b/app/helpers/ci/variables_helper.rb index 84572363a8d..a492c48e58c 100644 --- a/app/helpers/ci/variables_helper.rb +++ b/app/helpers/ci/variables_helper.rb @@ -47,6 +47,10 @@ module Ci ] end + def ci_variable_maskable_raw_regex + Ci::Maskable::MASK_AND_RAW_REGEX.inspect.sub('\\A', '^').sub('\\z', '$')[1...-1] + end + def ci_variable_maskable_regex Ci::Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(%r{^/}, '').sub(%r{/[a-z]*$}, '').gsub('\/', '/') end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 53781364af7..f75d3657986 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -131,10 +131,6 @@ module CommitsHelper } end - def commit_signature_badge_classes(additional_classes) - %w(btn gpg-status-box) + Array(additional_classes) - end - def conditionally_paginate_diff_files(diffs, paginate:, page:, per:) if paginate diff_files = diffs.diff_files.to_a diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index f6de405cecb..9f4ed6b8150 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -178,6 +178,10 @@ module EmailsHelper strip_tags(render_message(:footer_message, style: '')) end + def service_desk_email_additional_text + # overridden on EE + end + def say_hi(user) _('Hi %{username}!') % { username: sanitize_name(user.name) } end @@ -290,15 +294,27 @@ module EmailsHelper added_reviewers = new_reviewers - previous_reviewers removed_reviewers = previous_reviewers - new_reviewers - added_reviewers_template_text = added_reviewers.size > 1 ? "were added as reviewers.<br>" : "was added as a reviewer.<br>" - removed_reviewers_template_text = removed_reviewers.size > 1 ? "were removed from reviewers." : "was removed from reviewers." - - added = format_reviewers_string(added_reviewers, html_tag) - removed = format_reviewers_string(removed_reviewers, html_tag) - - added_reviewers_text = added ? "#{added} #{added_reviewers_template_text}".html_safe : '' - removed_reviewers_text = removed ? "#{removed} #{removed_reviewers_template_text}".html_safe : '' - s_('ChangeReviewer|%{added_reviewers_text}%{removed_reviewers_text}').html_safe % { added_reviewers_text: added_reviewers_text, removed_reviewers_text: removed_reviewers_text } + added_reviewers_text = if added_reviewers.any? + n_( + '%{reviewer_names} was added as a reviewer.', + '%{reviewer_names} were added as reviewers.', + added_reviewers.size) % { + reviewer_names: format_reviewers_string(added_reviewers, html_tag) + } + end + + removed_reviewers_text = if removed_reviewers.any? + n_( + '%{reviewer_names} was removed from reviewers.', + '%{reviewer_names} were removed from reviewers.', + removed_reviewers.size) % { + reviewer_names: format_reviewers_string(removed_reviewers, html_tag) + } + end + + line_delimiter = html_tag.present? ? '<br>' : "\n" + + [added_reviewers_text, removed_reviewers_text].compact.join(line_delimiter).html_safe end end diff --git a/app/helpers/explore_helper.rb b/app/helpers/explore_helper.rb index 1defe480059..2967501f628 100644 --- a/app/helpers/explore_helper.rb +++ b/app/helpers/explore_helper.rb @@ -15,6 +15,8 @@ module ExploreHelper namespace_id: params[:namespace_id] } + exist_opts[:language] = params[:language] + options = exist_opts.merge(options).delete_if { |key, value| value.blank? } request_path_with_options(options) end diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index 8f0d01c7d6d..a4d90716129 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -45,9 +45,7 @@ module FormHelper end end - def dropdown_max_select(data, feature_flag) - return data[:'max-select'] unless feature_flag.nil? || Feature.enabled?(feature_flag) - + def dropdown_max_select(data) if data[:'max-select'] && data[:'max-select'] < ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS data[:'max-select'] else @@ -179,11 +177,7 @@ module FormHelper new_options[:title] = _('Select reviewer(s)') new_options[:data][:'dropdown-header'] = _('Reviewer(s)') - if Feature.enabled?(:limit_reviewer_and_assignee_size) - new_options[:data][:'max-select'] = ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS - else - new_options[:data].delete(:'max-select') - end + new_options[:data][:'max-select'] = ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS new_options end diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index e8fc6bc292f..129871ca3fd 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -113,7 +113,7 @@ module GroupsHelper end def render_setting_to_allow_project_access_token_creation?(group) - group.root? && current_user.can?(:admin_setting_to_allow_project_access_token_creation, group) + group.root? && current_user.can?(:admin_setting_to_allow_resource_access_token_creation, group) end def show_thanks_for_purchase_alert?(quantity) diff --git a/app/helpers/hooks_helper.rb b/app/helpers/hooks_helper.rb index 63544e28a0e..ac1e4456bc7 100644 --- a/app/helpers/hooks_helper.rb +++ b/app/helpers/hooks_helper.rb @@ -8,12 +8,12 @@ module HooksHelper } end - def link_to_test_hook(hook, trigger) - path = test_hook_path(hook, trigger) - trigger_human_name = integration_webhook_event_human_name(trigger) - - link_to path, rel: 'nofollow', method: :post do - content_tag(:span, trigger_human_name) + def webhook_test_items(hook, triggers) + triggers.map do |trigger| + { + href: test_hook_path(hook, trigger), + text: integration_webhook_event_human_name(trigger) + } end end diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb index 021b47ceab2..bba3fac7468 100644 --- a/app/helpers/icons_helper.rb +++ b/app/helpers/icons_helper.rb @@ -26,7 +26,7 @@ module IconsHelper # SVG Sprites currently don't work across domains, so in the case of a CDN # we have to set the current path deliberately to prevent addition of asset_host sprite_base_url = Gitlab.config.gitlab.url if ActionController::Base.asset_host - ActionController::Base.helpers.image_path('file_icons.svg', host: sprite_base_url) + ActionController::Base.helpers.image_path('file_icons/file_icons.svg', host: sprite_base_url) end def sprite_icon(icon_name, size: DEFAULT_ICON_SIZE, css_class: nil) diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb index 0e81cea8ac7..c5be044a27b 100644 --- a/app/helpers/ide_helper.rb +++ b/app/helpers/ide_helper.rb @@ -1,17 +1,20 @@ # frozen_string_literal: true module IdeHelper - def ide_data + def ide_data(project:, branch:, path:, merge_request:, fork_info:) { 'can-use-new-web-ide' => can_use_new_web_ide?.to_s, 'use-new-web-ide' => use_new_web_ide?.to_s, 'new-web-ide-help-page-path' => help_page_path('user/project/web_ide/index.md', anchor: 'vscode-reimplementation'), 'user-preferences-path' => profile_preferences_path, - 'branch-name' => @branch, - 'file-path' => @path, - 'fork-info' => @fork_info&.to_json, - 'merge-request' => @merge_request - }.merge(use_new_web_ide? ? new_ide_data : legacy_ide_data) + 'branch-name' => branch, + 'file-path' => path, + 'fork-info' => fork_info&.to_json, + 'editor-font-src-url' => font_url('jetbrains-mono/JetBrainsMono.woff2'), + 'editor-font-family' => 'JetBrains Mono', + 'editor-font-format' => 'woff2', + 'merge-request' => merge_request + }.merge(use_new_web_ide? ? new_ide_data(project: project) : legacy_ide_data(project: project)) end def can_use_new_web_ide? @@ -24,16 +27,16 @@ module IdeHelper private - def new_ide_data + def new_ide_data(project:) { - 'project-path' => @project&.path_with_namespace, + 'project-path' => project&.path_with_namespace, 'csp-nonce' => content_security_policy_nonce, # We will replace these placeholders in the FE 'ide-remote-path' => ide_remote_path(remote_host: ':remote_host', remote_path: ':remote_path') } end - def legacy_ide_data + def legacy_ide_data(project:) { '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'), @@ -43,13 +46,11 @@ module IdeHelper 'promotion-svg-path': image_path('illustrations/web-ide_promotion.svg'), 'ci-help-page-path' => help_page_path('ci/quick_start/index'), '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, - 'default-branch' => @project && @project.default_branch, - 'project' => convert_to_project_entity_json(@project), - 'enable-environments-guidance' => enable_environments_guidance?.to_s, - 'preview-markdown-path' => @project && preview_markdown_path(@project), + 'default-branch' => project && project.default_branch, + 'project' => convert_to_project_entity_json(project), + 'enable-environments-guidance' => enable_environments_guidance?(project).to_s, + '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'), @@ -63,8 +64,8 @@ module IdeHelper API::Entities::Project.represent(project, current_user: current_user).to_json end - def enable_environments_guidance? - experiment(:in_product_guidance_environments_webide, project: @project) do |e| + def enable_environments_guidance?(project) + experiment(:in_product_guidance_environments_webide, project: project) do |e| e.candidate { !has_dismissed_ide_environments_callout? } e.run diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb index 6fad1346426..e986b56fde4 100644 --- a/app/helpers/invite_members_helper.rb +++ b/app/helpers/invite_members_helper.rb @@ -45,7 +45,7 @@ module InviteMembersHelper full_path: source.full_path } - if show_invite_members_for_task?(source) + if current_user && show_invite_members_for_task?(source) dataset.merge!( tasks_to_be_done_options: tasks_to_be_done_options.to_json, projects: projects_for_source(source).to_json, @@ -71,11 +71,9 @@ module InviteMembersHelper {} end - def show_invite_members_for_task?(source) - return unless current_user - - invite_for_help_continuous_onboarding = source.is_a?(Project) && experiment(:invite_for_help_continuous_onboarding, namespace: source.namespace).assigned.name == 'candidate' - params[:open_modal] == 'invite_members_for_task' || invite_for_help_continuous_onboarding + # Overridden in EE + def show_invite_members_for_task?(_source) + params[:open_modal] == 'invite_members_for_task' end def tasks_to_be_done_options diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index fb407aa7eed..46d2d2c42d9 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -6,7 +6,7 @@ module IssuablesHelper include ::Sidebars::Concerns::HasPill def sidebar_gutter_toggle_icon - content_tag(:span, class: 'js-sidebar-toggle-container', data: { is_expanded: !sidebar_gutter_collapsed? }) do + content_tag(:span, class: 'js-sidebar-toggle-container gl-button-text', data: { is_expanded: !sidebar_gutter_collapsed? }) do sprite_icon('chevron-double-lg-left', css_class: "js-sidebar-expand #{'hidden' unless sidebar_gutter_collapsed?}") + sprite_icon('chevron-double-lg-right', css_class: "js-sidebar-collapse #{'hidden' if sidebar_gutter_collapsed?}") end @@ -152,7 +152,7 @@ module IssuablesHelper end if issuable.is_a?(Issue) && issuable.service_desk_reply_to - output << "#{html_escape(issuable.service_desk_reply_to)} via " + output << "#{html_escape(issuable.present(current_user: current_user).service_desk_reply_to)} via " end output << content_tag(:strong) do @@ -242,7 +242,6 @@ module IssuablesHelper updateEndpoint: "#{issuable_path(issuable)}.json", canUpdate: can?(current_user, :"update_#{issuable.to_ability_name}", issuable), canDestroy: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable), - canUpdateTimelineEvent: can?(current_user, :admin_incident_management_timeline_event, issuable), issuableRef: issuable.to_reference, markdownPreviewPath: preview_markdown_path(parent, target_type: issuable.model_name, target_id: issuable.iid), markdownDocsPath: help_page_path('user/markdown'), @@ -272,7 +271,17 @@ module IssuablesHelper sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier, # rubocop:disable CodeReuse/ActiveRecord iid: issuable.iid.to_s, isHidden: issue_hidden?(issuable), - canCreateIncident: create_issue_type_allowed?(issuable.project, :incident) + canCreateIncident: create_issue_type_allowed?(issuable.project, :incident), + **incident_only_initial_data(issuable) + } + end + + def incident_only_initial_data(issue) + return {} unless issue.incident? + + { + hasLinkedAlerts: issue.alert_management_alerts.any?, + canUpdateTimelineEvent: can?(current_user, :admin_incident_management_timeline_event, issue) } end @@ -299,7 +308,7 @@ module IssuablesHelper end def issuables_count_for_state(issuable_type, state) - Gitlab::IssuablesCountForState.new(finder, store_in_redis_cache: true)[state] + Gitlab::IssuablesCountForState.new(finder, fast_fail: true, store_in_redis_cache: true)[state] end def close_issuable_path(issuable) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 362f1e65425..39399c2919b 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -57,7 +57,7 @@ module IssuesHelper end def issue_hidden?(issue) - Feature.enabled?(:ban_user_feature_flag) && issue.hidden? + issue.hidden? end def hidden_issue_icon(issue) @@ -195,7 +195,6 @@ module IssuesHelper empty_state_svg_path: image_path('illustrations/issues.svg'), full_path: namespace.full_path, initial_sort: current_user&.user_preference&.issues_sort, - is_anonymous_search_disabled: Feature.enabled?(:disable_anonymous_search, type: :ops).to_s, is_issue_repositioning_disabled: issue_repositioning_disabled?.to_s, is_public_visibility_restricted: Gitlab::CurrentSettings.restricted_visibility_levels&.include?(Gitlab::VisibilityLevel::PUBLIC).to_s, diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb index 0971fdae8dd..50e3c3cc5fe 100644 --- a/app/helpers/jira_connect_helper.rb +++ b/app/helpers/jira_connect_helper.rb @@ -11,7 +11,8 @@ module JiraConnectHelper subscriptions_path: jira_connect_subscriptions_path(format: :json), users_path: current_user ? nil : jira_connect_users_path, # users_path is used to determine if user is signed in gitlab_user_path: current_user ? user_path(current_user) : nil, - oauth_metadata: Feature.enabled?(:jira_connect_oauth, current_user) ? jira_connect_oauth_data(installation).to_json : nil + oauth_metadata: Feature.enabled?(:jira_connect_oauth, current_user) ? jira_connect_oauth_data(installation).to_json : nil, + public_key_storage_enabled: Gitlab.config.jira_connect.enable_public_keys_storage || Gitlab::CurrentSettings.jira_connect_public_key_storage_enabled? } end diff --git a/app/helpers/json_helper.rb b/app/helpers/json_helper.rb index e61c789fd08..2a1a6272cc9 100644 --- a/app/helpers/json_helper.rb +++ b/app/helpers/json_helper.rb @@ -4,11 +4,11 @@ module JsonHelper # These two JSON helpers are short-form wrappers for the Gitlab::Json # class, which should be used in place of .to_json calls or calls to # the JSON class. - def json_generate(*args) - Gitlab::Json.generate(*args) + def json_generate(...) + Gitlab::Json.generate(...) end - def json_parse(*args) - Gitlab::Json.parse(*args) + def json_parse(...) + Gitlab::Json.parse(...) end end diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb deleted file mode 100644 index a07922e451a..00000000000 --- a/app/helpers/learn_gitlab_helper.rb +++ /dev/null @@ -1,107 +0,0 @@ -# frozen_string_literal: true - -module LearnGitlabHelper - IMAGE_PATH_PLAN = "learn_gitlab/section_plan.svg" - IMAGE_PATH_DEPLOY = "learn_gitlab/section_deploy.svg" - IMAGE_PATH_WORKSPACE = "learn_gitlab/section_workspace.svg" - LICENSE_SCANNING_RUN_URL = 'https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html' - - def learn_gitlab_enabled?(project) - return false unless current_user - - learn_gitlab_onboarding_available?(project) - end - - def learn_gitlab_data(project) - { - actions: onboarding_actions_data(project).to_json, - sections: onboarding_sections_data.to_json, - project: onboarding_project_data(project).to_json - } - end - - def learn_gitlab_onboarding_available?(project) - Onboarding::Progress.onboarding?(project.namespace) && - Onboarding::LearnGitlab.new(current_user).available? - end - - private - - def onboarding_actions_data(project) - attributes = onboarding_progress(project).attributes.symbolize_keys - - action_urls(project).to_h do |action, url| - [ - action, - { - url: url, - completed: attributes[Onboarding::Progress.column_name(action)].present?, - svg: image_path("learn_gitlab/#{action}.svg"), - enabled: true - } - ] - end - end - - def onboarding_sections_data - { - workspace: { - svg: image_path(IMAGE_PATH_WORKSPACE) - }, - plan: { - svg: image_path(IMAGE_PATH_PLAN) - }, - deploy: { - svg: image_path(IMAGE_PATH_DEPLOY) - } - } - end - - def onboarding_project_data(project) - { name: project.name } - end - - def action_urls(project) - action_issue_urls.merge( - issue_created: project_issues_path(project), - git_write: project_path(project), - merge_request_created: project_merge_requests_path(project), - user_added: project_members_url(project), - **deploy_section_action_urls(project) - ) - end - - def action_issue_urls - Onboarding::Completion::ACTION_ISSUE_IDS.transform_values do |id| - project_issue_url(learn_gitlab_project, id) - end - end - - def deploy_section_action_urls(project) - experiment( - :security_actions_continuous_onboarding, - namespace: project.namespace, - user: current_user, - sticky_to: current_user - ) do |e| - e.control { { security_scan_enabled: project_security_configuration_path(project) } } - e.candidate do - { - license_scanning_run: LICENSE_SCANNING_RUN_URL, - secure_dependency_scanning_run: project_security_configuration_path(project, anchor: 'dependency-scanning'), - secure_dast_run: project_security_configuration_path(project, anchor: 'dast') - } - end - end.run - end - - def learn_gitlab_project - @learn_gitlab_project ||= Onboarding::LearnGitlab.new(current_user).project - end - - def onboarding_progress(project) - Onboarding::Progress.find_by(namespace: project.namespace) # rubocop: disable CodeReuse/ActiveRecord - end -end - -LearnGitlabHelper.prepend_mod_with('LearnGitlabHelper') diff --git a/app/helpers/listbox_helper.rb b/app/helpers/listbox_helper.rb index 0aaeb39c82d..6a7e09f75e4 100644 --- a/app/helpers/listbox_helper.rb +++ b/app/helpers/listbox_helper.rb @@ -23,7 +23,7 @@ module ListboxHelper # # The final parameter `html_options` applies arbitrary attributes to the # returned tag. Some of these are passed to the underlying Vue component as - # props, e.g., to right-align the menu of items, add `data: { right: true }`. + # props, e.g., to right-align the menu of items, add `data: { placement: 'right' }`. # # Examples: # # Create a listbox with two items, with the first item selected @@ -32,7 +32,7 @@ module ListboxHelper # = gl_redirect_listbox_tag items, 'foo' # # # Create the same listbox, right-align the menu and add margin styling - # = gl_redirect_listbox_tag items, 'foo', class: 'gl-ml-3', data: { right: true } + # = gl_redirect_listbox_tag items, 'foo', class: 'gl-ml-3', data: { placement: 'right' } def gl_redirect_listbox_tag(items, selected, html_options = {}) # Add script tag for app/assets/javascripts/entrypoints/behaviors/redirect_listbox.js content_for :page_specific_javascripts do diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index 60796e628a3..01030690daf 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -5,42 +5,6 @@ module NamespacesHelper params.dig(:project, :namespace_id) || params[:namespace_id] end - def namespaces_options(selected = :current_user, display_path: false, groups: nil, extra_group: nil, groups_only: false) - groups ||= current_user.manageable_groups_with_routes - users = [current_user.namespace] - selected_id = selected - - unless extra_group.nil? || extra_group.is_a?(Group) - extra_group = Group.find(extra_group) if Namespace.find(extra_group).kind == 'group' - end - - if extra_group && extra_group.is_a?(Group) - extra_group = dedup_extra_group(extra_group) - - if Ability.allowed?(current_user, :read_group, extra_group) - # Assign the value to an invalid primary ID so that the select box works - extra_group.id = -1 unless extra_group.persisted? - selected_id = extra_group.id if selected == :extra_group - groups |= [extra_group] - else - selected_id = current_user.namespace.id - end - end - - options = [] - options << options_for_group(groups, display_path: display_path, type: 'group') - - unless groups_only - options << options_for_group(users, display_path: display_path, type: 'user') - - if selected == :current_user && current_user.namespace - selected_id = current_user.namespace.id - end - end - - grouped_options_for_select(options, selected_id) - end - def namespace_icon(namespace, size = 40) if namespace.is_a?(Group) group_icon_url(namespace) @@ -91,36 +55,13 @@ module NamespacesHelper } end - private - - # Many importers create a temporary Group, so use the real - # group if one exists by that name to prevent duplicates. - # rubocop: disable CodeReuse/ActiveRecord - def dedup_extra_group(extra_group) - unless extra_group.persisted? - existing_group = Group.find_by(path: extra_group.path) - extra_group = existing_group if existing_group&.persisted? - end - - extra_group - end - # rubocop: enable CodeReuse/ActiveRecord - - def options_for_group(namespaces, display_path:, type:) - group_label = type.pluralize - elements = namespaces.sort_by(&:human_name).map! do |n| - [display_path ? n.full_path : n.human_name, n.id, - data: { - options_parent: group_label, - visibility_level: n.visibility_level_value, - visibility: n.visibility, - name: n.name, - show_path: type == 'group' ? group_path(n) : user_path(n), - edit_path: type == 'group' ? edit_group_path(n) : nil - }] - end - - [group_label.camelize, elements] + def storage_usage_app_data(namespace) + { + namespace_id: namespace.id, + namespace_path: namespace.full_path, + user_namespace: namespace.user_namespace?.to_s, + default_per_page: page_size + } end end diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb index b017c9a81d1..ddd6469a9e4 100644 --- a/app/helpers/nav/new_dropdown_helper.rb +++ b/app/helpers/nav/new_dropdown_helper.rb @@ -32,7 +32,7 @@ module Nav id: 'new_project', title: _('New project/repository'), href: new_project_path(namespace_id: group.id), - data: { track_action: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_project_group', track_label: 'plus_menu_dropdown', track_property: 'navigation_top' } ) ) end @@ -43,7 +43,7 @@ module Nav id: 'new_subgroup', title: _('New subgroup'), href: new_group_path(parent_id: group.id, anchor: 'create-group-pane'), - data: { track_action: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown', track_property: 'navigation_top' } ) ) end @@ -59,7 +59,7 @@ module Nav end { - title: _('This group'), + title: _('In this group'), menu_items: menu_items.compact } end @@ -74,7 +74,7 @@ module Nav id: 'new_issue', title: _('New issue'), href: new_project_issue_path(project), - data: { track_action: 'click_link_new_issue', track_label: 'plus_menu_dropdown', qa_selector: 'new_issue_link' } + data: { track_action: 'click_link_new_issue', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', qa_selector: 'new_issue_link' } ) ) end @@ -85,7 +85,7 @@ module Nav id: 'new_mr', title: _('New merge request'), href: project_new_merge_request_path(merge_project), - data: { track_action: 'click_link_new_mr', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_mr', track_label: 'plus_menu_dropdown', track_property: 'navigation_top' } ) ) end @@ -96,7 +96,7 @@ module Nav id: 'new_snippet', title: _('New snippet'), href: new_project_snippet_path(project), - data: { track_action: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown', track_property: 'navigation_top' } ) ) end @@ -110,7 +110,7 @@ module Nav end { - title: _('This project'), + title: _('In this project'), menu_items: menu_items } end @@ -124,7 +124,7 @@ module Nav id: 'general_new_project', title: _('New project/repository'), href: new_project_path, - data: { track_action: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' } + data: { track_action: 'click_link_new_project', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', qa_selector: 'global_new_project_link' } ) ) end @@ -135,7 +135,7 @@ module Nav id: 'general_new_group', title: _('New group'), href: new_group_path, - data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_group_link' } + data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', qa_selector: 'global_new_group_link' } ) ) end @@ -146,13 +146,13 @@ module Nav id: 'general_new_snippet', title: _('New snippet'), href: new_snippet_path, - data: { track_action: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_snippet_link' } + data: { track_action: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', qa_selector: 'global_new_snippet_link' } ) ) end { - title: _('GitLab'), + title: _('In GitLab'), menu_items: menu_items } end @@ -165,7 +165,8 @@ module Nav href: href, data: { track_action: 'click_link_invite_members', - track_label: 'plus_menu_dropdown' + track_label: 'plus_menu_dropdown', + track_property: 'navigation_top' } ) end diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb index bd4d661ab49..fb11c183aeb 100644 --- a/app/helpers/nav/top_nav_helper.rb +++ b/app/helpers/nav/top_nav_helper.rb @@ -101,7 +101,7 @@ module Nav builder.add_primary_menu_item_with_shortcut( header: top_nav_localized_headers[:switch_to], active: nav == 'project' || active_nav_link?(path: %w[root#index projects#trending projects#starred dashboard/projects#index]), - data: { track_label: "projects_dropdown", track_action: "click_dropdown", qa_selector: "projects_dropdown" }, + data: { track_label: "projects_dropdown", track_action: "click_dropdown", track_property: "navigation_top", qa_selector: "projects_dropdown" }, view: PROJECTS_VIEW, shortcut_href: dashboard_projects_path, **projects_menu_item_attrs @@ -115,7 +115,7 @@ module Nav builder.add_primary_menu_item_with_shortcut( header: top_nav_localized_headers[:switch_to], active: nav == 'group' || active_nav_link?(path: %w[dashboard/groups explore/groups]), - data: { track_label: "groups_dropdown", track_action: "click_dropdown", qa_selector: "groups_dropdown" }, + data: { track_label: "groups_dropdown", track_action: "click_dropdown", track_property: "navigation_top", qa_selector: "groups_dropdown" }, view: GROUPS_VIEW, shortcut_href: dashboard_groups_path, **groups_menu_item_attrs @@ -233,7 +233,7 @@ module Nav tracking_attrs( "menu_#{label.underscore.parameterize(separator: '_')}", 'click_dropdown', - 'navigation' + 'navigation_top' )[:data] || {} end diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb index 6f7b2877100..4a218984af1 100644 --- a/app/helpers/page_layout_helper.rb +++ b/app/helpers/page_layout_helper.rb @@ -175,7 +175,7 @@ module PageLayoutHelper current_emoji: user.status.emoji.to_s, current_message: user.status.message.to_s, current_availability: user.status.availability.to_s, - current_clear_status_after: user.status.clear_status_at.to_s + current_clear_status_after: user.status.clear_status_at&.to_s(:iso8601) }) end diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb index 88e68a52199..2442856d7fe 100644 --- a/app/helpers/preferences_helper.rb +++ b/app/helpers/preferences_helper.rb @@ -30,6 +30,7 @@ module PreferencesHelper { projects: _("Your Projects (default)"), stars: _("Starred Projects"), + your_activity: _("Your Activity"), project_activity: _("Your Projects' Activity"), starred_project_activity: _("Starred Projects' Activity"), followed_user_activity: _("Followed Users' Activity"), diff --git a/app/helpers/projects/ml/experiments_helper.rb b/app/helpers/projects/ml/experiments_helper.rb index b9a219b3021..55216d412a5 100644 --- a/app/helpers/projects/ml/experiments_helper.rb +++ b/app/helpers/projects/ml/experiments_helper.rb @@ -5,6 +5,25 @@ module Projects require 'json' include ActionView::Helpers::NumberHelper + def show_candidate_view_model(candidate) + data = { + candidate: { + params: candidate.params, + metrics: candidate.latest_metrics, + info: { + iid: candidate.iid, + path_to_artifact: link_to_artifact(candidate), + experiment_name: candidate.experiment.name, + path_to_experiment: link_to_experiment(candidate.project, candidate.experiment), + status: candidate.status + }, + metadata: candidate.metadata + } + } + + Gitlab::Json.generate(data) + end + def candidates_table_items(candidates) items = candidates.map do |candidate| { @@ -25,24 +44,30 @@ module Projects Gitlab::Json.generate(candidates.flat_map(&selector).map(&:name).uniq) end - def candidate_as_data(candidate) - data = { - params: candidate.params, - metrics: candidate.latest_metrics, - info: { - iid: candidate.iid, - path_to_artifact: link_to_artifact(candidate), - experiment_name: candidate.experiment.name, - path_to_experiment: link_to_experiment(candidate), - status: candidate.status - }, - metadata: candidate.metadata - } + def experiments_as_data(project, experiments) + data = experiments.map do |exp| + { + name: exp.name, + path: link_to_experiment(project, exp), + candidate_count: exp.candidate_count + } + end Gitlab::Json.generate(data) end - private + def page_info(paginator) + { + has_next_page: paginator.has_next_page?, + has_previous_page: paginator.has_previous_page?, + start_cursor: paginator.cursor_for_previous_page, + end_cursor: paginator.cursor_for_next_page + } + end + + def formatted_page_info(page_info) + Gitlab::Json.generate(page_info) + end def link_to_artifact(candidate) artifact = candidate.artifact @@ -56,10 +81,8 @@ module Projects project_ml_candidate_path(candidate.project, candidate.iid) end - def link_to_experiment(candidate) - experiment = candidate.experiment - - project_ml_experiment_path(experiment.project, experiment.iid) + def link_to_experiment(project, experiment) + project_ml_experiment_path(project, experiment.iid) end def user_info(candidate) diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 507e05b9967..04190bc442b 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -123,6 +123,25 @@ module ProjectsHelper end end + def vue_fork_divergence_data(project, ref) + source_project = visible_fork_source(project) + + return {} unless source_project + + source_default_branch = source_project.default_branch + + { + source_name: source_project.full_name, + source_path: project_path(source_project), + ahead_compare_path: project_compare_path( + project, from: source_default_branch, to: ref, from_project_id: source_project.id + ), + behind_compare_path: project_compare_path( + source_project, from: ref, to: source_default_branch, from_project_id: project.id + ) + } + end + def remove_fork_project_warning_message(project) _("You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?") % { project_full_name: project.full_name } @@ -285,11 +304,7 @@ module ProjectsHelper current_page?(starred_explore_projects_path) end - def show_merge_request_count?(disabled: false, compact_mode: false) - !disabled && !compact_mode - end - - def show_issue_count?(disabled: false, compact_mode: false) + def show_count?(disabled: false, compact_mode: false) !disabled && !compact_mode end @@ -420,6 +435,10 @@ module ProjectsHelper project.merge_requests_enabled? && can?(user, :read_merge_request, project) end + def able_to_see_forks_count?(project, user) + project.forking_enabled? && can?(user, :read_code, project) + end + def fork_button_disabled_tooltip(project) return unless current_user diff --git a/app/helpers/registrations_helper.rb b/app/helpers/registrations_helper.rb index 91adc36749b..1724e11a6f1 100644 --- a/app/helpers/registrations_helper.rb +++ b/app/helpers/registrations_helper.rb @@ -10,6 +10,10 @@ module RegistrationsHelper qa_selector: 'new_user_username_field' } end + + def arkose_labs_challenge_enabled? + false + end end RegistrationsHelper.prepend_mod_with('RegistrationsHelper') diff --git a/app/helpers/routing/snippets_helper.rb b/app/helpers/routing/snippets_helper.rb index 19450c1d033..a815204a216 100644 --- a/app/helpers/routing/snippets_helper.rb +++ b/app/helpers/routing/snippets_helper.rb @@ -114,16 +114,16 @@ module Routing end end - def toggle_award_emoji_personal_snippet_path(*args) - toggle_award_emoji_snippet_path(*args) + def toggle_award_emoji_personal_snippet_path(...) + toggle_award_emoji_snippet_path(...) end - def toggle_award_emoji_project_project_snippet_path(*args) - toggle_award_emoji_project_snippet_path(*args) + def toggle_award_emoji_project_project_snippet_path(...) + toggle_award_emoji_project_snippet_path(...) end - def toggle_award_emoji_project_project_snippet_url(*args) - toggle_award_emoji_project_snippet_url(*args) + def toggle_award_emoji_project_project_snippet_url(...) + toggle_award_emoji_project_snippet_url(...) end private diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb deleted file mode 100644 index 7ee40c28bad..00000000000 --- a/app/helpers/selects_helper.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -module SelectsHelper - def project_select_tag(id, opts = {}) - opts[:class] = [*opts[:class], 'ajax-project-select'].join(' ') - - unless opts.delete(:scope) == :all - if @group - opts['data-group-id'] = @group.id - end - end - - with_feature_enabled_data_attribute = - case opts.delete(:with_feature_enabled) - when 'issues' then 'data-with-issues-enabled' - when 'merge_requests' then 'data-with-merge-requests-enabled' - end - - opts[with_feature_enabled_data_attribute] = true - - hidden_field_tag(id, opts[:selected], opts) - end - - def select2_tag(id, opts = {}) - klass_opts = [opts[:class]] - klass_opts << 'multiselect' if opts[:multiple] - - opts[:class] = klass_opts.join(' ') - value = opts[:selected] || '' - - hidden_field_tag(id, value, opts) - end -end - -SelectsHelper.prepend_mod_with('SelectsHelper') diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 56138ba95c2..8251e1cba8a 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -45,10 +45,7 @@ module SessionsHelper end def obfuscated_email(email) - regex = ::Gitlab::UntrustedRegexp.new('^(..?)(.*)(@.?)(.*)(\..*)$') - match = regex.match(email) - return email unless match - - match[1] + '*' * (match[2] || '').length + match[3] + '*' * (match[4] || '').length + match[5] + # Moved to Gitlab::Utils::Email in 15.9 + Gitlab::Utils::Email.obfuscated_email(email) end end diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb index f6257c92f3f..27020738515 100644 --- a/app/helpers/sidebars_helper.rb +++ b/app/helpers/sidebars_helper.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true module SidebarsHelper + include MergeRequestsHelper + include Nav::NewDropdownHelper + def sidebar_tracking_attributes_by_object(object) sidebar_attributes_for_object(object).fetch(:tracking_attrs, {}) end @@ -31,20 +34,65 @@ module SidebarsHelper Sidebars::Groups::Context.new(**context_data) end - def super_sidebar_context(user) + def super_sidebar_context(user, group:, project:) { name: user.name, username: user.username, avatar_url: user.avatar_url, assigned_open_issues_count: user.assigned_open_issues_count, - assigned_open_merge_requests_count: user.assigned_open_merge_requests_count, todos_pending_count: user.todos_pending_count, - issues_dashboard_path: issues_dashboard_path(assignee_username: user.username) + issues_dashboard_path: issues_dashboard_path(assignee_username: user.username), + total_merge_requests_count: user_merge_requests_counts[:total], + create_new_menu_groups: create_new_menu_groups(group: group, project: project), + merge_request_menu: create_merge_request_menu(user), + support_path: support_url, + display_whats_new: display_whats_new?, + whats_new_most_recent_release_items_count: whats_new_most_recent_release_items_count, + whats_new_version_digest: whats_new_version_digest, + show_version_check: show_version_check?, + gitlab_version: Gitlab.version_info, + gitlab_version_check: gitlab_version_check } end private + def create_new_menu_groups(group:, project:) + new_dropdown_sections = new_dropdown_view_model(group: group, project: project)[:menu_sections] + show_headers = new_dropdown_sections.length > 1 + new_dropdown_sections.map do |section| + { + name: show_headers ? section[:title] : '', + items: section[:menu_items].map do |item| + { + text: item[:title], + href: item[:href] + } + end + } + end + end + + def create_merge_request_menu(user) + [ + { + name: _('Merge requests'), + items: [ + { + text: _('Assigned'), + href: merge_requests_dashboard_path(assignee_username: user.username), + count: user_merge_requests_counts[:assigned] + }, + { + text: _('Review requests'), + href: merge_requests_dashboard_path(reviewer_username: user.username), + count: user_merge_requests_counts[:review_requested] + } + ] + } + ] + end + def sidebar_attributes_for_object(object) case object when Project @@ -98,7 +146,6 @@ module SidebarsHelper { current_user: user, container: project, - learn_gitlab_enabled: learn_gitlab_enabled?(project), current_ref: current_ref, ref_type: ref_type, jira_issues_integration: project_jira_issues_integration?, diff --git a/app/helpers/sorting_titles_values_helper.rb b/app/helpers/sorting_titles_values_helper.rb index b49cb617d80..db779a9d8c1 100644 --- a/app/helpers/sorting_titles_values_helper.rb +++ b/app/helpers/sorting_titles_values_helper.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true module SortingTitlesValuesHelper + SORT_NAME = 'name_asc' + SORT_UPDATED_OLDEST = 'updated_asc' + SORT_UPDATED_RECENT = 'updated_desc' + # Titles. def sort_title_created_date s_('SortOptions|Created date') diff --git a/app/helpers/ssh_keys_helper.rb b/app/helpers/ssh_keys_helper.rb index 4cd40836335..13d6851f3cd 100644 --- a/app/helpers/ssh_keys_helper.rb +++ b/app/helpers/ssh_keys_helper.rb @@ -23,6 +23,28 @@ module SshKeysHelper } end + def ssh_key_revoke_modal_data(key, path) + title = _('Revoke Key') + + { + path: path, + method: 'delete', + qa_selector: 'revoke_ssh_key_button', + title: title, + aria_label: title, + modal_attributes: { + 'data-qa-selector': 'ssh_key_revoke_modal', + title: _('Are you sure you want to revoke this SSH key?'), + message: _('This action cannot be undone, and will permanently delete the %{key} SSH key. All commits signed using this SSH key will be marked as unverified.') % { key: key.title }, + okVariant: 'danger', + okTitle: _('Revoke') + }, + toggle: 'tooltip', + placement: 'top', + container: 'body' + } + end + def ssh_key_allowed_algorithms allowed_algorithms = Gitlab::CurrentSettings.allowed_key_types.flat_map do |ssh_key_type_name| Gitlab::SSHPublicKey.supported_algorithms_for_name(ssh_key_type_name) diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb index 04619ad3bda..137b24102e0 100644 --- a/app/helpers/tab_helper.rb +++ b/app/helpers/tab_helper.rb @@ -9,7 +9,7 @@ module TabHelper # the <gl-tabs/> component. Can be populated by # gl_tab_link_to elements. # - # See more at: https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-tabs-tab--default + # See more at: https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-tabs--default def gl_tabs_nav(html_options = {}, &block) gl_tabs_classes = %w[nav gl-tabs-nav] diff --git a/app/helpers/timeboxes_routing_helper.rb b/app/helpers/timeboxes_routing_helper.rb deleted file mode 100644 index 6a5bef74dc9..00000000000 --- a/app/helpers/timeboxes_routing_helper.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -module TimeboxesRoutingHelper - def milestone_path(milestone, *args) - if milestone.group_milestone? - group_milestone_path(milestone.group, milestone, *args) - elsif milestone.project_milestone? - project_milestone_path(milestone.project, milestone, *args) - end - end - - def milestone_url(milestone, *args) - if milestone.group_milestone? - group_milestone_url(milestone.group, milestone, *args) - elsif milestone.project_milestone? - project_milestone_url(milestone.project, milestone, *args) - end - end -end - -TimeboxesRoutingHelper.prepend_mod_with('TimeboxesRoutingHelper') diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index daaf86e55a0..4a9dd30a5a2 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -139,6 +139,8 @@ module TodosHelper variant = 'info' if state == 'closed' when AlertManagement::Alert variant = 'info' if state == 'resolved' + else + variant = 'info' end content_tag(:span, class: 'todo-target-state') do diff --git a/app/helpers/tooling/visual_review_helper.rb b/app/helpers/tooling/visual_review_helper.rb index cd3b8be5aac..47afae49759 100644 --- a/app/helpers/tooling/visual_review_helper.rb +++ b/app/helpers/tooling/visual_review_helper.rb @@ -22,5 +22,9 @@ module Tooling 'id': 'review-app-toolbar-script', 'src': 'https://gitlab.com/assets/webpack/visual_review_toolbar.js' } end + + def review_apps_enabled? + Gitlab::Utils.to_boolean(ENV['REVIEW_APPS_ENABLED'], default: false) + end end end diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb index 370dbb10462..0aeea323ddb 100644 --- a/app/helpers/tree_helper.rb +++ b/app/helpers/tree_helper.rb @@ -14,8 +14,8 @@ module TreeHelper end # Simple shortcut to File.join - def tree_join(*args) - File.join(*args) + def tree_join(...) + File.join(...) end def on_top_of_branch?(project = @project, ref = @ref) diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb index 6ab78b58457..2b8368dd29f 100644 --- a/app/helpers/users/callouts_helper.rb +++ b/app/helpers/users/callouts_helper.rb @@ -25,10 +25,6 @@ module Users !user_dismissed?(GCP_SIGNUP_OFFER) end - def render_flash_user_callout(flash_type, message, feature_name) - render 'shared/flash_user_callout', flash_type: flash_type, message: message, feature_name: feature_name - end - def render_dashboard_ultimate_trial(user) end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index a382b5e7b74..62b9eb2b506 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -120,10 +120,6 @@ module UsersHelper !user.confirmed? end - def ban_feature_available? - Feature.enabled?(:ban_user_feature_flag) - end - def confirm_user_data(user) message = if user.unconfirmed_email.present? _('This user has an unconfirmed email address (%{email}). You may force a confirmation.') % { email: user.unconfirmed_email } @@ -262,9 +258,11 @@ module UsersHelper if with_schema_markup job_title = '<span itemprop="jobTitle">'.html_safe + job_title + "</span>".html_safe organization = '<span itemprop="worksFor">'.html_safe + organization + "</span>".html_safe - end - html_escape(s_('Profile|%{job_title} at %{organization}')) % { job_title: job_title, organization: organization } + html_escape(s_('Profile|%{job_title} at %{organization}')) % { job_title: job_title, organization: organization } + else + s_('Profile|%{job_title} at %{organization}') % { job_title: job_title, organization: organization } + end end def user_table_headers @@ -302,6 +300,10 @@ module UsersHelper other: s_('User|Other') }.with_indifferent_access.freeze end + + def saved_replies_enabled? + Feature.enabled?(:saved_replies, current_user) + end end UsersHelper.prepend_mod_with('UsersHelper') diff --git a/app/helpers/web_hooks/web_hooks_helper.rb b/app/helpers/web_hooks/web_hooks_helper.rb index bda9bf58fb7..514db6ba8a2 100644 --- a/app/helpers/web_hooks/web_hooks_helper.rb +++ b/app/helpers/web_hooks/web_hooks_helper.rb @@ -2,8 +2,6 @@ module WebHooks module WebHooksHelper - EXPIRY_TTL = 1.hour - def show_project_hook_failed_callout?(project:) return false if project_hook_page? return false unless current_user @@ -12,17 +10,11 @@ module WebHooks # Assumes include of Users::CalloutsHelper return false if web_hook_disabled_dismissed?(project) - any_project_hook_failed?(project) # Most expensive query last + project.fetch_web_hook_failure end private - def any_project_hook_failed?(project) - Rails.cache.fetch("any_web_hook_failed:#{project.id}", expires_in: EXPIRY_TTL) do - ProjectHook.for_projects(project).disabled.exists? - end - end - def project_hook_page? current_controller?('projects/hooks') || current_controller?('projects/hook_logs') end |