Pages corrections widget
This commit is contained in:
parent
430940cc12
commit
ed9dadd77a
@ -117,28 +117,33 @@ export function CalendarWidget() {
|
||||
if (currentEventCount !== lastEventCountRef.current) {
|
||||
lastEventCountRef.current = currentEventCount;
|
||||
|
||||
// Prepare notification items
|
||||
const notificationItems = upcomingEvents.map(event => ({
|
||||
id: event.id,
|
||||
title: event.title,
|
||||
message: event.isAllDay
|
||||
? `Aujourd'hui (toute la journée)`
|
||||
: `Le ${format(event.start, 'dd/MM à HH:mm', { locale: fr })}`,
|
||||
link: '/agenda',
|
||||
timestamp: event.start,
|
||||
metadata: {
|
||||
calendarId: event.calendarId,
|
||||
calendarName: event.calendarName,
|
||||
isAllDay: event.isAllDay,
|
||||
},
|
||||
}));
|
||||
// Always prepare notification items (even if count hasn't changed)
|
||||
const notificationItems = upcomingEvents.map(event => ({
|
||||
id: event.id,
|
||||
title: event.title,
|
||||
message: event.isAllDay
|
||||
? `Aujourd'hui (toute la journée)`
|
||||
: `Le ${format(event.start, 'dd/MM à HH:mm', { locale: fr })}`,
|
||||
link: '/agenda',
|
||||
timestamp: event.start,
|
||||
metadata: {
|
||||
calendarId: event.calendarId,
|
||||
calendarName: event.calendarName,
|
||||
isAllDay: event.isAllDay,
|
||||
},
|
||||
}));
|
||||
|
||||
// Trigger notification update
|
||||
await triggerNotification({
|
||||
source: 'calendar',
|
||||
count: currentEventCount,
|
||||
items: notificationItems,
|
||||
});
|
||||
// Always trigger notification update to keep count fresh in Redis
|
||||
// This ensures the count doesn't expire even if it hasn't changed
|
||||
await triggerNotification({
|
||||
source: 'calendar',
|
||||
count: currentEventCount,
|
||||
items: notificationItems,
|
||||
});
|
||||
|
||||
// Update last count reference
|
||||
if (currentEventCount !== lastEventCountRef.current) {
|
||||
lastEventCountRef.current = currentEventCount;
|
||||
}
|
||||
|
||||
setEvents(upcomingEvents.slice(0, 5)); // Keep only 5 for display
|
||||
|
||||
@ -195,36 +195,38 @@ export function Email() {
|
||||
lastUnreadCountRef.current = currentUnreadCount;
|
||||
isInitializedRef.current = true;
|
||||
} else {
|
||||
// Trigger notification if count changed or new emails detected
|
||||
if (currentUnreadCount !== lastUnreadCountRef.current || hasNewEmails) {
|
||||
const previousCount = lastUnreadCountRef.current;
|
||||
// Update count if it changed
|
||||
if (currentUnreadCount !== lastUnreadCountRef.current) {
|
||||
lastUnreadCountRef.current = currentUnreadCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare notification items (unread emails only, max 10)
|
||||
const notificationItems = transformedEmails
|
||||
.filter(e => !e.read)
|
||||
.slice(0, 10)
|
||||
.map(email => {
|
||||
const account = accountMap.get((email as any).accountId);
|
||||
return {
|
||||
id: email.id,
|
||||
title: email.subject || 'Sans objet',
|
||||
message: `De ${email.fromName || email.from.split('@')[0]}`,
|
||||
link: '/courrier',
|
||||
timestamp: new Date(email.date),
|
||||
metadata: {
|
||||
accountId: (email as any).accountId,
|
||||
accountEmail: account?.email,
|
||||
},
|
||||
};
|
||||
});
|
||||
// Always prepare notification items (unread emails only, max 10)
|
||||
const notificationItems = transformedEmails
|
||||
.filter(e => !e.read)
|
||||
.slice(0, 10)
|
||||
.map(email => {
|
||||
const account = accountMap.get((email as any).accountId);
|
||||
return {
|
||||
id: email.id,
|
||||
title: email.subject || 'Sans objet',
|
||||
message: `De ${email.fromName || email.from.split('@')[0]}`,
|
||||
link: '/courrier',
|
||||
timestamp: new Date(email.date),
|
||||
metadata: {
|
||||
accountId: (email as any).accountId,
|
||||
accountEmail: account?.email,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// Trigger notification update (for badge)
|
||||
await triggerNotification({
|
||||
source: 'email',
|
||||
count: currentUnreadCount,
|
||||
items: notificationItems,
|
||||
});
|
||||
// Always trigger notification update to keep count fresh in Redis
|
||||
// This ensures the count doesn't expire even if it hasn't changed
|
||||
await triggerNotification({
|
||||
source: 'email',
|
||||
count: currentUnreadCount,
|
||||
items: notificationItems,
|
||||
});
|
||||
|
||||
// Dispatch event for Outlook-style notifications (for new emails detected by ID)
|
||||
if (hasNewEmails) {
|
||||
|
||||
@ -218,40 +218,44 @@ export function Duties() {
|
||||
// Calculate current task count
|
||||
const currentTaskCount = sortedTasks.length;
|
||||
|
||||
// Trigger notification if count changed
|
||||
if (currentTaskCount !== lastTaskCountRef.current) {
|
||||
// Always trigger notification to keep the count fresh in Redis
|
||||
// This prevents the count from expiring if it hasn't changed
|
||||
const shouldUpdate = currentTaskCount !== lastTaskCountRef.current || lastTaskCountRef.current === -1;
|
||||
|
||||
if (shouldUpdate) {
|
||||
lastTaskCountRef.current = currentTaskCount;
|
||||
|
||||
// Prepare notification items (max 10)
|
||||
const notificationItems = sortedTasks
|
||||
.slice(0, 10)
|
||||
.map(task => ({
|
||||
id: task.id.toString(),
|
||||
title: task.headline,
|
||||
message: task.dateToFinish
|
||||
? `Due: ${formatDate(task.dateToFinish)}`
|
||||
: 'Tâche en retard',
|
||||
link: (task as any).source === 'twenty-crm'
|
||||
? (task as any).url
|
||||
: `https://agilite.slm-lab.net/tickets/showTicket/${task.id.replace('twenty-', '')}`,
|
||||
timestamp: task.dateToFinish
|
||||
? new Date(task.dateToFinish)
|
||||
: new Date(),
|
||||
metadata: {
|
||||
source: (task as any).source || 'leantime',
|
||||
projectName: task.projectName,
|
||||
status: task.status,
|
||||
},
|
||||
}));
|
||||
|
||||
// Trigger notification update
|
||||
await triggerNotification({
|
||||
source: 'leantime',
|
||||
count: currentTaskCount,
|
||||
items: notificationItems,
|
||||
});
|
||||
}
|
||||
|
||||
// Prepare notification items (max 10)
|
||||
const notificationItems = sortedTasks
|
||||
.slice(0, 10)
|
||||
.map(task => ({
|
||||
id: task.id.toString(),
|
||||
title: task.headline,
|
||||
message: task.dateToFinish
|
||||
? `Due: ${formatDate(task.dateToFinish)}`
|
||||
: 'Tâche en retard',
|
||||
link: (task as any).source === 'twenty-crm'
|
||||
? (task as any).url
|
||||
: `https://agilite.slm-lab.net/tickets/showTicket/${task.id.replace('twenty-', '')}`,
|
||||
timestamp: task.dateToFinish
|
||||
? new Date(task.dateToFinish)
|
||||
: new Date(),
|
||||
metadata: {
|
||||
source: (task as any).source || 'leantime',
|
||||
projectName: task.projectName,
|
||||
status: task.status,
|
||||
},
|
||||
}));
|
||||
|
||||
// Always trigger notification update to keep count fresh in Redis
|
||||
// This ensures the count doesn't expire even if it hasn't changed
|
||||
await triggerNotification({
|
||||
source: 'leantime',
|
||||
count: currentTaskCount,
|
||||
items: notificationItems,
|
||||
});
|
||||
|
||||
setTasks(sortedTasks);
|
||||
|
||||
// Dispatch event for Outlook-style notifications (when tasks are due)
|
||||
|
||||
@ -27,12 +27,21 @@ export const NotificationBadge = memo(function NotificationBadge({ className }:
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [manualFetchAttempted, setManualFetchAttempted] = useState(false);
|
||||
|
||||
console.log('[NOTIFICATION_BADGE] Auth status:', status);
|
||||
console.log('[NOTIFICATION_BADGE] Session:', session ? 'exists' : 'null');
|
||||
console.log('[NOTIFICATION_BADGE] Current notification count:', notificationCount);
|
||||
console.log('[NOTIFICATION_BADGE] Current notifications:', notifications.length > 0 ? `${notifications.length} loaded` : 'none loaded');
|
||||
console.log('[NOTIFICATION_BADGE] Loading state:', loading);
|
||||
console.log('[NOTIFICATION_BADGE] Error state:', error);
|
||||
console.log('[NOTIFICATION_BADGE] 📊 Notification state:', {
|
||||
authStatus: status,
|
||||
hasSession: !!session,
|
||||
totalUnread: notificationCount.unread,
|
||||
total: notificationCount.total,
|
||||
sources: Object.keys(notificationCount.sources || {}).map(source => ({
|
||||
source,
|
||||
unread: notificationCount.sources[source]?.unread || 0,
|
||||
total: notificationCount.sources[source]?.total || 0,
|
||||
})),
|
||||
hasUnread: notificationCount.unread > 0,
|
||||
notificationsLoaded: notifications.length,
|
||||
loading,
|
||||
error: error || null,
|
||||
});
|
||||
|
||||
// Manual fetch function with error handling
|
||||
const manualFetch = async () => {
|
||||
|
||||
@ -96,32 +96,34 @@ export function Parole() {
|
||||
lastUnreadCountRef.current = currentUnreadCount;
|
||||
isInitializedRef.current = true;
|
||||
} else {
|
||||
// Si le count a changé ou nouveaux messages détectés, déclencher notification
|
||||
if (currentUnreadCount !== lastUnreadCountRef.current || hasNewMessages) {
|
||||
const previousCount = lastUnreadCountRef.current;
|
||||
// Update count if it changed
|
||||
if (currentUnreadCount !== lastUnreadCountRef.current) {
|
||||
lastUnreadCountRef.current = currentUnreadCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Préparer les items pour les notifications (messages, max 10)
|
||||
const notificationItems = data.messages
|
||||
.slice(0, 10)
|
||||
.map((msg: any) => ({
|
||||
id: msg.id,
|
||||
title: msg.sender.name || msg.sender.username,
|
||||
message: msg.text || msg.message || '',
|
||||
link: '/parole',
|
||||
timestamp: new Date(msg.rawTimestamp || msg.timestamp),
|
||||
metadata: {
|
||||
roomName: msg.roomName,
|
||||
roomType: msg.roomType,
|
||||
},
|
||||
}));
|
||||
// Always prepare notification items (messages, max 10)
|
||||
const notificationItems = data.messages
|
||||
.slice(0, 10)
|
||||
.map((msg: any) => ({
|
||||
id: msg.id,
|
||||
title: msg.sender.name || msg.sender.username,
|
||||
message: msg.text || msg.message || '',
|
||||
link: '/parole',
|
||||
timestamp: new Date(msg.rawTimestamp || msg.timestamp),
|
||||
metadata: {
|
||||
roomName: msg.roomName,
|
||||
roomType: msg.roomType,
|
||||
},
|
||||
}));
|
||||
|
||||
// Déclencher notification update (for badge)
|
||||
await triggerNotification({
|
||||
source: 'rocketchat',
|
||||
count: currentUnreadCount,
|
||||
items: notificationItems,
|
||||
});
|
||||
// Always trigger notification update to keep count fresh in Redis
|
||||
// This ensures the count doesn't expire even if it hasn't changed
|
||||
await triggerNotification({
|
||||
source: 'rocketchat',
|
||||
count: currentUnreadCount,
|
||||
items: notificationItems,
|
||||
});
|
||||
|
||||
// Dispatch event for Outlook-style notifications (for new messages detected by ID)
|
||||
if (hasNewMessages) {
|
||||
|
||||
@ -58,7 +58,14 @@ export function useNotifications() {
|
||||
);
|
||||
|
||||
if (isMountedRef.current) {
|
||||
console.log('[useNotifications] Received notification count:', data);
|
||||
console.log('[useNotifications] Received notification count:', {
|
||||
total: data.total,
|
||||
unread: data.unread,
|
||||
sources: Object.keys(data.sources || {}).map(source => ({
|
||||
source,
|
||||
count: data.sources[source]?.unread || 0,
|
||||
})),
|
||||
});
|
||||
setNotificationCount(data);
|
||||
}
|
||||
} catch (err: any) {
|
||||
|
||||
@ -20,7 +20,7 @@ export class NotificationRegistry {
|
||||
private static COUNT_CACHE_KEY = (userId: string) => `notifications:count:${userId}`;
|
||||
private static ITEMS_CACHE_KEY = (userId: string, source: string) =>
|
||||
`notifications:items:${userId}:${source}`;
|
||||
private static COUNT_CACHE_TTL = 30; // 30 seconds (aligned with refresh interval)
|
||||
private static COUNT_CACHE_TTL = 300; // 5 minutes (increased to prevent premature expiration)
|
||||
private static ITEMS_CACHE_TTL = 300; // 5 minutes for items
|
||||
|
||||
public static getInstance(): NotificationRegistry {
|
||||
@ -72,12 +72,31 @@ export class NotificationRegistry {
|
||||
total: previousSourceCount + count,
|
||||
unread: previousSourceCount + count,
|
||||
};
|
||||
logger.debug('[NOTIFICATION_REGISTRY] Call count incremented', {
|
||||
source,
|
||||
previousCount: previousSourceCount,
|
||||
newCount: currentCount.sources[source].unread,
|
||||
});
|
||||
} else {
|
||||
// For regular updates, set the count (widgets send their total)
|
||||
currentCount.sources[source] = {
|
||||
total: count,
|
||||
unread: count,
|
||||
};
|
||||
// Only update if the new count is different or if we're setting it for the first time
|
||||
if (count !== previousSourceCount || !currentCount.sources[source]) {
|
||||
currentCount.sources[source] = {
|
||||
total: count,
|
||||
unread: count,
|
||||
};
|
||||
logger.debug('[NOTIFICATION_REGISTRY] Count updated', {
|
||||
source,
|
||||
previousCount: previousSourceCount,
|
||||
newCount: count,
|
||||
});
|
||||
} else {
|
||||
// Count hasn't changed, but refresh the TTL to keep it alive
|
||||
logger.debug('[NOTIFICATION_REGISTRY] Count unchanged, refreshing TTL', {
|
||||
source,
|
||||
count,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate total
|
||||
|
||||
Loading…
Reference in New Issue
Block a user