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
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-01-24 15:09:01 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-01-24 15:09:01 +0300
commit2c2dd5e36c4ed5f09f488be288882d98f9124d12 (patch)
treead4c478bb1c588387a881b26a7db7c3237b9d4f3 /app
parent2ff184ad761fbfbe25a3d827c8f704349963a8d2 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue7
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue18
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue10
-rw-r--r--app/assets/javascripts/repository/index.js2
-rw-r--r--app/controllers/admin/runners_controller.rb5
-rw-r--r--app/controllers/import/base_controller.rb4
-rw-r--r--app/controllers/import/bitbucket_server_controller.rb2
-rw-r--r--app/controllers/import/manifest_controller.rb2
-rw-r--r--app/finders/contributed_projects_finder.rb4
-rw-r--r--app/finders/personal_projects_finder.rb4
-rw-r--r--app/helpers/analytics_navbar_helper.rb66
-rw-r--r--app/helpers/projects_helper.rb5
-rw-r--r--app/helpers/tab_helper.rb11
-rw-r--r--app/models/ci/build.rb3
-rw-r--r--app/models/project.rb2
-rw-r--r--app/services/system_note_service.rb21
-rw-r--r--app/services/system_notes/issuables_service.rb6
-rw-r--r--app/views/admin/runners/show.html.haml6
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml47
-rw-r--r--app/views/layouts/nav/sidebar/_project_analytics_link.html.haml16
-rw-r--r--app/workers/concerns/application_worker.rb1
-rw-r--r--app/workers/concerns/cronjob_queue.rb1
-rw-r--r--app/workers/concerns/worker_context.rb27
23 files changed, 204 insertions, 66 deletions
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index f6b9ea5d30d..5917c96990e 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -34,7 +34,10 @@ export default {
projectPath: this.projectPath,
};
},
- update: data => data.project.userPermissions,
+ update: data => data.project?.userPermissions,
+ error(error) {
+ throw error;
+ },
},
},
mixins: [getRefMixin],
@@ -172,7 +175,7 @@ export default {
);
}
- if (this.userPermissions.pushCode) {
+ if (this.userPermissions?.pushCode) {
items.push(
{
type: ROW_TYPES.divider,
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index fe1724acf89..573b0c4963e 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -40,16 +40,19 @@ export default {
};
},
update: data => {
- const pipelines = data.project.repository.tree.lastCommit.pipelines.edges;
+ const pipelines = data.project?.repository?.tree?.lastCommit?.pipelines?.edges;
return {
- ...data.project.repository.tree.lastCommit,
- pipeline: pipelines.length && pipelines[0].node,
+ ...data.project?.repository?.tree?.lastCommit,
+ pipeline: pipelines?.length && pipelines[0].node,
};
},
context: {
isSingleRequest: true,
},
+ error(error) {
+ throw error;
+ },
},
},
props: {
@@ -62,7 +65,7 @@ export default {
data() {
return {
projectPath: '',
- commit: {},
+ commit: null,
showDescription: false,
};
},
@@ -79,6 +82,11 @@ export default {
return this.commit.sha.substr(0, 8);
},
},
+ watch: {
+ currentPath() {
+ this.commit = null;
+ },
+ },
methods: {
toggleShowDescription() {
this.showDescription = !this.showDescription;
@@ -91,7 +99,7 @@ export default {
<template>
<div class="info-well d-none d-sm-flex project-last-commit commit p-3">
<gl-loading-icon v-if="isLoading" size="md" color="dark" class="m-auto" />
- <template v-else>
+ <template v-else-if="commit">
<user-avatar-link
v-if="commit.author"
:link-href="commit.author.webUrl"
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index 92e33b013c3..7b34e9ef60d 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -86,7 +86,8 @@ export default {
},
})
.then(({ data }) => {
- if (!data) return;
+ if (data.errors) throw data.errors;
+ if (!data?.project?.repository) return;
const pageInfo = this.hasNextPage(data.project.repository.tree);
@@ -99,12 +100,15 @@ export default {
{},
);
- if (pageInfo && pageInfo.hasNextPage) {
+ if (pageInfo?.hasNextPage) {
this.nextPageCursor = pageInfo.endCursor;
this.fetchFiles();
}
})
- .catch(() => createFlash(__('An error occurred while fetching folder content.')));
+ .catch(error => {
+ createFlash(__('An error occurred while fetching folder content.'));
+ throw error;
+ });
},
normalizeData(key, data) {
return this.entries[key].concat(data.map(({ node }) => node));
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index 2ef0c078f13..a26acbbe301 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -23,7 +23,7 @@ export default function setupVueRepositoryList() {
projectPath,
projectShortPath,
ref,
- vueFileListLfsBadge: gon?.features?.vueFileListLfsBadge,
+ vueFileListLfsBadge: gon.features?.vueFileListLfsBadge || false,
commits: [],
},
});
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index 783c59822f1..9eaa55039c8 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -66,7 +66,7 @@ class Admin::RunnersController < Admin::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def assign_builds_and_projects
- @builds = runner.builds.order('id DESC').first(30)
+ @builds = runner.builds.order('id DESC').preload_project_and_pipeline_project.first(30)
@projects =
if params[:search].present?
::Project.search(params[:search])
@@ -75,7 +75,8 @@ class Admin::RunnersController < Admin::ApplicationController
end
@projects = @projects.where.not(id: runner.projects.select(:id)) if runner.projects.any?
- @projects = @projects.page(params[:page]).per(30)
+ @projects = @projects.inc_routes
+ @projects = @projects.page(params[:page]).per(30).without_count
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb
index f16f752f85b..04919a4b9d0 100644
--- a/app/controllers/import/base_controller.rb
+++ b/app/controllers/import/base_controller.rb
@@ -7,14 +7,14 @@ class Import::BaseController < ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def find_already_added_projects(import_type)
- current_user.created_projects.where(import_type: import_type).includes(:import_state)
+ current_user.created_projects.where(import_type: import_type).with_import_state
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def find_jobs(import_type)
current_user.created_projects
- .includes(:import_state)
+ .with_import_state
.where(import_type: import_type)
.to_json(only: [:id], methods: [:import_status])
end
diff --git a/app/controllers/import/bitbucket_server_controller.rb b/app/controllers/import/bitbucket_server_controller.rb
index dc72a4e4fd9..5fb7b5dccc5 100644
--- a/app/controllers/import/bitbucket_server_controller.rb
+++ b/app/controllers/import/bitbucket_server_controller.rb
@@ -82,7 +82,7 @@ class Import::BitbucketServerController < Import::BaseController
# rubocop: disable CodeReuse/ActiveRecord
def filter_added_projects(import_type, import_sources)
- current_user.created_projects.where(import_type: import_type, import_source: import_sources).includes(:import_state)
+ current_user.created_projects.where(import_type: import_type, import_source: import_sources).with_import_state
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/controllers/import/manifest_controller.rb b/app/controllers/import/manifest_controller.rb
index 7ba8b3ce938..9aec870c6ea 100644
--- a/app/controllers/import/manifest_controller.rb
+++ b/app/controllers/import/manifest_controller.rb
@@ -87,7 +87,7 @@ class Import::ManifestController < Import::BaseController
group.all_projects
.where(import_type: 'manifest')
.where(creator_id: current_user)
- .includes(:import_state)
+ .with_import_state
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/contributed_projects_finder.rb b/app/finders/contributed_projects_finder.rb
index f8c7f0c3167..a351d30229e 100644
--- a/app/finders/contributed_projects_finder.rb
+++ b/app/finders/contributed_projects_finder.rb
@@ -12,16 +12,14 @@ class ContributedProjectsFinder < UnionFinder
# visible by this user.
#
# Returns an ActiveRecord::Relation.
- # rubocop: disable CodeReuse/ActiveRecord
def execute(current_user = nil)
# Do not show contributed projects if the user profile is private.
return Project.none unless can_read_profile?(current_user)
segments = all_projects(current_user)
- find_union(segments, Project).includes(:namespace).order_id_desc
+ find_union(segments, Project).with_namespace.order_id_desc
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/app/finders/personal_projects_finder.rb b/app/finders/personal_projects_finder.rb
index 20f5b221a89..e7094d73905 100644
--- a/app/finders/personal_projects_finder.rb
+++ b/app/finders/personal_projects_finder.rb
@@ -17,15 +17,13 @@ class PersonalProjectsFinder < UnionFinder
# min_access_level: integer
#
# Returns an ActiveRecord::Relation.
- # rubocop: disable CodeReuse/ActiveRecord
def execute(current_user = nil)
return Project.none unless can?(current_user, :read_user_profile, @user)
segments = all_projects(current_user)
- find_union(segments, Project).includes(:namespace).order_updated_desc
+ find_union(segments, Project).with_namespace.order_updated_desc
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/app/helpers/analytics_navbar_helper.rb b/app/helpers/analytics_navbar_helper.rb
new file mode 100644
index 00000000000..d9aadfaeb15
--- /dev/null
+++ b/app/helpers/analytics_navbar_helper.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module AnalyticsNavbarHelper
+ class NavbarSubItem
+ attr_reader :title, :path, :link, :link_to_options
+
+ def initialize(title:, path:, link:, link_to_options: {})
+ @title = title
+ @path = path
+ @link = link
+ @link_to_options = link_to_options.merge(title: title)
+ end
+ end
+
+ def project_analytics_navbar_links(project, current_user)
+ [
+ cycle_analytics_navbar_link(project, current_user),
+ repository_analytics_navbar_link(project, current_user),
+ ci_cd_analytics_navbar_link(project, current_user)
+ ].compact
+ end
+
+ private
+
+ def navbar_sub_item(args)
+ NavbarSubItem.new(args)
+ end
+
+ def cycle_analytics_navbar_link(project, current_user)
+ return unless Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, project)
+ return unless project_nav_tab?(:cycle_analytics)
+
+ navbar_sub_item(
+ title: _('Cycle Analytics'),
+ path: 'cycle_analytics#show',
+ link: project_cycle_analytics_path(project),
+ link_to_options: { class: 'shortcuts-project-cycle-analytics' }
+ )
+ end
+
+ def repository_analytics_navbar_link(project, current_user)
+ return if Feature.disabled?(:analytics_pages_under_project_analytics_sidebar, project)
+ return if project.empty_repo?
+
+ navbar_sub_item(
+ title: _('Repository Analytics'),
+ path: 'graphs#charts',
+ link: charts_project_graph_path(project, current_ref),
+ link_to_options: { class: 'shortcuts-repository-charts' }
+ )
+ end
+
+ def ci_cd_analytics_navbar_link(project, current_user)
+ return unless Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, project)
+ return unless project_nav_tab?(:pipelines)
+ return unless project.feature_available?(:builds, current_user) || !project.empty_repo?
+
+ navbar_sub_item(
+ title: _('CI / CD Analytics'),
+ path: 'pipelines#charts',
+ link: charts_project_pipelines_path(project)
+ )
+ end
+end
+
+AnalyticsNavbarHelper.prepend_if_ee('EE::AnalyticsNavbarHelper')
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 339d68871ae..3000cfb678e 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -403,6 +403,10 @@ 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
@@ -643,7 +647,6 @@ module ProjectsHelper
projects#show
projects#activity
releases#index
- cycle_analytics#show
]
end
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 58edb327be0..0f156003a01 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -12,6 +12,7 @@ module TabHelper
# :action - One or more action names to check (optional).
# :path - A shorthand path, such as 'dashboard#index', to check (optional).
# :html_options - Extra options to be passed to the list element (optional).
+ # :unless - Callable object to skip rendering the 'active' class on `li` element (optional).
# block - An optional block that will become the contents of the returned
# `li` element.
#
@@ -56,6 +57,14 @@ module TabHelper
# nav_link(path: 'admin/appearances#show') { "Hello"}
# # => '<li class="active">Hello</li>'
#
+ # # Shorthand path + unless
+ # # Add `active` class when TreeController is requested, except the `index` action.
+ # nav_link(controller: 'tree', unless: -> { action_name?('index') }) { "Hello" }
+ # # => '<li class="active">Hello</li>'
+ #
+ # # When `TreeController#index` is requested
+ # # => '<li>Hello</li>'
+ #
# Returns a list item element String
def nav_link(options = {}, &block)
klass = active_nav_link?(options) ? 'active' : ''
@@ -73,6 +82,8 @@ module TabHelper
end
def active_nav_link?(options)
+ return false if options[:unless]&.call
+
if path = options.delete(:path)
unless path.respond_to?(:each)
path = [path]
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 369a793f3d5..d1edf3e9c03 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -172,6 +172,9 @@ module Ci
scope :queued_before, ->(time) { where(arel_table[:queued_at].lt(time)) }
scope :order_id_desc, -> { order('ci_builds.id DESC') }
+ PROJECT_ROUTE_AND_NAMESPACE_ROUTE = { project: [:project_feature, :route, { namespace: :route }] }.freeze
+ scope :preload_project_and_pipeline_project, -> { preload(PROJECT_ROUTE_AND_NAMESPACE_ROUTE, pipeline: PROJECT_ROUTE_AND_NAMESPACE_ROUTE) }
+
acts_as_taggable
add_authentication_token_field :token, encrypted: :optional
diff --git a/app/models/project.rb b/app/models/project.rb
index 236111cba94..cd191589351 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -411,6 +411,8 @@ class Project < ApplicationRecord
scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') }
scope :inc_routes, -> { includes(:route, namespace: :route) }
scope :with_statistics, -> { includes(:statistics) }
+ scope :with_namespace, -> { includes(:namespace) }
+ scope :with_import_state, -> { includes(:import_state) }
scope :with_service, ->(service) { joins(service).eager_load(service) }
scope :with_shared_runners, -> { where(shared_runners_enabled: true) }
scope :with_container_registry, -> { where(container_registry_enabled: true) }
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 033c80fd8ed..8a0f44b4e93 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -100,9 +100,7 @@ module SystemNoteService
end
def close_after_error_tracking_resolve(issue, project, author)
- body = _('resolved the corresponding error and closed the issue.')
-
- create_note(NoteSummary.new(issue, project, author, body, action: 'closed'))
+ ::SystemNotes::IssuablesService.new(noteable: issue, project: project, author: author).close_after_error_tracking_resolve
end
def change_status(noteable, project, author, status, source = nil)
@@ -243,23 +241,6 @@ module SystemNoteService
def zoom_link_removed(issue, project, author)
::SystemNotes::ZoomService.new(noteable: issue, project: project, author: author).zoom_link_removed
end
-
- private
-
- def create_note(note_summary)
- note = Note.create(note_summary.note.merge(system: true))
- note.system_note_metadata = SystemNoteMetadata.new(note_summary.metadata) if note_summary.metadata?
-
- note
- end
-
- def url_helpers
- @url_helpers ||= Gitlab::Routing.url_helpers
- end
-
- def content_tag(*args)
- ActionController::Base.helpers.content_tag(*args)
- end
end
SystemNoteService.prepend_if_ee('EE::SystemNoteService')
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index 6fffd2ed4bf..d7787dac4b8 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -282,6 +282,12 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: action))
end
+ def close_after_error_tracking_resolve
+ body = _('resolved the corresponding error and closed the issue.')
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'closed'))
+ end
+
private
def cross_reference_note_content(gfm_reference)
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index 62be38e9dd2..f860b7a61a2 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -48,7 +48,7 @@
= project.full_name
%td
.float-right
- = link_to 'Disable', [:admin, project.namespace.becomes(Namespace), project, runner_project], method: :delete, class: 'btn btn-danger btn-sm'
+ = link_to 'Disable', admin_namespace_project_runner_project_path(project.namespace, project, runner_project), method: :delete, class: 'btn btn-danger btn-sm'
%table.table.unassigned-projects
%thead
@@ -70,10 +70,10 @@
= project.full_name
%td
.float-right
- = form_for [:admin, project.namespace.becomes(Namespace), project, project.runner_projects.new] do |f|
+ = form_for project.runner_projects.new, url: admin_namespace_project_runner_projects_path(project.namespace, project), method: :post do |f|
= f.hidden_field :runner_id, value: @runner.id
= f.submit 'Enable', class: 'btn btn-sm'
- = paginate @projects, theme: "gitlab"
+ = paginate_without_count @projects
.col-md-6
%h4 Recent jobs served by this Runner
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 3464cc1ea07..3096b2e43fe 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -1,3 +1,5 @@
+- should_display_analytics_pages_in_sidebar = Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, @project)
+
.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
.nav-sidebar-inner-scroll
- can_edit = can?(current_user, :admin_project, @project)
@@ -8,7 +10,9 @@
.sidebar-context-title
= @project.name
%ul.sidebar-top-level-items
- = nav_link(path: sidebar_projects_paths, html_options: { class: 'home' }) do
+ - paths = sidebar_projects_paths
+ - paths << 'cycle_analytics#show' unless should_display_analytics_pages_in_sidebar
+ = nav_link(path: paths, html_options: { class: 'home' }) do
= link_to project_path(@project), class: 'shortcuts-project rspec-project-link', data: { qa_selector: 'project_link' } do
.nav-icon-container
= sprite_icon('home')
@@ -34,15 +38,18 @@
= link_to project_releases_path(@project), title: _('Releases'), class: 'shortcuts-project-releases' do
%span= _('Releases')
- - if can?(current_user, :read_cycle_analytics, @project)
- = nav_link(path: 'cycle_analytics#show') do
- = link_to project_cycle_analytics_path(@project), title: _('Cycle Analytics'), class: 'shortcuts-project-cycle-analytics' do
- %span= _('Cycle Analytics')
- = render_if_exists 'layouts/nav/project_insights_link'
+ - unless should_display_analytics_pages_in_sidebar
+ - if can?(current_user, :read_cycle_analytics, @project)
+ = nav_link(path: 'cycle_analytics#show') do
+ = link_to project_cycle_analytics_path(@project), title: _('Cycle Analytics'), class: 'shortcuts-project-cycle-analytics' do
+ %span= _('Cycle Analytics')
+
+ = render_if_exists 'layouts/nav/project_insights_link'
+
- if project_nav_tab? :files
- = nav_link(controller: sidebar_repository_paths) do
+ = nav_link(controller: sidebar_repository_paths, unless: -> { should_display_analytics_pages_in_sidebar && current_path?('projects/graphs#charts') }) do
= link_to project_tree_path(@project), class: 'shortcuts-tree qa-project-menu-repo' do
.nav-icon-container
= sprite_icon('doc-text')
@@ -83,9 +90,10 @@
= link_to project_compare_index_path(@project, from: @repository.root_ref, to: current_ref) do
= _('Compare')
- = nav_link(path: 'graphs#charts') do
- = link_to charts_project_graph_path(@project, current_ref) do
- = _('Charts')
+ - unless should_display_analytics_pages_in_sidebar
+ = nav_link(path: 'graphs#charts') do
+ = link_to charts_project_graph_path(@project, current_ref) do
+ = _('Charts')
= render_if_exists 'projects/sidebar/repository_locked_files'
@@ -170,7 +178,7 @@
= number_with_delimiter(@project.open_merge_requests_count)
- if project_nav_tab? :pipelines
- = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts]) do
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts], unless: -> { should_display_analytics_pages_in_sidebar && current_path?('projects/pipelines#charts') }) do
= link_to project_pipelines_path(@project), class: 'shortcuts-pipelines qa-link-pipelines rspec-link-pipelines', data: { qa_selector: 'ci_cd_link' } do
.nav-icon-container
= sprite_icon('rocket')
@@ -201,13 +209,13 @@
%span
= _('Artifacts')
- - if project_nav_tab? :pipelines
+ - if !should_display_analytics_pages_in_sidebar && project_nav_tab?(:pipelines)
= nav_link(controller: :pipeline_schedules) do
= link_to pipeline_schedules_path(@project), title: _('Schedules'), class: 'shortcuts-builds' do
%span
= _('Schedules')
- - if @project.feature_available?(:builds, current_user) && !@project.empty_repo?
+ - if !should_display_analytics_pages_in_sidebar && @project.feature_available?(:builds, current_user) && !@project.empty_repo?
= nav_link(path: 'pipelines#charts') do
= link_to charts_project_pipelines_path(@project), title: _('Charts'), class: 'shortcuts-pipelines-charts' do
%span
@@ -290,7 +298,7 @@
= render_if_exists 'layouts/nav/sidebar/project_packages_link'
- = render_if_exists 'layouts/nav/sidebar/project_analytics_link' # EE-specific
+ = render 'layouts/nav/sidebar/project_analytics_link'
- if project_nav_tab? :wiki
- wiki_url = project_wiki_path(@project, :home)
@@ -410,11 +418,12 @@
= link_to project_network_path(@project, current_ref), title: _('Network'), class: 'shortcuts-network' do
= _('Graph')
- -# Shortcut to Repository > Charts (formerly, top-nav item "Graphs")
- - unless @project.empty_repo?
- %li.hidden
- = link_to charts_project_graph_path(@project, current_ref), title: _('Charts'), class: 'shortcuts-repository-charts' do
- = _('Charts')
+ - unless should_display_analytics_pages_in_sidebar
+ -# Shortcut to Repository > Charts (formerly, top-nav item "Graphs")
+ - unless @project.empty_repo?
+ %li.hidden
+ = link_to charts_project_graph_path(@project, current_ref), title: _('Charts'), class: 'shortcuts-repository-charts' do
+ = _('Charts')
-# Shortcut to Issues > New Issue
- if project_nav_tab?(:issues)
diff --git a/app/views/layouts/nav/sidebar/_project_analytics_link.html.haml b/app/views/layouts/nav/sidebar/_project_analytics_link.html.haml
new file mode 100644
index 00000000000..3eb8c024588
--- /dev/null
+++ b/app/views/layouts/nav/sidebar/_project_analytics_link.html.haml
@@ -0,0 +1,16 @@
+- navbar_sub_item = project_analytics_navbar_links(@project, current_user).sort_by(&:title)
+- all_paths = navbar_sub_item.map(&:path)
+
+- if navbar_sub_item.any?
+ = nav_link(path: all_paths) do
+ = link_to navbar_sub_item.first.link, data: { qa_selector: 'project_analytics_link' } do
+ .nav-icon-container
+ = sprite_icon('chart')
+ %span.nav-item-name
+ = _('Analytics')
+
+ %ul.sidebar-sub-level-items
+ - navbar_sub_item.each do |menu_item|
+ = nav_link(path: menu_item.path) do
+ = link_to(menu_item.link, menu_item.link_to_options) do
+ %span= menu_item.title
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 62748808ff1..733156ab758 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -9,6 +9,7 @@ module ApplicationWorker
include Sidekiq::Worker # rubocop:disable Cop/IncludeSidekiqWorker
include WorkerAttributes
+ include WorkerContext
included do
set_queue
diff --git a/app/workers/concerns/cronjob_queue.rb b/app/workers/concerns/cronjob_queue.rb
index 0683b229381..25ee4539cab 100644
--- a/app/workers/concerns/cronjob_queue.rb
+++ b/app/workers/concerns/cronjob_queue.rb
@@ -8,5 +8,6 @@ module CronjobQueue
included do
queue_namespace :cronjob
sidekiq_options retry: false
+ worker_context project: nil, namespace: nil, user: nil
end
end
diff --git a/app/workers/concerns/worker_context.rb b/app/workers/concerns/worker_context.rb
new file mode 100644
index 00000000000..d85565e3446
--- /dev/null
+++ b/app/workers/concerns/worker_context.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module WorkerContext
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def worker_context(attributes)
+ @worker_context = Gitlab::ApplicationContext.new(attributes)
+ end
+
+ def get_worker_context
+ @worker_context || superclass_context
+ end
+
+ private
+
+ def superclass_context
+ return unless superclass.include?(WorkerContext)
+
+ superclass.get_worker_context
+ end
+ end
+
+ def with_context(context, &block)
+ Gitlab::ApplicationContext.new(context).use(&block)
+ end
+end