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:
Diffstat (limited to 'app/assets/javascripts/invite_members')
-rw-r--r--app/assets/javascripts/invite_members/components/group_select.vue50
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue26
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_trigger.vue3
-rw-r--r--app/assets/javascripts/invite_members/constants.js5
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js2
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_trigger.js22
6 files changed, 86 insertions, 22 deletions
diff --git a/app/assets/javascripts/invite_members/components/group_select.vue b/app/assets/javascripts/invite_members/components/group_select.vue
index 4a72e97db8c..2d1e57a1177 100644
--- a/app/assets/javascripts/invite_members/components/group_select.vue
+++ b/app/assets/javascripts/invite_members/components/group_select.vue
@@ -1,13 +1,20 @@
<script>
-import { GlDropdown, GlDropdownItem, GlDropdownText, GlSearchBoxByType } from '@gitlab/ui';
+import {
+ GlAvatarLabeled,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
+ GlSearchBoxByType,
+} from '@gitlab/ui';
import { debounce } from 'lodash';
-import Api from '~/api';
import { s__ } from '~/locale';
-import { SEARCH_DELAY } from '../constants';
+import { getGroups, getDescendentGroups } from '~/rest_api';
+import { SEARCH_DELAY, GROUP_FILTERS } from '../constants';
export default {
name: 'GroupSelect',
components: {
+ GlAvatarLabeled,
GlDropdown,
GlDropdownItem,
GlDropdownText,
@@ -16,6 +23,18 @@ export default {
model: {
prop: 'selectedGroup',
},
+ props: {
+ groupsFilter: {
+ type: String,
+ required: false,
+ default: GROUP_FILTERS.ALL,
+ },
+ parentGroupId: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ },
data() {
return {
isFetching: false,
@@ -43,12 +62,13 @@ export default {
methods: {
retrieveGroups: debounce(function debouncedRetrieveGroups() {
this.isFetching = true;
- return Api.groups(this.searchTerm, this.$options.defaultFetchOptions)
+ return this.fetchGroups()
.then((response) => {
this.groups = response.map((group) => ({
id: group.id,
name: group.full_name,
path: group.path,
+ avatarUrl: group.avatar_url,
}));
this.isFetching = false;
})
@@ -61,6 +81,18 @@ export default {
this.$emit('input', this.selectedGroup);
},
+ fetchGroups() {
+ switch (this.groupsFilter) {
+ case GROUP_FILTERS.DESCENDANT_GROUPS:
+ return getDescendentGroups(
+ this.parentGroupId,
+ this.searchTerm,
+ this.$options.defaultFetchOptions,
+ );
+ default:
+ return getGroups(this.searchTerm, this.$options.defaultFetchOptions);
+ }
+ },
},
i18n: {
dropdownText: s__('GroupSelect|Select a group'),
@@ -82,7 +114,7 @@ export default {
menu-class="gl-w-full!"
>
<gl-search-box-by-type
- v-model.trim="searchTerm"
+ v-model="searchTerm"
:is-loading="isFetching"
:placeholder="$options.i18n.searchPlaceholder"
data-qa-selector="group_select_dropdown_search_field"
@@ -93,7 +125,13 @@ export default {
:name="group.name"
@click="selectGroup(group)"
>
- {{ group.name }}
+ <gl-avatar-labeled
+ :label="group.name"
+ :src="group.avatarUrl"
+ :entity-id="group.id"
+ :entity-name="group.name"
+ :size="32"
+ />
</gl-dropdown-item>
<gl-dropdown-text v-if="isFetchResultEmpty && !isFetching" data-testid="empty-result-message">
<span class="gl-text-gray-500">{{ $options.i18n.emptySearchResult }}</span>
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 d00a0f1633b..84c8594c6b6 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -16,7 +16,7 @@ import GroupSelect from '~/invite_members/components/group_select.vue';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import { s__, sprintf } from '~/locale';
-import { INVITE_MEMBERS_IN_COMMENT } from '../constants';
+import { INVITE_MEMBERS_IN_COMMENT, GROUP_FILTERS } from '../constants';
import eventHub from '../event_hub';
export default {
@@ -54,6 +54,16 @@ export default {
type: Number,
required: true,
},
+ groupSelectFilter: {
+ type: String,
+ required: false,
+ default: GROUP_FILTERS.ALL,
+ },
+ groupSelectParentId: {
+ type: Number,
+ required: false,
+ default: null,
+ },
helpLink: {
type: String,
required: true,
@@ -68,6 +78,7 @@ export default {
newUsersToInvite: [],
selectedDate: undefined,
groupToBeSharedWith: {},
+ source: 'unknown',
};
},
computed: {
@@ -195,6 +206,7 @@ export default {
...this.basePostData,
email: usersToInviteByEmail,
access_level: this.selectedAccessLevel,
+ invite_source: this.source,
};
},
addByUserIdPostData(usersToAddById) {
@@ -202,6 +214,7 @@ export default {
...this.basePostData,
user_id: usersToAddById,
access_level: this.selectedAccessLevel,
+ invite_source: this.source,
};
},
shareWithGroupPostData(groupToBeSharedWith) {
@@ -251,11 +264,11 @@ export default {
),
},
},
- accessLevel: s__('InviteMembersModal|Choose a role permission'),
+ accessLevel: s__('InviteMembersModal|Select a role'),
accessExpireDate: s__('InviteMembersModal|Access expiration date (optional)'),
toastMessageSuccessful: s__('InviteMembersModal|Members were successfully added'),
toastMessageUnsuccessful: s__('InviteMembersModal|Some of the members could not be added'),
- readMoreText: s__(`InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`),
+ readMoreText: s__(`InviteMembersModal|%{linkStart}Learn more%{linkEnd} about roles.`),
inviteButtonText: s__('InviteMembersModal|Invite'),
cancelButtonText: s__('InviteMembersModal|Cancel'),
headerCloseLabel: s__('InviteMembersModal|Close invite team members'),
@@ -290,7 +303,12 @@ export default {
:aria-labelledby="$options.membersTokenSelectLabelId"
:placeholder="$options.labels[inviteeType].placeHolder"
/>
- <group-select v-if="isInviteGroup" v-model="groupToBeSharedWith" />
+ <group-select
+ v-if="isInviteGroup"
+ v-model="groupToBeSharedWith"
+ :groups-filter="groupSelectFilter"
+ :parent-group-id="groupSelectParentId"
+ />
</div>
<label class="gl-font-weight-bold gl-mt-3">{{ $options.labels.accessLevel }}</label>
diff --git a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
index e297bb6c806..ec7d466336e 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -29,8 +29,7 @@ export default {
},
triggerSource: {
type: String,
- required: false,
- default: 'unknown',
+ required: true,
},
trackExperiment: {
type: String,
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index a651b81c60e..0c5538d5b86 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -1,3 +1,8 @@
export const SEARCH_DELAY = 200;
export const INVITE_MEMBERS_IN_COMMENT = 'invite_members_in_comment';
+
+export const GROUP_FILTERS = {
+ ALL: 'all',
+ DESCENDANT_GROUPS: 'descendant_groups',
+};
diff --git a/app/assets/javascripts/invite_members/init_invite_members_modal.js b/app/assets/javascripts/invite_members/init_invite_members_modal.js
index fc77bd53ba4..7501e9f4e6e 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -21,6 +21,8 @@ export default function initInviteMembersModal() {
isProject: parseBoolean(el.dataset.isProject),
accessLevels: JSON.parse(el.dataset.accessLevels),
defaultAccessLevel: parseInt(el.dataset.defaultAccessLevel, 10),
+ groupSelectFilter: el.dataset.groupsFilter,
+ groupSelectParentId: parseInt(el.dataset.parentId, 10),
},
}),
});
diff --git a/app/assets/javascripts/invite_members/init_invite_members_trigger.js b/app/assets/javascripts/invite_members/init_invite_members_trigger.js
index a7b95960995..935edb35349 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_trigger.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_trigger.js
@@ -2,19 +2,21 @@ import Vue from 'vue';
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
export default function initInviteMembersTrigger() {
- const el = document.querySelector('.js-invite-members-trigger');
+ const triggers = document.querySelectorAll('.js-invite-members-trigger');
- if (!el) {
+ if (!triggers) {
return false;
}
- return new Vue({
- el,
- render: (createElement) =>
- createElement(InviteMembersTrigger, {
- props: {
- ...el.dataset,
- },
- }),
+ return triggers.forEach((el) => {
+ return new Vue({
+ el,
+ render: (createElement) =>
+ createElement(InviteMembersTrigger, {
+ props: {
+ ...el.dataset,
+ },
+ }),
+ });
});
}