diff options
Diffstat (limited to 'app/helpers')
43 files changed, 382 insertions, 140 deletions
diff --git a/app/helpers/active_sessions_helper.rb b/app/helpers/active_sessions_helper.rb index 8fb23f99cb3..b80152777a8 100644 --- a/app/helpers/active_sessions_helper.rb +++ b/app/helpers/active_sessions_helper.rb @@ -20,6 +20,6 @@ module ActiveSessionsHelper 'monitor-o' end - sprite_icon(icon_name, size: 16, css_class: 'gl-mt-2') + sprite_icon(icon_name, css_class: 'gl-mt-2') end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e8bd5ad9b9b..41b20a1d9a0 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -194,6 +194,10 @@ module ApplicationHelper 'https://' + promo_host end + def contact_sales_url + promo_url + '/sales' + end + def support_url Gitlab::CurrentSettings.current_application_settings.help_page_support_url.presence || promo_url + '/getting-help/' end @@ -231,6 +235,18 @@ module ApplicationHelper "#{request.path}?#{options.compact.to_param}" end + def use_startup_css? + Feature.enabled?(:startup_css) && !Rails.env.test? + end + + def stylesheet_link_tag_defer(path) + if use_startup_css? + stylesheet_link_tag(path, media: "print") + else + stylesheet_link_tag(path, media: "all") + end + end + def outdated_browser? browser.ie? end diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index ddaac37e7ed..404700bb25e 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -327,7 +327,8 @@ module ApplicationSettingsHelper :project_download_export_limit, :group_import_limit, :group_export_limit, - :group_download_export_limit + :group_download_export_limit, + :wiki_page_max_content_bytes ] end diff --git a/app/helpers/award_emoji_helper.rb b/app/helpers/award_emoji_helper.rb index 13df53a751b..af9ab93d459 100644 --- a/app/helpers/award_emoji_helper.rb +++ b/app/helpers/award_emoji_helper.rb @@ -12,7 +12,7 @@ module AwardEmojiHelper toggle_award_emoji_project_note_path(@project, awardable.id) end else - url_for([:toggle_award_emoji, @project.namespace.becomes(Namespace), @project, awardable]) + url_for([:toggle_award_emoji, @project, awardable]) end end end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index f4238e7711a..615c834c529 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -48,24 +48,40 @@ module BlobHelper return unless blob = readable_blob(options, path, project, ref) common_classes = "btn btn-primary js-edit-blob ml-2 #{options[:extra_class]}" + data = { track_event: 'click_edit', track_label: 'Edit' } + + if Feature.enabled?(:web_ide_primary_edit, project.group) + common_classes += " btn-inverted" + data[:track_property] = 'secondary' + end edit_button_tag(blob, common_classes, _('Edit'), edit_blob_path(project, ref, path, options), project, - ref) + ref, + data) end def ide_edit_button(project = @project, ref = @ref, path = @path, blob:) return unless blob + common_classes = 'btn btn-primary ide-edit-button ml-2' + data = { track_event: 'click_edit_ide', track_label: 'Web IDE' } + + unless Feature.enabled?(:web_ide_primary_edit, project.group) + common_classes += " btn-inverted" + data[:track_property] = 'secondary' + end + edit_button_tag(blob, - 'btn btn-inverted btn-primary ide-edit-button ml-2', + common_classes, _('Web IDE'), ide_edit_path(project, ref, path), project, - ref) + ref, + data) end def modify_file_button(project = @project, ref = @ref, path = @path, blob:, label:, action:, btn_class:, modal_type:) @@ -184,6 +200,10 @@ module BlobHelper @gitlab_ci_ymls ||= template_dropdown_names(TemplateFinder.build(:gitlab_ci_ymls, project).execute) end + def metrics_dashboard_ymls(project) + @metrics_dashboard_ymls ||= template_dropdown_names(TemplateFinder.build(:metrics_dashboard_ymls, project).execute) + end + def dockerfile_names(project) @dockerfile_names ||= template_dropdown_names(TemplateFinder.build(:dockerfiles, project).execute) end @@ -325,16 +345,16 @@ module BlobHelper button_tag(button_text, class: "#{common_classes} disabled has-tooltip", title: _('You can only edit files when you are on a branch'), data: { container: 'body' }) end - def edit_link_tag(link_text, edit_path, common_classes) - link_to link_text, edit_path, class: "#{common_classes} btn-sm" + def edit_link_tag(link_text, edit_path, common_classes, data) + link_to link_text, edit_path, class: "#{common_classes} btn-sm", data: data end - def edit_button_tag(blob, common_classes, text, edit_path, project, ref) + def edit_button_tag(blob, common_classes, text, edit_path, project, ref, data) if !on_top_of_branch?(project, ref) edit_disabled_button_tag(text, common_classes) # This condition only applies to users who are logged in elsif !current_user || (current_user && can_modify_blob?(blob, project, ref)) - edit_link_tag(text, edit_path, common_classes) + edit_link_tag(text, edit_path, common_classes, data) elsif can?(current_user, :fork_project, project) && can?(current_user, :create_merge_request_in, project) edit_fork_button_tag(common_classes, project, text, edit_blob_fork_params(edit_path)) end @@ -343,7 +363,7 @@ module BlobHelper def show_suggest_pipeline_creation_celebration? experiment_enabled?(:suggest_pipeline) && @blob.path == Gitlab::FileDetector::PATTERNS[:gitlab_ci] && - @blob.auxiliary_viewer.valid?(project: @project, sha: @commit.sha, user: current_user) && + @blob.auxiliary_viewer&.valid?(project: @project, sha: @commit.sha, user: current_user) && @project.uses_default_ci_config? && cookies[suggest_pipeline_commit_cookie_name].present? end diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb index 60c19e6fecd..2a0242fe2fa 100644 --- a/app/helpers/branches_helper.rb +++ b/app/helpers/branches_helper.rb @@ -8,6 +8,14 @@ module BranchesHelper def protected_branch?(project, branch) ProtectedBranch.protected?(project, branch.name) end + + def access_levels_data(access_levels) + return [] unless access_levels + + access_levels.map do |level| + { id: level.id, type: :role, access_level: level.access_level } + end + end end BranchesHelper.prepend_if_ee('EE::BranchesHelper') diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb new file mode 100644 index 00000000000..749726e0e33 --- /dev/null +++ b/app/helpers/ci/pipelines_helper.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Ci + module PipelinesHelper + def pipeline_warnings(pipeline) + return unless pipeline.warning_messages.any? + + content_tag(:div, class: 'alert alert-warning') do + content_tag(:h4, 'Warning:') << + content_tag(:div) do + pipeline.warning_messages.each do |warning| + concat(markdown(warning.content)) + end + end + end + end + end +end diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb index c85d2a68f14..b97e847c397 100644 --- a/app/helpers/clusters_helper.rb +++ b/app/helpers/clusters_helper.rb @@ -24,6 +24,18 @@ module ClustersHelper } end + def js_cluster_form_data(cluster, can_edit) + { + enabled: cluster.enabled?.to_s, + editable: can_edit.to_s, + environment_scope: cluster.environment_scope, + base_domain: cluster.base_domain, + application_ingress_external_ip: cluster.application_ingress_external_ip, + auto_devops_help_path: help_page_path('topics/autodevops/index'), + external_endpoint_help_path: help_page_path('user/clusters/applications.md', anchor: 'pointing-your-dns-at-the-external-endpoint') + } + end + # This method is depreciated and will be removed when associated HAML files are moved to JavaScript def provider_icon(provider = nil) img_data = js_clusters_list_data.dig(:img_tags, provider&.to_sym) || diff --git a/app/helpers/custom_metrics_helper.rb b/app/helpers/custom_metrics_helper.rb index fbea6d2050f..5ea386e268d 100644 --- a/app/helpers/custom_metrics_helper.rb +++ b/app/helpers/custom_metrics_helper.rb @@ -2,10 +2,8 @@ module CustomMetricsHelper def custom_metrics_data(project, metric) - custom_metrics_path = project.namespace.becomes(::Namespace) - { - 'custom-metrics-path' => url_for([custom_metrics_path, project, metric]), + 'custom-metrics-path' => url_for([project, metric]), 'metric-persisted' => metric.persisted?.to_s, 'edit-project-service-path' => edit_project_service_path(project, PrometheusService), 'validate-query-path' => validate_query_project_prometheus_metrics_path(project), diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb index 7bf3795d73a..0ba03cd90ea 100644 --- a/app/helpers/dashboard_helper.rb +++ b/app/helpers/dashboard_helper.rb @@ -40,7 +40,7 @@ module DashboardHelper end) if doc_href.present? - link_to_doc = link_to(sprite_icon('question', size: 16), doc_href, + link_to_doc = link_to(sprite_icon('question'), doc_href, class: 'gl-ml-2', title: _('Documentation'), target: '_blank', rel: 'noopener noreferrer') diff --git a/app/helpers/environment_helper.rb b/app/helpers/environment_helper.rb index bd400009c96..c4487ae8e4a 100644 --- a/app/helpers/environment_helper.rb +++ b/app/helpers/environment_helper.rb @@ -19,7 +19,7 @@ module EnvironmentHelper end def deployment_path(deployment) - [deployment.project.namespace.becomes(Namespace), deployment.project, deployment.deployable] + [deployment.project, deployment.deployable] end def deployment_link(deployment, text: nil) diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb index b522a9dfb4f..39be8ae9f60 100644 --- a/app/helpers/environments_helper.rb +++ b/app/helpers/environments_helper.rb @@ -98,20 +98,21 @@ module EnvironmentsHelper 'deployments-endpoint' => project_environment_deployments_path(project, environment, format: :json), 'alerts-endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json), 'operations-settings-path' => project_settings_operations_path(project), - 'can-access-operations-settings' => can?(current_user, :admin_operations, project).to_s + 'can-access-operations-settings' => can?(current_user, :admin_operations, project).to_s, + 'panel-preview-endpoint' => project_metrics_dashboards_builder_path(project, format: :json) } end def static_metrics_data { 'documentation-path' => help_page_path('administration/monitoring/prometheus/index.md'), - 'add-dashboard-documentation-path' => help_page_path('user/project/integrations/prometheus.md', anchor: 'adding-a-new-dashboard-to-your-project'), + 'add-dashboard-documentation-path' => help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'), 'empty-getting-started-svg-path' => image_path('illustrations/monitoring/getting_started.svg'), 'empty-loading-svg-path' => image_path('illustrations/monitoring/loading.svg'), 'empty-no-data-svg-path' => image_path('illustrations/monitoring/no_data.svg'), 'empty-no-data-small-svg-path' => image_path('illustrations/chart-empty-state-small.svg'), 'empty-unable-to-connect-svg-path' => image_path('illustrations/monitoring/unable_to_connect.svg'), - 'custom-dashboard-base-path' => Metrics::Dashboard::CustomDashboardService::DASHBOARD_ROOT + 'custom-dashboard-base-path' => Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT } end end diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 207230fd92e..0167f2ef698 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -199,8 +199,7 @@ module EventsHelper elsif event.design_note? design_url(event.note_target, anchor: dom_id(event.note)) else - polymorphic_url([event.project.namespace.becomes(Namespace), - event.project, event.note_target], + polymorphic_url([event.project, event.note_target], anchor: dom_id(event.target)) end end diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index ecacde65c10..67bfeb22d92 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -11,7 +11,7 @@ module FormHelper content_tag(:h4, headline) << content_tag(:ul) do messages = model.errors.map do |attribute, message| - message = model.errors.full_message(attribute, message) + message = html_escape_once(model.errors.full_message(attribute, message)).html_safe message = content_tag(:span, message, class: 'str-truncated-100') if truncate.include?(attribute) content_tag(:li, message) diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index 04f34f5a3ae..d71e6b4c004 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -100,8 +100,12 @@ module GitlabRoutingHelper toggle_award_emoji_snippet_path(*args) end - def toggle_award_emoji_namespace_project_project_snippet_path(*args) - toggle_award_emoji_namespace_project_snippet_path(*args) + def toggle_award_emoji_project_project_snippet_path(*args) + toggle_award_emoji_project_snippet_path(*args) + end + + def toggle_award_emoji_project_project_snippet_url(*args) + toggle_award_emoji_project_snippet_url(*args) end ## Members @@ -271,7 +275,7 @@ module GitlabRoutingHelper end end - def gitlab_raw_snippet_blob_url(snippet, path, ref = nil) + def gitlab_raw_snippet_blob_url(snippet, path, ref = nil, **options) params = { snippet_id: snippet, ref: ref || snippet.repository.root_ref, @@ -279,26 +283,14 @@ module GitlabRoutingHelper } if snippet.is_a?(ProjectSnippet) - project_snippet_blob_raw_url(snippet.project, params) + project_snippet_blob_raw_url(snippet.project, **params, **options) else - snippet_blob_raw_url(params) + snippet_blob_raw_url(**params, **options) end end - def gitlab_raw_snippet_blob_path(blob, ref = nil) - snippet = blob.container - - params = { - snippet_id: snippet, - ref: ref || blob.repository.root_ref, - path: blob.path - } - - if snippet.is_a?(ProjectSnippet) - project_snippet_blob_raw_path(snippet.project, params) - else - snippet_blob_raw_path(params) - end + def gitlab_raw_snippet_blob_path(snippet, path, ref = nil, **options) + gitlab_raw_snippet_blob_url(snippet, path, ref, only_path: true, **options) end def gitlab_snippet_notes_path(snippet, *args) diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb index 49b15cde009..24072d1ab46 100644 --- a/app/helpers/graph_helper.rb +++ b/app/helpers/graph_helper.rb @@ -17,7 +17,7 @@ module GraphHelper end def success_ratio(counts) - return 100 if counts[:failed].zero? + return 100 if counts[:failed] == 0 ratio = (counts[:success].to_f / (counts[:success] + counts[:failed])) * 100 ratio.to_i diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 61c9bd74451..eb80acd869f 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -28,6 +28,7 @@ module GroupsHelper def group_packages_nav_link_paths %w[ + groups/packages#index groups/container_registries#index ] end @@ -129,7 +130,7 @@ module GroupsHelper end def remove_group_message(group) - _("You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?") % + _("You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?") % { group_name: group.name } end @@ -157,6 +158,15 @@ module GroupsHelper groups.to_json end + def group_packages_nav? + group_packages_list_nav? || + group_container_registry_nav? + end + + def group_packages_list_nav? + @group.packages_feature_enabled? + end + private def get_group_sidebar_links diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb index add15cc0d12..9957d5c6330 100644 --- a/app/helpers/icons_helper.rb +++ b/app/helpers/icons_helper.rb @@ -6,6 +6,8 @@ module IconsHelper extend self include FontAwesome::Rails::IconHelper + DEFAULT_ICON_SIZE = 16 + # Creates an icon tag given icon name(s) and possible icon modifiers. # # Right now this method simply delegates directly to `fa_icon` from the @@ -21,7 +23,7 @@ module IconsHelper options.include?(:base) ? fa_stacked_icon(names, options) : fa_icon(names, options) end - def custom_icon(icon_name, size: 16) + def custom_icon(icon_name, size: DEFAULT_ICON_SIZE) # We can't simply do the below, because there are some .erb SVGs. # File.read(Rails.root.join("app/views/shared/icons/_#{icon_name}.svg")).html_safe render "shared/icons/#{icon_name}.svg", size: size @@ -43,7 +45,7 @@ module IconsHelper ActionController::Base.helpers.image_path('file_icons.svg', host: sprite_base_url) end - def sprite_icon(icon_name, size: nil, css_class: nil) + def sprite_icon(icon_name, size: DEFAULT_ICON_SIZE, css_class: nil) if known_sprites&.exclude?(icon_name) exception = ArgumentError.new("#{icon_name} is not a known icon in @gitlab-org/gitlab-svg") Gitlab::ErrorTracking.track_and_raise_for_dev_exception(exception) @@ -52,7 +54,13 @@ module IconsHelper css_classes = [] css_classes << "s#{size}" if size css_classes << "#{css_class}" unless css_class.blank? - content_tag(:svg, content_tag(:use, "", { "xlink:href" => "#{sprite_icon_path}##{icon_name}" } ), class: css_classes.empty? ? nil : css_classes.join(' ')) + + content_tag( + :svg, + content_tag(:use, '', { 'xlink:href' => "#{sprite_icon_path}##{icon_name}" } ), + class: css_classes.empty? ? nil : css_classes.join(' '), + data: { testid: "#{icon_name}-icon" } + ) end def loading_icon(container: false, color: 'orange', size: 'sm', css_class: nil) @@ -94,11 +102,11 @@ module IconsHelper if value icon('circle', class: 'cgreen') else - icon('power-off', class: 'clgray') + sprite_icon('power', css_class: 'clgray') end end - def visibility_level_icon(level, fw: true, options: {}) + def visibility_level_icon(level, options: {}) name = case level when Gitlab::VisibilityLevel::PRIVATE @@ -106,13 +114,12 @@ module IconsHelper when Gitlab::VisibilityLevel::INTERNAL 'shield' else # Gitlab::VisibilityLevel::PUBLIC - 'globe' + 'earth' end - name = [name] - name << "fw" if fw + css_class = options.delete(:class) - icon(name.join(' '), options) + sprite_icon(name, size: DEFAULT_ICON_SIZE, css_class: css_class) end def file_type_icon_class(type, mode, name) diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb index 1ee67211ab0..329bbb5ad82 100644 --- a/app/helpers/import_helper.rb +++ b/app/helpers/import_helper.rb @@ -56,7 +56,7 @@ module ImportHelper link_url = 'https://github.com/settings/tokens' link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: link_url } - _('Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import.').html_safe % { link_start: link_start, link_end: '</a>'.html_safe } + html_escape(_('Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to import.')) % { link_start: link_start, link_end: '</a>'.html_safe, code_open: '<code>'.html_safe, code_close: '</code>'.html_safe } end def import_configure_github_admin_message diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index c9ba42491f3..0b859a39c4f 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -205,7 +205,7 @@ module IssuablesHelper author_output end - output << content_tag(:span, (issuable_first_contribution_icon if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!')) + output << content_tag(:span, (sprite_icon('first-contribution', css_class: 'gl-icon gl-vertical-align-middle') if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!')) output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-sm-none d-md-inline-block gl-ml-3") output << content_tag(:span, (issuable.task_status_short if issuable.tasks?), id: "task_status_short", class: "d-md-none") @@ -247,13 +247,6 @@ module IssuablesHelper html.html_safe end - def issuable_first_contribution_icon - content_tag(:span, class: 'fa-stack') do - concat(icon('certificate', class: "fa-stack-2x")) - concat(content_tag(:strong, '1', class: 'fa-inverse fa-stack-1x')) - end - end - def assigned_issuables_count(issuable_type) case issuable_type when :issues diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 61fe075303c..55170cbfa6b 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -41,7 +41,7 @@ module IssuesHelper end def confidential_icon(issue) - sprite_icon('eye-slash', size: 16, css_class: 'gl-vertical-align-text-bottom') if issue.confidential? + sprite_icon('eye-slash', css_class: 'gl-vertical-align-text-bottom') if issue.confidential? end def award_user_list(awards, current_user, limit: 10) diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index caf39741543..1125ecb9b41 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -170,12 +170,6 @@ module MergeRequestsHelper current_user.fork_of(project) end end - - def mr_tabs_position_enabled? - strong_memoize(:mr_tabs_position_enabled) do - Feature.enabled?(:mr_tabs_position, @project, default_enabled: true) - end - end end MergeRequestsHelper.prepend_if_ee('EE::MergeRequestsHelper') diff --git a/app/helpers/mirror_helper.rb b/app/helpers/mirror_helper.rb index 6f6cb91e696..50fc5e521fc 100644 --- a/app/helpers/mirror_helper.rb +++ b/app/helpers/mirror_helper.rb @@ -9,7 +9,7 @@ module MirrorHelper end def mirror_lfs_sync_message - _('The Git LFS objects will <strong>not</strong> be synced.').html_safe + html_escape(_('The Git LFS objects will %{strong_open}not%{strong_close} be synced.')) % { strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe } end end diff --git a/app/helpers/namespace_storage_limit_alert_helper.rb b/app/helpers/namespace_storage_limit_alert_helper.rb new file mode 100644 index 00000000000..d7174c38254 --- /dev/null +++ b/app/helpers/namespace_storage_limit_alert_helper.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module NamespaceStorageLimitAlertHelper + # Overridden in EE + def display_namespace_storage_limit_alert! + end +end + +NamespaceStorageLimitAlertHelper.prepend_if_ee('EE::NamespaceStorageLimitAlertHelper') diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 782f1d3e759..2ba1d841c2e 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -57,12 +57,14 @@ module NotesHelper def add_diff_note_button(line_code, position, line_type) return if @diff_notes_disabled - button_tag '', - class: 'add-diff-note js-add-diff-note-button', - type: 'submit', name: 'button', - data: diff_view_line_data(line_code, position, line_type), - title: _('Add a comment to this line') do - sprite_icon('comment', size: 12) + content_tag(:span, class: 'add-diff-note tooltip-wrapper') do + button_tag '', + class: 'note-button add-diff-note js-add-diff-note-button', + type: 'submit', name: 'button', + data: diff_view_line_data(line_code, position, line_type), + title: _('Add a comment to this line') do + sprite_icon('comment', size: 12) + end end end @@ -126,7 +128,7 @@ module NotesHelper if @snippet.is_a?(PersonalSnippet) [@note] else - [@project.namespace.becomes(Namespace), @project, @note] + [@project, @note] end end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 68dfd008921..9a64fe98f86 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -120,8 +120,4 @@ module NotificationsHelper def can_read_project?(project) can?(current_user, :read_project, project) end - - def notification_event_disabled?(event) - event == :fixed_pipeline && !Gitlab::Ci::Features.pipeline_fixed_notifications? - end end diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb index 3444773fe88..37e91153710 100644 --- a/app/helpers/operations_helper.rb +++ b/app/helpers/operations_helper.rb @@ -45,7 +45,7 @@ module OperationsHelper send_email: setting.send_email.to_s, pagerduty_active: setting.pagerduty_active.to_s, pagerduty_token: setting.pagerduty_token.to_s, - pagerduty_webhook_url: project_incidents_pagerduty_url(@project, token: setting.pagerduty_token), + pagerduty_webhook_url: project_incidents_integrations_pagerduty_url(@project, token: setting.pagerduty_token), pagerduty_reset_key_path: reset_pagerduty_token_project_settings_operations_path(@project) } end diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb new file mode 100644 index 00000000000..e6ecc403a88 --- /dev/null +++ b/app/helpers/packages_helper.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +module PackagesHelper + def package_sort_path(options = {}) + "#{request.path}?#{options.to_param}" + end + + def nuget_package_registry_url(project_id) + expose_url(api_v4_projects_packages_nuget_index_path(id: project_id, format: '.json')) + end + + def package_registry_instance_url(registry_type) + expose_url("api/#{::API::API.version}/packages/#{registry_type}") + end + + def package_registry_project_url(project_id, registry_type = :maven) + project_api_path = expose_path(api_v4_projects_path(id: project_id)) + package_registry_project_path = "#{project_api_path}/packages/#{registry_type}" + expose_url(package_registry_project_path) + end + + def package_from_presenter(package) + presenter = ::Packages::Detail::PackagePresenter.new(package) + + presenter.detail_view.to_json + end + + def pypi_registry_url(project_id) + full_url = expose_url(api_v4_projects_packages_pypi_simple_package_name_path({ id: project_id, package_name: '' }, true)) + full_url.sub!('://', '://__token__:<your_personal_token>@') + end + + def composer_registry_url(group_id) + expose_url(api_v4_group___packages_composer_packages_path(id: group_id, format: '.json')) + end + + def packages_coming_soon_enabled?(resource) + ::Feature.enabled?(:packages_coming_soon, resource) && ::Gitlab.dev_env_or_com? + end + + def packages_coming_soon_data(resource) + return unless packages_coming_soon_enabled?(resource) + + { + project_path: ::Gitlab.com? ? 'gitlab-org/gitlab' : 'gitlab-org/gitlab-test', + suggested_contributions: help_page_path('user/packages/index', anchor: 'suggested-contributions') + } + end + + def packages_list_data(type, resource) + { + resource_id: resource.id, + page_type: type, + empty_list_help_url: help_page_path('administration/packages/index'), + empty_list_illustration: image_path('illustrations/no-packages.svg'), + coming_soon_json: packages_coming_soon_data(resource).to_json + } + end +end diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb index 271359fcfd1..5a917a02d51 100644 --- a/app/helpers/preferences_helper.rb +++ b/app/helpers/preferences_helper.rb @@ -71,7 +71,7 @@ module PreferencesHelper def language_choices options_for_select( - Gitlab::I18n::AVAILABLE_LANGUAGES.map(&:reverse).sort, + Gitlab::I18n.selectable_locales.map(&:reverse).sort, current_user.preferred_language ) end diff --git a/app/helpers/product_analytics_helper.rb b/app/helpers/product_analytics_helper.rb new file mode 100644 index 00000000000..b040a8581b2 --- /dev/null +++ b/app/helpers/product_analytics_helper.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module ProductAnalyticsHelper + def product_analytics_tracker_url + ProductAnalytics::Tracker::URL + end + + def product_analytics_tracker_collector_url + ProductAnalytics::Tracker::COLLECTOR_URL + end +end diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb index d6e8e738a1c..c2f0b8854e1 100644 --- a/app/helpers/projects/alert_management_helper.rb +++ b/app/helpers/projects/alert_management_helper.rb @@ -5,7 +5,8 @@ module Projects::AlertManagementHelper { 'project-path' => project.full_path, 'enable-alert-management-path' => project_settings_operations_path(project, anchor: 'js-alert-management-settings'), - 'populating-alerts-help-url' => help_page_url('user/project/operations/alert_management.html', anchor: 'enable-alert-management'), + 'alerts-help-url' => help_page_url('operations/incident_management/index.md'), + 'populating-alerts-help-url' => help_page_url('operations/incident_management/index.md', anchor: 'enable-alert-management'), 'empty-alert-svg-path' => image_path('illustrations/alert-management-empty-state.svg'), 'user-can-enable-alert-management' => can?(current_user, :admin_operations, project).to_s, 'alert-management-enabled' => alert_management_enabled?(project).to_s diff --git a/app/helpers/projects/incidents_helper.rb b/app/helpers/projects/incidents_helper.rb new file mode 100644 index 00000000000..e96f0f5a384 --- /dev/null +++ b/app/helpers/projects/incidents_helper.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Projects::IncidentsHelper + def incidents_data(project) + { + 'project-path' => project.full_path, + 'new-issue-path' => new_project_issue_path(project), + 'incident-template-name' => 'incident', + 'incident-type' => 'incident', + 'issue-path' => project_issues_path(project), + 'empty-list-svg-path' => image_path('illustrations/incident-empty-state.svg') + } + end +end + +Projects::IncidentsHelper.prepend_if_ee('EE::Projects::IncidentsHelper') diff --git a/app/helpers/projects/issues/service_desk_helper.rb b/app/helpers/projects/issues/service_desk_helper.rb new file mode 100644 index 00000000000..0f87e5ed837 --- /dev/null +++ b/app/helpers/projects/issues/service_desk_helper.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Projects::Issues::ServiceDeskHelper + def service_desk_meta(project) + empty_state_meta = { + is_service_desk_supported: Gitlab::ServiceDesk.supported?, + is_service_desk_enabled: project.service_desk_enabled?, + can_edit_project_settings: can?(current_user, :admin_project, project) + } + + if Gitlab::ServiceDesk.supported? + empty_state_meta.merge(supported_meta(project)) + else + empty_state_meta.merge(unsupported_meta(project)) + end + end + + private + + def supported_meta(project) + { + service_desk_address: project.service_desk_address, + service_desk_help_page: help_page_path('user/project/service_desk'), + edit_project_page: edit_project_path(project), + svg_path: image_path('illustrations/service_desk_empty.svg') + } + end + + def unsupported_meta(project) + { + incoming_email_help_page: help_page_path('administration/incoming_email', anchor: 'set-it-up'), + svg_path: image_path('illustrations/service-desk-setup.svg') + } + end +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 840e3ef9daa..1ce4903f8df 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -104,7 +104,7 @@ module ProjectsHelper end def remove_project_message(project) - _("You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?") % + _("You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?") % { project_full_name: project.full_name } end @@ -184,9 +184,8 @@ module ProjectsHelper end def autodeploy_flash_notice(branch_name) - translation = _("Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}") % - { branch_name: truncate(sanitize(branch_name)), link_to_autodeploy_doc: link_to_autodeploy_doc } - translation.html_safe + html_escape(_("Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}")) % + { branch_name: tag.strong(truncate(sanitize(branch_name))), link_to_autodeploy_doc: link_to_autodeploy_doc } end def project_list_cache_key(project, pipeline_status: true) @@ -353,14 +352,14 @@ module ProjectsHelper description = if share_with_group && share_with_members - _("You can invite a new member to <strong>%{project_name}</strong> or invite another group.") + _("You can invite a new member to %{project_name} or invite another group.") elsif share_with_group - _("You can invite another group to <strong>%{project_name}</strong>.") + _("You can invite another group to %{project_name}.") elsif share_with_members - _("You can invite a new member to <strong>%{project_name}</strong>.") + _("You can invite a new member to %{project_name}.") end - description.html_safe % { project_name: project.name } + html_escape(description) % { project_name: tag.strong(project.name) } end def metrics_external_dashboard_url @@ -421,6 +420,10 @@ module ProjectsHelper nav_tabs << :operations end + if can_view_product_analytics?(current_user, project) + nav_tabs << :product_analytics + end + tab_ability_map.each do |tab, ability| if can?(current_user, ability, project) nav_tabs << tab @@ -429,9 +432,19 @@ module ProjectsHelper apply_external_nav_tabs(nav_tabs, project) + nav_tabs += package_nav_tabs(project, current_user) + nav_tabs end + def package_nav_tabs(project, current_user) + [].tap do |tabs| + if ::Gitlab.config.packages.enabled && can?(current_user, :read_package, project) + tabs << :packages + end + end + end + def apply_external_nav_tabs(nav_tabs, project) nav_tabs << :external_issue_tracker if project.external_issue_tracker nav_tabs << :external_wiki if project.external_wiki @@ -455,6 +468,7 @@ module ProjectsHelper serverless: :read_cluster, error_tracking: :read_sentry_issue, alert_management: :read_alert_management_alert, + incidents: :read_incidents, labels: :read_label, issues: :read_issue, project_members: :read_project_member, @@ -468,6 +482,11 @@ module ProjectsHelper end end + def can_view_product_analytics?(current_user, project) + Feature.enabled?(:product_analytics, project) && + can?(current_user, :read_product_analytics, project) + end + def search_tab_ability_map @search_tab_ability_map ||= tab_ability_map.merge( blobs: :download_code, @@ -584,6 +603,7 @@ module ProjectsHelper def project_permissions_settings(project) feature = project.project_feature { + packagesEnabled: !!project.packages_enabled, visibilityLevel: project.visibility_level, requestAccessEnabled: !!project.request_access_enabled, issuesAccessLevel: feature.issues_access_level, @@ -604,6 +624,8 @@ module ProjectsHelper def project_permissions_panel_data(project) { + packagesAvailable: ::Gitlab.config.packages.enabled, + packagesHelpPath: help_page_path('user/packages/index'), currentSettings: project_permissions_settings(project), canDisableEmails: can_disable_emails?(project, current_user), canChangeVisibilityLevel: can_change_visibility_level?(project, current_user), @@ -719,9 +741,13 @@ module ProjectsHelper functions error_tracking alert_management + incidents + incident_management user gcp logs + product_analytics + metrics_dashboard ] end @@ -748,7 +774,7 @@ module ProjectsHelper def project_access_token_available?(project) return false if ::Gitlab.com? - ::Feature.enabled?(:resource_access_token, project) + ::Feature.enabled?(:resource_access_token, project, default_enabled: true) end end diff --git a/app/helpers/releases_helper.rb b/app/helpers/releases_helper.rb index a3d944c64cc..f1dff18523f 100644 --- a/app/helpers/releases_helper.rb +++ b/app/helpers/releases_helper.rb @@ -19,7 +19,7 @@ module ReleasesHelper documentation_path: help_page }.tap do |data| if can?(current_user, :create_release, @project) - data[:new_release_path] = if Feature.enabled?(:new_release_page, @project) + data[:new_release_path] = if Feature.enabled?(:new_release_page, @project, default_enabled: true) new_project_release_path(@project) else new_project_tag_path(@project) @@ -37,7 +37,8 @@ module ReleasesHelper def data_for_new_release_page new_edit_pages_shared_data.merge( - default_branch: @project.default_branch + default_branch: @project.default_branch, + releases_page_path: project_releases_path(@project) ) end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 1b9876b9a6a..377aee1ae9e 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -229,6 +229,7 @@ module SearchHelper opts[:data]['group-id'] = @group.id opts[:data]['labels-endpoint'] = group_labels_path(@group) opts[:data]['milestones-endpoint'] = group_milestones_path(@group) + opts[:data]['releases-endpoint'] = group_releases_path(@group) else opts[:data]['labels-endpoint'] = dashboard_labels_path opts[:data]['milestones-endpoint'] = dashboard_milestones_path diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb index 1f9cce80bed..e9d39cc8175 100644 --- a/app/helpers/services_helper.rb +++ b/app/helpers/services_helper.rb @@ -35,19 +35,6 @@ module ServicesHelper "#{event}_events" end - def service_event_action_field_name(action) - "#{action}_on_event_enabled" - end - - def event_action_title(action) - case action - when "comment" - s_("ProjectService|Comment") - else - action.humanize - end - end - def service_save_button(disabled: false) button_tag(class: 'btn btn-success', type: 'submit', disabled: disabled, data: { qa_selector: 'save_changes_button' }) do icon('spinner spin', class: 'hidden js-btn-spinner') + @@ -95,10 +82,6 @@ module ServicesHelper end end - def integration_form_refactor? - Feature.enabled?(:integration_form_refactor, @project, default_enabled: true) - end - def integration_form_data(integration) { id: integration.id, @@ -116,23 +99,13 @@ module ServicesHelper end def trigger_events_for_service(integration) - return [] unless integration_form_refactor? - ServiceEventSerializer.new(service: integration).represent(integration.configurable_events).to_json end def fields_for_service(integration) - return [] unless integration_form_refactor? - ServiceFieldSerializer.new(service: integration).represent(integration.global_fields).to_json end - def show_service_trigger_events?(integration) - return false if integration.is_a?(JiraService) || integration_form_refactor? - - integration.configurable_events.present? - end - def project_jira_issues_integration? false end diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb index d6a9e447fbc..10c95da394f 100644 --- a/app/helpers/snippets_helper.rb +++ b/app/helpers/snippets_helper.rb @@ -60,9 +60,9 @@ module SnippetsHelper def snippet_badge(snippet) return unless attrs = snippet_badge_attributes(snippet) - css_class, text = attrs + icon_name, text = attrs tag.span(class: %w[badge badge-gray]) do - concat(tag.i(class: ['fa', css_class])) + concat(sprite_icon(icon_name, size: 14, css_class: 'gl-vertical-align-middle')) concat(' ') concat(text) end @@ -70,25 +70,24 @@ module SnippetsHelper def snippet_badge_attributes(snippet) if snippet.private? - ['fa-lock', _('private')] + ['lock', _('private')] end end - def embedded_raw_snippet_button - blob = @snippet.blob + def embedded_raw_snippet_button(snippet, blob) return if blob.empty? || blob.binary? || blob.stored_externally? link_to(external_snippet_icon('doc-code'), - gitlab_raw_snippet_url(@snippet), + gitlab_raw_snippet_blob_url(snippet, blob.path), class: 'btn', target: '_blank', rel: 'noopener noreferrer', title: 'Open raw') end - def embedded_snippet_download_button + def embedded_snippet_download_button(snippet, blob) link_to(external_snippet_icon('download'), - gitlab_raw_snippet_url(@snippet, inline: false), + gitlab_raw_snippet_blob_url(snippet, blob.path, nil, inline: false), class: 'btn', target: '_blank', title: 'Download', diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index ed1b35338ae..de6990041a6 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -238,7 +238,7 @@ module SortingHelper end link_to(url, type: 'button', class: link_class, title: s_('SortOptions|Sort direction')) do - sprite_icon(icon, size: 16) + sprite_icon(icon) end end @@ -581,6 +581,47 @@ module SortingHelper def sort_value_expire_date 'expired_asc' end + + def packages_sort_options_hash + { + sort_value_recently_created => sort_title_created_date, + sort_value_oldest_created => sort_title_created_date, + sort_value_name => sort_title_name, + sort_value_name_desc => sort_title_name, + sort_value_version_desc => sort_title_version, + sort_value_version_asc => sort_title_version, + sort_value_type_desc => sort_title_type, + sort_value_type_asc => sort_title_type, + sort_value_project_name_desc => sort_title_project_name, + sort_value_project_name_asc => sort_title_project_name + } + end + + def packages_reverse_sort_order_hash + { + sort_value_recently_created => sort_value_oldest_created, + sort_value_oldest_created => sort_value_recently_created, + sort_value_name => sort_value_name_desc, + sort_value_name_desc => sort_value_name, + sort_value_version_desc => sort_value_version_asc, + sort_value_version_asc => sort_value_version_desc, + sort_value_type_desc => sort_value_type_asc, + sort_value_type_asc => sort_value_type_desc, + sort_value_project_name_desc => sort_value_project_name_asc, + sort_value_project_name_asc => sort_value_project_name_desc + } + end + + def packages_sort_option_title(sort_value) + packages_sort_options_hash[sort_value] || sort_title_created_date + end + + def packages_sort_direction_button(sort_value) + reverse_sort = packages_reverse_sort_order_hash[sort_value] + url = package_sort_path(sort: reverse_sort) + + sort_direction_button(url, reverse_sort, sort_value) + end end SortingHelper.prepend_if_ee('::EE::SortingHelper') diff --git a/app/helpers/timeboxes_helper.rb b/app/helpers/timeboxes_helper.rb index 0bffdba7349..34919f994ee 100644 --- a/app/helpers/timeboxes_helper.rb +++ b/app/helpers/timeboxes_helper.rb @@ -40,7 +40,7 @@ module TimeboxesHelper opts = { milestone_title: milestone.title, state: state } if @project - polymorphic_path([@project.namespace.becomes(Namespace), @project, type], opts) + polymorphic_path([@project, type], opts) elsif @group polymorphic_url([type, @group], opts) else @@ -155,7 +155,7 @@ module TimeboxesHelper opened = milestone.opened_issues_count closed = milestone.closed_issues_count - return _("Issues") if total.zero? + return _("Issues") if total == 0 content = [] @@ -187,7 +187,7 @@ module TimeboxesHelper def milestone_releases_tooltip_text(milestone) count = milestone.releases.count - return _("Releases") if count.zero? + return _("Releases") if count == 0 n_("%{releases} release", "%{releases} releases", count) % { releases: count } end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index b9a6cab07a8..9865f7dfbef 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -163,7 +163,8 @@ module TodosHelper { id: '', text: 'Any Type' }, { id: 'Issue', text: 'Issue' }, { id: 'MergeRequest', text: 'Merge Request' }, - { id: 'DesignManagement::Design', text: 'Design' } + { id: 'DesignManagement::Design', text: 'Design' }, + { id: 'AlertManagement::Alert', text: 'Alert' } ] end diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb index 34c8ce51df0..98159369fb1 100644 --- a/app/helpers/user_callouts_helper.rb +++ b/app/helpers/user_callouts_helper.rb @@ -7,13 +7,15 @@ module UserCalloutsHelper SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed' TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight' WEBHOOKS_MOVED = 'webhooks_moved' + CUSTOMIZE_HOMEPAGE = 'customize_homepage' def show_admin_integrations_moved? !user_dismissed?(ADMIN_INTEGRATIONS_MOVED) end def show_gke_cluster_integration_callout?(project) - can?(current_user, :create_cluster, project) && + active_nav_link?(controller: sidebar_operations_paths) && + can?(current_user, :create_cluster, project) && !user_dismissed?(GKE_CLUSTER_INTEGRATION) end @@ -35,14 +37,14 @@ module UserCalloutsHelper !user_dismissed?(SUGGEST_POPOVER_DISMISSED) end - def show_tabs_feature_highlight? - current_user && !user_dismissed?(TABS_POSITION_HIGHLIGHT) && !Rails.env.test? - end - def show_webhooks_moved_alert? !user_dismissed?(WEBHOOKS_MOVED) end + def show_customize_homepage_banner?(customize_homepage) + customize_homepage && !user_dismissed?(CUSTOMIZE_HOMEPAGE) + end + private def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil) diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb index cf2d2d178e1..ad33ac66f38 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -80,7 +80,7 @@ module WikiHelper link_to(wiki_path(wiki, action: :pages, sort: sort, direction: reversed_direction), type: 'button', class: link_class, title: _('Sort direction')) do - sprite_icon("sort-#{icon_class}", size: 16) + sprite_icon("sort-#{icon_class}") end end |