| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- <template>
- <v-menu offset-y v-model="isOpen">
- <template #activator="{ on: { click }, attrs }">
- <v-tooltip bottom>
- <template #activator="{ on: on_tooltips , attrs: attrs_tooltips }">
- <v-btn
- icon
- v-bind="[attrs, attrs_tooltips]"
- color=""
- v-on="on_tooltips"
- @click="click"
- >
- <v-badge
- color="orange"
- offset-y="10"
- :value="unreadNotification.length > 0"
- :content="unreadNotification.length"
- >
- <v-icon class="ot_white--text" small>
- fa-bell
- </v-icon>
- </v-badge>
- </v-btn>
- </template>
- <span>{{ $t('notification') }}</span>
- </v-tooltip>
- </template>
- <v-card scrollable max-width="400">
- <v-card-title class="ot_header_menu text-body-2 font-weight-bold">
- {{ $t('notification') }}
- </v-card-title>
- <v-card-text class="ma-0 pa-0 header-menu">
- <v-list dense :subheader="true">
- <template v-for="(notification, index) in notifications">
- <v-list-item :key="index" :class="`${notification.notificationUsers.length === 0 ? 'unread' : ''}`">
- <v-list-item-content>
- <v-list-item-title class="list_item mt-2 mb-2" v-text="getMessage(notification)"/>
- </v-list-item-content>
- <v-list-item-icon v-if="notification.link" class="pt-4">
- <v-icon @click="download(notification.link)">mdi-download</v-icon>
- </v-list-item-icon>
- </v-list-item>
- <v-divider></v-divider>
- </template>
- </v-list>
- <v-card v-intersect="update"></v-card>
- <v-row
- v-if="loading"
- class="fill-height mt-3 mb-3"
- align="center"
- justify="center"
- >
- <v-progress-circular
- indeterminate
- color="grey lighten-1"
- ></v-progress-circular>
- </v-row>
- </v-card-text>
- <v-card-actions class="ma-0 pa-0">
- <template>
- <v-list-item
- id="all_notifications"
- :key="$t('all_notification')"
- :href="notificationUrl"
- router
- >
- <v-list-item-title class="text-body-2 ot_white--text" v-text="$t('all_notification')"/>
- </v-list-item>
- </template>
- </v-card-actions>
- </v-card>
- </v-menu>
- </template>
- <script lang="ts">
- import {computed, ComputedRef, defineComponent, onUnmounted, Ref, ref, useContext, useFetch, watch} from '@nuxtjs/composition-api'
- import {NOTIFICATION_TYPE, QUERY_TYPE} from "~/types/enums";
- import {Notification} from "~/models/Core/Notification";
- import {repositoryHelper} from "~/services/store/repository";
- import {ApiResponse, HydraMetadata} from "~/types/interfaces";
- import {queryHelper} from "~/services/store/query";
- import {NotificationUsers} from "~/models/Core/NotificationUsers";
- import {$accessProfile} from "~/services/profile/accessProfile";
- export default defineComponent({
- setup: function () {
- const {$dataProvider, $dataPersister, $config, store, app: { i18n }} = useContext()
- const profileAccess = store.state.profile.access
- $accessProfile.setStore(store)
- const currentAccessId = $accessProfile.getCurrentAccessId()
- const loading: Ref<Boolean> = ref(true)
- const isOpen: Ref<Boolean> = ref(false)
- const page: Ref<number> = ref(1)
- const data: Ref<ApiResponse> = ref({} as ApiResponse)
- /**
- * On récupère les notifications via l'API qui seront stockées dans le store
- */
- const {fetch, fetchState} = useFetch(async () => {
- data.value = await $dataProvider.invoke({
- type: QUERY_TYPE.MODEL,
- model: Notification,
- listArgs: {
- itemsPerPage: 10,
- page: page.value
- }
- })
- loading.value = false
- })
- /**
- * On récupère les Notifications via le store
- */
- const notifications: ComputedRef = computed(() => {
- const query = repositoryHelper.getRepository(Notification).with('message').orderBy('id', 'desc')
- return queryHelper.getCollection(query)
- })
- /**
- * on calcul le nombre de notification non lues
- */
- const unreadNotification: ComputedRef<Array<Notification>> = computed(() => {
- return notifications.value.filter((notification: Notification) => {
- return notification.notificationUsers.length === 0
- })
- })
- /**
- * Les metadata dépendront de la dernière valeur du GET lancé
- */
- const metadata: ComputedRef<HydraMetadata> = computed(() => {
- return data.value.metadata
- })
- /**
- * Lorsque l'utilisateur scroll on regarde la nextPage a charger et on le fait que si le pending du fetch est false
- * (si on a fini de télécharger les éléments précédents)
- */
- const update = async () => {
- if (!fetchState.pending && metadata.value?.nextPage && metadata.value.nextPage > 0) {
- loading.value = true
- page.value = metadata.value.nextPage
- await fetch()
- //Si des notifications n'avaient pas été marquées comme lues, on le fait immédiatement.
- markNotificationsAsRead()
- }
- }
- /**
- * On construit le message qui va devoir s'afficher pour une notification
- * @param notification
- */
- const getMessage = (notification:Notification) => {
- switch (notification.type){
- case NOTIFICATION_TYPE.FILE :
- return `${i18n.t('your_file')} ${notification.message?.fileName} ${i18n.t('is_ready_to_be_downloaded')}`
- break;
- case NOTIFICATION_TYPE.MESSAGE:
- if(notification.message?.action)
- return `${i18n.t('your_message')} ${notification.message?.fileName} ${i18n.t('is_ready_to_be')} ${notification.message.action}`
- return `${i18n.t('your_message')} ${notification.message?.about ?? ''} ${i18n.t('has_been_sent')} `
- break;
- case NOTIFICATION_TYPE.SYSTEM :
- if(notification.message?.about)
- return `${i18n.t(notification.message.about)}`
- break;
- default:
- return i18n.t(notification.name)
- }
- }
- /**
- * Dès l'ouverture du menu, on indique que les notifications non lues, le sont.
- */
- const unwatch = watch(isOpen, (newValue, oldValue) => {
- if(newValue){
- markNotificationsAsRead()
- }
- })
- onUnmounted(() => {
- unwatch()
- })
- /**
- * Marque les notification non lues comme lues
- */
- const markNotificationsAsRead = () => {
- unreadNotification.value.map((notification:Notification)=>{
- notification.notificationUsers = ['read']
- repositoryHelper.persist(Notification, notification)
- createNewNotificationUsers(notification)
- })
- }
- /**
- * Créer une nouvelle notification users coté back.
- * @param notification
- */
- const createNewNotificationUsers = (notification: Notification) =>{
- const newNotificationUsers = repositoryHelper.persist(NotificationUsers, new NotificationUsers(
- {
- access:`/api/accesses/${currentAccessId}`,
- notification:`/api/notifications/${notification.id}`,
- isRead: true
- }
- )) as NotificationUsers
- $dataPersister.invoke({
- type: QUERY_TYPE.MODEL,
- model: NotificationUsers,
- idTemp: newNotificationUsers.id,
- showProgress: false
- })
- }
- /**
- * Download le lien
- * @param link
- */
- const download = (link: string) => {
- const url_parts: Array<string> = link.split('/api');
- if(profileAccess.originalAccess)
- url_parts[0] = `api/${profileAccess.originalAccess.id}/${currentAccessId}`
- else
- url_parts[0] = `api/${currentAccessId}`
- window.open(`${$config.baseURL_Legacy}/${url_parts.join('')}`);
- }
- return {
- data,
- getMessage,
- notificationUrl: `${$config.baseURL_adminLegacy}/notifications/list/`,
- loading,
- notifications,
- update,
- unreadNotification,
- isOpen,
- download
- }
- }
- })
- </script>
- <style scoped>
- #all_notifications{
- background: var(--v-ot_green-base, white);
- color: white;
- }
- .list_item{
- white-space: normal;
- }
- .unread{
- background: #ecf0f5;
- }
- </style>
|