Refonte du système de notifications : passage aux notifications dérivées

Remplace le système de notifications stockées par un système de providers
qui dérivent les notifications des données existantes (commentaires, réponses,
demandes de projet, demandes de rendez-vous, validations de brief).

- Ajout du NotificationCollector et de l'interface NotificationProvider
- Création de 5 providers : Comment, Reply, ProjectRequest, AppointmentRequest, Content
- Métadonnées de notifications stockées directement sur les entités source
- Nouvelles routes mark-as-read et mark-all-read
- Mise à jour du frontend pour le nouveau système
- Route de migration pour les données existantes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-01-15 10:31:31 +01:00
parent c68b51f639
commit a7d315942a
26 changed files with 1406 additions and 137 deletions

View file

@ -11,48 +11,76 @@ export const useUserStore = defineStore('user', () => {
const { projects } = storeToRefs(useProjectsStore());
/**
* Liste des notifications agrégées depuis tous les projets.
* Les notifications sont maintenant dérivées côté backend avec isRead pré-calculé.
*/
const notifications = computed(() => {
return projects.value?.flatMap((project) => {
if (!projects.value || !user.value) return [];
return projects.value.flatMap((project) => {
if (!project.notifications) return [];
return project.notifications
.filter((notification) => notification.author.uuid !== user.value.uuid)
.map((notification) => ({
...notification,
project: project,
isRead: notification.readby?.includes(user.value.uuid),
}));
return project.notifications.map((notification) => ({
...notification,
project: project,
// isRead est maintenant fourni par le backend
}));
});
});
function readNotification(notificationId, projectId) {
console.log('Read notification', notificationId, projectId);
/**
* Marque une notification comme lue dans le store local.
* @param {string} notificationId - L'ID de la notification
* @param {string} projectUri - L'URI du projet (optionnel, pour retrouver le projet)
*/
function markNotificationRead(notificationId, projectUri = null) {
if (!user.value?.uuid) return;
projects.value = projects.value.map((project) => {
// Si projectUri fourni, cibler le bon projet
if (projectUri && project.uri !== projectUri && `/${project.uri}` !== projectUri) {
return project;
}
return {
...project,
notifications: (project.notifications || []).map((notification) =>
notification.id === notificationId
? {
...notification,
isRead: true,
readby: [...new Set([...(notification.readby || []), user.value.uuid])],
}
: notification
),
};
});
}
/**
* Marque toutes les notifications comme lues dans le store local.
*/
function markAllNotificationsRead() {
if (!user.value?.uuid) return;
projects.value = projects.value.map((project) => ({
...project,
notifications:
project.uuid === projectId || project.uri === projectId
? project.notifications.map((notification) =>
notification.id === notificationId
? {
...notification,
readby: [
...new Set([...notification.readby, user.value.uuid]),
],
}
: notification
)
: project.notifications,
notifications: (project.notifications || []).map((notification) => ({
...notification,
isRead: true,
readby: [...new Set([...(notification.readby || []), user.value.uuid])],
})),
}));
}
// Anciennes fonctions gardées pour rétro-compatibilité
function readNotification(notificationId, projectId) {
markNotificationRead(notificationId, projectId);
}
function readAllNotifications() {
projects.value = projects.value.map((project) => ({
...project,
notifications: project.notifications.map((notification) => ({
...notification,
readby: [...new Set([...notification.readby, user.value.uuid])],
})),
}));
markAllNotificationsRead();
}
function canEditComment(comment) {
@ -63,6 +91,10 @@ export const useUserStore = defineStore('user', () => {
user,
isLogged,
notifications,
// Nouvelles fonctions
markNotificationRead,
markAllNotificationsRead,
// Anciennes fonctions (rétro-compatibilité)
readNotification,
readAllNotifications,
canEditComment,