From e4384360a16dd9a19d4d2d25d0ef1f2b862ed2a6 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 19 Jul 2023 14:16:28 +0000 Subject: Add latest changes from gitlab-org/gitlab@16-2-stable-ee --- .../admin/application_settings/settings_helper.rb | 19 ++++- app/helpers/application_helper.rb | 20 ++--- app/helpers/application_settings_helper.rb | 3 +- app/helpers/auth_helper.rb | 3 +- app/helpers/blob_helper.rb | 4 +- app/helpers/button_helper.rb | 62 ++++++++++++++ app/helpers/calendar_helper.rb | 2 +- app/helpers/ci/jobs_helper.rb | 14 ++-- app/helpers/ci/pipeline_schedules_helper.rb | 19 +++++ app/helpers/ci/pipelines_helper.rb | 12 --- app/helpers/clusters_helper.rb | 6 -- app/helpers/colors_helper.rb | 4 +- app/helpers/emails_helper.rb | 2 +- app/helpers/environment_helper.rb | 7 -- app/helpers/environments_helper.rb | 26 +----- app/helpers/feed_token_helper.rb | 12 +++ app/helpers/form_helper.rb | 8 +- app/helpers/groups_helper.rb | 5 ++ app/helpers/integrations_helper.rb | 8 ++ app/helpers/issuables_helper.rb | 6 +- app/helpers/issues_helper.rb | 4 +- app/helpers/namespaces_helper.rb | 8 -- app/helpers/nav/new_dropdown_helper.rb | 8 +- app/helpers/nav/top_nav_helper.rb | 10 +-- app/helpers/packages_helper.rb | 10 +++ app/helpers/projects/observability_helper.rb | 13 +++ app/helpers/projects/pages_helper.rb | 12 +++ app/helpers/projects/pipeline_helper.rb | 2 +- app/helpers/projects_helper.rb | 95 ++++++---------------- app/helpers/rss_helper.rb | 2 +- app/helpers/search_helper.rb | 89 +++----------------- app/helpers/sidebars_helper.rb | 24 +++++- app/helpers/sorting_helper.rb | 11 +-- app/helpers/storage_helper.rb | 6 +- app/helpers/time_helper.rb | 4 - app/helpers/timeboxes_helper.rb | 4 +- app/helpers/users_helper.rb | 6 +- app/helpers/web_ide_button_helper.rb | 4 - 38 files changed, 275 insertions(+), 279 deletions(-) create mode 100644 app/helpers/ci/pipeline_schedules_helper.rb create mode 100644 app/helpers/feed_token_helper.rb create mode 100644 app/helpers/projects/observability_helper.rb (limited to 'app/helpers') diff --git a/app/helpers/admin/application_settings/settings_helper.rb b/app/helpers/admin/application_settings/settings_helper.rb index 0a7f20caa02..9ea07ba4e6e 100644 --- a/app/helpers/admin/application_settings/settings_helper.rb +++ b/app/helpers/admin/application_settings/settings_helper.rb @@ -16,12 +16,23 @@ module Admin project.repository&.gitlab_ci_yml.blank? end + def code_suggestions_description + link_start = code_suggestions_link_start(code_suggestions_docs_url) + + # rubocop:disable Layout/LineLength + # rubocop:disable Style/FormatString + s_('CodeSuggestionsSM|Enable Code Suggestions for users of this instance. %{link_start}What are Code Suggestions?%{link_end}') + .html_safe % { link_start: link_start, link_end: ''.html_safe } + # rubocop:enable Style/FormatString + # rubocop:enable Layout/LineLength + end + def code_suggestions_token_explanation link_start = code_suggestions_link_start(code_suggestions_pat_docs_url) # rubocop:disable Layout/LineLength # rubocop:disable Style/FormatString - s_('CodeSuggestionsSM|Your personal access token from GitLab.com. See the %{link_start}documentation%{link_end} for information on creating a personal access token.') + s_('CodeSuggestionsSM|On GitLab.com, create a token. This token is required to use Code Suggestions on your self-managed instance. %{link_start}How do I create a token?%{link_end}') .html_safe % { link_start: link_start, link_end: ''.html_safe } # rubocop:enable Style/FormatString # rubocop:enable Layout/LineLength @@ -33,8 +44,8 @@ module Admin # rubocop:disable Layout/LineLength # rubocop:disable Style/FormatString - s_('CodeSuggestionsSM|• Agree to the %{terms_link_start}GitLab Testing Agreement%{link_end}.%{br} • Acknowledge that GitLab will send data from the instance, including personal data, to Google for cloud hosting.%{br}    We may also send data to %{ai_docs_link_start}third-party AI providers%{link_end} to provide this feature.') - .html_safe % { terms_link_start: terms_link_start, ai_docs_link_start: ai_docs_link_start, link_end: ''.html_safe, br: '
'.html_safe } + s_('CodeSuggestionsSM|By enabling this feature, you agree to the %{terms_link_start}GitLab Testing Agreement%{link_end} and acknowledge that GitLab will send data from the instance, including personal data, to our %{ai_docs_link_start}AI providers%{link_end} to provide this feature.') + .html_safe % { terms_link_start: terms_link_start, ai_docs_link_start: ai_docs_link_start, link_end: ''.html_safe } # rubocop:enable Style/FormatString # rubocop:enable Layout/LineLength end @@ -53,7 +64,7 @@ module Admin end def code_suggestions_ai_docs_url - 'https://docs.gitlab.com/ee/user/ai_features.html' + 'https://docs.gitlab.com/ee/user/ai_features.html#third-party-services' end def code_suggestions_pat_docs_url diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7f1c28de8a7..ce338a8afdc 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -124,7 +124,8 @@ module ApplicationHelper page: body_data_page, page_type_id: controller.params[:id], find_file: find_file_path, - group: @group&.path + group: @group&.path, + group_full_path: @group&.full_path }.merge(project_data) end @@ -135,6 +136,7 @@ module ApplicationHelper project_id: @project.id, project: @project.path, group: @project.group&.path, + group_full_path: @project.group&.full_path, namespace_id: @project.namespace&.id } end @@ -274,15 +276,7 @@ module ApplicationHelper end def stylesheet_link_tag_defer(path) - if startup_css_enabled? - stylesheet_link_tag(path, media: "print", crossorigin: ActionController::Base.asset_host ? 'anonymous' : nil) - else - stylesheet_link_tag(path, media: "all", crossorigin: ActionController::Base.asset_host ? 'anonymous' : nil) - end - end - - def startup_css_enabled? - !Feature.enabled?(:remove_startup_css) && !params.has_key?(:no_startup_css) + stylesheet_link_tag(path, media: "all", crossorigin: ActionController::Base.asset_host ? 'anonymous' : nil) end def sign_in_with_redirect? @@ -336,7 +330,7 @@ module ApplicationHelper class_names << 'with-system-header' if appearance.show_header? class_names << 'with-system-footer' if appearance.show_footer? - class_names + class_names.join(' ') end # Returns active css class when condition returns true @@ -354,7 +348,7 @@ module ApplicationHelper def linkedin_url(user) name = user.linkedin - if name =~ %r{\Ahttps?://(www\.)?linkedin\.com/in/} + if %r{\Ahttps?://(www\.)?linkedin\.com/in/}.match?(name) name else "https://www.linkedin.com/in/#{name}" @@ -363,7 +357,7 @@ module ApplicationHelper def twitter_url(user) name = user.twitter - if name =~ %r{\Ahttps?://(www\.)?twitter\.com/} + if %r{\Ahttps?://(www\.)?twitter\.com/}.match?(name) name else "https://twitter.com/#{name}" diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index adbf7ab7cf2..aa2466372e1 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -497,7 +497,8 @@ module ApplicationSettingsHelper :projects_api_rate_limit_unauthenticated, :gitlab_dedicated_instance, :ci_max_includes, - :allow_account_deletion + :allow_account_deletion, + :gitlab_shell_operation_limit ].tap do |settings| next if Gitlab.com? diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index 0feaee2bd93..c928c6479de 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -53,7 +53,8 @@ module AuthHelper saml: 'saml_login_button', openid_connect: 'oidc_login_button', github: 'github_login_button', - gitlab: 'gitlab_oauth_login_button' + gitlab: 'gitlab_oauth_login_button', + facebook: 'facebook_login_button' }[provider.to_sym] end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index be9306ce80b..6746e6549ec 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -118,8 +118,8 @@ module BlobHelper "#{blob_raw_path.rpartition('/').first}/" end - # SVGs can contain malicious JavaScript; only include whitelisted - # elements and attributes. Note that this whitelist is by no means complete + # SVGs can contain malicious JavaScript; only include allowlisted + # elements and attributes. Note that this allowlist is by no means complete # and may omit some elements. def sanitize_svg_data(data) Gitlab::Sanitizers::SVG.clean(data) diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb index 64d6ba155cd..6e0ba748d85 100644 --- a/app/helpers/button_helper.rb +++ b/app/helpers/button_helper.rb @@ -98,6 +98,68 @@ module ButtonHelper href: href, data: data end + + # Creates a link that looks like a button. + # + # It renders a Pajamas::ButtonComponent. + # + # It has the same API as `link_to`, but with some additional options + # specific to button rendering. + # + # Examples: + # # Default button + # link_button_to _('Foo'), some_path + # + # # Default button using a block + # link_button_to some_path do + # _('Foo') + # end + # + # # Confirm variant + # link_button_to _('Foo'), some_path, variant: :confirm + # + # # With icon + # link_button_to _('Foo'), some_path, icon: 'pencil' + # + # # Icon-only + # # NOTE: The content must be `nil` in order to correctly render. Use aria-label + # # to ensure the link is accessible. + # link_button_to nil, some_path, icon: 'pencil', 'aria-label': _('Foo') + # + # # Small button + # link_button_to _('Foo'), some_path, size: :small + # + # # Secondary category danger button + # link_button_to _('Foo'), some_path, variant: :danger, category: :secondary + # + # For accessibility, ensure that icon-only links have aria-label set. + def link_button_to(name = nil, href = nil, options = nil, &block) + if block + options = href + href = name + end + + options ||= {} + + # Ignore args that don't make sense for links, like disabled, loading, etc. + options_for_button = %i[ + category + variant + size + block + selected + icon + target + method + ] + + args = options.slice(*options_for_button) + button_options = options.except(*options_for_button) + + render Pajamas::ButtonComponent.new(href: href, **args, button_options: button_options) do + block.present? ? yield : name + end + end end ButtonHelper.prepend_mod_with('ButtonHelper') diff --git a/app/helpers/calendar_helper.rb b/app/helpers/calendar_helper.rb index ad4116fc3da..d70a860d468 100644 --- a/app/helpers/calendar_helper.rb +++ b/app/helpers/calendar_helper.rb @@ -3,7 +3,7 @@ module CalendarHelper def calendar_url_options { format: :ics, - feed_token: current_user.try(:feed_token), + feed_token: generate_feed_token(:ics), due_date: Issue::DueNextMonthAndPreviousTwoWeeks.name, sort: 'closest_future_date' } end diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb index a7e1de173bd..991b1f4d74e 100644 --- a/app/helpers/ci/jobs_helper.rb +++ b/app/helpers/ci/jobs_helper.rb @@ -2,16 +2,16 @@ module Ci module JobsHelper - def jobs_data + def jobs_data(project, build) { - "endpoint" => project_job_path(@project, @build, format: :json), - "project_path" => @project.full_path, + "endpoint" => project_job_path(project, build, format: :json), + "project_path" => project.full_path, "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, - "build_stage" => @build.stage_name, + "runner_settings_url" => project_runners_path(build.project, anchor: 'js-runners-settings'), + "page_path" => project_job_path(project, build), + "build_status" => build.status, + "build_stage" => build.stage_name, "log_state" => '', "build_options" => javascript_build_options, "retry_outdated_job_docs_url" => help_page_path('ci/pipelines/settings', anchor: 'retry-outdated-jobs') diff --git a/app/helpers/ci/pipeline_schedules_helper.rb b/app/helpers/ci/pipeline_schedules_helper.rb new file mode 100644 index 00000000000..e5125353b99 --- /dev/null +++ b/app/helpers/ci/pipeline_schedules_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Ci + module PipelineSchedulesHelper + def js_pipeline_schedules_form_data(project, schedule) + { + full_path: project.full_path, + daily_limit: schedule.daily_limit, + timezone_data: timezone_data.to_json, + project_id: project.id, + default_branch: project.default_branch, + settings_link: project_settings_ci_cd_path(project), + schedules_path: pipeline_schedules_path(project) + } + end + end +end + +Ci::PipelineSchedulesHelper.prepend_mod_with('Ci::PipelineSchedulesHelper') diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb index b222ca5538d..a034e4331c0 100644 --- a/app/helpers/ci/pipelines_helper.rb +++ b/app/helpers/ci/pipelines_helper.rb @@ -68,18 +68,6 @@ module Ci ] end - def has_pipeline_badges?(pipeline) - pipeline.schedule? || - pipeline.child? || - pipeline.latest? || - pipeline.merge_train_pipeline? || - pipeline.has_yaml_errors? || - pipeline.failure_reason? || - pipeline.auto_devops_source? || - pipeline.detached_merge_request_pipeline? || - pipeline.stuck? - end - def pipelines_list_data(project, list_url) artifacts_endpoint_placeholder = ':pipeline_artifacts_id' diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb index 458d81b3401..5c410a28229 100644 --- a/app/helpers/clusters_helper.rb +++ b/app/helpers/clusters_helper.rb @@ -57,12 +57,6 @@ module ClustersHelper render_if_exists 'clusters/clusters/environments' when 'apps' render 'applications' - when 'integrations' - if Feature.enabled?(:remove_monitor_metrics) - render('details', expanded: expanded) - else - render 'integrations' - end when 'settings' render 'advanced_settings_container' else diff --git a/app/helpers/colors_helper.rb b/app/helpers/colors_helper.rb index bc72122220a..80cf6f197e5 100644 --- a/app/helpers/colors_helper.rb +++ b/app/helpers/colors_helper.rb @@ -4,7 +4,9 @@ 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 + unless hex_color.is_a?(String) && HEX_COLOR_PATTERN.match?(hex_color) + raise ArgumentError, "invalid hex color `#{hex_color}`" + end hex_color.length == 7 ? hex_color[1, 7].scan(/.{2}/).map(&:hex) : hex_color[1, 4].scan(/./).map { |v| (v * 2).hex } end diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index 9f4ed6b8150..7213bd074fc 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -41,7 +41,7 @@ module EmailsHelper end def sanitize_name(name) - if name =~ URI::DEFAULT_PARSER.regexp[:URI_REF] + if URI::DEFAULT_PARSER.regexp[:URI_REF].match?(name) name.tr('.', '_') else name diff --git a/app/helpers/environment_helper.rb b/app/helpers/environment_helper.rb index 00109212934..8140ee97291 100644 --- a/app/helpers/environment_helper.rb +++ b/app/helpers/environment_helper.rb @@ -79,7 +79,6 @@ 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(project, 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), @@ -96,10 +95,4 @@ module EnvironmentHelper def environments_detail_data_json(user, project, environment) environments_detail_data(user, project, environment).to_json end - - def environment_metrics_path(project, environment) - return {} if Feature.enabled?(:remove_monitor_metrics) - - { environment_metrics_path: project_metrics_dashboard_path(project, environment: environment) } - end end diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb index 525fdd3e9f6..3360a5256af 100644 --- a/app/helpers/environments_helper.rb +++ b/app/helpers/environments_helper.rb @@ -26,7 +26,7 @@ module EnvironmentsHelper metrics_data = {} metrics_data.merge!(project_metrics_data(project)) if project - metrics_data.merge!(environment_metrics_data(environment, project)) if environment + metrics_data.merge!(environment_metrics_data(environment)) if environment metrics_data.merge!(project_and_environment_metrics_data(project, environment)) if project && environment metrics_data.merge!(static_metrics_data) @@ -46,14 +46,6 @@ module EnvironmentsHelper can?(current_user, :destroy_environment, environment) end - def environment_data(environment) - Gitlab::Json.generate({ - id: environment.id, - name: environment.name, - external_url: environment.external_url - }) - end - private def project_metrics_data(project) @@ -74,34 +66,20 @@ module EnvironmentsHelper } end - def environment_metrics_data(environment, project = nil) + def environment_metrics_data(environment) return {} unless environment { - 'metrics_dashboard_base_path' => metrics_dashboard_base_path(environment, project), 'current_environment_name' => environment.name, 'has_metrics' => environment.has_metrics?.to_s, 'environment_state' => environment.state.to_s } end - def metrics_dashboard_base_path(environment, project) - # This is needed to support our transition from environment scoped metric paths to project scoped. - if project - path = project_metrics_dashboard_path(project) - - return path if request.path.include?(path) - end - - project_metrics_dashboard_path(project, environment: environment) - end - def project_and_environment_metrics_data(project, environment) return {} unless project && environment { - 'metrics_endpoint' => additional_metrics_project_environment_path(project, environment, format: :json), - 'dashboard_endpoint' => metrics_dashboard_project_environment_path(project, environment, format: :json), 'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json), 'operations_settings_path' => project_settings_operations_path(project), 'can_access_operations_settings' => can?(current_user, :admin_operations, project).to_s, diff --git a/app/helpers/feed_token_helper.rb b/app/helpers/feed_token_helper.rb new file mode 100644 index 00000000000..751a8df4782 --- /dev/null +++ b/app/helpers/feed_token_helper.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module FeedTokenHelper + def generate_feed_token(type) + feed_token = current_user&.feed_token + return unless feed_token + + final_path = "#{current_request.path}.#{type}" + digest = OpenSSL::HMAC.hexdigest("SHA256", feed_token, final_path) + "#{User::FEED_TOKEN_PREFIX}#{digest}-#{current_user.id}" + end +end diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index 3d0b899e867..d5f38debae4 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -165,8 +165,8 @@ module FormHelper def multiple_assignees_dropdown_options(options) new_options = options.dup - new_options[:title] = _('Select assignee(s)') - new_options[:data][:'dropdown-header'] = 'Assignee(s)' + new_options[:title] = _('Select assignees') + new_options[:data][:'dropdown-header'] = 'Assignees' new_options[:data][:'max-select'] = ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS new_options @@ -175,8 +175,8 @@ module FormHelper def multiple_reviewers_dropdown_options(options) new_options = options.dup - new_options[:title] = _('Select reviewer(s)') - new_options[:data][:'dropdown-header'] = _('Reviewer(s)') + new_options[:title] = _('Select reviewers') + new_options[:data][:'dropdown-header'] = _('Reviewers') new_options[:data][:'max-select'] = ::Issuable::MAX_NUMBER_OF_ASSIGNEES_OR_REVIEWERS diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index a4f463a23be..e552b01f7ba 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -25,6 +25,10 @@ module GroupsHelper Ability.allowed?(current_user, :admin_group_member, group) end + def can_admin_service_accounts?(group) + false + end + def group_icon_url(group, options = {}) if group.is_a?(String) group = Group.find_by_full_path(group) @@ -143,6 +147,7 @@ module GroupsHelper def group_overview_tabs_app_data(group) { + group_id: group.id, subgroups_and_projects_endpoint: group_children_path(group, format: :json), shared_projects_endpoint: group_shared_projects_path(group, format: :json), archived_projects_endpoint: group_children_path(group, format: :json, archived: 'only'), diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb index ffea23bf55d..4b5fadf3397 100644 --- a/app/helpers/integrations_helper.rb +++ b/app/helpers/integrations_helper.rb @@ -30,6 +30,10 @@ module IntegrationsHelper _("Alert") when "incident" _("Incident") + when "group_mention" + _("Group mention in public") + when "group_confidential_mention" + _("Group mention in private") end end # rubocop:enable Metrics/CyclomaticComplexity @@ -290,6 +294,10 @@ module IntegrationsHelper s_("ProjectService|Trigger event when a new, unique alert is recorded.") when "incident" s_("ProjectService|Trigger event when an incident is created.") + when "group_mention" + s_("ProjectService|Trigger event when a group is mentioned in a public context.") + when "group_confidential_mention" + s_("ProjectService|Trigger event when a group is mentioned in a confidential context.") end end # rubocop:enable Metrics/CyclomaticComplexity diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index e247577aed0..e921e9bae4d 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -43,14 +43,10 @@ module IssuablesHelper due_date_with_remaining_days(milestone[:due_date], milestone[:start_date]) end - def sidebar_due_date_tooltip_label(due_date) - [_('Due date'), due_date_with_remaining_days(due_date)].compact.join('
') - end - def due_date_with_remaining_days(due_date, start_date = nil) return unless due_date - "#{due_date.to_s(:medium)} (#{remaining_days_in_words(due_date, start_date)})" + "#{due_date.to_fs(:medium)} (#{remaining_days_in_words(due_date, start_date)})" end def multi_label_name(current_labels, default_label) diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 341c50abf84..d9b9b27d16c 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -231,13 +231,15 @@ module IssuesHelper can_read_crm_organization: can?(current_user, :read_crm_organization, group).to_s, has_any_issues: @has_issues.to_s, has_any_projects: @has_projects.to_s, - new_project_path: new_project_path(namespace_id: group.id) + new_project_path: new_project_path(namespace_id: group.id), + group_id: group.id ) end def dashboard_issues_list_data(current_user) { autocomplete_award_emojis_path: autocomplete_award_emojis_path, + autocomplete_users_path: autocomplete_users_path, calendar_path: url_for(safe_params.merge(calendar_url_options)), dashboard_labels_path: dashboard_labels_path(format: :json, include_ancestor_groups: true), dashboard_milestones_path: dashboard_milestones_path(format: :json), diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index 01030690daf..ff5e4248d98 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -5,14 +5,6 @@ module NamespacesHelper params.dig(:project, :namespace_id) || params[:namespace_id] end - def namespace_icon(namespace, size = 40) - if namespace.is_a?(Group) - group_icon_url(namespace) - else - avatar_icon_for_user(namespace.owner, size) - end - end - def cascading_namespace_settings_popover_data(attribute, group, settings_path_helper) locked_by_ancestor = group.namespace_settings.public_send("#{attribute}_locked_by_ancestor?") # rubocop:disable GitlabSecurity/PublicSend diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb index 201007863b2..306c4d8694e 100644 --- a/app/helpers/nav/new_dropdown_helper.rb +++ b/app/helpers/nav/new_dropdown_helper.rb @@ -70,7 +70,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', track_property: 'navigation_top', qa_selector: 'new_issue_link' } + data: { track_action: 'click_link_new_issue', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', testid: 'new_issue_link' } ) ) end @@ -116,7 +116,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', track_property: 'navigation_top', qa_selector: 'global_new_project_link' } + data: { track_action: 'click_link_new_project', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', testid: 'global_new_project_link' } ) ) end @@ -127,7 +127,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', track_property: 'navigation_top', qa_selector: 'global_new_group_link' } + data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', testid: 'global_new_group_link' } ) ) end @@ -138,7 +138,7 @@ 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', track_property: 'navigation_top', qa_selector: 'global_new_snippet_link' } + data: { track_action: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', testid: 'global_new_snippet_link' } ) ) end diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb index c41cf7f500f..d74efac76aa 100644 --- a/app/helpers/nav/top_nav_helper.rb +++ b/app/helpers/nav/top_nav_helper.rb @@ -109,7 +109,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", track_property: "navigation_top", qa_selector: "projects_dropdown" }, + data: { track_label: "projects_dropdown", track_action: "click_dropdown", track_property: "navigation_top", testid: "projects_dropdown" }, view: PROJECTS_VIEW, shortcut_href: dashboard_projects_path, **projects_menu_item_attrs @@ -123,7 +123,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", track_property: "navigation_top", qa_selector: "groups_dropdown" }, + data: { track_label: "groups_dropdown", track_action: "click_dropdown", track_property: "navigation_top", testid: "groups_dropdown" }, view: GROUPS_VIEW, shortcut_href: dashboard_groups_path, **groups_menu_item_attrs @@ -218,7 +218,7 @@ module Nav active: active_nav_link?(controller: 'admin/sessions'), icon: 'lock', href: new_admin_session_path, - data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } + data: { testid: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } ) end end @@ -316,7 +316,7 @@ module Nav id: 'your', title: title, href: dashboard_projects_path, - data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } + data: { testid: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } ) end @@ -330,7 +330,7 @@ module Nav id: 'your', title: title, href: dashboard_groups_path, - data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } + data: { testid: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) } ) builder.build end diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb index 8861f1ffe9a..31fcc77925b 100644 --- a/app/helpers/packages_helper.rb +++ b/app/helpers/packages_helper.rb @@ -74,6 +74,16 @@ module PackagesHelper Ability.allowed?(current_user, :admin_group, group) end + def can_delete_packages?(project) + Gitlab.config.packages.enabled && + Ability.allowed?(current_user, :destroy_package, project) + end + + def can_delete_group_packages?(group) + group.packages_feature_enabled? && + Ability.allowed?(current_user, :destroy_package, group) + end + def cleanup_settings_data { project_id: @project.id, diff --git a/app/helpers/projects/observability_helper.rb b/app/helpers/projects/observability_helper.rb new file mode 100644 index 00000000000..24bc1928a36 --- /dev/null +++ b/app/helpers/projects/observability_helper.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Projects + module ObservabilityHelper + def observability_tracing_view_model(project) + Gitlab::Json.generate({ + tracingUrl: Gitlab::Observability.tracing_url(project), + provisioningUrl: Gitlab::Observability.provisioning_url(project), + oauthUrl: Gitlab::Observability.oauth_url + }) + end + end +end diff --git a/app/helpers/projects/pages_helper.rb b/app/helpers/projects/pages_helper.rb index f46c11db1db..d90ea0ec598 100644 --- a/app/helpers/projects/pages_helper.rb +++ b/app/helpers/projects/pages_helper.rb @@ -7,5 +7,17 @@ module Projects (Gitlab.config.pages.external_http || Gitlab.config.pages.external_https) && project.can_create_custom_domains? end + + def pages_subdomain(project) + Gitlab::Pages::UrlBuilder + .new(project) + .project_namespace + end + + def build_pages_url(project, with_unique_domain:) + Gitlab::Pages::UrlBuilder + .new(project) + .pages_url(with_unique_domain: with_unique_domain) + end end end diff --git a/app/helpers/projects/pipeline_helper.rb b/app/helpers/projects/pipeline_helper.rb index caebbd5250e..42e8e44c94c 100644 --- a/app/helpers/projects/pipeline_helper.rb +++ b/app/helpers/projects/pipeline_helper.rb @@ -44,7 +44,7 @@ module Projects failed: pipeline.failure_reason?.to_s, auto_devops: pipeline.auto_devops_source?.to_s, detached: pipeline.detached_merge_request_pipeline?.to_s, - stuck: pipeline.stuck?, + stuck: pipeline.stuck?.to_s, ref_text: pipeline.ref_text } end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 9415e7d4dc3..e27ee1acb22 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -172,18 +172,6 @@ module ProjectsHelper project.fork_source if project.fork_source && can?(current_user, :read_project, project.fork_source) end - def project_search_tabs?(tab) - return false unless @project.present? - - abilities = Array(search_tab_ability_map[tab]) - - if @project.respond_to?(:each) # support multi-project select - @project.any? { |project| abilities.any? { |ability| can?(current_user, ability, project) } } - else - abilities.any? { |ability| can?(current_user, ability, @project) } - end - end - def can_change_visibility_level?(project, current_user) can?(current_user, :change_visibility_level, project) end @@ -511,9 +499,9 @@ module ProjectsHelper def clusters_deprecation_alert_message if has_active_license? - s_('ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}. Contact GitLab Support if you have any additional questions.') + s_('ClusterIntegration|The certificate-based Kubernetes integration is deprecated and will be removed in the future. You should %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}. For more information, see the %{deprecationLinkStart}deprecation epic%{deprecationLinkEnd}, or contact GitLab support.') else - s_('ClusterIntegration|The certificate-based Kubernetes integration has been deprecated and will be turned off at the end of February 2023. Please %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}.') + s_('ClusterIntegration|The certificate-based Kubernetes integration is deprecated and will be removed in the future. You should %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}. For more information, see the %{deprecationLinkStart}deprecation epic%{deprecationLinkEnd}.') end end @@ -547,8 +535,32 @@ module ProjectsHelper project.ssh_url_to_repo end + def can_view_branch_rules? + can?(current_user, :maintainer_access, @project) + end + + def can_push_code? + current_user&.can?(:push_code, @project) + end + + def can_admin_associated_clusters?(project) + can_admin_project_clusters?(project) || can_admin_group_clusters?(project) + end + + def branch_rules_path + project_settings_repository_path(@project, anchor: 'js-branch-rules') + end + private + def can_admin_project_clusters?(project) + project.clusters.any? && can?(current_user, :admin_cluster, project) + end + + def can_admin_group_clusters?(project) + project.group && project.group.clusters.any? && can?(current_user, :admin_cluster, project.group) + end + def create_merge_request_path(project, source_project, ref, merge_request) return if merge_request.present? return unless can?(current_user, :create_merge_request_from, project) @@ -590,41 +602,6 @@ module ProjectsHelper s_(str).html_safe % { provider: provider, link_start: link_start, link_end: ''.html_safe } end - def tab_ability_map - { - cycle_analytics: :read_cycle_analytics, - environments: :read_environment, - metrics_dashboards: :metrics_dashboard, - milestones: :read_milestone, - snippets: :read_snippet, - settings: :admin_project, - builds: :read_build, - clusters: :read_cluster, - serverless: :read_cluster, - terraform: :read_terraform_state, - error_tracking: :read_sentry_issue, - alert_management: :read_alert_management_alert, - incidents: :read_issue, - labels: :read_label, - issues: :read_issue, - project_members: :read_project_member, - wiki: :read_wiki, - feature_flags: :read_feature_flag, - analytics: :read_analytics - } - end - - def search_tab_ability_map - @search_tab_ability_map ||= tab_ability_map.merge( - blobs: :read_code, - commits: :read_code, - merge_requests: :read_merge_request, - notes: [:read_merge_request, :read_code, :read_issue, :read_snippet], - users: :read_project_member, - wiki_blobs: :read_wiki - ) - end - def project_lfs_status(project) if project.lfs_enabled? content_tag(:span, class: 'lfs-enabled') do @@ -880,24 +857,4 @@ module ProjectsHelper end end -def can_admin_associated_clusters?(project) - can_admin_project_clusters?(project) || can_admin_group_clusters?(project) -end - -def can_admin_project_clusters?(project) - project.clusters.any? && can?(current_user, :admin_cluster, project) -end - -def can_admin_group_clusters?(project) - project.group && project.group.clusters.any? && can?(current_user, :admin_cluster, project.group) -end - -def can_view_branch_rules? - can?(current_user, :maintainer_access, @project) -end - -def branch_rules_path - project_settings_repository_path(@project, anchor: 'js-branch-rules') -end - ProjectsHelper.prepend_mod_with('ProjectsHelper') diff --git a/app/helpers/rss_helper.rb b/app/helpers/rss_helper.rb index 67c7d244f11..90dd4e8fedb 100644 --- a/app/helpers/rss_helper.rb +++ b/app/helpers/rss_helper.rb @@ -2,6 +2,6 @@ module RssHelper def rss_url_options - { format: :atom, feed_token: current_user.try(:feed_token) } + { format: :atom, feed_token: generate_feed_token(:atom) } end end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 8fbbd18c9ae..cd32023adb6 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -373,17 +373,10 @@ module SearchHelper def users_autocomplete(term, limit = 5) return [] unless current_user && Ability.allowed?(current_user, :read_users_list) - users = if Feature.enabled?(:autocomplete_users_use_search_service) - ::SearchService - .new(current_user, { scope: 'users', per_page: limit, search: term }) - .search_objects - else - is_current_user_admin = current_user.can_admin_all_resources? - scope = is_current_user_admin ? User.all : User.without_forbidden_states - scope.search(term, with_private_emails: is_current_user_admin, use_minimum_char_limit: false).limit(limit) - end - - users.map do |user| + ::SearchService + .new(current_user, { scope: 'users', per_page: limit, search: term }) + .search_objects + .map do |user| { category: "Users", id: user.id, @@ -471,65 +464,15 @@ module SearchHelper result end - def show_code_search_tab? - return true if project_search_tabs?(:blobs) - - @project.nil? && search_service.show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_code_tab) - end - - def show_wiki_search_tab? - return true if project_search_tabs?(:wiki_blobs) - - @project.nil? && search_service.show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_wiki_tab) - end - - def show_commits_search_tab? - return true if project_search_tabs?(:commits) - - @project.nil? && search_service.show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_commits_tab) - end - - def show_issues_search_tab? - return true if project_search_tabs?(:issues) - - @project.nil? && feature_flag_tab_enabled?(:global_search_issues_tab) - end - - def show_merge_requests_search_tab? - return true if project_search_tabs?(:merge_requests) - - @project.nil? && feature_flag_tab_enabled?(:global_search_merge_requests_tab) - end - - def show_comments_search_tab? - return true if project_search_tabs?(:notes) - - @project.nil? && search_service.show_elasticsearch_tabs? - end - - def show_snippets_search_tab? - search_service.show_snippets? && @project.nil? && feature_flag_tab_enabled?(:global_search_snippet_titles_tab) - end - - # search page scope navigation - def search_navigation + def nav_options { - projects: { sort: 1, label: _("Projects"), data: { qa_selector: 'projects_tab' }, condition: @project.nil? }, - blobs: { sort: 2, label: _("Code"), data: { qa_selector: 'code_tab' }, condition: show_code_search_tab? }, - # sort: 3 is reserved for EE items - issues: { sort: 4, label: _("Issues"), condition: show_issues_search_tab? }, - merge_requests: { sort: 5, label: _("Merge requests"), condition: show_merge_requests_search_tab? }, - wiki_blobs: { sort: 6, label: _("Wiki"), condition: show_wiki_search_tab? }, - commits: { sort: 7, label: _("Commits"), condition: show_commits_search_tab? }, - notes: { sort: 8, label: _("Comments"), condition: show_comments_search_tab? }, - milestones: { sort: 9, label: _("Milestones"), condition: project_search_tabs?(:milestones) || @project.nil? }, - users: { sort: 10, label: _("Users"), condition: show_user_search_tab? }, - snippet_titles: { sort: 11, label: _("Titles and Descriptions"), search: { snippets: true, group_id: nil, project_id: nil }, condition: show_snippets_search_tab? } + show_snippets: search_service.show_snippets? } end def search_navigation_json - sorted_navigation = search_navigation.sort_by { |_, h| h[:sort] } + search_navigation = Search::Navigation.new(user: current_user, project: @project, group: @group, options: nav_options) + sorted_navigation = search_navigation.tabs.sort_by { |_, h| h[:sort] } sorted_navigation.each_with_object({}) do |(key, value), hash| hash[key] = search_filter_link_json(key, value[:label], value[:data], value[:search]) if value[:condition] @@ -611,14 +554,6 @@ module SearchHelper simple_search_highlight_and_truncate(issuable.description, search_term, highlighter: '\1') end - def show_user_search_tab? - return project_search_tabs?(:users) 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) - end - def issuable_state_to_badge_class(issuable) # Closed is considered "danger" for MR so we need to handle separately if issuable.is_a?(::MergeRequest) @@ -647,10 +582,6 @@ module SearchHelper end end - def feature_flag_tab_enabled?(flag) - @group.present? || Feature.enabled?(flag, current_user, type: :ops) - end - def sanitized_search_params sanitized_params = params.dup @@ -664,6 +595,10 @@ module SearchHelper sanitized_params end + + def wiki_blob_link(wiki_blob) + project_wiki_path(wiki_blob.project, wiki_blob.basename) + end end SearchHelper.prepend_mod_with('SearchHelper') diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb index 02a912d0227..90917cb96e0 100644 --- a/app/helpers/sidebars_helper.rb +++ b/app/helpers/sidebars_helper.rb @@ -23,6 +23,10 @@ module SidebarsHelper end end + def organization_sidebar_context(organization, user, **args) + Sidebars::Context.new(container: organization, current_user: user, **args) + end + def project_sidebar_context(project, user, current_ref, ref_type: nil, **args) context_data = project_sidebar_context_data(project, user, current_ref, ref_type: ref_type) Sidebars::Projects::Context.new(**context_data, **args) @@ -95,7 +99,7 @@ module SidebarsHelper def super_sidebar_nav_panel( nav: nil, project: nil, user: nil, group: nil, current_ref: nil, ref_type: nil, - viewed_user: nil) + viewed_user: nil, organization: nil) context_adds = { route_is_active: method(:active_nav_link?), is_super_sidebar: true } case nav when 'project' @@ -117,12 +121,25 @@ module SidebarsHelper Sidebars::Search::Panel.new(context) when 'admin' Sidebars::Admin::Panel.new(Sidebars::Context.new(current_user: user, container: nil, **context_adds)) + when 'organization' + context = organization_sidebar_context(organization, user, **context_adds) + Sidebars::Organizations::SuperSidebarPanel.new(context) else context = your_work_sidebar_context(user, **context_adds) Sidebars::YourWork::Panel.new(context) end end + def command_palette_data(project: nil) + return {} unless project&.repo_exists? + return {} if project.empty_repo? + + { + project_files_url: project_files_path(project, project.default_branch, format: :json), + project_blob_url: project_blob_path(project, project.default_branch) + } + end + private def search_data @@ -142,7 +159,8 @@ module SidebarsHelper customized: user.status&.customized?, availability: user.status&.availability.to_s, emoji: user.status&.emoji, - message: user.status&.message_html&.html_safe, + message_html: user.status&.message_html&.html_safe, + message: user.status&.message, clear_after: user_clear_status_at(user) } end @@ -162,7 +180,7 @@ module SidebarsHelper 'data-track-label': item[:id], 'data-track-action': 'click_link', 'data-track-property': 'nav_create_menu', - 'data-qa-selector': 'create_menu_item', + 'data-testid': 'create_menu_item', 'data-qa-create-menu-item': item[:id] } } diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 9038d972f65..1405bc7be37 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -2,6 +2,7 @@ module SortingHelper include SortingTitlesValuesHelper + include ButtonHelper # rubocop: disable Metrics/AbcSize def sort_options_hash @@ -167,10 +168,6 @@ module SortingHelper } end - def sortable_item(item, path, sorted_by) - link_to item, path, class: sorted_by == item ? 'is-active' : '' - end - def issuable_sort_option_overrides { sort_value_oldest_created => sort_value_created_date, @@ -275,7 +272,7 @@ module SortingHelper end def sort_direction_button(reverse_url, reverse_sort, sort_value) - link_class = 'gl-button btn btn-default btn-icon has-tooltip reverse-sort-btn rspec-reverse-sort' + link_class = 'has-tooltip reverse-sort-btn rspec-reverse-sort' icon = sort_direction_icon(sort_value) url = reverse_url @@ -284,9 +281,7 @@ module SortingHelper link_class += ' disabled' end - link_to(url, type: 'button', class: link_class, title: s_('SortOptions|Sort direction')) do - sprite_icon(icon) - end + link_button_to nil, url, class: link_class, title: s_('SortOptions|Sort direction'), icon: icon end def issuable_sort_direction_button(sort_value) diff --git a/app/helpers/storage_helper.rb b/app/helpers/storage_helper.rb index a60143db739..669d13c14c2 100644 --- a/app/helpers/storage_helper.rb +++ b/app/helpers/storage_helper.rb @@ -21,6 +21,10 @@ module StorageHelper counter_uploads: storage_counter(statistics.uploads_size) } - _("Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}") % counters + _( + "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / " \ + "Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / " \ + "Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}" + ) % counters end end diff --git a/app/helpers/time_helper.rb b/app/helpers/time_helper.rb index cb6f60ab79b..ad473875a53 100644 --- a/app/helpers/time_helper.rb +++ b/app/helpers/time_helper.rb @@ -17,10 +17,6 @@ module TimeHelper end end - def date_from_to(from, to) - "#{from.to_s(:short)} - #{to.to_s(:short)}" - end - def duration_in_numbers(duration_in_seconds) seconds = duration_in_seconds % 1.minute minutes = (duration_in_seconds / 1.minute) % (1.hour / 1.minute) diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb index 66c9011fbcc..cb6ed059ec9 100644 --- a/app/helpers/timeboxes_helper.rb +++ b/app/helpers/timeboxes_helper.rb @@ -109,7 +109,7 @@ module TimeboxesHelper content = [ title, "
", - date.to_s(:medium), + date.to_fs(:medium), "(#{time_ago} #{state})" ].join(" ") @@ -172,7 +172,7 @@ module TimeboxesHelper def milestone_tooltip_due_date(milestone) if milestone.due_date - "#{milestone.due_date.to_s(:medium)} (#{remaining_days_in_words(milestone.due_date, milestone.start_date)})" + "#{milestone.due_date.to_fs(:medium)} (#{remaining_days_in_words(milestone.due_date, milestone.start_date)})" else _('Milestone') end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index acc7d8a5a10..29998a996e2 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -12,7 +12,7 @@ module UsersHelper # The user.status can be nil when the user has no status, so we need to protect against that case. # iso8601 is the official RFC supported format for frontend parsing of date: # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date - user.status&.clear_status_at&.to_s(:iso8601) + user.status&.clear_status_at&.to_fs(:iso8601) end def user_link(user) @@ -190,7 +190,9 @@ module UsersHelper user_activity_path: user_activity_path(user, :json), utc_offset: local_timezone_instance(user.timezone).now.utc_offset, user_id: user.id, - snippets_empty_state: image_path('illustrations/empty-state/empty-snippets-md.svg') + snippets_empty_state: image_path('illustrations/empty-state/empty-snippets-md.svg'), + new_snippet_path: (new_snippet_path if can?(current_user, :create_snippet)), + follow_empty_state: image_path('illustrations/empty-state/empty-friends-md.svg') } end diff --git a/app/helpers/web_ide_button_helper.rb b/app/helpers/web_ide_button_helper.rb index 9ec22a659d3..185e1b8e0a8 100644 --- a/app/helpers/web_ide_button_helper.rb +++ b/app/helpers/web_ide_button_helper.rb @@ -33,10 +33,6 @@ module WebIdeButtonHelper can_view_pipeline_editor?(project) && path == project.ci_config_path_or_default end - def can_push_code? - current_user&.can?(:push_code, @project) - end - def fork? !project_fork.nil? && !can_push_code? end -- cgit v1.2.3