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