1<script> 2import { GlDropdown, GlDropdownDivider, GlTooltipDirective } from '@gitlab/ui'; 3import Api from '~/api'; 4import { sprintf } from '~/locale'; 5import { CUSTOM_LEVEL, i18n } from '../constants'; 6import CustomNotificationsModal from './custom_notifications_modal.vue'; 7import NotificationsDropdownItem from './notifications_dropdown_item.vue'; 8 9export default { 10 name: 'NotificationsDropdown', 11 components: { 12 GlDropdown, 13 GlDropdownDivider, 14 NotificationsDropdownItem, 15 CustomNotificationsModal, 16 }, 17 directives: { 18 GlTooltip: GlTooltipDirective, 19 }, 20 inject: { 21 containerClass: { 22 default: '', 23 }, 24 disabled: { 25 default: false, 26 }, 27 dropdownItems: { 28 default: [], 29 }, 30 buttonSize: { 31 default: 'medium', 32 }, 33 initialNotificationLevel: { 34 default: '', 35 }, 36 projectId: { 37 default: null, 38 }, 39 groupId: { 40 default: null, 41 }, 42 showLabel: { 43 default: false, 44 }, 45 }, 46 data() { 47 return { 48 selectedNotificationLevel: this.initialNotificationLevel, 49 isLoading: false, 50 notificationsModalVisible: false, 51 }; 52 }, 53 computed: { 54 notificationLevels() { 55 return this.dropdownItems.map((level) => ({ 56 level, 57 title: this.$options.i18n.notificationTitles[level] || '', 58 description: this.$options.i18n.notificationDescriptions[level] || '', 59 })); 60 }, 61 isCustomNotification() { 62 return this.selectedNotificationLevel === CUSTOM_LEVEL; 63 }, 64 buttonIcon() { 65 if (this.isLoading) { 66 return null; 67 } 68 69 return this.selectedNotificationLevel === 'disabled' ? 'notifications-off' : 'notifications'; 70 }, 71 buttonText() { 72 return this.showLabel 73 ? this.$options.i18n.notificationTitles[this.selectedNotificationLevel] 74 : null; 75 }, 76 buttonTooltip() { 77 const notificationTitle = 78 this.$options.i18n.notificationTitles[this.selectedNotificationLevel] || 79 this.selectedNotificationLevel; 80 81 return this.disabled 82 ? this.$options.i18n.notificationDescriptions.owner_disabled 83 : sprintf(this.$options.i18n.notificationTooltipTitle, { 84 notification_title: notificationTitle, 85 }); 86 }, 87 }, 88 methods: { 89 openNotificationsModal() { 90 if (this.isCustomNotification) { 91 this.notificationsModalVisible = true; 92 } 93 }, 94 selectItem(level) { 95 if (level !== this.selectedNotificationLevel) { 96 this.updateNotificationLevel(level); 97 } 98 }, 99 async updateNotificationLevel(level) { 100 this.isLoading = true; 101 102 try { 103 await Api.updateNotificationSettings(this.projectId, this.groupId, { level }); 104 this.selectedNotificationLevel = level; 105 this.openNotificationsModal(); 106 } catch (error) { 107 this.$toast.show(this.$options.i18n.updateNotificationLevelErrorMessage); 108 } finally { 109 this.isLoading = false; 110 } 111 }, 112 }, 113 customLevel: CUSTOM_LEVEL, 114 i18n, 115 modalId: 'custom-notifications-modal', 116}; 117</script> 118 119<template> 120 <div :class="containerClass"> 121 <gl-dropdown 122 v-gl-tooltip="{ title: buttonTooltip }" 123 data-testid="notification-dropdown" 124 :size="buttonSize" 125 :icon="buttonIcon" 126 :loading="isLoading" 127 :disabled="disabled" 128 :split="isCustomNotification" 129 :text="buttonText" 130 @click="openNotificationsModal" 131 > 132 <notifications-dropdown-item 133 v-for="item in notificationLevels" 134 :key="item.level" 135 :level="item.level" 136 :title="item.title" 137 :description="item.description" 138 :notification-level="selectedNotificationLevel" 139 @item-selected="selectItem" 140 /> 141 <gl-dropdown-divider /> 142 <notifications-dropdown-item 143 :key="$options.customLevel" 144 :level="$options.customLevel" 145 :title="$options.i18n.notificationTitles.custom" 146 :description="$options.i18n.notificationDescriptions.custom" 147 :notification-level="selectedNotificationLevel" 148 @item-selected="selectItem" 149 /> 150 </gl-dropdown> 151 <custom-notifications-modal v-model="notificationsModalVisible" :modal-id="$options.modalId" /> 152 </div> 153</template> 154