debian-mirror-gitlab/app/assets/javascripts/search/topbar/components/searchable_dropdown.vue

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

196 lines
4.7 KiB
Vue
Raw Normal View History

2021-02-22 17:27:13 +05:30
<script>
import {
GlDropdown,
GlDropdownItem,
2021-09-30 23:02:18 +05:30
GlDropdownSectionHeader,
2021-02-22 17:27:13 +05:30
GlSearchBoxByType,
GlLoadingIcon,
GlIcon,
GlButton,
GlSkeletonLoader,
GlTooltipDirective,
} from '@gitlab/ui';
2021-04-29 21:17:54 +05:30
import { __ } from '~/locale';
2021-02-22 17:27:13 +05:30
import { ANY_OPTION } from '../constants';
2021-09-04 01:27:46 +05:30
import SearchableDropdownItem from './searchable_dropdown_item.vue';
2021-02-22 17:27:13 +05:30
export default {
2021-04-29 21:17:54 +05:30
i18n: {
clearLabel: __('Clear'),
2021-09-30 23:02:18 +05:30
frequentlySearched: __('Frequently searched'),
2021-04-29 21:17:54 +05:30
},
2021-02-22 17:27:13 +05:30
name: 'SearchableDropdown',
components: {
GlDropdown,
GlDropdownItem,
2021-09-30 23:02:18 +05:30
GlDropdownSectionHeader,
2021-02-22 17:27:13 +05:30
GlSearchBoxByType,
GlLoadingIcon,
GlIcon,
GlButton,
GlSkeletonLoader,
2021-09-04 01:27:46 +05:30
SearchableDropdownItem,
2021-02-22 17:27:13 +05:30
},
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
headerText: {
type: String,
required: false,
default: "__('Filter')",
},
2021-09-04 01:27:46 +05:30
name: {
2021-02-22 17:27:13 +05:30
type: String,
required: false,
default: 'name',
},
2021-09-04 01:27:46 +05:30
fullName: {
2021-02-22 17:27:13 +05:30
type: String,
required: false,
default: 'name',
},
loading: {
type: Boolean,
required: false,
default: false,
},
selectedItem: {
type: Object,
required: true,
},
items: {
type: Array,
required: false,
default: () => [],
},
2021-09-30 23:02:18 +05:30
frequentItems: {
type: Array,
required: false,
default: () => [],
},
2021-02-22 17:27:13 +05:30
},
data() {
return {
searchText: '',
2021-09-30 23:02:18 +05:30
hasBeenOpened: false,
2021-02-22 17:27:13 +05:30
};
},
2021-09-30 23:02:18 +05:30
computed: {
showFrequentItems() {
return !this.searchText && this.frequentItems.length > 0;
},
},
2021-02-22 17:27:13 +05:30
methods: {
isSelected(selected) {
return selected.id === this.selectedItem.id;
},
openDropdown() {
2021-09-30 23:02:18 +05:30
if (!this.hasBeenOpened) {
this.hasBeenOpened = true;
this.$emit('first-open');
}
2021-02-22 17:27:13 +05:30
this.$emit('search', this.searchText);
},
resetDropdown() {
this.$emit('change', ANY_OPTION);
},
2021-09-04 01:27:46 +05:30
updateDropdown(item) {
this.$emit('change', item);
},
2021-02-22 17:27:13 +05:30
},
ANY_OPTION,
};
</script>
<template>
<gl-dropdown
class="gl-w-full"
2021-09-04 01:27:46 +05:30
menu-class="global-search-dropdown-menu"
2021-02-22 17:27:13 +05:30
toggle-class="gl-text-truncate"
:header-text="headerText"
2021-09-04 01:27:46 +05:30
:right="true"
@show="openDropdown"
2021-02-22 17:27:13 +05:30
@shown="$refs.searchBox.focusInput()"
>
<template #button-content>
<span class="dropdown-toggle-text gl-flex-grow-1 gl-text-truncate">
2021-09-04 01:27:46 +05:30
{{ selectedItem[name] }}
2021-02-22 17:27:13 +05:30
</span>
2021-09-30 23:02:18 +05:30
<gl-loading-icon v-if="loading" size="sm" inline class="gl-mr-3" />
2021-02-22 17:27:13 +05:30
<gl-button
v-if="!isSelected($options.ANY_OPTION)"
v-gl-tooltip
name="clear"
category="tertiary"
2021-04-29 21:17:54 +05:30
:title="$options.i18n.clearLabel"
:aria-label="$options.i18n.clearLabel"
2021-02-22 17:27:13 +05:30
class="gl-p-0! gl-mr-2"
@keydown.enter.stop="resetDropdown"
@click.stop="resetDropdown"
>
2021-03-11 19:13:27 +05:30
<gl-icon name="clear" />
2021-02-22 17:27:13 +05:30
</gl-button>
<gl-icon name="chevron-down" />
</template>
<div class="gl-sticky gl-top-0 gl-z-index-1 gl-bg-white">
<gl-search-box-by-type
ref="searchBox"
v-model="searchText"
class="gl-m-3"
:debounce="500"
2021-09-04 01:27:46 +05:30
@input="openDropdown"
2021-02-22 17:27:13 +05:30
/>
<gl-dropdown-item
class="gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-pb-2! gl-mb-2"
2022-10-11 01:57:18 +05:30
is-check-item
2021-02-22 17:27:13 +05:30
:is-checked="isSelected($options.ANY_OPTION)"
2022-10-11 01:57:18 +05:30
is-check-centered
2021-09-04 01:27:46 +05:30
@click="updateDropdown($options.ANY_OPTION)"
2021-02-22 17:27:13 +05:30
>
2021-09-04 01:27:46 +05:30
<span data-testid="item-title">{{ $options.ANY_OPTION.name }}</span>
2021-02-22 17:27:13 +05:30
</gl-dropdown-item>
</div>
2021-09-30 23:02:18 +05:30
<div
v-if="showFrequentItems"
class="gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-pb-2 gl-mb-2"
>
<gl-dropdown-section-header>{{
$options.i18n.frequentlySearched
}}</gl-dropdown-section-header>
<searchable-dropdown-item
v-for="item in frequentItems"
:key="item.id"
:item="item"
:selected-item="selectedItem"
:search-text="searchText"
:name="name"
:full-name="fullName"
data-testid="frequent-items"
@change="updateDropdown"
/>
</div>
2021-02-22 17:27:13 +05:30
<div v-if="!loading">
2021-09-04 01:27:46 +05:30
<searchable-dropdown-item
2021-02-22 17:27:13 +05:30
v-for="item in items"
:key="item.id"
2021-09-04 01:27:46 +05:30
:item="item"
:selected-item="selectedItem"
:search-text="searchText"
:name="name"
:full-name="fullName"
2021-09-30 23:02:18 +05:30
data-testid="searchable-items"
2021-09-04 01:27:46 +05:30
@change="updateDropdown"
/>
2021-02-22 17:27:13 +05:30
</div>
<div v-if="loading" class="gl-mx-4 gl-mt-3">
<gl-skeleton-loader :height="100">
<rect y="0" width="90%" height="20" rx="4" />
<rect y="40" width="70%" height="20" rx="4" />
<rect y="80" width="80%" height="20" rx="4" />
</gl-skeleton-loader>
</div>
</gl-dropdown>
</template>