diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue | 104 |
1 files changed, 86 insertions, 18 deletions
diff --git a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue index 7d2af7983d1..521b1a1075a 100644 --- a/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue +++ b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue @@ -1,34 +1,74 @@ <script> -import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui'; +import { + GlDropdown, + GlDropdownDivider, + GlDropdownItem, + GlDropdownSectionHeader, + GlSearchBoxByType, +} from '@gitlab/ui'; import { __ } from '~/locale'; +export const EMPTY_NAMESPACE_ID = -1; export const i18n = { DEFAULT_TEXT: __('Select a new namespace'), + DEFAULT_EMPTY_NAMESPACE_TEXT: __('No namespace'), GROUPS: __('Groups'), USERS: __('Users'), }; -const filterByName = (data, searchTerm = '') => - data.filter((d) => d.humanName.toLowerCase().includes(searchTerm)); +const filterByName = (data, searchTerm = '') => { + if (!searchTerm) { + return data; + } + + return data.filter((d) => d.humanName.toLowerCase().includes(searchTerm.toLowerCase())); +}; export default { name: 'NamespaceSelect', components: { GlDropdown, + GlDropdownDivider, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType, }, props: { - data: { - type: Object, - required: true, + groupNamespaces: { + type: Array, + required: false, + default: () => [], + }, + userNamespaces: { + type: Array, + required: false, + default: () => [], }, fullWidth: { type: Boolean, required: false, default: false, }, + defaultText: { + type: String, + required: false, + default: i18n.DEFAULT_TEXT, + }, + includeHeaders: { + type: Boolean, + required: false, + default: true, + }, + emptyNamespaceTitle: { + type: String, + required: false, + default: i18n.DEFAULT_EMPTY_NAMESPACE_TEXT, + }, + includeEmptyNamespace: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { @@ -38,21 +78,33 @@ export default { }, computed: { hasUserNamespaces() { - return this.data.user?.length; + return this.userNamespaces.length; }, hasGroupNamespaces() { - return this.data.group?.length; + return this.groupNamespaces.length; }, filteredGroupNamespaces() { if (!this.hasGroupNamespaces) return []; - return filterByName(this.data.group, this.searchTerm); + return filterByName(this.groupNamespaces, this.searchTerm); }, filteredUserNamespaces() { if (!this.hasUserNamespaces) return []; - return filterByName(this.data.user, this.searchTerm); + return filterByName(this.userNamespaces, this.searchTerm); }, selectedNamespaceText() { - return this.selectedNamespace?.humanName || this.$options.i18n.DEFAULT_TEXT; + return this.selectedNamespace?.humanName || this.defaultText; + }, + filteredEmptyNamespaceTitle() { + const { includeEmptyNamespace, emptyNamespaceTitle, searchTerm } = this; + + if (!includeEmptyNamespace) { + return ''; + } + if (!searchTerm) { + return emptyNamespaceTitle; + } + + return emptyNamespaceTitle.toLowerCase().includes(searchTerm.toLowerCase()); }, }, methods: { @@ -60,31 +112,47 @@ export default { this.selectedNamespace = item; this.$emit('select', item); }, + handleSelectEmptyNamespace() { + this.handleSelect({ id: EMPTY_NAMESPACE_ID, humanName: this.emptyNamespaceTitle }); + }, }, i18n, }; </script> <template> - <gl-dropdown :text="selectedNamespaceText" :block="fullWidth"> + <gl-dropdown :text="selectedNamespaceText" :block="fullWidth" data-qa-selector="namespaces_list"> <template #header> <gl-search-box-by-type v-model.trim="searchTerm" /> </template> - <div v-if="hasGroupNamespaces" class="qa-namespaces-list-groups"> - <gl-dropdown-section-header>{{ $options.i18n.GROUPS }}</gl-dropdown-section-header> + <div v-if="filteredEmptyNamespaceTitle"> + <gl-dropdown-item + data-qa-selector="namespaces_list_item" + @click="handleSelectEmptyNamespace()" + > + {{ emptyNamespaceTitle }} + </gl-dropdown-item> + <gl-dropdown-divider /> + </div> + <div v-if="hasGroupNamespaces" data-qa-selector="namespaces_list_groups"> + <gl-dropdown-section-header v-if="includeHeaders">{{ + $options.i18n.GROUPS + }}</gl-dropdown-section-header> <gl-dropdown-item v-for="item in filteredGroupNamespaces" :key="item.id" - class="qa-namespaces-list-item" + data-qa-selector="namespaces_list_item" @click="handleSelect(item)" >{{ item.humanName }}</gl-dropdown-item > </div> - <div v-if="hasUserNamespaces" class="qa-namespaces-list-users"> - <gl-dropdown-section-header>{{ $options.i18n.USERS }}</gl-dropdown-section-header> + <div v-if="hasUserNamespaces" data-qa-selector="namespaces_list_users"> + <gl-dropdown-section-header v-if="includeHeaders">{{ + $options.i18n.USERS + }}</gl-dropdown-section-header> <gl-dropdown-item v-for="item in filteredUserNamespaces" :key="item.id" - class="qa-namespaces-list-item" + data-qa-selector="namespaces_list_item" @click="handleSelect(item)" >{{ item.humanName }}</gl-dropdown-item > |