|
@@ -1,34 +1,32 @@
|
|
|
<template>
|
|
<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-btn
|
|
|
|
|
+ ref="btn"
|
|
|
|
|
+ icon
|
|
|
|
|
+ color=""
|
|
|
|
|
+ @click="click"
|
|
|
|
|
+ >
|
|
|
|
|
+ <v-badge
|
|
|
|
|
+ color="orange"
|
|
|
|
|
+ offset-y="10"
|
|
|
|
|
+ :value="unreadNotification.length > 0"
|
|
|
|
|
+ :content="unreadNotification.length"
|
|
|
|
|
+ >
|
|
|
|
|
+ <v-icon class="text-ot-white" small>
|
|
|
|
|
+ fa-bell
|
|
|
|
|
+ </v-icon>
|
|
|
|
|
+ </v-badge>
|
|
|
|
|
+ </v-btn>
|
|
|
|
|
+
|
|
|
|
|
+ <v-tooltip bottom :activator="btn">
|
|
|
|
|
+ <span>{{ $t('notification') }}</span>
|
|
|
|
|
+ </v-tooltip>
|
|
|
|
|
+
|
|
|
|
|
+ <v-menu :activator="btn" offset-y v-model="isOpen">
|
|
|
<v-card scrollable max-width="400">
|
|
<v-card scrollable max-width="400">
|
|
|
- <v-card-title class="ot-header_menu text-body-2 font-weight-bold">
|
|
|
|
|
|
|
+ <v-card-title class="ot-header-menu text-body-2 font-weight-bold">
|
|
|
{{ $t('notification') }}
|
|
{{ $t('notification') }}
|
|
|
</v-card-title>
|
|
</v-card-title>
|
|
|
|
|
+
|
|
|
<v-card-text class="ma-0 pa-0 header-menu">
|
|
<v-card-text class="ma-0 pa-0 header-menu">
|
|
|
<v-list dense :subheader="true">
|
|
<v-list dense :subheader="true">
|
|
|
<template v-for="(notification, index) in notifications">
|
|
<template v-for="(notification, index) in notifications">
|
|
@@ -37,13 +35,15 @@
|
|
|
<v-list-item-title class="list_item mt-2 mb-2" v-text="getMessage(notification)"/>
|
|
<v-list-item-title class="list_item mt-2 mb-2" v-text="getMessage(notification)"/>
|
|
|
</v-list-item-content>
|
|
</v-list-item-content>
|
|
|
<v-list-item-icon v-if="notification.link" class="pt-4">
|
|
<v-list-item-icon v-if="notification.link" class="pt-4">
|
|
|
- <v-icon @click="download(notification.link)">mdi-download</v-icon>
|
|
|
|
|
|
|
+ <v-icon @click="download(notification.link)" icon="mdi-download" />
|
|
|
</v-list-item-icon>
|
|
</v-list-item-icon>
|
|
|
</v-list-item>
|
|
</v-list-item>
|
|
|
<v-divider></v-divider>
|
|
<v-divider></v-divider>
|
|
|
</template>
|
|
</template>
|
|
|
</v-list>
|
|
</v-list>
|
|
|
|
|
+
|
|
|
<v-card v-intersect="update"></v-card>
|
|
<v-card v-intersect="update"></v-card>
|
|
|
|
|
+
|
|
|
<v-row
|
|
<v-row
|
|
|
v-if="loading"
|
|
v-if="loading"
|
|
|
class="fill-height mt-3 mb-3"
|
|
class="fill-height mt-3 mb-3"
|
|
@@ -56,6 +56,7 @@
|
|
|
></v-progress-circular>
|
|
></v-progress-circular>
|
|
|
</v-row>
|
|
</v-row>
|
|
|
</v-card-text>
|
|
</v-card-text>
|
|
|
|
|
+
|
|
|
<v-card-actions class="ma-0 pa-0">
|
|
<v-card-actions class="ma-0 pa-0">
|
|
|
<template>
|
|
<template>
|
|
|
<v-list-item
|
|
<v-list-item
|
|
@@ -64,7 +65,7 @@
|
|
|
:href="notificationUrl"
|
|
:href="notificationUrl"
|
|
|
router
|
|
router
|
|
|
>
|
|
>
|
|
|
- <v-list-item-title class="text-body-2 ot-white--text" v-text="$t('all_notification')"/>
|
|
|
|
|
|
|
+ <v-list-item-title class="text-body-2 text-ot-white" v-text="$t('all_notification')"/>
|
|
|
</v-list-item>
|
|
</v-list-item>
|
|
|
</template>
|
|
</template>
|
|
|
</v-card-actions>
|
|
</v-card-actions>
|
|
@@ -72,185 +73,159 @@
|
|
|
</v-menu>
|
|
</v-menu>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
-<script lang="ts">
|
|
|
|
|
-import {computed, ComputedRef, defineComponent, onUnmounted, Ref, ref, useContext, useFetch, watch} from '@nuxtjs/composition-api'
|
|
|
|
|
|
|
+<script setup lang="ts">
|
|
|
import {NOTIFICATION_TYPE, QUERY_TYPE} from "~/types/enum/enums";
|
|
import {NOTIFICATION_TYPE, QUERY_TYPE} from "~/types/enum/enums";
|
|
|
import {Notification} from "~/models/Core/Notification";
|
|
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 {NotificationUsers} from "~/models/Core/NotificationUsers";
|
|
|
-import {$accessProfile} from "~/services/accessProfile";
|
|
|
|
|
-
|
|
|
|
|
-export default defineComponent({
|
|
|
|
|
- setup: function () {
|
|
|
|
|
- const {$dataProvider, $dataPersister, $config, store, app: { i18n }} = useContext()
|
|
|
|
|
- const accessProfile = 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)
|
|
|
|
|
|
|
+import {useAccessProfileStore} from "~/stores/accessProfile";
|
|
|
|
|
+import {ComputedRef, Ref} from "@vue/reactivity";
|
|
|
|
|
+import {useEntityFetch} from "~/composables/data/useEntityFetch";
|
|
|
|
|
+import {Pagination} from "~/types/data";
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 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
|
|
|
|
|
- })
|
|
|
|
|
|
|
+const accessProfileStore = useAccessProfileStore()
|
|
|
|
|
+const currentAccessId = accessProfileStore.id
|
|
|
|
|
+const loading: Ref<Boolean> = ref(true)
|
|
|
|
|
+const isOpen: Ref<Boolean> = ref(false)
|
|
|
|
|
+const page: Ref<number> = ref(1)
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 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)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+const i18n = useI18n()
|
|
|
|
|
+const runtimeConfig = useRuntimeConfig()
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 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
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
|
|
+const btn = ref(null)
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * Les metadata dépendront de la dernière valeur du GET lancé
|
|
|
|
|
- */
|
|
|
|
|
- const metadata: ComputedRef<HydraMetadata> = computed(() => {
|
|
|
|
|
- return data.value.metadata
|
|
|
|
|
- })
|
|
|
|
|
|
|
+const { fetchCollection } = useEntityFetch()
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 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)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+const { data: collection, pending } = await fetchCollection(Notification)
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 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()
|
|
|
|
|
- })
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * On récupère les Notifications via le store
|
|
|
|
|
+ */
|
|
|
|
|
+const notifications: ComputedRef = computed(() => {
|
|
|
|
|
+ // TODO: revoir pour reprendre le order by et tout
|
|
|
|
|
+ return collection.value !== null ? collection.value.items : []
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * Marque les notification non lues comme lues
|
|
|
|
|
- */
|
|
|
|
|
- const markNotificationsAsRead = () => {
|
|
|
|
|
- unreadNotification.value.map((notification:Notification)=>{
|
|
|
|
|
- notification.notificationUsers = ['read']
|
|
|
|
|
- repositoryHelper.persist(Notification, notification)
|
|
|
|
|
- createNewNotificationUsers(notification)
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Les metadata dépendront de la dernière valeur du GET lancé
|
|
|
|
|
+ */
|
|
|
|
|
+const pagination: ComputedRef<Pagination> = computed(() => {
|
|
|
|
|
+ return collection.value !== null ? collection.value.pagination : {}
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 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
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * On calcule le nombre de notifications non lues
|
|
|
|
|
+ */
|
|
|
|
|
+const unreadNotification: ComputedRef<Array<Notification>> = computed(() => {
|
|
|
|
|
+ return notifications.value.filter((notification: Notification) => {
|
|
|
|
|
+ return notification.notificationUsers.length === 0
|
|
|
|
|
+ })
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
- $dataPersister.invoke({
|
|
|
|
|
- type: QUERY_TYPE.MODEL,
|
|
|
|
|
- model: NotificationUsers,
|
|
|
|
|
- idTemp: newNotificationUsers.id,
|
|
|
|
|
- showProgress: false
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 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')}`
|
|
|
|
|
+
|
|
|
|
|
+ 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')} `
|
|
|
|
|
+
|
|
|
|
|
+ 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()
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * Download le lien
|
|
|
|
|
- * @param link
|
|
|
|
|
- */
|
|
|
|
|
- const download = (link: string) => {
|
|
|
|
|
- const url_parts: Array<string> = link.split('/api');
|
|
|
|
|
- if(accessProfile.originalAccess)
|
|
|
|
|
- url_parts[0] = `api/${accessProfile.originalAccess.id}/${currentAccessId}`
|
|
|
|
|
- else
|
|
|
|
|
- url_parts[0] = `api/${currentAccessId}`
|
|
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ unwatch()
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
- window.open(`${$config.baseURL_Legacy}/${url_parts.join('')}`);
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Marque les notifications 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(accessProfileStore.originalAccess)
|
|
|
|
|
+ url_parts[0] = `api/${accessProfileStore.originalAccess.id}/${currentAccessId}`
|
|
|
|
|
+ else
|
|
|
|
|
+ url_parts[0] = `api/${currentAccessId}`
|
|
|
|
|
+
|
|
|
|
|
+ window.open(`${runtimeConfig.baseUrlLegacy}/${url_parts.join('')}`);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const notificationUrl = `${runtimeConfig.baseURL_adminLegacy}/notifications/list/`
|
|
|
|
|
|
|
|
- return {
|
|
|
|
|
- data,
|
|
|
|
|
- getMessage,
|
|
|
|
|
- notificationUrl: `${$config.baseURL_adminLegacy}/notifications/list/`,
|
|
|
|
|
- loading,
|
|
|
|
|
- notifications,
|
|
|
|
|
- update,
|
|
|
|
|
- unreadNotification,
|
|
|
|
|
- isOpen,
|
|
|
|
|
- download
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-})
|
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
-<style scoped>
|
|
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
#all_notifications{
|
|
#all_notifications{
|
|
|
- background: var(--v-theme-ot-green, white);
|
|
|
|
|
|
|
+ background: rgb(var(--v-theme-ot-green, white));
|
|
|
color: white;
|
|
color: white;
|
|
|
}
|
|
}
|
|
|
.list_item{
|
|
.list_item{
|