diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-03 09:09:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-12-03 09:09:47 +0300 |
commit | 9214e550c07793a8deb6d5cd5bb136d0d010a7ca (patch) | |
tree | bf094d583e9f57e2816a6f272bcbff302e264efe /app/assets/javascripts/members | |
parent | e1e9056d03fec6d72771c7a4ba3fc1174b5ac009 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/members')
3 files changed, 154 insertions, 0 deletions
diff --git a/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue b/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue new file mode 100644 index 00000000000..f2acc3215cd --- /dev/null +++ b/app/assets/javascripts/members/components/filter_sort/filter_sort_container.vue @@ -0,0 +1,18 @@ +<script> +import { mapState } from 'vuex'; +import MembersFilteredSearchBar from './members_filtered_search_bar.vue'; + +export default { + name: 'FilterSortContainer', + components: { MembersFilteredSearchBar }, + computed: { + ...mapState(['filteredSearchBar']), + }, +}; +</script> + +<template> + <div v-if="filteredSearchBar.show" class="gl-bg-gray-10 gl-p-5"> + <members-filtered-search-bar /> + </div> +</template> diff --git a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue new file mode 100644 index 00000000000..c1df0b94234 --- /dev/null +++ b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue @@ -0,0 +1,132 @@ +<script> +import { mapState } from 'vuex'; +import { GlFilteredSearchToken } from '@gitlab/ui'; +import { setUrlParams, queryToObject } from '~/lib/utils/url_utility'; +import { getParameterByName } from '~/lib/utils/common_utils'; +import { s__ } from '~/locale'; +import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; +import { SEARCH_TOKEN_TYPE, SORT_PARAM } from '~/members/constants'; + +export default { + name: 'MembersFilteredSearchBar', + components: { FilteredSearchBar }, + availableTokens: [ + { + type: 'two_factor', + icon: 'lock', + title: s__('Members|2FA'), + token: GlFilteredSearchToken, + unique: true, + operators: [{ value: '=', description: 'is' }], + options: [ + { value: 'enabled', title: s__('Members|Enabled') }, + { value: 'disabled', title: s__('Members|Disabled') }, + ], + requiredPermissions: 'canManageMembers', + }, + { + type: 'with_inherited_permissions', + icon: 'group', + title: s__('Members|Membership'), + token: GlFilteredSearchToken, + unique: true, + operators: [{ value: '=', description: 'is' }], + options: [ + { value: 'exclude', title: s__('Members|Direct') }, + { value: 'only', title: s__('Members|Inherited') }, + ], + }, + ], + data() { + return { + initialFilterValue: [], + }; + }, + computed: { + ...mapState(['sourceId', 'filteredSearchBar', 'canManageMembers']), + tokens() { + return this.$options.availableTokens.filter(token => { + if ( + Object.prototype.hasOwnProperty.call(token, 'requiredPermissions') && + !this[token.requiredPermissions] + ) { + return false; + } + + return this.filteredSearchBar.tokens?.includes(token.type); + }); + }, + }, + created() { + const query = queryToObject(window.location.search); + + const tokens = this.tokens + .filter(token => query[token.type]) + .map(token => ({ + type: token.type, + value: { + data: query[token.type], + operator: '=', + }, + })); + + if (query[this.filteredSearchBar.searchParam]) { + tokens.push({ + type: SEARCH_TOKEN_TYPE, + value: { + data: query[this.filteredSearchBar.searchParam], + }, + }); + } + + this.initialFilterValue = tokens; + }, + methods: { + handleFilter(tokens) { + const params = tokens.reduce((accumulator, token) => { + const { type, value } = token; + + if (!type || !value) { + return accumulator; + } + + if (type === SEARCH_TOKEN_TYPE) { + if (value.data !== '') { + return { + ...accumulator, + [this.filteredSearchBar.searchParam]: value.data, + }; + } + } else { + return { + ...accumulator, + [type]: value.data, + }; + } + + return accumulator; + }, {}); + + const sortParam = getParameterByName(SORT_PARAM); + + window.location.href = setUrlParams( + { ...params, ...(sortParam && { sort: sortParam }) }, + window.location.href, + true, + ); + }, + }, +}; +</script> + +<template> + <filtered-search-bar + :namespace="sourceId.toString()" + :tokens="tokens" + :recent-searches-storage-key="filteredSearchBar.recentSearchesStorageKey" + :search-input-placeholder="filteredSearchBar.placeholder" + :initial-filter-value="initialFilterValue" + data-testid="members-filtered-search-bar" + @onFilter="handleFilter" + /> +</template> diff --git a/app/assets/javascripts/members/constants.js b/app/assets/javascripts/members/constants.js index 5885420a122..a23e9b942ef 100644 --- a/app/assets/javascripts/members/constants.js +++ b/app/assets/javascripts/members/constants.js @@ -69,3 +69,7 @@ export const DAYS_TO_EXPIRE_SOON = 7; export const LEAVE_MODAL_ID = 'member-leave-modal'; export const REMOVE_GROUP_LINK_MODAL_ID = 'remove-group-link-modal-id'; + +export const SEARCH_TOKEN_TYPE = 'filtered-search-term'; + +export const SORT_PARAM = 'sort'; |