diff options
Diffstat (limited to 'app')
19 files changed, 78 insertions, 32 deletions
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js index 26507a85fa8..fe580aab108 100644 --- a/app/assets/javascripts/filtered_search/dropdown_user.js +++ b/app/assets/javascripts/filtered_search/dropdown_user.js @@ -1,3 +1,4 @@ +import { ACTIVE_AND_BLOCKED_USER_STATES } from '~/users_select/constants'; import { addClassIfElementExists } from '../lib/utils/dom_utils'; import DropdownAjaxFilter from './dropdown_ajax_filter'; @@ -14,7 +15,7 @@ export default class DropdownUser extends DropdownAjaxFilter { return { ...super.ajaxFilterConfig(), params: { - active: true, + states: ACTIVE_AND_BLOCKED_USER_STATES, group_id: this.getGroupId(), project_id: this.getProjectId(), current_user: true, diff --git a/app/assets/javascripts/filtered_search/droplab/plugins/ajax_filter.js b/app/assets/javascripts/filtered_search/droplab/plugins/ajax_filter.js index d0f2d205bb6..d6abab4c9ed 100644 --- a/app/assets/javascripts/filtered_search/droplab/plugins/ajax_filter.js +++ b/app/assets/javascripts/filtered_search/droplab/plugins/ajax_filter.js @@ -1,6 +1,7 @@ /* eslint-disable */ import AjaxCache from '~/lib/utils/ajax_cache'; +import { mergeUrlParams } from '~/lib/utils/url_utility'; const AjaxFilter = { init: function (hook) { @@ -62,7 +63,7 @@ const AjaxFilter = { this.loading = true; var params = config.params || {}; params[config.searchKey] = searchValue; - var url = config.endpoint + this.buildParams(params); + var url = mergeUrlParams(params, config.endpoint, { spreadArrays: true }); return AjaxCache.retrieve(url) .then((data) => { this._loadData(data, config); diff --git a/app/assets/javascripts/jobs/components/job/sidebar/sidebar.vue b/app/assets/javascripts/jobs/components/job/sidebar/sidebar.vue index b0db48df01f..aac6a0ad6d3 100644 --- a/app/assets/javascripts/jobs/components/job/sidebar/sidebar.vue +++ b/app/assets/javascripts/jobs/components/job/sidebar/sidebar.vue @@ -63,10 +63,23 @@ export default { commit() { return this.job?.pipeline?.commit || {}; }, + selectedStageData() { + return this.stages.find((val) => val.name === this.selectedStage); + }, shouldShowJobRetryForwardDeploymentModal() { return this.job.retry_path && this.hasForwardDeploymentFailure; }, }, + watch: { + job(value, oldValue) { + const hasNewStatus = value.status.text !== oldValue.status.text; + const isCurrentStage = value?.stage === this.selectedStage; + + if (hasNewStatus && isCurrentStage) { + this.fetchJobsForStage(this.selectedStageData); + } + }, + }, methods: { ...mapActions(['fetchJobsForStage']), }, diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js index ca90eee69c7..b1a0baf8150 100644 --- a/app/assets/javascripts/lib/utils/url_utility.js +++ b/app/assets/javascripts/lib/utils/url_utility.js @@ -178,7 +178,7 @@ export function mergeUrlParams(params, url, options = {}) { const mergedKeys = sort ? Object.keys(merged).sort() : Object.keys(merged); const newQuery = mergedKeys - .filter((key) => merged[key] !== null) + .filter((key) => merged[key] !== null && merged[key] !== undefined) .map((key) => { let value = merged[key]; const encodedKey = encodeURIComponent(key); diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js index d75a4158440..c4d542083bd 100644 --- a/app/assets/javascripts/notes/mixins/discussion_navigation.js +++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js @@ -2,7 +2,7 @@ import { mapGetters, mapActions, mapState } from 'vuex'; import { scrollToElement, contentTop } from '~/lib/utils/common_utils'; function getAllDiscussionElements() { - const containerEl = window.mrTabs?.currentAction === 'diffs' ? '.diffs' : '.notes'; + const containerEl = window.mrTabs?.currentAction === 'diffs' ? '.diffs' : '.tab-pane.notes'; return Array.from( document.querySelectorAll( `${containerEl} div[data-discussion-id]:not([data-discussion-resolved])`, diff --git a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue index 95c1f575fe4..b68148e5461 100644 --- a/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue +++ b/app/assets/javascripts/pages/admin/application_settings/general/components/signup_form.vue @@ -59,6 +59,8 @@ export default { 'emailRestrictions', 'afterSignUpText', 'pendingUserCount', + 'projectSharingHelpLink', + 'groupSharingHelpLink', ], data() { return { @@ -83,6 +85,8 @@ export default { supportedSyntaxLinkUrl: this.supportedSyntaxLinkUrl, emailRestrictions: this.emailRestrictions, afterSignUpText: this.afterSignUpText, + projectSharingHelpLink: this.projectSharingHelpLink, + groupSharingHelpLink: this.groupSharingHelpLink, }, }; }, @@ -219,7 +223,7 @@ export default { ), userCapLabel: s__('ApplicationSettings|User cap'), userCapDescription: s__( - 'ApplicationSettings|After the instance reaches the user cap, any user who is added or requests access must be approved by an administrator. Leave blank for unlimited.', + 'ApplicationSettings|After the instance reaches the user cap, any user who is added or requests access must be approved by an administrator. Leave blank for an unlimited user cap. If you change the user cap to unlimited, you must re-enable %{projectSharingLinkStart}project sharing%{projectSharingLinkEnd} and %{groupSharingLinkStart}group sharing%{groupSharingLinkEnd}.', ), domainDenyListGroupLabel: s__('ApplicationSettings|Domain denylist'), domainDenyListLabel: s__('ApplicationSettings|Enable domain denylist for sign-ups'), @@ -308,6 +312,7 @@ export default { <gl-form-group :label="$options.i18n.userCapLabel" :description="$options.i18n.userCapDescription" + data-testid="user-cap-form-group" > <gl-form-input v-model="form.userCap" @@ -315,6 +320,17 @@ export default { name="application_setting[new_user_signups_cap]" data-testid="user-cap-input" /> + + <template #description> + <gl-sprintf :message="$options.i18n.userCapDescription"> + <template #projectSharingLink="{ content }"> + <gl-link :href="projectSharingHelpLink" target="_blank">{{ content }}</gl-link> + </template> + <template #groupSharingLink="{ content }"> + <gl-link :href="groupSharingHelpLink" target="_blank">{{ content }}</gl-link> + </template> + </gl-sprintf> + </template> </gl-form-group> <gl-form-group :label="$options.i18n.minimumPasswordLengthLabel"> diff --git a/app/assets/javascripts/projects/commits/store/actions.js b/app/assets/javascripts/projects/commits/store/actions.js index 603fdfdf80a..9365066418b 100644 --- a/app/assets/javascripts/projects/commits/store/actions.js +++ b/app/assets/javascripts/projects/commits/store/actions.js @@ -3,6 +3,7 @@ import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { joinPaths } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; +import { ACTIVE_AND_BLOCKED_USER_STATES } from '~/users_select/constants'; import * as types from './mutation_types'; export default { @@ -23,7 +24,7 @@ export default { .get(joinPaths(gon.relative_url_root || '', '/-/autocomplete/users.json'), { params: { project_id: projectId, - active: true, + states: ACTIVE_AND_BLOCKED_USER_STATES, search: author, }, }) diff --git a/app/assets/javascripts/projects/settings/api/access_dropdown_api.js b/app/assets/javascripts/projects/settings/api/access_dropdown_api.js index 10f6c28a7bf..df99aac6b9e 100644 --- a/app/assets/javascripts/projects/settings/api/access_dropdown_api.js +++ b/app/assets/javascripts/projects/settings/api/access_dropdown_api.js @@ -12,7 +12,7 @@ const buildUrl = (urlRoot, url) => { return newUrl; }; -export const getUsers = (query) => { +export const getUsers = (query, states) => { return axios.get(buildUrl(gon.relative_url_root || '', USERS_PATH), { params: { search: query, @@ -20,6 +20,7 @@ export const getUsers = (query) => { active: true, project_id: gon.current_project_id, push_code: true, + states, }, }); }; diff --git a/app/assets/javascripts/users_select/constants.js b/app/assets/javascripts/users_select/constants.js index 6b91d7e7c10..c100c1f4ca5 100644 --- a/app/assets/javascripts/users_select/constants.js +++ b/app/assets/javascripts/users_select/constants.js @@ -7,4 +7,7 @@ export const AJAX_USERS_SELECT_PARAMS_MAP = { current_user: 'showCurrentUser', author_id: 'authorId', skip_users: 'skipUsers', + states: 'states', }; + +export const ACTIVE_AND_BLOCKED_USER_STATES = ['active', 'blocked']; diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js index a0550737e24..fbf7e0b3a86 100644 --- a/app/assets/javascripts/users_select/index.js +++ b/app/assets/javascripts/users_select/index.js @@ -29,27 +29,29 @@ function UsersSelect(currentUser, els, options = {}) { } } - const { handleClick } = options; + const { handleClick, states } = options; $els.each((i, dropdown) => { const userSelect = this; - const options = {}; const $dropdown = $(dropdown); - options.projectId = $dropdown.data('projectId'); - options.groupId = $dropdown.data('groupId'); - options.showCurrentUser = $dropdown.data('currentUser'); - options.todoFilter = $dropdown.data('todoFilter'); - options.todoStateFilter = $dropdown.data('todoStateFilter'); - options.iid = $dropdown.data('iid'); - options.issuableType = $dropdown.data('issuableType'); - options.targetBranch = $dropdown.data('targetBranch'); - options.showSuggested = $dropdown.data('showSuggested'); + const options = { + states, + projectId: $dropdown.data('projectId'), + groupId: $dropdown.data('groupId'), + showCurrentUser: $dropdown.data('currentUser'), + todoFilter: $dropdown.data('todoFilter'), + todoStateFilter: $dropdown.data('todoStateFilter'), + iid: $dropdown.data('iid'), + issuableType: $dropdown.data('issuableType'), + targetBranch: $dropdown.data('targetBranch'), + authorId: $dropdown.data('authorId'), + showSuggested: $dropdown.data('showSuggested'), + }; const showNullUser = $dropdown.data('nullUser'); const defaultNullUser = $dropdown.data('nullUserDefault'); const showMenuAbove = $dropdown.data('showMenuAbove'); const showAnyUser = $dropdown.data('anyUser'); const firstUser = $dropdown.data('firstUser'); - options.authorId = $dropdown.data('authorId'); const defaultLabel = $dropdown.data('defaultLabel'); const issueURL = $dropdown.data('issueUpdate'); const $selectbox = $dropdown.closest('.selectbox'); diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue index fe69e96bd87..97c6de37054 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue @@ -200,7 +200,7 @@ export default { data-testid="pipeline-info-container" data-qa-selector="merge_request_pipeline_info_content" > - {{ pipeline.details.name }} + {{ pipeline.details.event_type_name || pipeline.details.name }} <gl-link :href="pipeline.path" class="pipeline-id gl-font-weight-normal pipeline-number" diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss index 29ab1f91b7c..4a5143befc5 100644 --- a/app/assets/stylesheets/page_bundles/merge_requests.scss +++ b/app/assets/stylesheets/page_bundles/merge_requests.scss @@ -269,7 +269,7 @@ $tabs-holder-z-index: 250; position: -webkit-sticky; position: sticky; - top: var(--top-pos); + top: calc(var(--top-pos) + var(--performance-bar-height, 0px)); max-height: calc(100vh - var(--top-pos) - var(--system-header-height, 0px) - var(--performance-bar-height, 0px) - var(--review-bar-height, 0px)); .drag-handle { diff --git a/app/finders/autocomplete/users_finder.rb b/app/finders/autocomplete/users_finder.rb index 33d9a8a3dbc..bb91f84de99 100644 --- a/app/finders/autocomplete/users_finder.rb +++ b/app/finders/autocomplete/users_finder.rb @@ -12,7 +12,7 @@ module Autocomplete attr_reader :current_user, :project, :group, :search, :skip_users, :author_id, :todo_filter, :todo_state_filter, - :filter_by_current_user + :filter_by_current_user, :states def initialize(params:, current_user:, project:, group:) @current_user = current_user @@ -24,6 +24,7 @@ module Autocomplete @todo_filter = params[:todo_filter] @todo_state_filter = params[:todo_state_filter] @filter_by_current_user = params[:current_user] + @states = params[:states] || ['active'] end def execute @@ -60,7 +61,8 @@ module Autocomplete # reorder_by_name() is called _before_ optionally_search(), otherwise # reorder_by_name will break the ORDER BY applied in optionally_search(). find_users - .active + .where(state: states) + .non_internal .reorder_by_name .optionally_search(search, use_minimum_char_limit: use_minimum_char_limit) .where_not_in(skip_users) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 9678d8bf2fd..b48f843135d 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -561,7 +561,9 @@ module ApplicationSettingsHelper supported_syntax_link_url: 'https://github.com/google/re2/wiki/Syntax', email_restrictions: @application_setting.email_restrictions.to_s, after_sign_up_text: @application_setting[:after_sign_up_text].to_s, - pending_user_count: pending_user_count + pending_user_count: pending_user_count, + project_sharing_help_link: help_page_path('user/group/access_and_permissions', anchor: 'prevent-a-project-from-being-shared-with-groups'), + group_sharing_help_link: help_page_path('user/group/access_and_permissions', anchor: 'prevent-group-sharing-outside-the-group-hierarchy') } end end diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb index 221a2284106..7baa98b59f9 100644 --- a/app/models/ci/build_trace_chunk.rb +++ b/app/models/ci/build_trace_chunk.rb @@ -10,7 +10,7 @@ module Ci belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id - default_value_for :data_store, :redis_trace_chunks + attribute :data_store, default: :redis_trace_chunks after_create { metrics.increment_trace_operation(operation: :chunked) } diff --git a/app/models/ci/secure_file.rb b/app/models/ci/secure_file.rb index ffff7eebbee..df38398e5a9 100644 --- a/app/models/ci/secure_file.rb +++ b/app/models/ci/secure_file.rb @@ -27,7 +27,7 @@ module Ci serialize :metadata, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize - default_value_for(:file_store) { Ci::SecureFileUploader.default_store } + attribute :file_store, default: -> { Ci::SecureFileUploader.default_store } mount_file_store_uploader Ci::SecureFileUploader diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb index 5cdc6ff12cb..aa0cd476191 100644 --- a/app/presenters/ci/pipeline_presenter.rb +++ b/app/presenters/ci/pipeline_presenter.rb @@ -53,8 +53,7 @@ module Ci }.freeze end - delegator_override :name - def name + def event_type_name # Currently, `merge_request_event_type` is the only source to name pipelines # but this could be extended with the other types in the future. localized_names.fetch(pipeline.merge_request_event_type, s_('Pipeline|Pipeline')) diff --git a/app/serializers/ci/pipeline_entity.rb b/app/serializers/ci/pipeline_entity.rb index 20aeb978520..8edb07e4f59 100644 --- a/app/serializers/ci/pipeline_entity.rb +++ b/app/serializers/ci/pipeline_entity.rb @@ -4,7 +4,7 @@ class Ci::PipelineEntity < Grape::Entity include RequestAwareEntity include Gitlab::Utils::StrongMemoize - delegate :name, :failure_reason, :coverage, to: :presented_pipeline + delegate :event_type_name, :failure_reason, :coverage, to: :presented_pipeline expose :id expose :iid @@ -40,7 +40,8 @@ class Ci::PipelineEntity < Grape::Entity expose :stages, using: StageEntity expose :duration expose :finished_at - expose :name + expose :event_type_name + expose :event_type_name, as: :name # To be removed in 15.7 end expose :merge_request, if: -> (*) { has_presentable_merge_request? }, with: MergeRequestForPipelineEntity do |pipeline| diff --git a/app/serializers/merge_requests/pipeline_entity.rb b/app/serializers/merge_requests/pipeline_entity.rb index f4fb01604d0..9c2545a2834 100644 --- a/app/serializers/merge_requests/pipeline_entity.rb +++ b/app/serializers/merge_requests/pipeline_entity.rb @@ -17,8 +17,12 @@ class MergeRequests::PipelineEntity < Grape::Entity expose :commit, using: CommitEntity expose :details do - expose :name do |pipeline| - pipeline.present.name + expose :event_type_name do |pipeline| + pipeline.present.event_type_name + end + + expose :name do |pipeline| # To be removed in 15.7 + pipeline.present.event_type_name end expose :artifacts do |pipeline, options| |