1<script> 2import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui'; 3import { mapGetters, mapActions } from 'vuex'; 4import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility'; 5import { 6 DISCUSSION_FILTERS_DEFAULT_VALUE, 7 HISTORY_ONLY_FILTER_VALUE, 8 COMMENTS_ONLY_FILTER_VALUE, 9 DISCUSSION_TAB_LABEL, 10 DISCUSSION_FILTER_TYPES, 11 NOTE_UNDERSCORE, 12} from '../constants'; 13import notesEventHub from '../event_hub'; 14 15export default { 16 components: { 17 GlDropdown, 18 GlDropdownItem, 19 GlDropdownDivider, 20 }, 21 props: { 22 filters: { 23 type: Array, 24 required: true, 25 }, 26 selectedValue: { 27 type: Number, 28 default: DISCUSSION_FILTERS_DEFAULT_VALUE, 29 required: false, 30 }, 31 }, 32 data() { 33 return { 34 currentValue: doesHashExistInUrl(NOTE_UNDERSCORE) 35 ? DISCUSSION_FILTERS_DEFAULT_VALUE 36 : this.selectedValue, 37 defaultValue: DISCUSSION_FILTERS_DEFAULT_VALUE, 38 displayFilters: true, 39 }; 40 }, 41 computed: { 42 ...mapGetters(['getNotesDataByProp', 'timelineEnabled', 'isLoading']), 43 currentFilter() { 44 if (!this.currentValue) return this.filters[0]; 45 return this.filters.find((filter) => filter.value === this.currentValue); 46 }, 47 }, 48 created() { 49 if (window.mrTabs) { 50 const { eventHub, currentTab } = window.mrTabs; 51 52 eventHub.$on('MergeRequestTabChange', this.toggleFilters); 53 this.toggleFilters(currentTab); 54 } 55 56 notesEventHub.$on('dropdownSelect', this.selectFilter); 57 window.addEventListener('hashchange', this.handleLocationHash); 58 }, 59 mounted() { 60 this.toggleCommentsForm(); 61 }, 62 destroyed() { 63 notesEventHub.$off('dropdownSelect', this.selectFilter); 64 window.removeEventListener('hashchange', this.handleLocationHash); 65 }, 66 methods: { 67 ...mapActions([ 68 'filterDiscussion', 69 'setCommentsDisabled', 70 'setTargetNoteHash', 71 'setTimelineView', 72 ]), 73 selectFilter(value, persistFilter = true) { 74 const filter = parseInt(value, 10); 75 76 if (filter === this.currentValue) return; 77 78 if (this.timelineEnabled && filter !== COMMENTS_ONLY_FILTER_VALUE) { 79 this.setTimelineView(false); 80 } 81 this.currentValue = filter; 82 this.filterDiscussion({ 83 path: this.getNotesDataByProp('discussionsPath'), 84 filter, 85 persistFilter, 86 }); 87 this.toggleCommentsForm(); 88 }, 89 toggleCommentsForm() { 90 this.setCommentsDisabled(this.currentValue === HISTORY_ONLY_FILTER_VALUE); 91 }, 92 toggleFilters(tab) { 93 this.displayFilters = tab === DISCUSSION_TAB_LABEL; 94 }, 95 handleLocationHash() { 96 const hash = getLocationHash(); 97 98 if (/^note_/.test(hash) && this.currentValue !== DISCUSSION_FILTERS_DEFAULT_VALUE) { 99 this.selectFilter(this.defaultValue, false); 100 this.setTargetNoteHash(hash); 101 } 102 }, 103 filterType(value) { 104 if (value === 0) { 105 return DISCUSSION_FILTER_TYPES.ALL; 106 } else if (value === 1) { 107 return DISCUSSION_FILTER_TYPES.COMMENTS; 108 } 109 return DISCUSSION_FILTER_TYPES.HISTORY; 110 }, 111 }, 112}; 113</script> 114 115<template> 116 <gl-dropdown 117 v-if="displayFilters" 118 id="discussion-filter-dropdown" 119 class="gl-mr-3 full-width-mobile discussion-filter-container js-discussion-filter-container" 120 data-qa-selector="discussion_filter_dropdown" 121 :text="currentFilter.title" 122 :disabled="isLoading" 123 > 124 <div v-for="filter in filters" :key="filter.value" class="dropdown-item-wrapper"> 125 <gl-dropdown-item 126 :is-check-item="true" 127 :is-checked="filter.value === currentValue" 128 :class="{ 'is-active': filter.value === currentValue }" 129 :data-filter-type="filterType(filter.value)" 130 data-qa-selector="filter_menu_item" 131 @click.prevent="selectFilter(filter.value)" 132 > 133 {{ filter.title }} 134 </gl-dropdown-item> 135 <gl-dropdown-divider v-if="filter.value === defaultValue" /> 136 </div> 137 </gl-dropdown> 138</template> 139