diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-02 12:09:59 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-02 12:09:59 +0000 |
commit | 3eec6c2511af2b10cd25be64dcd84c4a35a7bcdb (patch) | |
tree | 8af0733be4f7cb507353ed97ca8d6b4e9e374b7f /app/assets/javascripts/vue_shared | |
parent | 1930898566965dbc1bd779089ec9e58e17674268 (diff) | |
download | gitlab-ce-3eec6c2511af2b10cd25be64dcd84c4a35a7bcdb.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared')
2 files changed, 175 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.stories.js b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.stories.js new file mode 100644 index 00000000000..eeed5e9dc3a --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.stories.js @@ -0,0 +1,27 @@ +/* eslint-disable @gitlab/require-i18n-strings */ + +import { __ } from '~/locale'; +import DropdownWidget from './dropdown_widget.vue'; + +export default { + component: DropdownWidget, + title: 'vue_shared/components/dropdown/dropdown_widget/dropdown_widget', +}; + +const Template = (args, { argTypes }) => ({ + components: { DropdownWidget }, + props: Object.keys(argTypes), + template: '<dropdown-widget v-bind="$props" v-on="$props" />', +}); + +export const Default = Template.bind({}); +Default.args = { + options: [ + { id: 'gid://gitlab/Milestone/-1', title: __('Any Milestone') }, + { id: 'gid://gitlab/Milestone/0', title: __('No Milestone') }, + { id: 'gid://gitlab/Milestone/-2', title: __('Upcoming') }, + { id: 'gid://gitlab/Milestone/-3', title: __('Started') }, + ], + selectText: 'Select', + searchText: 'Search', +}; diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue new file mode 100644 index 00000000000..857131e544e --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue @@ -0,0 +1,148 @@ +<script> +import { + GlLoadingIcon, + GlDropdown, + GlDropdownForm, + GlDropdownDivider, + GlDropdownItem, + GlSearchBoxByType, +} from '@gitlab/ui'; +import { __ } from '~/locale'; + +export default { + components: { + GlLoadingIcon, + GlDropdown, + GlDropdownForm, + GlDropdownDivider, + GlDropdownItem, + GlSearchBoxByType, + }, + props: { + selectText: { + type: String, + required: false, + default: __('Select'), + }, + searchText: { + type: String, + required: false, + default: __('Search'), + }, + presetOptions: { + type: Array, + required: false, + default: () => [], + }, + options: { + type: Array, + required: false, + default: () => [], + }, + isLoading: { + type: Boolean, + required: false, + default: false, + }, + selected: { + type: Object, + required: false, + default: () => {}, + }, + searchTerm: { + type: String, + required: false, + default: '', + }, + }, + computed: { + isSearchEmpty() { + return this.searchTerm === '' && !this.isLoading; + }, + noOptionsFound() { + return !this.isSearchEmpty && this.options.length === 0; + }, + }, + methods: { + selectOption(option) { + this.$emit('set-option', option || null); + }, + isSelected(option) { + return this.selected && this.selected.title === option.title; + }, + showDropdown() { + this.$refs.dropdown.show(); + }, + setFocus() { + this.$refs.search.focusInput(); + }, + setSearchTerm(search) { + this.$emit('set-search', search); + }, + }, + i18n: { + noMatchingResults: __('No matching results'), + }, +}; +</script> + +<template> + <gl-dropdown + ref="dropdown" + :text="selectText" + lazy + menu-class="gl-w-full!" + class="gl-w-full" + v-on="$listeners" + @shown="setFocus" + > + <template #header> + <gl-search-box-by-type + ref="search" + :value="searchTerm" + :placeholder="searchText" + class="js-dropdown-input-field" + @input="setSearchTerm" + /> + </template> + <gl-dropdown-form class="gl-relative gl-min-h-7"> + <gl-loading-icon + v-if="isLoading" + size="md" + class="gl-absolute gl-left-0 gl-top-0 gl-right-0" + /> + <template v-else> + <template v-if="isSearchEmpty && presetOptions.length > 0"> + <gl-dropdown-item + v-for="option in presetOptions" + :key="option.id" + :is-checked="isSelected(option)" + :is-check-centered="true" + :is-check-item="true" + @click="selectOption(option)" + > + {{ option.title }} + </gl-dropdown-item> + <gl-dropdown-divider /> + </template> + <gl-dropdown-item + v-for="option in options" + :key="option.id" + :is-checked="isSelected(option)" + :is-check-centered="true" + :is-check-item="true" + data-testid="unselected-option" + @click="selectOption(option)" + > + {{ option.title }} + </gl-dropdown-item> + <gl-dropdown-item v-if="noOptionsFound" class="gl-pl-6!"> + {{ $options.i18n.noMatchingResults }} + </gl-dropdown-item> + </template> + </gl-dropdown-form> + <template #footer> + <slot name="footer"></slot> + </template> + </gl-dropdown> +</template> |