summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue')
-rw-r--r--app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue244
1 files changed, 244 insertions, 0 deletions
diff --git a/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue
new file mode 100644
index 00000000000..83df9056af2
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/labels/labels_select_widget/dropdown_contents.vue
@@ -0,0 +1,244 @@
+<script>
+import { GlButton, GlDropdown, GlDropdownItem, GlLink } from '@gitlab/ui';
+import { debounce } from 'lodash';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+import { __, s__, sprintf } from '~/locale';
+import DropdownContentsCreateView from './dropdown_contents_create_view.vue';
+import DropdownContentsLabelsView from './dropdown_contents_labels_view.vue';
+import DropdownFooter from './dropdown_footer.vue';
+import DropdownHeader from './dropdown_header.vue';
+import { isDropdownVariantStandalone, isDropdownVariantSidebar } from './utils';
+
+export default {
+ components: {
+ DropdownContentsLabelsView,
+ DropdownContentsCreateView,
+ DropdownHeader,
+ DropdownFooter,
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlLink,
+ },
+ props: {
+ labelsCreateTitle: {
+ type: String,
+ required: true,
+ },
+ selectedLabels: {
+ type: Array,
+ required: true,
+ },
+ allowMultiselect: {
+ type: Boolean,
+ required: true,
+ },
+ labelsListTitle: {
+ type: String,
+ required: true,
+ },
+ dropdownButtonText: {
+ type: String,
+ required: true,
+ },
+ footerCreateLabelTitle: {
+ type: String,
+ required: true,
+ },
+ footerManageLabelTitle: {
+ type: String,
+ required: true,
+ },
+ variant: {
+ type: String,
+ required: true,
+ },
+ isVisible: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ fullPath: {
+ type: String,
+ required: true,
+ },
+ workspaceType: {
+ type: String,
+ required: true,
+ },
+ attrWorkspacePath: {
+ type: String,
+ required: true,
+ },
+ labelCreateType: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ showDropdownContentsCreateView: false,
+ localSelectedLabels: [...this.selectedLabels],
+ isDirty: false,
+ searchKey: '',
+ };
+ },
+ computed: {
+ dropdownContentsView() {
+ if (this.showDropdownContentsCreateView) {
+ return 'dropdown-contents-create-view';
+ }
+ return 'dropdown-contents-labels-view';
+ },
+ dropdownTitle() {
+ return this.showDropdownContentsCreateView ? this.labelsCreateTitle : this.labelsListTitle;
+ },
+ buttonText() {
+ if (!this.localSelectedLabels.length) {
+ return this.dropdownButtonText || __('Label');
+ } else if (this.localSelectedLabels.length > 1) {
+ return sprintf(s__('LabelSelect|%{firstLabelName} +%{remainingLabelCount} more'), {
+ firstLabelName: this.localSelectedLabels[0].title,
+ remainingLabelCount: this.localSelectedLabels.length - 1,
+ });
+ }
+ return this.localSelectedLabels[0].title;
+ },
+ showDropdownFooter() {
+ return !this.showDropdownContentsCreateView && !this.isStandalone;
+ },
+ isStandalone() {
+ return isDropdownVariantStandalone(this.variant);
+ },
+ isSidebar() {
+ return isDropdownVariantSidebar(this.variant);
+ },
+ },
+ watch: {
+ localSelectedLabels: {
+ handler() {
+ this.isDirty = true;
+ },
+ deep: true,
+ },
+ isVisible(newVal) {
+ if (newVal) {
+ this.$refs.dropdown.show();
+ this.isDirty = false;
+ this.localSelectedLabels = this.selectedLabels;
+ } else {
+ this.$refs.dropdown.hide();
+ this.setLabels();
+ }
+ },
+ selectedLabels(newVal) {
+ if (!this.isDirty || !this.isSidebar) {
+ this.localSelectedLabels = newVal;
+ }
+ },
+ },
+ created() {
+ this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS);
+ },
+ beforeDestroy() {
+ this.debouncedSearchKeyUpdate.cancel();
+ },
+ methods: {
+ toggleDropdownContentsCreateView() {
+ this.showDropdownContentsCreateView = !this.showDropdownContentsCreateView;
+ },
+ toggleDropdownContent() {
+ this.toggleDropdownContentsCreateView();
+ // Required to recalculate dropdown position as its size changes
+ if (this.$refs.dropdown?.$refs.dropdown) {
+ this.$refs.dropdown.$refs.dropdown.$_popper.scheduleUpdate();
+ }
+ },
+ setLabels() {
+ if (!this.isDirty) {
+ return;
+ }
+ this.$emit('setLabels', this.localSelectedLabels);
+ },
+ handleDropdownHide() {
+ this.$emit('closeDropdown');
+ if (!this.isSidebar) {
+ this.setLabels();
+ }
+ },
+ setSearchKey(value) {
+ this.searchKey = value;
+ },
+ setFocus() {
+ this.$refs.header.focusInput();
+ },
+ hideDropdown() {
+ this.$refs.dropdown.hide();
+ },
+ showDropdown() {
+ this.$refs.dropdown.show();
+ },
+ clearSearch() {
+ if (!this.allowMultiselect || this.isStandalone) {
+ return;
+ }
+ this.searchKey = '';
+ this.setFocus();
+ },
+ selectFirstItem() {
+ this.$refs.dropdownContentsView.selectFirstItem();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown
+ ref="dropdown"
+ :text="buttonText"
+ class="gl-w-full"
+ block
+ data-testid="labels-select-dropdown-contents"
+ data-qa-selector="labels_dropdown_content"
+ @hide="handleDropdownHide"
+ @shown="setFocus"
+ >
+ <template #header>
+ <dropdown-header
+ ref="header"
+ :search-key="searchKey"
+ :labels-create-title="labelsCreateTitle"
+ :labels-list-title="labelsListTitle"
+ :show-dropdown-contents-create-view="showDropdownContentsCreateView"
+ :is-standalone="isStandalone"
+ @toggleDropdownContentsCreateView="toggleDropdownContent"
+ @closeDropdown="hideDropdown"
+ @input="debouncedSearchKeyUpdate"
+ @searchEnter="selectFirstItem"
+ />
+ </template>
+ <template #default>
+ <component
+ :is="dropdownContentsView"
+ ref="dropdownContentsView"
+ v-model="localSelectedLabels"
+ :search-key="searchKey"
+ :allow-multiselect="allowMultiselect"
+ :full-path="fullPath"
+ :workspace-type="workspaceType"
+ :attr-workspace-path="attrWorkspacePath"
+ :label-create-type="labelCreateType"
+ @hideCreateView="toggleDropdownContent"
+ @input="clearSearch"
+ />
+ </template>
+ <template #footer>
+ <dropdown-footer
+ v-if="showDropdownFooter"
+ :footer-create-label-title="footerCreateLabelTitle"
+ :footer-manage-label-title="footerManageLabelTitle"
+ @toggleDropdownContentsCreateView="toggleDropdownContent"
+ />
+ </template>
+ </gl-dropdown>
+</template>