diff options
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue')
-rw-r--r-- | app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue | 278 |
1 files changed, 66 insertions, 212 deletions
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue index 0499dfe468f..3c834770563 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue @@ -1,57 +1,40 @@ <script> -import $ from 'jquery'; import Vue from 'vue'; -import Vuex, { mapState, mapActions, mapGetters } from 'vuex'; -import { isInViewport } from '~/lib/utils/common_utils'; +import Vuex from 'vuex'; import { __ } from '~/locale'; - +import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; import { DropdownVariant } from './constants'; -import DropdownButton from './dropdown_button.vue'; import DropdownContents from './dropdown_contents.vue'; -import DropdownTitle from './dropdown_title.vue'; import DropdownValue from './dropdown_value.vue'; import DropdownValueCollapsed from './dropdown_value_collapsed.vue'; import issueLabelsQuery from './graphql/issue_labels.query.graphql'; -import labelsSelectModule from './store'; +import { + isDropdownVariantSidebar, + isDropdownVariantStandalone, + isDropdownVariantEmbedded, +} from './utils'; Vue.use(Vuex); export default { - store: new Vuex.Store(labelsSelectModule()), components: { - DropdownTitle, DropdownValue, - DropdownButton, DropdownContents, DropdownValueCollapsed, + SidebarEditableItem, }, - inject: ['iid', 'projectPath'], + inject: ['iid', 'projectPath', 'allowLabelEdit'], props: { allowLabelRemove: { type: Boolean, required: false, default: false, }, - allowLabelEdit: { - type: Boolean, - required: false, - default: false, - }, - allowLabelCreate: { - type: Boolean, - required: false, - default: false, - }, allowMultiselect: { type: Boolean, required: false, default: false, }, - allowScopedLabels: { - type: Boolean, - required: false, - default: false, - }, variant: { type: String, required: false, @@ -67,16 +50,6 @@ export default { required: false, default: false, }, - labelsFetchPath: { - type: String, - required: false, - default: '', - }, - labelsManagePath: { - type: String, - required: false, - default: '', - }, labelsFilterBasePath: { type: String, required: false, @@ -138,149 +111,25 @@ export default { }, }, }, - computed: { - ...mapState(['showDropdownButton', 'showDropdownContents']), - ...mapGetters([ - 'isDropdownVariantSidebar', - 'isDropdownVariantStandalone', - 'isDropdownVariantEmbedded', - ]), - dropdownButtonVisible() { - return this.isDropdownVariantSidebar ? this.showDropdownButton : true; - }, - }, - watch: { - selectedLabels(selectedLabels) { - this.setInitialState({ - selectedLabels, - }); - }, - showDropdownContents(showDropdownContents) { - this.setContentIsOnViewport(showDropdownContents); - }, - isEditing(newVal) { - if (newVal) { - this.toggleDropdownContents(); - } - }, - }, - mounted() { - this.setInitialState({ - variant: this.variant, - allowLabelRemove: this.allowLabelRemove, - allowLabelEdit: this.allowLabelEdit, - allowLabelCreate: this.allowLabelCreate, - allowMultiselect: this.allowMultiselect, - allowScopedLabels: this.allowScopedLabels, - dropdownButtonText: this.dropdownButtonText, - selectedLabels: this.selectedLabels, - labelsFetchPath: this.labelsFetchPath, - labelsManagePath: this.labelsManagePath, - labelsFilterBasePath: this.labelsFilterBasePath, - labelsFilterParam: this.labelsFilterParam, - labelsListTitle: this.labelsListTitle, - footerCreateLabelTitle: this.footerCreateLabelTitle, - footerManageLabelTitle: this.footerManageLabelTitle, - }); - - this.$store.subscribeAction({ - after: this.handleVuexActionDispatch, - }); - - document.addEventListener('mousedown', this.handleDocumentMousedown); - document.addEventListener('click', this.handleDocumentClick); - }, - beforeDestroy() { - document.removeEventListener('mousedown', this.handleDocumentMousedown); - document.removeEventListener('click', this.handleDocumentClick); - }, methods: { - ...mapActions(['setInitialState', 'toggleDropdownContents']), - /** - * This method stores a mousedown event's target. - * Required by the click listener because the click - * event itself has no reference to this element. - */ - handleDocumentMousedown({ target }) { - this.mousedownTarget = target; - }, - /** - * This method listens for document-wide click event - * and toggle dropdown if user clicks anywhere outside - * the dropdown while dropdown is visible. - */ - handleDocumentClick({ target }) { - // We also perform the toggle exception check for the - // last mousedown event's target to avoid hiding the - // box when the mousedown happened inside the box and - // only the mouseup did not. - if ( - this.showDropdownContents && - !this.preventDropdownToggleOnClick(target) && - !this.preventDropdownToggleOnClick(this.mousedownTarget) - ) { - this.toggleDropdownContents(); - } - }, - /** - * This method checks whether a given click target - * should prevent the dropdown from being toggled. - */ - preventDropdownToggleOnClick(target) { - // This approach of element detection is needed - // as the dropdown wrapper is not using `GlDropdown` as - // it will also require us to use `BDropdownForm` - // which is yet to be implemented in GitLab UI. - const hasExceptionClass = [ - 'js-dropdown-button', - 'js-btn-cancel-create', - 'js-sidebar-dropdown-toggle', - ].some( - (className) => - target?.classList.contains(className) || - target?.parentElement?.classList.contains(className), - ); - - const hasExceptionParent = ['.js-btn-back', '.js-labels-list'].some( - (className) => $(target).parents(className).length, - ); - - const isInDropdownButtonCollapsed = this.$refs.dropdownButtonCollapsed?.$el.contains(target); - - const isInDropdownContents = this.$refs.dropdownContents?.$el.contains(target); - - return ( - hasExceptionClass || - hasExceptionParent || - isInDropdownButtonCollapsed || - isInDropdownContents - ); - }, handleDropdownClose(labels) { - // Only emit label updates if there are any labels to update - // on UI. - if (this.showDropdownContents) { - this.toggleDropdownContents(); - } if (labels.length) this.$emit('updateSelectedLabels', labels); this.$emit('onDropdownClose'); }, + collapseDropdown() { + this.$refs.editable.collapse(); + }, handleCollapsedValueClick() { this.$emit('toggleCollapse'); }, - setContentIsOnViewport(showDropdownContents) { - if (!showDropdownContents) { - this.contentIsOnViewport = true; - - return; - } - + showDropdown() { this.$nextTick(() => { - if (this.$refs.dropdownContents) { - this.contentIsOnViewport = isInViewport(this.$refs.dropdownContents.$el); - } + this.$refs.dropdownContents.showDropdown(); }); }, + isDropdownVariantSidebar, + isDropdownVariantStandalone, + isDropdownVariantEmbedded, }, }; </script> @@ -289,58 +138,63 @@ export default { <div class="labels-select-wrapper position-relative" :class="{ - 'is-standalone': isDropdownVariantStandalone, - 'is-embedded': isDropdownVariantEmbedded, + 'is-standalone': isDropdownVariantStandalone(variant), + 'is-embedded': isDropdownVariantEmbedded(variant), }" > - <template v-if="isDropdownVariantSidebar"> + <template v-if="isDropdownVariantSidebar(variant)"> <dropdown-value-collapsed ref="dropdownButtonCollapsed" :labels="issueLabels" @onValueClick="handleCollapsedValueClick" /> - <dropdown-title - :allow-label-edit="allowLabelEdit" - :labels-select-in-progress="labelsSelectInProgress" - /> - <dropdown-value - :disable-labels="labelsSelectInProgress" - :selected-labels="issueLabels" - :allow-label-remove="allowLabelRemove" - :allow-scoped-labels="allowScopedLabels" - :labels-filter-base-path="labelsFilterBasePath" - :labels-filter-param="labelsFilterParam" - @onLabelRemove="$emit('onLabelRemove', $event)" + <sidebar-editable-item + ref="editable" + :title="__('Labels')" + :loading="labelsSelectInProgress" + :can-edit="allowLabelEdit" + @open="showDropdown" > - <slot></slot> - </dropdown-value> - <dropdown-button v-show="dropdownButtonVisible" class="gl-mt-2" /> - <dropdown-contents - v-if="dropdownButtonVisible && showDropdownContents" - ref="dropdownContents" - :allow-multiselect="allowMultiselect" - :labels-list-title="labelsListTitle" - :footer-create-label-title="footerCreateLabelTitle" - :footer-manage-label-title="footerManageLabelTitle" - :render-on-top="!contentIsOnViewport" - :labels-create-title="labelsCreateTitle" - :selected-labels="selectedLabels" - @closeDropdown="handleDropdownClose" - /> - </template> - <template v-if="isDropdownVariantStandalone || isDropdownVariantEmbedded"> - <dropdown-button v-show="dropdownButtonVisible" /> - <dropdown-contents - v-if="dropdownButtonVisible && showDropdownContents" - ref="dropdownContents" - :allow-multiselect="allowMultiselect" - :labels-list-title="labelsListTitle" - :footer-create-label-title="footerCreateLabelTitle" - :footer-manage-label-title="footerManageLabelTitle" - :render-on-top="!contentIsOnViewport" - :selected-labels="selectedLabels" - @closeDropdown="handleDropdownClose" - /> + <template #collapsed> + <dropdown-value + :disable-labels="labelsSelectInProgress" + :selected-labels="issueLabels" + :allow-label-remove="allowLabelRemove" + :labels-filter-base-path="labelsFilterBasePath" + :labels-filter-param="labelsFilterParam" + @onLabelRemove="$emit('onLabelRemove', $event)" + > + <slot></slot> + </dropdown-value> + </template> + <template #default="{ edit }"> + <dropdown-value + :disable-labels="labelsSelectInProgress" + :selected-labels="issueLabels" + :allow-label-remove="allowLabelRemove" + :labels-filter-base-path="labelsFilterBasePath" + :labels-filter-param="labelsFilterParam" + class="gl-mb-2" + @onLabelRemove="$emit('onLabelRemove', $event)" + > + <slot></slot> + </dropdown-value> + <dropdown-contents + v-if="edit" + ref="dropdownContents" + :dropdown-button-text="dropdownButtonText" + :allow-multiselect="allowMultiselect" + :labels-list-title="labelsListTitle" + :footer-create-label-title="footerCreateLabelTitle" + :footer-manage-label-title="footerManageLabelTitle" + :labels-create-title="labelsCreateTitle" + :selected-labels="selectedLabels" + :variant="variant" + @closeDropdown="collapseDropdown" + @setLabels="handleDropdownClose" + /> + </template> + </sidebar-editable-item> </template> </div> </template> |