diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue | 56 |
1 files changed, 48 insertions, 8 deletions
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 index 153b0981813..2a79ccc2648 100644 --- 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 @@ -1,22 +1,28 @@ <script> import { + GlIcon, GlLoadingIcon, GlDropdown, GlDropdownForm, GlDropdownDivider, GlDropdownItem, + GlDropdownSectionHeader, GlSearchBoxByType, } from '@gitlab/ui'; import { __ } from '~/locale'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue'; export default { components: { + GlIcon, GlLoadingIcon, GlDropdown, GlDropdownForm, GlDropdownDivider, GlDropdownItem, + GlDropdownSectionHeader, GlSearchBoxByType, + TooltipOnTruncate, }, props: { selectText: { @@ -39,6 +45,11 @@ export default { required: false, default: () => [], }, + groupedOptions: { + type: Array, + required: false, + default: () => [], + }, isLoading: { type: Boolean, required: false, @@ -79,11 +90,7 @@ export default { if (Array.isArray(this.selected)) { return this.selected.some((label) => label.title === option.title); } - return ( - this.selected && - ((option.name && this.selected.name === option.name) || - (option.title && this.selected.title === option.title)) - ); + return this.selected && option.id && this.selected.id === option.id; }, showDropdown() { this.$refs.dropdown.show(); @@ -101,6 +108,9 @@ export default { // TODO: this has some knowledge of the context where the component is used. We could later rework it. return option.username || null; }, + optionKey(option) { + return option.key ? option.key : option.id; + }, }, i18n: { noMatchingResults: __('No matching results'), @@ -154,10 +164,10 @@ export default { </template> <gl-dropdown-item v-for="option in options" - :key="option.id" + :key="optionKey(option)" :is-checked="isSelected(option)" - :is-check-centered="true" - :is-check-item="true" + is-check-centered + is-check-item :avatar-url="avatarUrl(option)" :secondary-text="secondaryText(option)" data-testid="unselected-option" @@ -167,6 +177,36 @@ export default { {{ option.title }} </slot> </gl-dropdown-item> + <template v-for="(optionGroup, index) in groupedOptions"> + <gl-dropdown-divider v-if="index !== 0" :key="index" /> + <gl-dropdown-section-header :key="optionGroup.id"> + <div class="gl-display-flex gl-max-w-full"> + <tooltip-on-truncate + :title="optionGroup.title" + class="gl-text-truncate gl-flex-grow-1" + > + {{ optionGroup.title }} + </tooltip-on-truncate> + <span v-if="optionGroup.secondaryText" class="gl-float-right gl-font-weight-normal"> + <gl-icon name="clock" class="gl-mr-2" /> + {{ optionGroup.secondaryText }} + </span> + </div> + </gl-dropdown-section-header> + <gl-dropdown-item + v-for="option in optionGroup.options" + :key="optionKey(option)" + :is-checked="isSelected(option)" + is-check-centered + is-check-item + data-testid="unselected-option" + @click="selectOption(option)" + > + <slot name="item" :item="option"> + {{ option.title }} + </slot> + </gl-dropdown-item> + </template> <gl-dropdown-item v-if="noOptionsFound" class="gl-pl-6!"> {{ $options.i18n.noMatchingResults }} </gl-dropdown-item> |