summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue
diff options
context:
space:
mode:
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.vue56
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>