Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 15:26:25 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-07-20 15:26:25 +0300
commita09983ae35713f5a2bbb100981116d31ce99826e (patch)
tree2ee2af7bd104d57086db360a7e6d8c9d5d43667a /app/helpers
parent18c5ab32b738c0b6ecb4d0df3994000482f34bd8 (diff)
Add latest changes from gitlab-org/gitlab@13-2-stable-ee
Diffstat (limited to 'app/helpers')
-rw-r--r--app/helpers/analytics/unique_visits_helper.rb32
-rw-r--r--app/helpers/application_helper.rb9
-rw-r--r--app/helpers/application_settings_helper.rb10
-rw-r--r--app/helpers/auto_devops_helper.rb4
-rw-r--r--app/helpers/blob_helper.rb3
-rw-r--r--app/helpers/builds_helper.rb38
-rw-r--r--app/helpers/ci/builds_helper.rb40
-rw-r--r--app/helpers/ci/jobs_helper.rb23
-rw-r--r--app/helpers/ci/pipeline_schedules_helper.rb15
-rw-r--r--app/helpers/ci/runners_helper.rb45
-rw-r--r--app/helpers/ci/status_helper.rb148
-rw-r--r--app/helpers/ci/variables_helper.rb54
-rw-r--r--app/helpers/ci_status_helper.rb146
-rw-r--r--app/helpers/ci_variables_helper.rb52
-rw-r--r--app/helpers/clusters_helper.rb8
-rw-r--r--app/helpers/commits_helper.rb12
-rw-r--r--app/helpers/cookies_helper.rb16
-rw-r--r--app/helpers/dashboard_helper.rb2
-rw-r--r--app/helpers/diff_helper.rb7
-rw-r--r--app/helpers/dropdowns_helper.rb5
-rw-r--r--app/helpers/environments_helper.rb26
-rw-r--r--app/helpers/events_helper.rb64
-rw-r--r--app/helpers/export_helper.rb2
-rw-r--r--app/helpers/gitlab_routing_helper.rb30
-rw-r--r--app/helpers/groups_helper.rb4
-rw-r--r--app/helpers/icons_helper.rb19
-rw-r--r--app/helpers/ide_helper.rb4
-rw-r--r--app/helpers/import_helper.rb6
-rw-r--r--app/helpers/issuables_helper.rb17
-rw-r--r--app/helpers/issues_helper.rb7
-rw-r--r--app/helpers/jobs_helper.rb19
-rw-r--r--app/helpers/markup_helper.rb1
-rw-r--r--app/helpers/members_helper.rb8
-rw-r--r--app/helpers/merge_requests_helper.rb2
-rw-r--r--app/helpers/namespaces_helper.rb39
-rw-r--r--app/helpers/nav_helper.rb2
-rw-r--r--app/helpers/notify_helper.rb11
-rw-r--r--app/helpers/onboarding_experiment_helper.rb9
-rw-r--r--app/helpers/operations_helper.rb54
-rw-r--r--app/helpers/pipeline_schedules_helper.rb13
-rw-r--r--app/helpers/preferences_helper.rb5
-rw-r--r--app/helpers/projects/alert_management_helper.rb16
-rw-r--r--app/helpers/projects_helper.rb35
-rw-r--r--app/helpers/releases_helper.rb27
-rw-r--r--app/helpers/runners_helper.rb43
-rw-r--r--app/helpers/search_helper.rb109
-rw-r--r--app/helpers/services_helper.rb75
-rw-r--r--app/helpers/storage_helper.rb5
-rw-r--r--app/helpers/system_note_helper.rb4
-rw-r--r--app/helpers/todos_helper.rb20
-rw-r--r--app/helpers/tree_helper.rb2
-rw-r--r--app/helpers/wiki_helper.rb44
52 files changed, 910 insertions, 481 deletions
diff --git a/app/helpers/analytics/unique_visits_helper.rb b/app/helpers/analytics/unique_visits_helper.rb
new file mode 100644
index 00000000000..ded7f54e44e
--- /dev/null
+++ b/app/helpers/analytics/unique_visits_helper.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Analytics
+ module UniqueVisitsHelper
+ extend ActiveSupport::Concern
+
+ def visitor_id
+ return cookies[:visitor_id] if cookies[:visitor_id].present?
+ return unless current_user
+
+ uuid = SecureRandom.uuid
+ cookies[:visitor_id] = { value: uuid, expires: 24.months }
+ uuid
+ end
+
+ def track_visit(target_id)
+ return unless Feature.enabled?(:track_unique_visits)
+ return unless Gitlab::CurrentSettings.usage_ping_enabled?
+ return unless visitor_id
+
+ Gitlab::Analytics::UniqueVisits.new.track_visit(visitor_id, target_id)
+ end
+
+ class_methods do
+ def track_unique_visits(controller_actions, target_id:)
+ after_action only: controller_actions, if: -> { request.format.html? && request.headers['DNT'] != '1' } do
+ track_visit(target_id)
+ end
+ end
+ end
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index bdfdf5a69b3..e8bd5ad9b9b 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -335,6 +335,15 @@ module ApplicationHelper
}
end
+ def page_startup_api_calls
+ @api_startup_calls
+ end
+
+ def add_page_startup_api_call(api_path, options: {})
+ @api_startup_calls ||= {}
+ @api_startup_calls[api_path] = options
+ end
+
def autocomplete_data_sources(object, noteable_type)
return {} unless object && noteable_type
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index e709d15a946..aa118a9bc45 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -190,6 +190,7 @@ module ApplicationSettingsHelper
:container_expiration_policies_enable_historic_entries,
:container_registry_token_expire_delay,
:default_artifacts_expire_in,
+ :default_branch_name,
:default_branch_protection,
:default_ci_config_path,
:default_group_visibility,
@@ -244,6 +245,7 @@ module ApplicationSettingsHelper
:metrics_method_call_threshold,
:minimum_password_length,
:mirror_available,
+ :notify_on_unknown_sign_in,
:pages_domain_verification_enabled,
:password_authentication_enabled_for_web,
:password_authentication_enabled_for_git,
@@ -319,7 +321,13 @@ module ApplicationSettingsHelper
:email_restrictions_enabled,
:email_restrictions,
:issues_create_limit,
- :raw_blob_request_limit
+ :raw_blob_request_limit,
+ :project_import_limit,
+ :project_export_limit,
+ :project_download_export_limit,
+ :group_import_limit,
+ :group_export_limit,
+ :group_download_export_limit
]
end
diff --git a/app/helpers/auto_devops_helper.rb b/app/helpers/auto_devops_helper.rb
index 0f14680607e..c27f5d4ebce 100644
--- a/app/helpers/auto_devops_helper.rb
+++ b/app/helpers/auto_devops_helper.rb
@@ -22,4 +22,8 @@ module AutoDevopsHelper
s_('CICD|instance enabled')
end
end
+
+ def auto_devops_settings_path(project)
+ project_settings_ci_cd_path(project, anchor: 'autodevops-settings')
+ end
end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 69fe3303840..f4238e7711a 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -52,13 +52,12 @@ module BlobHelper
edit_button_tag(blob,
common_classes,
_('Edit'),
- Feature.enabled?(:web_ide_default) ? ide_edit_path(project, ref, path) : edit_blob_path(project, ref, path, options),
+ edit_blob_path(project, ref, path, options),
project,
ref)
end
def ide_edit_button(project = @project, ref = @ref, path = @path, blob:)
- return if Feature.enabled?(:web_ide_default)
return unless blob
edit_button_tag(blob,
diff --git a/app/helpers/builds_helper.rb b/app/helpers/builds_helper.rb
deleted file mode 100644
index 2def3488184..00000000000
--- a/app/helpers/builds_helper.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module BuildsHelper
- def build_summary(build, skip: false)
- if build.has_trace?
- if skip
- link_to _("View job log"), pipeline_job_url(build.pipeline, build)
- else
- build.trace.html(last_lines: 10).html_safe
- end
- else
- _("No job log")
- end
- end
-
- def sidebar_build_class(build, current_build)
- build_class = []
- build_class << 'active' if build.id === current_build.id
- build_class << 'retried' if build.retried?
- build_class.join(' ')
- end
-
- def javascript_build_options
- {
- page_path: project_job_path(@project, @build),
- build_status: @build.status,
- build_stage: @build.stage,
- log_state: ''
- }
- end
-
- def build_failed_issue_options
- {
- title: _("Job Failed #%{build_id}") % { build_id: @build.id },
- description: project_job_url(@project, @build)
- }
- end
-end
diff --git a/app/helpers/ci/builds_helper.rb b/app/helpers/ci/builds_helper.rb
new file mode 100644
index 00000000000..bfdb830f2c3
--- /dev/null
+++ b/app/helpers/ci/builds_helper.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Ci
+ module BuildsHelper
+ def build_summary(build, skip: false)
+ if build.has_trace?
+ if skip
+ link_to _('View job log'), pipeline_job_url(build.pipeline, build)
+ else
+ build.trace.html(last_lines: 10).html_safe
+ end
+ else
+ _('No job log')
+ end
+ end
+
+ def sidebar_build_class(build, current_build)
+ build_class = []
+ build_class << 'active' if build.id === current_build.id
+ build_class << 'retried' if build.retried?
+ build_class.join(' ')
+ end
+
+ def javascript_build_options
+ {
+ page_path: project_job_path(@project, @build),
+ build_status: @build.status,
+ build_stage: @build.stage,
+ log_state: ''
+ }
+ end
+
+ def build_failed_issue_options
+ {
+ title: _("Job Failed #%{build_id}") % { build_id: @build.id },
+ description: project_job_url(@project, @build)
+ }
+ end
+ end
+end
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
new file mode 100644
index 00000000000..0344413b849
--- /dev/null
+++ b/app/helpers/ci/jobs_helper.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Ci
+ module JobsHelper
+ def jobs_data
+ {
+ "endpoint" => project_job_path(@project, @build, format: :json),
+ "project_path" => @project.full_path,
+ "deployment_help_url" => help_page_path('user/project/clusters/index.html', anchor: 'troubleshooting'),
+ "runner_help_url" => help_page_path('ci/runners/README.html', anchor: 'set-maximum-job-timeout-for-a-runner'),
+ "runner_settings_url" => project_runners_path(@build.project, anchor: 'js-runners-settings'),
+ "variables_settings_url" => project_variables_path(@build.project, anchor: 'js-cicd-variables-settings'),
+ "page_path" => project_job_path(@project, @build),
+ "build_status" => @build.status,
+ "build_stage" => @build.stage,
+ "log_state" => '',
+ "build_options" => javascript_build_options
+ }
+ end
+ end
+end
+
+Ci::JobsHelper.prepend_if_ee('::EE::Ci::JobsHelper')
diff --git a/app/helpers/ci/pipeline_schedules_helper.rb b/app/helpers/ci/pipeline_schedules_helper.rb
new file mode 100644
index 00000000000..20e5c90a60e
--- /dev/null
+++ b/app/helpers/ci/pipeline_schedules_helper.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineSchedulesHelper
+ def timezone_data
+ ActiveSupport::TimeZone.all.map do |timezone|
+ {
+ name: timezone.name,
+ offset: timezone.now.utc_offset,
+ identifier: timezone.tzinfo.identifier
+ }
+ end
+ end
+ end
+end
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
new file mode 100644
index 00000000000..8cdb28b2874
--- /dev/null
+++ b/app/helpers/ci/runners_helper.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Ci
+ module RunnersHelper
+ def runner_status_icon(runner)
+ status = runner.status
+ case status
+ when :not_connected
+ content_tag :i, nil,
+ class: "fa fa-warning",
+ title: "New runner. Has not connected yet"
+
+ when :online, :offline, :paused
+ content_tag :i, nil,
+ class: "fa fa-circle runner-status-#{status}",
+ title: "Runner is #{status}, last contact was #{time_ago_in_words(runner.contacted_at)} ago"
+ end
+ end
+
+ def runner_link(runner)
+ display_name = truncate(runner.display_name, length: 15)
+ id = "\##{runner.id}"
+
+ if current_user && current_user.admin
+ link_to admin_runner_path(runner) do
+ display_name + id
+ end
+ else
+ display_name + id
+ end
+ end
+
+ # Due to inability of performing sorting of runners by cached "contacted_at" values we have to show uncached values if sorting by "contacted_asc" is requested.
+ # Please refer to the following issue for more details: https://gitlab.com/gitlab-org/gitlab-foss/issues/55920
+ def runner_contacted_at(runner)
+ if params[:sort] == 'contacted_asc'
+ runner.uncached_contacted_at
+ else
+ runner.contacted_at
+ end
+ end
+ end
+end
+
+Ci::RunnersHelper.prepend_if_ee('EE::Ci::RunnersHelper')
diff --git a/app/helpers/ci/status_helper.rb b/app/helpers/ci/status_helper.rb
new file mode 100644
index 00000000000..bca49324a19
--- /dev/null
+++ b/app/helpers/ci/status_helper.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+##
+# DEPRECATED
+#
+# These helpers are deprecated in favor of detailed CI/CD statuses.
+#
+# See 'detailed_status?` method and `Gitlab::Ci::Status` module.
+#
+module Ci
+ module StatusHelper
+ def ci_label_for_status(status)
+ if detailed_status?(status)
+ return status.label
+ end
+
+ label = case status
+ when 'success'
+ 'passed'
+ when 'success-with-warnings'
+ 'passed with warnings'
+ when 'manual'
+ 'waiting for manual action'
+ when 'scheduled'
+ 'waiting for delayed job'
+ else
+ status
+ end
+ translation = "CiStatusLabel|#{label}"
+ s_(translation)
+ end
+
+ def ci_text_for_status(status)
+ if detailed_status?(status)
+ return status.text
+ end
+
+ case status
+ when 'success'
+ s_('CiStatusText|passed')
+ when 'success-with-warnings'
+ s_('CiStatusText|passed')
+ when 'manual'
+ s_('CiStatusText|blocked')
+ when 'scheduled'
+ s_('CiStatusText|delayed')
+ else
+ # All states are already being translated inside the detailed statuses:
+ # :running => Gitlab::Ci::Status::Running
+ # :skipped => Gitlab::Ci::Status::Skipped
+ # :failed => Gitlab::Ci::Status::Failed
+ # :success => Gitlab::Ci::Status::Success
+ # :canceled => Gitlab::Ci::Status::Canceled
+ # The following states are customized above:
+ # :manual => Gitlab::Ci::Status::Manual
+ status_translation = "CiStatusText|#{status}"
+ s_(status_translation)
+ end
+ end
+
+ def ci_status_for_statuseable(subject)
+ status = subject.try(:status) || 'not found'
+ status.humanize
+ end
+
+ # rubocop:disable Metrics/CyclomaticComplexity
+ def ci_icon_for_status(status, size: 16)
+ if detailed_status?(status)
+ return sprite_icon(status.icon, size: size)
+ end
+
+ icon_name =
+ case status
+ when 'success'
+ 'status_success'
+ when 'success-with-warnings'
+ 'status_warning'
+ when 'failed'
+ 'status_failed'
+ when 'pending'
+ 'status_pending'
+ when 'waiting_for_resource'
+ 'status_pending'
+ when 'preparing'
+ 'status_preparing'
+ when 'running'
+ 'status_running'
+ when 'play'
+ 'play'
+ when 'created'
+ 'status_created'
+ when 'skipped'
+ 'status_skipped'
+ when 'manual'
+ 'status_manual'
+ when 'scheduled'
+ 'status_scheduled'
+ else
+ 'status_canceled'
+ end
+
+ sprite_icon(icon_name, size: size)
+ end
+ # rubocop:enable Metrics/CyclomaticComplexity
+
+ def ci_icon_class_for_status(status)
+ group = detailed_status?(status) ? status.group : status.dasherize
+
+ "ci-status-icon-#{group}"
+ end
+
+ def pipeline_status_cache_key(pipeline_status)
+ "pipeline-status/#{pipeline_status.sha}-#{pipeline_status.status}"
+ end
+
+ def render_commit_status(commit, status, ref: nil, tooltip_placement: 'left')
+ project = commit.project
+ path = pipelines_project_commit_path(project, commit, ref: ref)
+
+ render_status_with_link(
+ status,
+ path,
+ tooltip_placement: tooltip_placement,
+ icon_size: 24)
+ end
+
+ def render_status_with_link(status, path = nil, type: _('pipeline'), tooltip_placement: 'left', cssclass: '', container: 'body', icon_size: 16)
+ klass = "ci-status-link #{ci_icon_class_for_status(status)} d-inline-flex #{cssclass}"
+ title = "#{type.titleize}: #{ci_label_for_status(status)}"
+ data = { toggle: 'tooltip', placement: tooltip_placement, container: container }
+
+ if path
+ link_to ci_icon_for_status(status, size: icon_size), path,
+ class: klass, title: title, data: data
+ else
+ content_tag :span, ci_icon_for_status(status, size: icon_size),
+ class: klass, title: title, data: data
+ end
+ end
+
+ def detailed_status?(status)
+ status.respond_to?(:text) &&
+ status.respond_to?(:group) &&
+ status.respond_to?(:label) &&
+ status.respond_to?(:icon)
+ end
+ end
+end
diff --git a/app/helpers/ci/variables_helper.rb b/app/helpers/ci/variables_helper.rb
new file mode 100644
index 00000000000..b20390d58e9
--- /dev/null
+++ b/app/helpers/ci/variables_helper.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Ci
+ module VariablesHelper
+ def ci_variable_protected_by_default?
+ Gitlab::CurrentSettings.current_application_settings.protected_ci_variables
+ end
+
+ def create_deploy_token_path(entity, opts = {})
+ if entity.is_a?(::Group)
+ create_deploy_token_group_settings_repository_path(entity, opts)
+ else
+ # TODO: change this path to 'create_deploy_token_project_settings_ci_cd_path'
+ # See MR comment for more detail: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27059#note_311585356
+ create_deploy_token_project_settings_repository_path(entity, opts)
+ end
+ end
+
+ def revoke_deploy_token_path(entity, token)
+ if entity.is_a?(::Group)
+ revoke_group_deploy_token_path(entity, token)
+ else
+ revoke_project_deploy_token_path(entity, token)
+ end
+ end
+
+ def ci_variable_protected?(variable, only_key_value)
+ if variable && !only_key_value
+ variable.protected
+ else
+ ci_variable_protected_by_default?
+ end
+ end
+
+ def ci_variable_masked?(variable, only_key_value)
+ if variable && !only_key_value
+ variable.masked
+ else
+ false
+ end
+ end
+
+ def ci_variable_type_options
+ [
+ %w(Variable env_var),
+ %w(File file)
+ ]
+ end
+
+ def ci_variable_maskable_regex
+ Ci::Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(/^\//, '').sub(/\/[a-z]*$/, '').gsub('\/', '/')
+ end
+ end
+end
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
deleted file mode 100644
index 80d1b7e7edb..00000000000
--- a/app/helpers/ci_status_helper.rb
+++ /dev/null
@@ -1,146 +0,0 @@
-# frozen_string_literal: true
-
-##
-# DEPRECATED
-#
-# These helpers are deprecated in favor of detailed CI/CD statuses.
-#
-# See 'detailed_status?` method and `Gitlab::Ci::Status` module.
-#
-module CiStatusHelper
- def ci_label_for_status(status)
- if detailed_status?(status)
- return status.label
- end
-
- label = case status
- when 'success'
- 'passed'
- when 'success-with-warnings'
- 'passed with warnings'
- when 'manual'
- 'waiting for manual action'
- when 'scheduled'
- 'waiting for delayed job'
- else
- status
- end
- translation = "CiStatusLabel|#{label}"
- s_(translation)
- end
-
- def ci_text_for_status(status)
- if detailed_status?(status)
- return status.text
- end
-
- case status
- when 'success'
- s_('CiStatusText|passed')
- when 'success-with-warnings'
- s_('CiStatusText|passed')
- when 'manual'
- s_('CiStatusText|blocked')
- when 'scheduled'
- s_('CiStatusText|delayed')
- else
- # All states are already being translated inside the detailed statuses:
- # :running => Gitlab::Ci::Status::Running
- # :skipped => Gitlab::Ci::Status::Skipped
- # :failed => Gitlab::Ci::Status::Failed
- # :success => Gitlab::Ci::Status::Success
- # :canceled => Gitlab::Ci::Status::Canceled
- # The following states are customized above:
- # :manual => Gitlab::Ci::Status::Manual
- status_translation = "CiStatusText|#{status}"
- s_(status_translation)
- end
- end
-
- def ci_status_for_statuseable(subject)
- status = subject.try(:status) || 'not found'
- status.humanize
- end
-
- # rubocop:disable Metrics/CyclomaticComplexity
- def ci_icon_for_status(status, size: 16)
- if detailed_status?(status)
- return sprite_icon(status.icon, size: size)
- end
-
- icon_name =
- case status
- when 'success'
- 'status_success'
- when 'success-with-warnings'
- 'status_warning'
- when 'failed'
- 'status_failed'
- when 'pending'
- 'status_pending'
- when 'waiting_for_resource'
- 'status_pending'
- when 'preparing'
- 'status_preparing'
- when 'running'
- 'status_running'
- when 'play'
- 'play'
- when 'created'
- 'status_created'
- when 'skipped'
- 'status_skipped'
- when 'manual'
- 'status_manual'
- when 'scheduled'
- 'status_scheduled'
- else
- 'status_canceled'
- end
-
- sprite_icon(icon_name, size: size)
- end
- # rubocop:enable Metrics/CyclomaticComplexity
-
- def ci_icon_class_for_status(status)
- group = detailed_status?(status) ? status.group : status.dasherize
-
- "ci-status-icon-#{group}"
- end
-
- def pipeline_status_cache_key(pipeline_status)
- "pipeline-status/#{pipeline_status.sha}-#{pipeline_status.status}"
- end
-
- def render_commit_status(commit, status, ref: nil, tooltip_placement: 'left')
- project = commit.project
- path = pipelines_project_commit_path(project, commit, ref: ref)
-
- render_status_with_link(
- status,
- path,
- tooltip_placement: tooltip_placement,
- icon_size: 24)
- end
-
- def render_status_with_link(status, path = nil, type: _('pipeline'), tooltip_placement: 'left', cssclass: '', container: 'body', icon_size: 16)
- klass = "ci-status-link #{ci_icon_class_for_status(status)} d-inline-flex #{cssclass}"
- title = "#{type.titleize}: #{ci_label_for_status(status)}"
- data = { toggle: 'tooltip', placement: tooltip_placement, container: container }
-
- if path
- link_to ci_icon_for_status(status, size: icon_size), path,
- class: klass, title: title, data: data
- else
- content_tag :span, ci_icon_for_status(status, size: icon_size),
- class: klass, title: title, data: data
- end
- end
-
- def detailed_status?(status)
- status.respond_to?(:text) &&
- status.respond_to?(:group) &&
- status.respond_to?(:label) &&
- status.respond_to?(:icon)
- end
-end
diff --git a/app/helpers/ci_variables_helper.rb b/app/helpers/ci_variables_helper.rb
deleted file mode 100644
index cd0718c1b82..00000000000
--- a/app/helpers/ci_variables_helper.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-module CiVariablesHelper
- def ci_variable_protected_by_default?
- Gitlab::CurrentSettings.current_application_settings.protected_ci_variables
- end
-
- def create_deploy_token_path(entity, opts = {})
- if entity.is_a?(Group)
- create_deploy_token_group_settings_repository_path(entity, opts)
- else
- # TODO: change this path to 'create_deploy_token_project_settings_ci_cd_path'
- # See MR comment for more detail: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27059#note_311585356
- create_deploy_token_project_settings_repository_path(entity, opts)
- end
- end
-
- def revoke_deploy_token_path(entity, token)
- if entity.is_a?(Group)
- revoke_group_deploy_token_path(entity, token)
- else
- revoke_project_deploy_token_path(entity, token)
- end
- end
-
- def ci_variable_protected?(variable, only_key_value)
- if variable && !only_key_value
- variable.protected
- else
- ci_variable_protected_by_default?
- end
- end
-
- def ci_variable_masked?(variable, only_key_value)
- if variable && !only_key_value
- variable.masked
- else
- false
- end
- end
-
- def ci_variable_type_options
- [
- %w(Variable env_var),
- %w(File file)
- ]
- end
-
- def ci_variable_maskable_regex
- Ci::Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(/^\//, '').sub(/\/[a-z]*$/, '').gsub('\/', '/')
- end
-end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index 1204f882707..c85d2a68f14 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -1,11 +1,6 @@
# frozen_string_literal: true
module ClustersHelper
- # EE overrides this
- def has_multiple_clusters?
- false
- end
-
def create_new_cluster_label(provider: nil)
case provider
when 'aws'
@@ -19,6 +14,7 @@ module ClustersHelper
def js_clusters_list_data(path = nil)
{
+ ancestor_help_path: help_page_path('user/group/clusters/index', anchor: 'cluster-precedence'),
endpoint: path,
img_tags: {
aws: { path: image_path('illustrations/logos/amazon_eks.svg'), text: s_('ClusterIntegration|Amazon EKS') },
@@ -95,5 +91,3 @@ module ClustersHelper
can?(user, :admin_cluster, cluster)
end
end
-
-ClustersHelper.prepend_if_ee('EE::ClustersHelper')
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 2a0c2e73dd6..f8490d79427 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -79,7 +79,7 @@ module CommitsHelper
# Returns a link formatted as a commit tag link
def commit_tag_link(url, text)
link_to(url, class: 'badge badge-gray ref-name') do
- sprite_icon('tag', size: 12, css_class: 'append-right-5 vertical-align-middle') + "#{text}"
+ sprite_icon('tag', size: 12, css_class: 'gl-mr-2 vertical-align-middle') + "#{text}"
end
end
@@ -181,15 +181,11 @@ module CommitsHelper
end
def view_file_button(commit_sha, diff_new_path, project, replaced: false)
+ path = project_blob_path(project, tree_join(commit_sha, diff_new_path))
title = replaced ? _('View replaced file @ ') : _('View file @ ')
- link_to(
- project_blob_path(project,
- tree_join(commit_sha, diff_new_path)),
- class: 'btn view-file js-view-file'
- ) do
- raw(title) + content_tag(:span, Commit.truncate_sha(commit_sha),
- class: 'commit-sha')
+ link_to(path, class: 'btn') do
+ raw(title) + content_tag(:span, truncate_sha(commit_sha), class: 'commit-sha')
end
end
diff --git a/app/helpers/cookies_helper.rb b/app/helpers/cookies_helper.rb
index 3a7e9987190..938379818de 100644
--- a/app/helpers/cookies_helper.rb
+++ b/app/helpers/cookies_helper.rb
@@ -1,9 +1,19 @@
# frozen_string_literal: true
module CookiesHelper
- def set_secure_cookie(key, value, httponly: false, permanent: false)
- cookie_jar = permanent ? cookies.permanent : cookies
+ COOKIE_TYPE_PERMANENT = :permanent
+ COOKIE_TYPE_ENCRYPTED = :encrypted
- cookie_jar[key] = { value: value, secure: Gitlab.config.gitlab.https, httponly: httponly }
+ def set_secure_cookie(key, value, httponly: false, expires: nil, type: nil)
+ cookie_jar = case type
+ when COOKIE_TYPE_PERMANENT
+ cookies.permanent
+ when COOKIE_TYPE_ENCRYPTED
+ cookies.encrypted
+ else
+ cookies
+ end
+
+ cookie_jar[key] = { value: value, secure: Gitlab.config.gitlab.https, httponly: httponly, expires: expires }
end
end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index b38feb0fb6c..7bf3795d73a 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -41,7 +41,7 @@ module DashboardHelper
if doc_href.present?
link_to_doc = link_to(sprite_icon('question', size: 16), doc_href,
- class: 'prepend-left-5', title: _('Documentation'),
+ class: 'gl-ml-2', title: _('Documentation'),
target: '_blank', rel: 'noopener noreferrer')
concat(link_to_doc)
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 4c3c4931387..3b25de521d0 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -135,8 +135,7 @@ module DiffHelper
def diff_file_html_data(project, diff_file_path, diff_commit_id)
{
- blob_diff_path: project_blob_diff_path(project,
- tree_join(diff_commit_id, diff_file_path)),
+ blob_diff_path: project_blob_diff_path(project, tree_join(diff_commit_id, diff_file_path)),
view: diff_view
}
end
@@ -175,6 +174,10 @@ module DiffHelper
end
end
+ def apply_diff_view_cookie!
+ set_secure_cookie(:diff_view, params.delete(:view), type: CookiesHelper::COOKIE_TYPE_PERMANENT) if params[:view].present?
+ end
+
private
def diff_btn(title, name, selected)
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 64c5fae7d96..772a5f79a4d 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -15,7 +15,10 @@ module DropdownsHelper
dropdown_output = dropdown_toggle_link(toggle_text, data_attr, options)
end
- dropdown_output << content_tag(:div, class: "dropdown-menu dropdown-select #{options[:dropdown_class] if options.key?(:dropdown_class)}") do
+ content_tag_options = { class: "dropdown-menu dropdown-select #{options[:dropdown_class] if options.key?(:dropdown_class)}" }
+ content_tag_options[:data] = { qa_selector: "#{options[:dropdown_qa_selector]}" } if options[:dropdown_qa_selector]
+
+ dropdown_output << content_tag(:div, content_tag_options) do
output = []
if options.key?(:title)
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 41a255434af..b522a9dfb4f 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -24,7 +24,7 @@ module EnvironmentsHelper
def metrics_data(project, environment)
metrics_data = {}
metrics_data.merge!(project_metrics_data(project)) if project
- metrics_data.merge!(environment_metrics_data(environment)) if environment
+ metrics_data.merge!(environment_metrics_data(environment, project)) if environment
metrics_data.merge!(project_and_environment_metrics_data(project, environment)) if project && environment
metrics_data.merge!(static_metrics_data)
@@ -36,7 +36,8 @@ module EnvironmentsHelper
"environment-name": environment.name,
"environments-path": project_environments_path(project, format: :json),
"environment-id": environment.id,
- "cluster-applications-documentation-path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack')
+ "cluster-applications-documentation-path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'),
+ "clusters-path": project_clusters_path(project, format: :json)
}
end
@@ -65,11 +66,11 @@ module EnvironmentsHelper
}
end
- def environment_metrics_data(environment)
+ def environment_metrics_data(environment, project = nil)
return {} unless environment
{
- 'metrics-dashboard-base-path' => environment_metrics_path(environment),
+ 'metrics-dashboard-base-path' => metrics_dashboard_base_path(environment, project),
'current-environment-name' => environment.name,
'has-metrics' => "#{environment.has_metrics?}",
'prometheus-status' => "#{environment.prometheus_status}",
@@ -77,6 +78,17 @@ module EnvironmentsHelper
}
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
+
+ environment_metrics_path(environment)
+ end
+
def project_and_environment_metrics_data(project, environment)
return {} unless project && environment
@@ -84,14 +96,16 @@ module EnvironmentsHelper
'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),
- 'alerts-endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, 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
}
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'),
'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'),
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index c1f343edd10..207230fd92e 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -29,7 +29,11 @@ module EventsHelper
def event_action_name(event)
target = if event.target_type
- if event.note?
+ if event.design? || event.design_note?
+ 'design'
+ elsif event.wiki_page?
+ 'wiki page'
+ elsif event.note?
event.note_target_type
else
event.target_type.titleize.downcase
@@ -58,11 +62,28 @@ module EventsHelper
end
def event_filter_visible(feature_key)
+ return designs_visible? if feature_key == :designs
return true unless @project
@project.feature_available?(feature_key, current_user)
end
+ def designs_visible?
+ if @project
+ design_activity_enabled?(@project)
+ elsif @group
+ design_activity_enabled?(@group)
+ elsif @projects
+ @projects.with_namespace.include_project_feature.any? { |p| design_activity_enabled?(p) }
+ else
+ true
+ end
+ end
+
+ def design_activity_enabled?(project)
+ Ability.allowed?(current_user, :read_design_activity, project)
+ end
+
def comments_visible?
event_filter_visible(:repository) ||
event_filter_visible(:merge_requests) ||
@@ -94,6 +115,12 @@ module EventsHelper
elsif event.milestone?
words << "##{event.target_iid}" if event.target_iid
words << "in"
+ elsif event.design?
+ words << event.design.to_reference
+ words << "in"
+ elsif event.wiki_page?
+ words << event.target_title
+ words << "in"
elsif event.target
prefix =
if event.merge_request?
@@ -180,10 +207,19 @@ module EventsHelper
def event_wiki_title_html(event)
capture do
- concat content_tag(:span, _('wiki page'), class: "event-target-type append-right-4")
+ concat content_tag(:span, _('wiki page'), class: "event-target-type gl-mr-2")
concat link_to(event.target_title, event_wiki_page_target_url(event),
title: event.target_title,
- class: 'has-tooltip event-target-link append-right-4')
+ class: 'has-tooltip event-target-link gl-mr-2')
+ end
+ end
+
+ def event_design_title_html(event)
+ capture do
+ concat content_tag(:span, _('design'), class: "event-target-type gl-mr-2")
+ concat link_to(event.design.reference_link_text, design_url(event.design),
+ title: event.target_title,
+ class: 'has-tooltip event-design event-target-link gl-mr-2')
end
end
@@ -194,8 +230,8 @@ module EventsHelper
def event_note_title_html(event)
if event.note_target
capture do
- concat content_tag(:span, event.note_target_type, class: "event-target-type append-right-4")
- concat link_to(event.note_target_reference, event_note_target_url(event), title: event.target_title, class: 'has-tooltip event-target-link append-right-4')
+ concat content_tag(:span, event.note_target_type, class: "event-target-type gl-mr-2")
+ concat link_to(event.note_target_reference, event_note_target_url(event), title: event.target_title, class: 'has-tooltip event-target-link gl-mr-2')
end
else
content_tag(:strong, '(deleted)')
@@ -214,6 +250,18 @@ module EventsHelper
sprite_icon(icon_name, size: size) if icon_name
end
+ DESIGN_ICONS = {
+ 'created' => 'upload',
+ 'updated' => 'pencil',
+ 'destroyed' => ICON_NAMES_BY_EVENT_TYPE['destroyed'],
+ 'archived' => 'archive'
+ }.freeze
+
+ def design_event_icon(action, size: 24)
+ icon_name = DESIGN_ICONS[action]
+ sprite_icon(icon_name, size: size) if icon_name
+ end
+
def icon_for_profile_event(event)
if current_path?('users#show')
content_tag :div, class: "system-note-image #{event.action_name.parameterize}-icon" do
@@ -228,7 +276,9 @@ module EventsHelper
def inline_event_icon(event)
unless current_path?('users#show')
- content_tag :span, class: "system-note-image-inline d-none d-sm-flex append-right-4 #{event.action_name.parameterize}-icon align-self-center" do
+ content_tag :span, class: "system-note-image-inline d-none d-sm-flex gl-mr-2 #{event.action_name.parameterize}-icon align-self-center" do
+ next design_event_icon(event.action, size: 14) if event.design?
+
icon_for_event(event.action_name, size: 14)
end
end
@@ -244,7 +294,7 @@ module EventsHelper
private
- def design_url(design, opts)
+ def design_url(design, opts = {})
designs_project_issue_url(
design.project,
design.issue,
diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb
index 483b350b99b..38a4f7f1b4b 100644
--- a/app/helpers/export_helper.rb
+++ b/app/helpers/export_helper.rb
@@ -6,7 +6,7 @@ module ExportHelper
[
_('Project and wiki repositories'),
_('Project uploads'),
- _('Project configuration, including services'),
+ _('Project configuration, excluding integrations'),
_('Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities'),
_('LFS objects'),
_('Issue Boards'),
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index 8a9380f4771..04f34f5a3ae 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -271,6 +271,36 @@ module GitlabRoutingHelper
end
end
+ def gitlab_raw_snippet_blob_url(snippet, path, ref = nil)
+ params = {
+ snippet_id: snippet,
+ ref: ref || snippet.repository.root_ref,
+ path: path
+ }
+
+ if snippet.is_a?(ProjectSnippet)
+ project_snippet_blob_raw_url(snippet.project, params)
+ else
+ snippet_blob_raw_url(params)
+ 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
+ end
+
def gitlab_snippet_notes_path(snippet, *args)
new_args = snippet_query_params(snippet, *args)
snippet_notes_path(snippet, *new_args)
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index a6c3c97a873..61c9bd74451 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -176,6 +176,10 @@ module GroupsHelper
links << :settings
end
+ if can?(current_user, :read_wiki, @group)
+ links << :wiki
+ end
+
links
end
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index 8a32d3c8a3f..add15cc0d12 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -28,10 +28,12 @@ module IconsHelper
end
def sprite_icon_path
- # SVG Sprites currently don't work across domains, so in the case of a CDN
- # we have to set the current path deliberately to prevent addition of asset_host
- sprite_base_url = Gitlab.config.gitlab.url if ActionController::Base.asset_host
- ActionController::Base.helpers.image_path('icons.svg', host: sprite_base_url)
+ @sprite_icon_path ||= begin
+ # SVG Sprites currently don't work across domains, so in the case of a CDN
+ # we have to set the current path deliberately to prevent addition of asset_host
+ sprite_base_url = Gitlab.config.gitlab.url if ActionController::Base.asset_host
+ ActionController::Base.helpers.image_path('icons.svg', host: sprite_base_url)
+ end
end
def sprite_file_icons_path
@@ -53,6 +55,15 @@ module IconsHelper
content_tag(:svg, content_tag(:use, "", { "xlink:href" => "#{sprite_icon_path}##{icon_name}" } ), class: css_classes.empty? ? nil : css_classes.join(' '))
end
+ def loading_icon(container: false, color: 'orange', size: 'sm', css_class: nil)
+ css_classes = ['gl-spinner', "gl-spinner-#{color}", "gl-spinner-#{size}"]
+ css_classes << "#{css_class}" unless css_class.blank?
+
+ spinner = content_tag(:span, "", { class: css_classes.join(' '), aria: { label: _('Loading') } })
+
+ container == true ? content_tag(:div, spinner, { class: 'gl-spinner-container' }) : spinner
+ end
+
def external_snippet_icon(name)
content_tag(:span, "", class: "gl-snippet-icon gl-snippet-icon-#{name}")
end
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index d6145493ba6..93f5ca7258d 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -9,10 +9,12 @@ module IdeHelper
"pipelines-empty-state-svg-path": image_path('illustrations/pipelines_empty.svg'),
"promotion-svg-path": image_path('illustrations/web-ide_promotion.svg'),
"ci-help-page-path" => help_page_path('ci/quick_start/README'),
- "web-ide-help-page-path" => help_page_path('user/project/web_ide/index.html'),
+ "web-ide-help-page-path" => help_page_path('user/project/web_ide/index.md'),
"clientside-preview-enabled": Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?.to_s,
"render-whitespace-in-code": current_user.render_whitespace_in_code.to_s,
"codesandbox-bundler-url": Gitlab::CurrentSettings.web_ide_clientside_preview_bundler_url
}
end
end
+
+::IdeHelper.prepend_if_ee('::EE::IdeHelper')
diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb
index 9122ad5b35a..1ee67211ab0 100644
--- a/app/helpers/import_helper.rb
+++ b/app/helpers/import_helper.rb
@@ -19,7 +19,11 @@ module ImportHelper
end
def provider_project_link_url(provider_url, full_path)
- Gitlab::Utils.append_path(provider_url, full_path)
+ if Gitlab::Utils.parse_url(full_path)&.absolute?
+ full_path
+ else
+ Gitlab::Utils.append_path(provider_url, full_path)
+ end
end
def import_will_timeout_message(_ci_cd_only)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index a848c814742..dccb89eec79 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -367,15 +367,6 @@ module IssuablesHelper
end
end
- def issuable_close_reopen_button_method(issuable)
- case issuable
- when Issue
- ''
- when MergeRequest
- 'put'
- end
- end
-
def issuable_author_is_current_user(issuable)
issuable.author == current_user
end
@@ -394,6 +385,14 @@ module IssuablesHelper
end
end
+ def issuable_squash_option?(issuable, project)
+ if issuable.persisted?
+ issuable.squash
+ else
+ project.squash_enabled_by_default?
+ end
+ end
+
private
def sidebar_gutter_collapsed?
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 244b97c7196..61fe075303c 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -41,7 +41,7 @@ module IssuesHelper
end
def confidential_icon(issue)
- icon('eye-slash') if issue.confidential?
+ sprite_icon('eye-slash', size: 16, css_class: 'gl-vertical-align-text-bottom') if issue.confidential?
end
def award_user_list(awards, current_user, limit: 10)
@@ -132,7 +132,10 @@ module IssuesHelper
end
def show_moved_service_desk_issue_warning?(issue)
- false
+ return false unless issue.moved_from
+ return false unless issue.from_service_desk?
+
+ issue.moved_from.project.service_desk_enabled? && !issue.project.service_desk_enabled?
end
end
diff --git a/app/helpers/jobs_helper.rb b/app/helpers/jobs_helper.rb
deleted file mode 100644
index 46edba261dd..00000000000
--- a/app/helpers/jobs_helper.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module JobsHelper
- def jobs_data
- {
- "endpoint" => project_job_path(@project, @build, format: :json),
- "project_path" => @project.full_path,
- "deployment_help_url" => help_page_path('user/project/clusters/index.html', anchor: 'troubleshooting-failed-deployment-jobs'),
- "runner_help_url" => help_page_path('ci/runners/README.html', anchor: 'setting-maximum-job-timeout-for-a-runner'),
- "runner_settings_url" => project_runners_path(@build.project, anchor: 'js-runners-settings'),
- "variables_settings_url" => project_variables_path(@build.project, anchor: 'js-cicd-variables-settings'),
- "page_path" => project_job_path(@project, @build),
- "build_status" => @build.status,
- "build_stage" => @build.stage,
- "log_state" => '',
- "build_options" => javascript_build_options
- }
- end
-end
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index 7ab2b33de8c..ed8931fe0f2 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -244,7 +244,6 @@ module MarkupHelper
content_tag :button,
type: 'button',
class: 'toolbar-btn js-md has-tooltip',
- tabindex: -1,
data: data,
title: options[:title],
aria: { label: options[:title] } do
diff --git a/app/helpers/members_helper.rb b/app/helpers/members_helper.rb
index 31995c27fac..d66f67fbb60 100644
--- a/app/helpers/members_helper.rb
+++ b/app/helpers/members_helper.rb
@@ -48,6 +48,14 @@ module MembersHelper
"#{request.path}?#{options.to_param}"
end
+ def member_path(member)
+ if member.is_a?(GroupMember)
+ group_group_member_path(member.source, member)
+ else
+ project_project_member_path(member.source, member)
+ end
+ end
+
private
def source_text(member)
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 7940ec1162b..caf39741543 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -118,7 +118,7 @@ module MergeRequestsHelper
auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS,
should_remove_source_branch: true,
sha: merge_request.diff_head_sha,
- squash: merge_request.squash
+ squash: merge_request.squash_on_merge?
}
end
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index b9f8d81bc4e..81451e398f2 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -56,45 +56,6 @@ module NamespacesHelper
namespaces_options(selected, options)
end
- def namespace_storage_alert(namespace)
- return {} if current_user.nil?
-
- payload = Namespaces::CheckStorageSizeService.new(namespace, current_user).execute.payload
-
- return {} if payload.empty?
-
- alert_level = payload[:alert_level]
- root_namespace = payload[:root_namespace]
-
- return {} if cookies["hide_storage_limit_alert_#{root_namespace.id}_#{alert_level}"] == 'true'
-
- payload
- end
-
- def namespace_storage_alert_style(alert_level)
- if alert_level == :error || alert_level == :alert
- 'danger'
- else
- alert_level.to_s
- end
- end
-
- def namespace_storage_alert_icon(alert_level)
- if alert_level == :error || alert_level == :alert
- 'error'
- elsif alert_level == :info
- 'information-o'
- else
- alert_level.to_s
- end
- end
-
- def namespace_storage_usage_link(namespace)
- # The usage quota page is only available in EE. This will be changed in
- # the future, see https://gitlab.com/gitlab-org/gitlab/-/issues/220042.
- nil
- end
-
private
# Many importers create a temporary Group, so use the real
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 9ea0b9cb584..d849ed9d076 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -27,7 +27,7 @@ module NavHelper
end
elsif current_path?('jobs#show')
%w[page-gutter build-sidebar right-sidebar-expanded]
- elsif current_controller?('wikis') && current_action?('show', 'create', 'edit', 'update', 'history', 'git_access', 'destroy')
+ elsif current_controller?('wikis') && current_action?('show', 'create', 'edit', 'update', 'history', 'git_access', 'destroy', 'diff')
%w[page-gutter wiki-sidebar right-sidebar-expanded]
else
[]
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
new file mode 100644
index 00000000000..fb68029928c
--- /dev/null
+++ b/app/helpers/notify_helper.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module NotifyHelper
+ def merge_request_reference_link(entity, *args)
+ link_to(entity.to_reference, merge_request_url(entity, *args))
+ end
+
+ def issue_reference_link(entity, *args)
+ link_to(entity.to_reference, issue_url(entity, *args))
+ end
+end
diff --git a/app/helpers/onboarding_experiment_helper.rb b/app/helpers/onboarding_experiment_helper.rb
deleted file mode 100644
index 138fc60479d..00000000000
--- a/app/helpers/onboarding_experiment_helper.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-module OnboardingExperimentHelper
- def allow_access_to_onboarding?
- ::Gitlab.dev_env_or_com? && Feature.enabled?(:user_onboarding)
- end
-end
-
-OnboardingExperimentHelper.prepend_if_ee('EE::OnboardingExperimentHelper')
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
new file mode 100644
index 00000000000..3444773fe88
--- /dev/null
+++ b/app/helpers/operations_helper.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module OperationsHelper
+ include Gitlab::Utils::StrongMemoize
+
+ def prometheus_service
+ strong_memoize(:prometheus_service) do
+ @project.find_or_initialize_service(::PrometheusService.to_param)
+ end
+ end
+
+ def alerts_service
+ strong_memoize(:alerts_service) do
+ @project.find_or_initialize_service(::AlertsService.to_param)
+ end
+ end
+
+ def alerts_settings_data(disabled: false)
+ {
+ 'prometheus_activated' => prometheus_service.manual_configuration?.to_s,
+ 'activated' => alerts_service.activated?.to_s,
+ 'prometheus_form_path' => scoped_integration_path(prometheus_service),
+ 'form_path' => scoped_integration_path(alerts_service),
+ 'prometheus_reset_key_path' => reset_alerting_token_project_settings_operations_path(@project),
+ 'prometheus_authorization_key' => @project.alerting_setting&.token,
+ 'prometheus_api_url' => prometheus_service.api_url,
+ 'authorization_key' => alerts_service.token,
+ 'prometheus_url' => notify_project_prometheus_alerts_url(@project, format: :json),
+ 'url' => alerts_service.url,
+ 'alerts_setup_url' => help_page_path('user/project/integrations/generic_alerts.md', anchor: 'setting-up-generic-alerts'),
+ 'alerts_usage_url' => project_alert_management_index_path(@project),
+ 'disabled' => disabled.to_s
+ }
+ end
+
+ def operations_settings_data
+ setting = project_incident_management_setting
+ templates = setting.available_issue_templates.map { |t| { key: t.key, name: t.name } }
+
+ {
+ operations_settings_endpoint: project_settings_operations_path(@project),
+ templates: templates.to_json,
+ create_issue: setting.create_issue.to_s,
+ issue_template_key: setting.issue_template_key.to_s,
+ 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_reset_key_path: reset_pagerduty_token_project_settings_operations_path(@project)
+ }
+ end
+end
+
+OperationsHelper.prepend_if_ee('EE::OperationsHelper')
diff --git a/app/helpers/pipeline_schedules_helper.rb b/app/helpers/pipeline_schedules_helper.rb
deleted file mode 100644
index 0e166106b32..00000000000
--- a/app/helpers/pipeline_schedules_helper.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module PipelineSchedulesHelper
- def timezone_data
- ActiveSupport::TimeZone.all.map do |timezone|
- {
- name: timezone.name,
- offset: timezone.now.utc_offset,
- identifier: timezone.tzinfo.identifier
- }
- end
- end
-end
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 7a0462e1b2c..271359fcfd1 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -70,7 +70,10 @@ module PreferencesHelper
end
def language_choices
- Gitlab::I18n::AVAILABLE_LANGUAGES.map(&:reverse).sort
+ options_for_select(
+ Gitlab::I18n::AVAILABLE_LANGUAGES.map(&:reverse).sort,
+ current_user.preferred_language
+ )
end
private
diff --git a/app/helpers/projects/alert_management_helper.rb b/app/helpers/projects/alert_management_helper.rb
index bc585899591..d6e8e738a1c 100644
--- a/app/helpers/projects/alert_management_helper.rb
+++ b/app/helpers/projects/alert_management_helper.rb
@@ -4,10 +4,11 @@ module Projects::AlertManagementHelper
def alert_management_data(current_user, project)
{
'project-path' => project.full_path,
- 'enable-alert-management-path' => edit_project_service_path(project, AlertsService),
+ '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'),
'empty-alert-svg-path' => image_path('illustrations/alert-management-empty-state.svg'),
- 'user-can-enable-alert-management' => can?(current_user, :admin_project, project).to_s,
- 'alert-management-enabled' => (!!project.alerts_service_activated?).to_s
+ 'user-can-enable-alert-management' => can?(current_user, :admin_operations, project).to_s,
+ 'alert-management-enabled' => alert_management_enabled?(project).to_s
}
end
@@ -15,7 +16,16 @@ module Projects::AlertManagementHelper
{
'alert-id' => alert_id,
'project-path' => project.full_path,
+ 'project-id' => project.id,
'project-issues-path' => project_issues_path(project)
}
end
+
+ private
+
+ def alert_management_enabled?(project)
+ !!(project.alerts_service_activated? || project.prometheus_service_active?)
+ end
end
+
+Projects::AlertManagementHelper.prepend_if_ee('EE::Projects::AlertManagementHelper')
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index bda9a69d71f..840e3ef9daa 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -180,7 +180,7 @@ module ProjectsHelper
end
def link_to_autodeploy_doc
- link_to _('About auto deploy'), help_page_path('autodevops/index.md#auto-deploy'), target: '_blank'
+ link_to _('About auto deploy'), help_page_path('topics/autodevops/stages.md', anchor: 'auto-deploy'), target: '_blank'
end
def autodeploy_flash_notice(branch_name)
@@ -384,9 +384,12 @@ module ProjectsHelper
end
def project_license_name(project)
- project.repository.license&.name
+ key = "project:#{project.id}:license_name"
+
+ Gitlab::SafeRequestStore.fetch(key) { project.repository.license&.name }
rescue GRPC::Unavailable, GRPC::DeadlineExceeded, Gitlab::Git::CommandError => e
Gitlab::ErrorTracking.track_exception(e)
+ Gitlab::SafeRequestStore[key] = nil
nil
end
@@ -397,7 +400,7 @@ module ProjectsHelper
nav_tabs = [:home]
unless project.empty_repo?
- nav_tabs << [:files, :commits, :network, :graphs, :forks] if can?(current_user, :download_code, project)
+ nav_tabs += [:files, :commits, :network, :graphs, :forks] if can?(current_user, :download_code, project)
nav_tabs << :releases if can?(current_user, :read_release, project)
end
@@ -418,30 +421,30 @@ module ProjectsHelper
nav_tabs << :operations
end
- if can?(current_user, :read_cycle_analytics, project)
- nav_tabs << :cycle_analytics
- end
-
tab_ability_map.each do |tab, ability|
if can?(current_user, ability, project)
nav_tabs << tab
end
end
- nav_tabs << external_nav_tabs(project)
+ apply_external_nav_tabs(nav_tabs, project)
- nav_tabs.flatten
+ nav_tabs
end
- def external_nav_tabs(project)
- [].tap do |tabs|
- tabs << :external_issue_tracker if project.external_issue_tracker
- tabs << :external_wiki if project.external_wiki
+ 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
+
+ if project.has_confluence?
+ nav_tabs.delete(:wiki)
+ nav_tabs << :confluence
end
end
def tab_ability_map
{
+ cycle_analytics: :read_cycle_analytics,
environments: :read_environment,
metrics_dashboards: :metrics_dashboard,
milestones: :read_milestone,
@@ -565,7 +568,7 @@ module ProjectsHelper
end
def project_child_container_class(view_path)
- view_path == "projects/issues/issues" ? "prepend-top-default" : "project-show-#{view_path}"
+ view_path == "projects/issues/issues" ? "gl-mt-3" : "project-show-#{view_path}"
end
def project_issues(project)
@@ -729,10 +732,6 @@ module ProjectsHelper
!project.repository.gitlab_ci_yml
end
- def vue_file_list_enabled?
- Feature.enabled?(:vue_file_list, @project, default_enabled: true)
- end
-
def native_code_navigation_enabled?(project)
Feature.enabled?(:code_navigation, project, default_enabled: true)
end
diff --git a/app/helpers/releases_helper.rb b/app/helpers/releases_helper.rb
index 1238567a4ed..a3d944c64cc 100644
--- a/app/helpers/releases_helper.rb
+++ b/app/helpers/releases_helper.rb
@@ -18,21 +18,40 @@ module ReleasesHelper
illustration_path: illustration,
documentation_path: help_page
}.tap do |data|
- data[:new_release_path] = new_project_tag_path(@project) if can?(current_user, :create_release, @project)
+ if can?(current_user, :create_release, @project)
+ data[:new_release_path] = if Feature.enabled?(:new_release_page, @project)
+ new_project_release_path(@project)
+ else
+ new_project_tag_path(@project)
+ end
+ end
end
end
def data_for_edit_release_page
+ new_edit_pages_shared_data.merge(
+ tag_name: @release.tag,
+ releases_page_path: project_releases_path(@project, anchor: @release.tag)
+ )
+ end
+
+ def data_for_new_release_page
+ new_edit_pages_shared_data.merge(
+ default_branch: @project.default_branch
+ )
+ end
+
+ private
+
+ def new_edit_pages_shared_data
{
project_id: @project.id,
- tag_name: @release.tag,
markdown_preview_path: preview_markdown_path(@project),
markdown_docs_path: help_page_path('user/markdown'),
- releases_page_path: project_releases_path(@project, anchor: @release.tag),
update_release_api_docs_path: help_page_path('api/releases/index.md', anchor: 'update-a-release'),
release_assets_docs_path: help_page(anchor: 'release-assets'),
manage_milestones_path: project_milestones_path(@project),
- new_milestone_path: new_project_milestone_url(@project)
+ new_milestone_path: new_project_milestone_path(@project)
}
end
end
diff --git a/app/helpers/runners_helper.rb b/app/helpers/runners_helper.rb
deleted file mode 100644
index d871aaa9c86..00000000000
--- a/app/helpers/runners_helper.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-module RunnersHelper
- def runner_status_icon(runner)
- status = runner.status
- case status
- when :not_connected
- content_tag :i, nil,
- class: "fa fa-warning",
- title: "New runner. Has not connected yet"
-
- when :online, :offline, :paused
- content_tag :i, nil,
- class: "fa fa-circle runner-status-#{status}",
- title: "Runner is #{status}, last contact was #{time_ago_in_words(runner.contacted_at)} ago"
- end
- end
-
- def runner_link(runner)
- display_name = truncate(runner.display_name, length: 15)
- id = "\##{runner.id}"
-
- if current_user && current_user.admin
- link_to admin_runner_path(runner) do
- display_name + id
- end
- else
- display_name + id
- end
- end
-
- # Due to inability of performing sorting of runners by cached "contacted_at" values we have to show uncached values if sorting by "contacted_asc" is requested.
- # Please refer to the following issue for more details: https://gitlab.com/gitlab-org/gitlab-foss/issues/55920
- def runner_contacted_at(runner)
- if params[:sort] == 'contacted_asc'
- runner.uncached_contacted_at
- else
- runner.contacted_at
- end
- end
-end
-
-RunnersHelper.prepend_if_ee('EE::RunnersHelper')
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 4e3b6aad8cc..1b9876b9a6a 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -3,6 +3,28 @@
module SearchHelper
SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets].freeze
+ def search_autocomplete_opts(term)
+ return unless current_user
+
+ resources_results = [
+ groups_autocomplete(term),
+ projects_autocomplete(term)
+ ].flatten
+
+ search_pattern = Regexp.new(Regexp.escape(term), "i")
+
+ generic_results = project_autocomplete + default_autocomplete + help_autocomplete
+ generic_results.concat(default_autocomplete_admin) if current_user.admin?
+ generic_results.select! { |result| result[:label] =~ search_pattern }
+
+ [
+ resources_results,
+ generic_results
+ ].flatten.uniq do |item|
+ item[:label]
+ end
+ end
+
def search_entries_info(collection, scope, term)
return if collection.to_a.empty?
@@ -62,7 +84,7 @@ module SearchHelper
}).html_safe
end
- # Overriden in EE
+ # Overridden in EE
def search_blob_title(project, path)
path
end
@@ -73,6 +95,91 @@ module SearchHelper
private
+ # Autocomplete results for various settings pages
+ def default_autocomplete
+ [
+ { category: "Settings", label: _("User settings"), url: profile_path },
+ { category: "Settings", label: _("SSH Keys"), url: profile_keys_path },
+ { category: "Settings", label: _("Dashboard"), url: root_path }
+ ]
+ end
+
+ # Autocomplete results for settings pages, for admins
+ def default_autocomplete_admin
+ [
+ { category: "Settings", label: _("Admin Section"), url: admin_root_path }
+ ]
+ end
+
+ # Autocomplete results for internal help pages
+ def help_autocomplete
+ [
+ { category: "Help", label: _("API Help"), url: help_page_path("api/README") },
+ { category: "Help", label: _("Markdown Help"), url: help_page_path("user/markdown") },
+ { category: "Help", label: _("Permissions Help"), url: help_page_path("user/permissions") },
+ { category: "Help", label: _("Public Access Help"), url: help_page_path("public_access/public_access") },
+ { category: "Help", label: _("Rake Tasks Help"), url: help_page_path("raketasks/README") },
+ { category: "Help", label: _("SSH Keys Help"), url: help_page_path("ssh/README") },
+ { category: "Help", label: _("System Hooks Help"), url: help_page_path("system_hooks/system_hooks") },
+ { category: "Help", label: _("Webhooks Help"), url: help_page_path("user/project/integrations/webhooks") },
+ { category: "Help", label: _("Workflow Help"), url: help_page_path("workflow/README") }
+ ]
+ end
+
+ # Autocomplete results for the current project, if it's defined
+ def project_autocomplete
+ if @project && @project.repository.root_ref
+ ref = @ref || @project.repository.root_ref
+
+ [
+ { category: "In this project", label: _("Files"), url: project_tree_path(@project, ref) },
+ { category: "In this project", label: _("Commits"), url: project_commits_path(@project, ref) },
+ { category: "In this project", label: _("Network"), url: project_network_path(@project, ref) },
+ { category: "In this project", label: _("Graph"), url: project_graph_path(@project, ref) },
+ { category: "In this project", label: _("Issues"), url: project_issues_path(@project) },
+ { category: "In this project", label: _("Merge Requests"), url: project_merge_requests_path(@project) },
+ { category: "In this project", label: _("Milestones"), url: project_milestones_path(@project) },
+ { category: "In this project", label: _("Snippets"), url: project_snippets_path(@project) },
+ { category: "In this project", label: _("Members"), url: project_project_members_path(@project) },
+ { category: "In this project", label: _("Wiki"), url: project_wikis_path(@project) }
+ ]
+ else
+ []
+ end
+ end
+
+ # Autocomplete results for the current user's groups
+ # rubocop: disable CodeReuse/ActiveRecord
+ def groups_autocomplete(term, limit = 5)
+ current_user.authorized_groups.order_id_desc.search(term).limit(limit).map do |group|
+ {
+ category: "Groups",
+ id: group.id,
+ label: "#{search_result_sanitize(group.full_name)}",
+ url: group_path(group),
+ avatar_url: group.avatar_url || ''
+ }
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # Autocomplete results for the current user's projects
+ # rubocop: disable CodeReuse/ActiveRecord
+ def projects_autocomplete(term, limit = 5)
+ current_user.authorized_projects.order_id_desc.search_by_title(term)
+ .sorted_by_stars_desc.non_archived.limit(limit).map do |p|
+ {
+ category: "Projects",
+ id: p.id,
+ value: "#{search_result_sanitize(p.name)}",
+ label: "#{search_result_sanitize(p.full_name)}",
+ url: project_path(p),
+ avatar_url: p.avatar_url || ''
+ }
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
def search_result_sanitize(str)
Sanitize.clean(str)
end
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index fe839b92ba6..1f9cce80bed 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -4,25 +4,29 @@ module ServicesHelper
def service_event_description(event)
case event
when "push", "push_events"
- "Event will be triggered by a push to the repository"
+ s_("ProjectService|Event will be triggered by a push to the repository")
when "tag_push", "tag_push_events"
- "Event will be triggered when a new tag is pushed to the repository"
+ s_("ProjectService|Event will be triggered when a new tag is pushed to the repository")
when "note", "note_events"
- "Event will be triggered when someone adds a comment"
+ s_("ProjectService|Event will be triggered when someone adds a comment")
when "confidential_note", "confidential_note_events"
- "Event will be triggered when someone adds a comment on a confidential issue"
+ s_("ProjectService|Event will be triggered when someone adds a comment on a confidential issue")
when "issue", "issue_events"
- "Event will be triggered when an issue is created/updated/closed"
- when "confidential_issue", "confidential_issues_events"
- "Event will be triggered when a confidential issue is created/updated/closed"
+ s_("ProjectService|Event will be triggered when an issue is created/updated/closed")
+ when "confidential_issue", "confidential_issue_events"
+ s_("ProjectService|Event will be triggered when a confidential issue is created/updated/closed")
when "merge_request", "merge_request_events"
- "Event will be triggered when a merge request is created/updated/merged"
+ s_("ProjectService|Event will be triggered when a merge request is created/updated/merged")
when "pipeline", "pipeline_events"
- "Event will be triggered when a pipeline status changes"
+ s_("ProjectService|Event will be triggered when a pipeline status changes")
when "wiki_page", "wiki_page_events"
- "Event will be triggered when a wiki page is created/updated"
+ s_("ProjectService|Event will be triggered when a wiki page is created/updated")
when "commit", "commit_events"
- "Event will be triggered when a commit is created/updated"
+ s_("ProjectService|Event will be triggered when a commit is created/updated")
+ when "deployment"
+ s_("ProjectService|Event will be triggered when a deployment finishes")
+ when "alert"
+ s_("ProjectService|Event will be triggered when a new, unique alert is recorded")
end
end
@@ -44,15 +48,8 @@ module ServicesHelper
end
end
- def event_action_description(action)
- case action
- when "comment"
- s_("ProjectService|Comment will be posted on each event")
- end
- end
-
- def service_save_button
- button_tag(class: 'btn btn-success', type: 'submit', data: { qa_selector: 'save_changes_button' }) do
+ 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') +
content_tag(:span, 'Save changes', class: 'js-btn-label')
end
@@ -90,7 +87,7 @@ module ServicesHelper
def scoped_test_integration_path(integration)
if @project.present?
- test_project_settings_integration_path(@project, integration)
+ test_project_service_path(@project, integration)
elsif @group.present?
test_group_settings_integration_path(@group, integration)
else
@@ -99,25 +96,45 @@ module ServicesHelper
end
def integration_form_refactor?
- Feature.enabled?(:integration_form_refactor, @project)
+ Feature.enabled?(:integration_form_refactor, @project, default_enabled: true)
end
- def trigger_events_for_service
+ def integration_form_data(integration)
+ {
+ id: integration.id,
+ show_active: integration.show_active_box?.to_s,
+ activated: (integration.active || integration.new_record?).to_s,
+ type: integration.to_param,
+ merge_request_events: integration.merge_requests_events.to_s,
+ commit_events: integration.commit_events.to_s,
+ enable_comments: integration.comment_on_event_enabled.to_s,
+ comment_detail: integration.comment_detail,
+ trigger_events: trigger_events_for_service(integration),
+ fields: fields_for_service(integration),
+ inherit_from_id: integration.inherit_from_id
+ }
+ end
+
+ def trigger_events_for_service(integration)
return [] unless integration_form_refactor?
- ServiceEventSerializer.new(service: @service).represent(@service.configurable_events).to_json
+ ServiceEventSerializer.new(service: integration).represent(integration.configurable_events).to_json
end
- def fields_for_service
+ def fields_for_service(integration)
return [] unless integration_form_refactor?
- ServiceFieldSerializer.new(service: @service).represent(@service.global_fields).to_json
+ ServiceFieldSerializer.new(service: integration).represent(integration.global_fields).to_json
end
- def show_service_trigger_events?
- return false if @service.is_a?(JiraService) || integration_form_refactor?
+ def show_service_trigger_events?(integration)
+ return false if integration.is_a?(JiraService) || integration_form_refactor?
+
+ integration.configurable_events.present?
+ end
- @service.configurable_events.present?
+ def project_jira_issues_integration?
+ false
end
extend self
diff --git a/app/helpers/storage_helper.rb b/app/helpers/storage_helper.rb
index ce810433a3a..13bf9c92d52 100644
--- a/app/helpers/storage_helper.rb
+++ b/app/helpers/storage_helper.rb
@@ -14,9 +14,10 @@ module StorageHelper
counter_repositories: storage_counter(statistics.repository_size),
counter_wikis: storage_counter(statistics.wiki_size),
counter_build_artifacts: storage_counter(statistics.build_artifacts_size),
- counter_lfs_objects: storage_counter(statistics.lfs_objects_size)
+ counter_lfs_objects: storage_counter(statistics.lfs_objects_size),
+ counter_snippets: storage_counter(statistics.snippets_size)
}
- _("Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects}") % counters
+ _("Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets}") % counters
end
end
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 7baa615d36f..6ea6a33ba5e 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -31,7 +31,9 @@ module SystemNoteHelper
'designs_added' => 'doc-image',
'designs_modified' => 'doc-image',
'designs_removed' => 'doc-image',
- 'designs_discussion_added' => 'doc-image'
+ 'designs_discussion_added' => 'doc-image',
+ 'status' => 'status',
+ 'alert_issue_added' => 'issues'
}.freeze
def system_note_icon_name(note)
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index 2b4f2f11d1e..b9a6cab07a8 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -22,6 +22,7 @@ module TodosHelper
when Todo::APPROVAL_REQUIRED then "set #{todo_action_subject(todo)} as an approver for"
when Todo::UNMERGEABLE then 'Could not merge'
when Todo::DIRECTLY_ADDRESSED then "directly addressed #{todo_action_subject(todo)} on"
+ when Todo::MERGE_TRAIN_REMOVED then "Removed from Merge Train:"
end
end
@@ -97,11 +98,13 @@ module TodosHelper
'mr'
when Issue
'issue'
+ when AlertManagement::Alert
+ 'alert'
end
content_tag(:span, nil, class: 'target-status') do
- content_tag(:span, nil, class: "status-box status-box-#{type}-#{todo.target.state.dasherize}") do
- todo.target.state.capitalize
+ content_tag(:span, nil, class: "status-box status-box-#{type}-#{todo.target.state.to_s.dasherize}") do
+ todo.target.state.to_s.capitalize
end
end
end
@@ -195,6 +198,10 @@ module TodosHelper
"&middot; #{content}".html_safe
end
+ def todo_author_display?(todo)
+ !todo.build_failed? && !todo.unmergeable?
+ end
+
private
def todos_design_path(todo, path_options)
@@ -214,7 +221,14 @@ module TodosHelper
end
def show_todo_state?(todo)
- (todo.target.is_a?(MergeRequest) || todo.target.is_a?(Issue)) && %w(closed merged).include?(todo.target.state)
+ case todo.target
+ when MergeRequest, Issue
+ %w(closed merged).include?(todo.target.state)
+ when AlertManagement::Alert
+ %i(resolved).include?(todo.target.state)
+ else
+ false
+ end
end
def todo_group_options
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 4dc00581703..90a5b6da4c7 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -191,8 +191,10 @@ module TreeHelper
def vue_file_list_data(project, ref)
{
+ can_push_code: current_user&.can?(:push_code, project) && "true",
project_path: project.full_path,
project_short_path: project.path,
+ fork_path: current_user&.fork_of(project)&.full_path,
ref: ref,
escaped_ref: ActionDispatch::Journey::Router::Utils.escape_path(ref),
full_name: project.name_with_namespace
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index 3c983606b73..cf2d2d178e1 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -3,6 +3,30 @@
module WikiHelper
include API::Helpers::RelatedResourcesHelpers
+ def wiki_page_title(page, action = nil)
+ titles = [_('Wiki')]
+
+ if page.persisted?
+ titles << page.human_title
+ breadcrumb_title(page.human_title)
+ wiki_breadcrumb_dropdown_links(page.slug)
+ end
+
+ titles << action if action
+ page_title(*titles.reverse)
+ add_to_breadcrumbs(_('Wiki'), wiki_path(page.wiki))
+ end
+
+ def link_to_wiki_page(page, **options)
+ link_to page.human_title, wiki_page_path(page.wiki, page), **options
+ end
+
+ def wiki_sidebar_toggle_button
+ content_tag :button, class: 'btn btn-default sidebar-toggle js-sidebar-wiki-toggle', role: 'button', type: 'button' do
+ sprite_icon('chevron-double-lg-left')
+ end
+ end
+
# Produces a pure text breadcrumb for a given page.
#
# page_slug - The slug of a WikiPage object.
@@ -71,10 +95,13 @@ module WikiHelper
def wiki_empty_state_messages(wiki)
case wiki.container
when Project
+ writable_body = s_("WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on.")
+ writable_body += s_("WikiEmpty| Have a Confluence wiki already? Use that instead.") if show_enable_confluence_integration?(wiki.container)
+
{
writable: {
title: s_('WikiEmpty|The wiki lets you write documentation for your project'),
- body: s_("WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on.")
+ body: writable_body
},
issuable: {
title: s_('WikiEmpty|This project has no wiki pages'),
@@ -104,4 +131,19 @@ module WikiHelper
raise NotImplementedError, "Unknown wiki container type #{wiki.container.class.name}"
end
end
+
+ def wiki_page_tracking_context(page)
+ {
+ 'wiki-format' => page.format,
+ 'wiki-title-size' => page.title.bytesize,
+ 'wiki-content-size' => page.raw_content.bytesize,
+ 'wiki-directory-nest-level' => page.path.scan('/').count
+ }
+ end
+
+ def show_enable_confluence_integration?(container)
+ container.is_a?(Project) &&
+ current_user&.can?(:admin_project, container) &&
+ !container.has_confluence?
+ end
end