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>2021-11-11 18:10:57 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-11-11 18:10:57 +0300
commite40f19ef830c5863089bc6a7a73e6695efa60a13 (patch)
treec540032381175c4e95e3b6378698f91acac5100f /app
parent1c7411c597334e20d2e92cc948f0699d339d2710 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue67
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue10
-rw-r--r--app/assets/javascripts/projects/project_new.js7
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js11
-rw-r--r--app/controllers/admin/application_settings_controller.rb4
-rw-r--r--app/helpers/tab_helper.rb6
-rw-r--r--app/models/concerns/strip_attribute.rb3
-rw-r--r--app/models/merge_request.rb4
-rw-r--r--app/models/user.rb12
-rw-r--r--app/models/users_statistics.rb36
-rw-r--r--app/services/groups/import_export/import_service.rb2
-rw-r--r--app/views/admin/dashboard/stats.html.haml63
-rw-r--r--app/views/groups/dependency_proxies/show.html.haml3
-rw-r--r--app/views/projects/_new_project_fields.html.haml7
-rw-r--r--app/views/users/_overview.html.haml16
-rw-r--r--app/workers/concerns/application_worker.rb6
-rw-r--r--app/workers/concerns/limited_capacity/worker.rb2
17 files changed, 183 insertions, 76 deletions
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
index 13e5d7c3019..71e8cf4f634 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
@@ -1,8 +1,16 @@
<script>
-import { GlAlert, GlFormGroup, GlFormInputGroup, GlSkeletonLoader, GlSprintf } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlFormGroup,
+ GlFormInputGroup,
+ GlSkeletonLoader,
+ GlSprintf,
+ GlEmptyState,
+} from '@gitlab/ui';
import { s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import ManifestsList from '~/packages_and_registries/dependency_proxy/components/manifests_list.vue';
import {
DEPENDENCY_PROXY_SETTINGS_DESCRIPTION,
DEPENDENCY_PROXY_DOCS_PATH,
@@ -13,15 +21,17 @@ import getDependencyProxyDetailsQuery from '~/packages_and_registries/dependency
export default {
components: {
- GlFormGroup,
GlAlert,
+ GlEmptyState,
+ GlFormGroup,
GlFormInputGroup,
+ GlSkeletonLoader,
GlSprintf,
ClipboardButton,
TitleArea,
- GlSkeletonLoader,
+ ManifestsList,
},
- inject: ['groupPath', 'dependencyProxyAvailable'],
+ inject: ['groupPath', 'dependencyProxyAvailable', 'noManifestsIllustration'],
i18n: {
proxyNotAvailableText: s__(
'DependencyProxy|Dependency Proxy feature is limited to public groups for now.',
@@ -33,6 +43,7 @@ export default {
copyImagePrefixText: s__('DependencyProxy|Copy prefix'),
blobCountAndSize: s__('DependencyProxy|Contains %{count} blobs of images (%{size})'),
pageTitle: s__('DependencyProxy|Dependency Proxy'),
+ noManifestTitle: s__('DependencyProxy|There are no images in the cache'),
},
data() {
return {
@@ -46,7 +57,7 @@ export default {
return !this.dependencyProxyAvailable;
},
variables() {
- return { fullPath: this.groupPath, first: GRAPHQL_PAGE_SIZE };
+ return this.queryVariables;
},
},
},
@@ -62,6 +73,38 @@ export default {
dependencyProxyEnabled() {
return this.group?.dependencyProxySetting?.enabled;
},
+ queryVariables() {
+ return { fullPath: this.groupPath, first: GRAPHQL_PAGE_SIZE };
+ },
+ pageInfo() {
+ return this.group.dependencyProxyManifests.pageInfo;
+ },
+ manifests() {
+ return this.group.dependencyProxyManifests.nodes;
+ },
+ },
+ methods: {
+ fetchNextPage() {
+ this.fetchMore({
+ first: GRAPHQL_PAGE_SIZE,
+ after: this.pageInfo?.endCursor,
+ });
+ },
+ fetchPreviousPage() {
+ this.fetchMore({
+ first: null,
+ last: GRAPHQL_PAGE_SIZE,
+ before: this.pageInfo?.startCursor,
+ });
+ },
+ fetchMore(variables) {
+ this.$apollo.queries.group.fetchMore({
+ variables: { ...this.queryVariables, ...variables },
+ updateQuery(_, { fetchMoreResult }) {
+ return fetchMoreResult;
+ },
+ });
+ },
},
};
</script>
@@ -103,6 +146,20 @@ export default {
</span>
</template>
</gl-form-group>
+
+ <manifests-list
+ v-if="manifests && manifests.length"
+ :manifests="manifests"
+ :pagination="pageInfo"
+ @prev-page="fetchPreviousPage"
+ @next-page="fetchNextPage"
+ />
+
+ <gl-empty-state
+ v-else
+ :svg-path="noManifestsIllustration"
+ :title="$options.i18n.noManifestTitle"
+ />
</div>
<gl-alert v-else :dismissible="false" data-testid="proxy-disabled">
{{ $options.i18n.proxyDisabledText }}
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue
index f3ac017268b..005c8feea3a 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue
@@ -21,13 +21,18 @@ export default {
},
},
i18n: {
- listTitle: s__('DependencyProxy|Manifest list'),
+ listTitle: s__('DependencyProxy|Image list'),
+ },
+ computed: {
+ showPagination() {
+ return this.pagination.hasNextPage || this.pagination.hasPreviousPage;
+ },
},
};
</script>
<template>
- <div class="gl-mt-5">
+ <div class="gl-mt-6">
<h3 class="gl-font-base">{{ $options.i18n.listTitle }}</h3>
<div
class="gl-border-t-1 gl-border-gray-100 gl-border-t-solid gl-display-flex gl-flex-direction-column"
@@ -36,6 +41,7 @@ export default {
</div>
<div class="gl-display-flex gl-justify-content-center">
<gl-keyset-pagination
+ v-if="showPagination"
v-bind="pagination"
class="gl-mt-3"
@prev="$emit('prev-page')"
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index b350db0c838..8d71a3dab68 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -43,6 +43,8 @@ const onProjectPathChange = ($projectNameInput, $projectPathInput, hasExistingPr
};
const setProjectNamePathHandlers = ($projectNameInput, $projectPathInput) => {
+ const specialRepo = document.querySelector('.js-user-readme-repo');
+
// eslint-disable-next-line @gitlab/no-global-event-off
$projectNameInput.off('keyup change').on('keyup change', () => {
onProjectNameChange($projectNameInput, $projectPathInput);
@@ -54,6 +56,11 @@ const setProjectNamePathHandlers = ($projectNameInput, $projectPathInput) => {
$projectPathInput.off('keyup change').on('keyup change', () => {
onProjectPathChange($projectNameInput, $projectPathInput, hasUserDefinedProjectName);
hasUserDefinedProjectPath = $projectPathInput.val().trim().length > 0;
+
+ specialRepo.classList.toggle(
+ 'gl-display-none',
+ $projectPathInput.val() !== $projectPathInput.data('username'),
+ );
});
};
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index d0a7b0d0b89..9c80506549e 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -37,10 +37,13 @@ export const SAST_IAC_SHORT_NAME = s__('ciReport|IaC Scanning');
export const SAST_IAC_DESCRIPTION = __(
'Analyze your infrastructure as code configuration files for known vulnerabilities.',
);
-export const SAST_IAC_HELP_PATH = helpPagePath('user/application_security/sast/index');
-export const SAST_IAC_CONFIG_HELP_PATH = helpPagePath('user/application_security/sast/index', {
- anchor: 'configuration',
-});
+export const SAST_IAC_HELP_PATH = helpPagePath('user/application_security/iac_scanning/index');
+export const SAST_IAC_CONFIG_HELP_PATH = helpPagePath(
+ 'user/application_security/iac_scanning/index',
+ {
+ anchor: 'configuration',
+ },
+);
export const DAST_NAME = __('Dynamic Application Security Testing (DAST)');
export const DAST_SHORT_NAME = s__('ciReport|DAST');
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 8039fac02ec..8644d95b96c 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -98,7 +98,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
# Specs are in spec/requests/self_monitoring_project_spec.rb
def create_self_monitoring_project
- job_id = SelfMonitoringProjectCreateWorker.perform_async # rubocop:disable CodeReuse/Worker
+ job_id = SelfMonitoringProjectCreateWorker.with_status.perform_async # rubocop:disable CodeReuse/Worker
render status: :accepted, json: {
job_id: job_id,
@@ -137,7 +137,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
# Specs are in spec/requests/self_monitoring_project_spec.rb
def delete_self_monitoring_project
- job_id = SelfMonitoringProjectDeleteWorker.perform_async # rubocop:disable CodeReuse/Worker
+ job_id = SelfMonitoringProjectDeleteWorker.with_status.perform_async # rubocop:disable CodeReuse/Worker
render status: :accepted, json: {
job_id: job_id,
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index d1046b7b668..e53e35baac3 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -33,7 +33,6 @@ module TabHelper
# :item_active - Overrides the default state focing the "active" css classes (optional).
#
def gl_tab_link_to(name = nil, options = {}, html_options = {}, &block)
- tab_class = 'nav-item'
link_classes = %w[nav-link gl-tab-nav-item]
active_link_classes = %w[active gl-tab-nav-item-active gl-tab-nav-item-active-indigo]
@@ -52,6 +51,8 @@ module TabHelper
end
html_options = html_options.except(:item_active)
+ extra_tab_classes = html_options.delete(:tab_class)
+ tab_class = %w[nav-item].push(*extra_tab_classes)
content_tag(:li, class: tab_class, role: 'presentation') do
if block_given?
@@ -215,6 +216,7 @@ def gl_tab_counter_badge(count, html_options = {})
badge_classes = %w[badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge]
content_tag(:span,
count,
- class: [*html_options[:class], badge_classes].join(' ')
+ class: [*html_options[:class], badge_classes].join(' '),
+ data: html_options[:data]
)
end
diff --git a/app/models/concerns/strip_attribute.rb b/app/models/concerns/strip_attribute.rb
index 1c433a3275e..817a4465f91 100644
--- a/app/models/concerns/strip_attribute.rb
+++ b/app/models/concerns/strip_attribute.rb
@@ -2,7 +2,8 @@
# == Strip Attribute module
#
-# Contains functionality to clean attributes before validation
+# Contains functionality to remove leading and trailing
+# whitespace from the attribute before validation
#
# Usage:
#
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index f2f9b527cc0..d220f4b837a 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -662,7 +662,7 @@ class MergeRequest < ApplicationRecord
# updates `merge_jid` with the MergeWorker#jid.
# This helps tracking enqueued and ongoing merge jobs.
def merge_async(user_id, params)
- jid = MergeWorker.perform_async(id, user_id, params.to_h)
+ jid = MergeWorker.with_status.perform_async(id, user_id, params.to_h)
update_column(:merge_jid, jid)
# merge_ongoing? depends on merge_jid
@@ -681,7 +681,7 @@ class MergeRequest < ApplicationRecord
# attribute is set *and* that the sidekiq job is still running. So a JID
# for a completed RebaseWorker is equivalent to a nil JID.
jid = Sidekiq::Worker.skipping_transaction_check do
- RebaseWorker.perform_async(id, user_id, skip_ci)
+ RebaseWorker.with_status.perform_async(id, user_id, skip_ci)
end
update_column(:rebase_jid, jid)
diff --git a/app/models/user.rb b/app/models/user.rb
index 2ca7909ebcb..394c64db3bf 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1992,6 +1992,18 @@ class User < ApplicationRecord
saved
end
+ def user_project
+ strong_memoize(:user_project) do
+ personal_projects.find_by(path: username, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ end
+ end
+
+ def user_readme
+ strong_memoize(:user_readme) do
+ user_project&.repository&.readme
+ end
+ end
+
protected
# override, from Devise::Validatable
diff --git a/app/models/users_statistics.rb b/app/models/users_statistics.rb
index a903541f69a..a314ae8920b 100644
--- a/app/models/users_statistics.rb
+++ b/app/models/users_statistics.rb
@@ -3,12 +3,6 @@
class UsersStatistics < ApplicationRecord
scope :order_created_at_desc, -> { order(created_at: :desc) }
- class << self
- def latest
- order_created_at_desc.first
- end
- end
-
def active
[
without_groups_and_projects,
@@ -26,30 +20,26 @@ class UsersStatistics < ApplicationRecord
end
class << self
- def create_current_stats!
- stats_by_role = highest_role_stats
+ def latest
+ order_created_at_desc.first
+ end
- create!(
- without_groups_and_projects: without_groups_and_projects_stats,
- with_highest_role_guest: stats_by_role[:guest],
- with_highest_role_reporter: stats_by_role[:reporter],
- with_highest_role_developer: stats_by_role[:developer],
- with_highest_role_maintainer: stats_by_role[:maintainer],
- with_highest_role_owner: stats_by_role[:owner],
- bots: bot_stats,
- blocked: blocked_stats
- )
+ def create_current_stats!
+ create!(highest_role_stats)
end
private
def highest_role_stats
{
- owner: batch_count_for_access_level(Gitlab::Access::OWNER),
- maintainer: batch_count_for_access_level(Gitlab::Access::MAINTAINER),
- developer: batch_count_for_access_level(Gitlab::Access::DEVELOPER),
- reporter: batch_count_for_access_level(Gitlab::Access::REPORTER),
- guest: batch_count_for_access_level(Gitlab::Access::GUEST)
+ without_groups_and_projects: without_groups_and_projects_stats,
+ with_highest_role_guest: batch_count_for_access_level(Gitlab::Access::GUEST),
+ with_highest_role_reporter: batch_count_for_access_level(Gitlab::Access::REPORTER),
+ with_highest_role_developer: batch_count_for_access_level(Gitlab::Access::DEVELOPER),
+ with_highest_role_maintainer: batch_count_for_access_level(Gitlab::Access::MAINTAINER),
+ with_highest_role_owner: batch_count_for_access_level(Gitlab::Access::OWNER),
+ bots: bot_stats,
+ blocked: blocked_stats
}
end
diff --git a/app/services/groups/import_export/import_service.rb b/app/services/groups/import_export/import_service.rb
index f9db552f743..c8c2124078d 100644
--- a/app/services/groups/import_export/import_service.rb
+++ b/app/services/groups/import_export/import_service.rb
@@ -14,7 +14,7 @@ module Groups
def async_execute
group_import_state = GroupImportState.safe_find_or_create_by!(group: group, user: current_user)
- jid = GroupImportWorker.perform_async(current_user.id, group.id)
+ jid = GroupImportWorker.with_status.perform_async(current_user.id, group.id)
if jid.present?
group_import_state.update!(jid: jid)
diff --git a/app/views/admin/dashboard/stats.html.haml b/app/views/admin/dashboard/stats.html.haml
index b98d11b734b..e0701812ba3 100644
--- a/app/views/admin/dashboard/stats.html.haml
+++ b/app/views/admin/dashboard/stats.html.haml
@@ -1,74 +1,75 @@
- page_title s_('AdminArea|Users statistics')
-%h3.my-4
+%h3.gl-my-6
= s_('AdminArea|Users statistics')
%table.table.gl-text-gray-500
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users without a Group and Project')
= render_if_exists 'admin/dashboard/included_free_in_license_tooltip'
- %td.p-3.text-right
- = @users_statistics&.without_groups_and_projects.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.without_groups_and_projects
+ = render_if_exists 'admin/dashboard/minimal_access_stats_row', users_statistics: @users_statistics
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Guest')
= render_if_exists 'admin/dashboard/included_free_in_license_tooltip'
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_guest.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_guest
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Reporter')
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_reporter.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_reporter
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Developer')
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_developer.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_developer
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Maintainer')
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_maintainer.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_maintainer
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Users with highest role')
%strong
= s_('AdminArea|Owner')
- %td.p-3.text-right
- = @users_statistics&.with_highest_role_owner.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.with_highest_role_owner
%tr
- %td.p-3
+ %td.gl-p-5!
= s_('AdminArea|Bots')
- %td.p-3.text-right
- = @users_statistics&.bots.to_i
+ %td.gl-text-right{ class: 'gl-p-5!' }
+ = @users_statistics&.bots
= render_if_exists 'admin/dashboard/billable_users_row'
%tr.bg-gray-light.gl-text-gray-900
- %td.p-3
+ %td.gl-p-5!
%strong
= s_('AdminArea|Active users')
- %td.p-3.text-right
+ %td.gl-text-right{ class: 'gl-p-5!' }
%strong
- = @users_statistics&.active.to_i
+ = @users_statistics&.active
%tr.bg-gray-light.gl-text-gray-900
- %td.p-3
+ %td.gl-p-5!
%strong
= s_('AdminArea|Blocked users')
- %td.p-3.text-right
+ %td.gl-text-right{ class: 'gl-p-5!' }
%strong
- = @users_statistics&.blocked.to_i
+ = @users_statistics&.blocked
%tr.bg-gray-light.gl-text-gray-900
- %td.p-3
+ %td.gl-p-5!
%strong
= s_('AdminArea|Total users')
- %td.p-3.text-right
+ %td.gl-text-right{ class: 'gl-p-5!' }
%strong
- = @users_statistics&.total.to_i
+ = @users_statistics&.total
diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml
index 83ab97f8e4f..47caec717af 100644
--- a/app/views/groups/dependency_proxies/show.html.haml
+++ b/app/views/groups/dependency_proxies/show.html.haml
@@ -3,4 +3,5 @@
- dependency_proxy_available = Feature.enabled?(:dependency_proxy_for_private_groups, default_enabled: true) || @group.public?
#js-dependency-proxy{ data: { group_path: @group.full_path,
- dependency_proxy_available: dependency_proxy_available.to_s } }
+ dependency_proxy_available: dependency_proxy_available.to_s,
+ no_manifests_illustration: image_path('illustrations/docker-empty-state.svg') } }
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index 5e20e21e314..c21240b340c 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -40,12 +40,17 @@
.form-group.project-path.col-sm-6
= f.label :path, class: 'label-bold' do
%span= _("Project slug")
- = f.text_field :path, placeholder: "my-awesome-project", class: "form-control gl-form-input", required: true, aria: { required: true }
+ = f.text_field :path, placeholder: "my-awesome-project", class: "form-control gl-form-input", required: true, aria: { required: true }, data: { username: current_user.username }
- if current_user.can_create_group?
.form-text.text-muted
- link_start_group_path = '<a href="%{path}">' % { path: new_group_path }
- project_tip = s_('ProjectsNew|Want to house several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}') % { link_start: link_start_group_path, link_end: '</a>' }
= project_tip.html_safe
+.gl-alert.gl-alert-success.gl-mb-4.gl-display-none.js-user-readme-repo
+ = sprite_icon('check-circle', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ - help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/profile/index', anchor: 'user-profile-readme') }
+ = html_escape(_('%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}')) % { project_path: "<strong>#{current_user.username} / #{current_user.username}</strong>".html_safe, help_link_start: help_link_start, help_link_end: '</a>'.html_safe }
.form-group
= f.label :description, class: 'label-bold' do
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index 8d33628da41..eb9caa796b5 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -9,6 +9,22 @@
%a.js-retry-load{ href: '#' }
= s_('UserProfile|Retry')
.user-calendar-activities
+- if @user.user_readme
+ .row
+ .col-12.gl-my-6
+ .gl-border-gray-100.gl-border-1.gl-border-solid.gl-rounded-small.gl-py-4.gl-px-6
+ .gl-display-flex
+ %ol.breadcrumb.gl-breadcrumb-list.gl-mb-4
+ %li.breadcrumb-item.gl-breadcrumb-item
+ = link_to @user.username, project_path(@user.user_project)
+ %span.gl-breadcrumb-separator
+ = sprite_icon("chevron-right", size: 16)
+ %li.breadcrumb-item.gl-breadcrumb-item
+ = link_to @user.user_readme.path, @user.user_project.readme_url
+ - if current_user == @user
+ .gl-ml-auto
+ = link_to _('Edit'), edit_blob_path(@user.user_project, @user.user_project.default_branch, @user.user_readme.path)
+ = render 'projects/blob/viewer', viewer: @user.user_readme.rich_viewer, load_async: false
.row
%div{ class: activity_pane_class }
- if can?(current_user, :read_cross_project)
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 1d55cd45840..03a0b5fae00 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -55,6 +55,12 @@ module ApplicationWorker
subclass.after_set_class_attribute { subclass.set_queue }
end
+ def with_status
+ status_from_class = self.sidekiq_options_hash['status_expiration']
+
+ set(status_expiration: status_from_class || Gitlab::SidekiqStatus::DEFAULT_EXPIRATION)
+ end
+
def generated_queue_name
Gitlab::SidekiqConfig::WorkerRouter.queue_name_from_worker_name(self)
end
diff --git a/app/workers/concerns/limited_capacity/worker.rb b/app/workers/concerns/limited_capacity/worker.rb
index b4cdfda680f..bcedb4efcc0 100644
--- a/app/workers/concerns/limited_capacity/worker.rb
+++ b/app/workers/concerns/limited_capacity/worker.rb
@@ -47,7 +47,7 @@ module LimitedCapacity
# would be occupied by a job that will be performed in the distant future.
# We let the cron worker enqueue new jobs, this could be seen as our retry and
# back off mechanism because the job might fail again if executed immediately.
- sidekiq_options retry: 0
+ sidekiq_options retry: 0, status_expiration: Gitlab::SidekiqStatus::DEFAULT_EXPIRATION
deduplicate :none
end