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>2022-08-16 00:09:52 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-08-16 00:09:52 +0300
commita2fd863d3be23fee66ec7036b8febb2605c17767 (patch)
tree27eb2c778723397d6326c72cd13e953bf9cb2564 /app
parentefbd20fd1ecd091f1270f73d617822a32c94376f (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue68
-rw-r--r--app/assets/javascripts/invite_members/constants.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue62
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/events/groups/group_deleted_event.rb16
-rw-r--r--app/services/groups/destroy_service.rb13
7 files changed, 133 insertions, 35 deletions
diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
index 674058bcaf0..87f1ed31a7f 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -6,6 +6,9 @@ import {
GlLink,
GlSprintf,
GlFormCheckboxGroup,
+ GlButton,
+ GlCollapse,
+ GlIcon,
} from '@gitlab/ui';
import { partition, isString, uniqueId, isEmpty } from 'lodash';
import InviteModalBase from 'ee_else_ce/invite_members/components/invite_modal_base.vue';
@@ -13,7 +16,7 @@ import Api from '~/api';
import ExperimentTracking from '~/experimentation/experiment_tracking';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { getParameterValues } from '~/lib/utils/url_utility';
-import { n__ } from '~/locale';
+import { n__, sprintf } from '~/locale';
import {
CLOSE_TO_LIMIT_COUNT,
USERS_FILTER_ALL,
@@ -38,6 +41,9 @@ export default {
GlDropdownItem,
GlSprintf,
GlFormCheckboxGroup,
+ GlButton,
+ GlCollapse,
+ GlIcon,
InviteModalBase,
MembersTokenSelect,
ModalConfetti,
@@ -110,6 +116,8 @@ export default {
mode: 'default',
// Kept in sync with "base"
selectedAccessLevel: undefined,
+ errorsLimit: 2,
+ isErrorsSectionExpanded: false,
};
},
computed: {
@@ -135,7 +143,7 @@ export default {
return n__(
"InviteMembersModal|The following member couldn't be invited",
"InviteMembersModal|The following %d members couldn't be invited",
- Object.keys(this.invalidMembers).length,
+ this.errorList.length,
);
},
tasksToBeDoneEnabled() {
@@ -187,6 +195,29 @@ export default {
? this.$options.labels.placeHolderDisabled
: this.$options.labels.placeHolder;
},
+ errorList() {
+ return Object.entries(this.invalidMembers).map(([member, error]) => {
+ return { member, displayedMemberName: this.tokenName(member), message: error };
+ });
+ },
+ errorsLimited() {
+ return this.errorList.slice(0, this.errorsLimit);
+ },
+ errorsExpanded() {
+ return this.errorList.slice(this.errorsLimit);
+ },
+ shouldErrorsSectionExpand() {
+ return Boolean(this.errorsExpanded.length);
+ },
+ errorCollapseText() {
+ if (this.isErrorsSectionExpanded) {
+ return this.$options.labels.expandedErrors;
+ }
+
+ return sprintf(this.$options.labels.collapsedErrors, {
+ count: this.errorsExpanded.length,
+ });
+ },
},
mounted() {
eventHub.$on('openModal', (options) => {
@@ -311,6 +342,9 @@ export default {
delete this.invalidMembers[memberName(token)];
this.invalidMembers = { ...this.invalidMembers };
},
+ toggleErrorExpansion() {
+ this.isErrorsSectionExpanded = !this.isErrorsSectionExpanded;
+ },
},
labels: MEMBER_MODAL_LABELS,
};
@@ -357,10 +391,36 @@ export default {
>
{{ $options.labels.memberErrorListText }}
<ul class="gl-pl-5 gl-mb-0">
- <li v-for="(error, member) in invalidMembers" :key="member">
- <strong>{{ tokenName(member) }}:</strong> {{ error }}
+ <li v-for="error in errorsLimited" :key="error.member" data-testid="errors-limited-item">
+ <strong>{{ error.displayedMemberName }}:</strong> {{ error.message }}
</li>
</ul>
+ <template v-if="shouldErrorsSectionExpand">
+ <gl-collapse v-model="isErrorsSectionExpanded">
+ <ul class="gl-pl-5 gl-mb-0">
+ <li
+ v-for="error in errorsExpanded"
+ :key="error.member"
+ data-testid="errors-expanded-item"
+ >
+ <strong>{{ error.displayedMemberName }}:</strong> {{ error.message }}
+ </li>
+ </ul>
+ </gl-collapse>
+ <gl-button
+ class="gl-text-decoration-none! gl-shadow-none! gl-mt-3"
+ data-testid="accordion-button"
+ variant="link"
+ @click="toggleErrorExpansion"
+ >
+ {{ errorCollapseText }}
+ <gl-icon
+ name="chevron-down"
+ class="gl-transition-medium"
+ :class="{ 'gl-rotate-180': isErrorsSectionExpanded }"
+ />
+ </gl-button>
+ </template>
</gl-alert>
<user-limit-notification
v-else
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index 6a0be3fc75b..1ceb63e2146 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -79,6 +79,8 @@ export const HEADER_CLOSE_LABEL = s__('InviteMembersModal|Close invite team memb
export const MEMBER_ERROR_LIST_TEXT = s__(
'InviteMembersModal|Review the invite errors and try again:',
);
+export const COLLAPSED_ERRORS = s__('InviteMembersModal|Show more (%{count})');
+export const EXPANDED_ERRORS = s__('InviteMembersModal|Show less');
export const MEMBER_MODAL_LABELS = {
modal: {
@@ -115,6 +117,8 @@ export const MEMBER_MODAL_LABELS = {
},
toastMessageSuccessful: TOAST_MESSAGE_SUCCESSFUL,
memberErrorListText: MEMBER_ERROR_LIST_TEXT,
+ collapsedErrors: COLLAPSED_ERRORS,
+ expandedErrors: EXPANDED_ERRORS,
};
export const GROUP_MODAL_LABELS = {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index d25d1ade7eb..6c5fc916799 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -51,9 +51,6 @@ export default {
isLoading() {
return this.glFeatures.mergeRequestWidgetGraphql && this.$apollo.queries.state.loading;
},
- showRebaseWithoutCi() {
- return this.glFeatures?.rebaseWithoutCiUi;
- },
rebaseInProgress() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
return this.state.rebaseInProgress;
@@ -195,7 +192,6 @@ export default {
</template>
<template v-if="!isLoading" #actions>
<gl-button
- v-if="showRebaseWithoutCi"
:loading="isMakingRequest"
variant="confirm"
size="small"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
index 3af4023d8e4..9c8819327e6 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
@@ -3,11 +3,15 @@ import * as Sentry from '@sentry/browser';
import { normalizeHeaders } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import Poll from '~/lib/utils/poll';
+import StatusIcon from '../extensions/status_icon.vue';
+import { EXTENSION_ICON_NAMES } from '../../constants';
const FETCH_TYPE_COLLAPSED = 'collapsed';
-// const FETCH_TYPE_EXPANDED = 'expanded';
export default {
+ components: {
+ StatusIcon,
+ },
props: {
/**
* @param {value.collapsed} Object
@@ -19,7 +23,8 @@ export default {
},
loadingText: {
type: String,
- required: true,
+ required: false,
+ default: __('Loading'),
},
errorText: {
type: String,
@@ -52,16 +57,30 @@ export default {
required: false,
default: false,
},
+ statusIconName: {
+ type: String,
+ default: 'neutral',
+ required: false,
+ validator: (value) => Object.keys(EXTENSION_ICON_NAMES).indexOf(value) > -1,
+ },
+ widgetName: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
- loading: false,
- statusIcon: null,
+ isLoading: false,
error: null,
};
},
+ watch: {
+ isLoading(newValue) {
+ this.$emit('is-loading', newValue);
+ },
+ },
async mounted() {
- this.loading = true;
+ this.isLoading = true;
try {
await this.fetch(this.fetchCollapsedData, FETCH_TYPE_COLLAPSED);
@@ -69,20 +88,14 @@ export default {
this.error = this.errorText;
}
- this.loading = false;
+ this.isLoading = false;
},
methods: {
fetch(handler, dataType) {
const requests = this.multiPolling ? handler() : [handler];
- const allData = [];
const promises = requests.map((request) => {
return new Promise((resolve, reject) => {
- const setData = (data) => {
- this.$emit('input', { ...this.value, [dataType]: data });
- resolve(data);
- };
-
const poll = new Poll({
resource: {
fetchData: () => request(),
@@ -95,17 +108,7 @@ export default {
return;
}
- if (this.multiPolling) {
- allData.push(response.data);
-
- if (allData.length === requests.length) {
- setData(allData);
- }
-
- return;
- }
-
- setData(response.data);
+ resolve(response.data);
},
errorCallback: (e) => {
Sentry.captureException(e);
@@ -117,7 +120,9 @@ export default {
});
});
- return Promise.all(promises);
+ return Promise.all(promises).then((data) => {
+ this.$emit('input', { ...this.value, [dataType]: this.multiPolling ? data : data[0] });
+ });
},
},
};
@@ -126,13 +131,18 @@ export default {
<template>
<section class="media-section" data-testid="widget-extension">
<div class="media gl-p-5">
- <!-- status icon will go here -->
+ <status-icon
+ :level="1"
+ :name="widgetName"
+ :is-loading="isLoading"
+ :icon-name="statusIconName"
+ />
<div
class="media-body gl-display-flex gl-flex-direction-row! gl-align-self-center"
data-testid="widget-extension-top-level"
>
<div class="gl-flex-grow-1" data-testid="widget-extension-top-level-summary">
- <slot name="summary">{{ summary }}</slot>
+ <slot name="summary">{{ isLoading ? loadingText : summary }}</slot>
</div>
<!-- actions will go here -->
<!-- toggle button will go here -->
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index ce5d0c45a1e..870c57fd6f3 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -37,7 +37,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:refactor_mr_widgets_extensions, project)
push_frontend_feature_flag(:refactor_code_quality_extension, project)
push_frontend_feature_flag(:refactor_mr_widget_test_summary, project)
- push_frontend_feature_flag(:rebase_without_ci_ui, project)
push_frontend_feature_flag(:issue_assignees_widget, @project)
push_frontend_feature_flag(:realtime_labels, project)
push_frontend_feature_flag(:refactor_security_extension, @project)
diff --git a/app/events/groups/group_deleted_event.rb b/app/events/groups/group_deleted_event.rb
new file mode 100644
index 00000000000..d89cce17be9
--- /dev/null
+++ b/app/events/groups/group_deleted_event.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Groups
+ class GroupDeletedEvent < ::Gitlab::EventStore::Event
+ def schema
+ {
+ 'type' => 'object',
+ 'properties' => {
+ 'group_id' => { 'type' => 'integer' },
+ 'root_namespace_id' => { 'type' => 'integer' }
+ },
+ 'required' => %w[group_id root_namespace_id]
+ }
+ end
+ end
+end
diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb
index bcf3110ca21..02a760ccf29 100644
--- a/app/services/groups/destroy_service.rb
+++ b/app/services/groups/destroy_service.rb
@@ -45,6 +45,8 @@ module Groups
.execute(blocking: true)
end
+ publish_event
+
group
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -91,6 +93,17 @@ module Groups
end
end
# rubocop:enable CodeReuse/ActiveRecord
+
+ def publish_event
+ event = Groups::GroupDeletedEvent.new(
+ data: {
+ group_id: group.id,
+ root_namespace_id: group.root_ancestor.id
+ }
+ )
+
+ Gitlab::EventStore.publish(event)
+ end
end
end