16 KiB
16 KiB
Notification and Widget Update System - Complete File & Route Analysis
📋 Table of Contents
🔔 Notification System
API Routes
1. GET /api/notifications
- File:
app/api/notifications/route.ts - Purpose: Fetch paginated notifications for authenticated user
- Query Parameters:
page(default: 1)limit(default: 20, max: 100)
- Response:
{ "notifications": Notification[], "page": number, "limit": number, "total": number } - Cache: 30 seconds client-side cache
- Authentication: Required (session-based)
2. GET /api/notifications/count
- File:
app/api/notifications/count/route.ts - Purpose: Get notification count (total and unread) for authenticated user
- Response:
{ "total": number, "unread": number, "sources": { [source]: { "total": number, "unread": number } } } - Cache: 10 seconds client-side cache
- Authentication: Required
3. POST /api/notifications/[id]/read
- File:
app/api/notifications/[id]/read/route.ts - Purpose: Mark a specific notification as read
- Parameters:
id(path parameter): Notification ID (format:source-sourceId)
- Response:
{ "success": boolean } - Authentication: Required
4. POST /api/notifications/read-all
- File:
app/api/notifications/read-all/route.ts - Purpose: Mark all notifications as read for authenticated user
- Response:
{ "success": boolean } - Authentication: Required
5. GET /api/debug/notifications
- File:
app/api/debug/notifications/route.ts - Purpose: Debug endpoint to test notification system
- Response: Detailed debug information including:
- Environment variables status
- User information
- Notification service test results
- Performance metrics
- Authentication: Required
Services
1. NotificationService (Singleton)
- File:
lib/services/notifications/notification-service.ts - Purpose: Core notification aggregation service
- Features:
- Multi-source notification aggregation (adapter pattern)
- Redis caching (30s for counts, 5min for lists)
- Background refresh scheduling
- Cache invalidation on read operations
- Lock mechanism to prevent concurrent refreshes
- Methods:
getInstance(): Get singleton instancegetNotifications(userId, page, limit): Fetch notificationsgetNotificationCount(userId): Get notification countsmarkAsRead(userId, notificationId): Mark notification as readmarkAllAsRead(userId): Mark all as readinvalidateCache(userId): Invalidate user cachesscheduleBackgroundRefresh(userId): Schedule background refresh
2. NotificationAdapter Interface
- File:
lib/services/notifications/notification-adapter.interface.ts - Purpose: Interface for notification source adapters
- Methods:
getNotifications(userId, page?, limit?): Fetch notificationsgetNotificationCount(userId): Get countsmarkAsRead(userId, notificationId): Mark as readmarkAllAsRead(userId): Mark all as readisConfigured(): Check if adapter is configured
3. LeantimeAdapter (Implementation)
- File:
lib/services/notifications/leantime-adapter.ts - Purpose: Leantime notification source adapter
- Features:
- Fetches notifications from Leantime API via JSON-RPC
- Maps Leantime user IDs by email
- Transforms Leantime notifications to unified format
- Supports marking notifications as read
- Configuration:
LEANTIME_API_URLenvironment variableLEANTIME_TOKENenvironment variable
Components
1. NotificationBadge
- File:
components/notification-badge.tsx - Purpose: Notification bell icon with badge and dropdown
- Features:
- Displays unread count badge
- Dropdown menu with recent notifications
- Manual refresh button
- Mark as read functionality
- Mark all as read functionality
- Source badges (e.g., "Agilité" for Leantime)
- Links to source systems
- Error handling and retry
- Used in:
components/main-nav.tsx
2. MainNav (Notification Integration)
- File:
components/main-nav.tsx - Purpose: Main navigation bar with notification badge
- Notification Features:
- Includes
<NotificationBadge />component - Browser notification permission handling
- User status-based notification management
- Includes
Hooks
1. useNotifications
- File:
hooks/use-notifications.ts - Purpose: React hook for notification management
- Features:
- Automatic polling (60 seconds interval)
- Rate limiting (5 seconds minimum between fetches)
- Debounced count fetching (300ms)
- Manual refresh support
- Mount/unmount lifecycle management
- Error handling
- Returns:
{ notifications: Notification[], notificationCount: NotificationCount, loading: boolean, error: string | null, fetchNotifications: (page?, limit?) => Promise<void>, fetchNotificationCount: () => Promise<void>, markAsRead: (notificationId: string) => Promise<boolean>, markAllAsRead: () => Promise<boolean> }
Types
1. Notification Types
- File:
lib/types/notification.ts - Interfaces:
Notification: Main notification interfaceid: string (format:source-sourceId)source: 'leantime' | 'nextcloud' | 'gitea' | 'dolibarr' | 'moodle'sourceId: stringtype: stringtitle: stringmessage: stringlink?: stringisRead: booleantimestamp: Datepriority: 'low' | 'normal' | 'high'user: { id: string, name?: string }metadata?: Record<string, any>
NotificationCount: Count interfacetotal: numberunread: numbersources: Record<string, { total: number, unread: number }>
🎨 Widget Update System
Dashboard Widgets
The main dashboard (app/page.tsx) contains the following widgets:
- QuoteCard - Daily quote widget
- Calendar - Upcoming events widget
- News - News articles widget
- Duties - Tasks/Devoirs widget (Leantime)
- Email - Email inbox widget
- Parole - Chat messages widget (Rocket.Chat)
Widget Components & Update Mechanisms
1. Calendar Widget
- Files:
components/calendar.tsx(Main dashboard widget)components/calendar-widget.tsx(Alternative implementation)components/calendar/calendar-widget.tsx(Calendar-specific widget)
- Update Mechanism:
- Manual Refresh: Refresh button in header
- Auto Refresh: Every 5 minutes (300000ms interval)
- API Endpoint:
/api/calendars?refresh=true - Features:
- Fetches calendars with events
- Filters upcoming events (today and future)
- Sorts by date (oldest first)
- Shows up to 7 events
- Displays calendar color coding
- State Management:
useStatefor events, loading, erroruseEffectfor initial fetch and interval setup
2. News Widget
- File:
components/news.tsx - Update Mechanism:
- Manual Refresh: Refresh button in header
- Initial Load: On component mount when authenticated
- API Endpoint:
/api/news?limit=100or/api/news?refresh=true&limit=100 - Features:
- Fetches up to 100 news articles
- Displays article count
- Click to open in new tab
- Scrollable list (max-height: 400px)
- State Management:
useStatefor news, loading, error, refreshinguseEffectfor initial fetch on authentication
3. Duties Widget (Tasks)
- File:
components/flow.tsx - Update Mechanism:
- Manual Refresh: Refresh button in header
- Initial Load: On component mount
- API Endpoint:
/api/leantime/tasks?refresh=true - Features:
- Fetches tasks from Leantime
- Filters out completed tasks (status 5)
- Sorts by due date (oldest first)
- Shows up to 7 tasks
- Displays task status badges
- Links to Leantime ticket view
- State Management:
useStatefor tasks, loading, error, refreshinguseEffectfor initial fetch
4. Email Widget
- File:
components/email.tsx - Update Mechanism:
- Manual Refresh: Refresh button in header
- Initial Load: On component mount
- API Endpoint:
/api/courrier?folder=INBOX&page=1&perPage=5(+&refresh=truefor refresh) - Features:
- Fetches 5 most recent emails from INBOX
- Sorts by date (most recent first)
- Shows read/unread status
- Displays sender, subject, date
- Link to full email view (
/courrier)
- State Management:
useStatefor emails, loading, error, mailUrluseEffectfor initial fetch
5. Parole Widget (Chat Messages)
- File:
components/parole.tsx - Update Mechanism:
- Manual Refresh: Refresh button in header
- Auto Polling: Every 30 seconds (30000ms interval)
- Initial Load: On authentication
- API Endpoint:
/api/rocket-chat/messages(+?refresh=truefor refresh) - Features:
- Fetches recent chat messages from Rocket.Chat
- Displays sender avatar, name, message
- Shows room/channel information
- Click to navigate to full chat (
/parole) - Authentication check with sign-in prompt
- State Management:
useStatefor messages, loading, error, refreshinguseEffectfor initial fetch and polling setup- Session status checking
6. QuoteCard Widget
- File:
components/quote-card.tsx - Update Mechanism: (To be verified - likely static or daily update)
Widget Update Patterns
Common Update Mechanisms:
-
Manual Refresh:
- All widgets have a refresh button in their header
- Triggers API call with
refresh=trueparameter - Shows loading/spinning state during refresh
-
Auto Refresh/Polling:
- Calendar: 5 minutes interval
- Parole: 30 seconds interval
- Others: On component mount only
-
Session-Based Loading:
- Widgets check authentication status
- Only fetch data when
status === 'authenticated' - Show loading state during authentication check
-
Error Handling:
- All widgets display error messages
- Retry buttons available
- Graceful degradation (empty states)
-
State Management:
- All widgets use React
useStatehooks - Loading states managed locally
- Error states managed locally
- All widgets use React
Related API Routes for Widgets
Calendar
- GET
/api/calendars: Fetch calendars with events - GET
/api/calendars/[id]/events: Fetch events for specific calendar - GET
/api/calendars/[id]: Get calendar details
News
- GET
/api/news: Fetch news articles- Query params:
limit,refresh
- Query params:
Tasks (Leantime)
- GET
/api/leantime/tasks: Fetch tasks- Query params:
refresh
- Query params:
Email (Courrier)
- GET
/api/courrier: Fetch emails- Query params:
folder,page,perPage,refresh
- Query params:
- POST
/api/courrier/refresh: Force refresh email cache
Chat (Rocket.Chat)
- GET
/api/rocket-chat/messages: Fetch messages- Query params:
refresh
- Query params:
📁 Complete File Structure
Notification Files
app/api/notifications/
├── route.ts # GET /api/notifications
├── count/
│ └── route.ts # GET /api/notifications/count
├── read-all/
│ └── route.ts # POST /api/notifications/read-all
└── [id]/
└── read/
└── route.ts # POST /api/notifications/[id]/read
app/api/debug/
└── notifications/
└── route.ts # GET /api/debug/notifications
lib/services/notifications/
├── notification-service.ts # Core notification service
├── notification-adapter.interface.ts # Adapter interface
└── leantime-adapter.ts # Leantime adapter implementation
lib/types/
└── notification.ts # Notification type definitions
hooks/
└── use-notifications.ts # React hook for notifications
components/
├── notification-badge.tsx # Notification UI component
└── main-nav.tsx # Navigation with notification badge
Widget Files
app/
└── page.tsx # Main dashboard with widgets
components/
├── calendar.tsx # Calendar widget
├── calendar-widget.tsx # Alternative calendar widget
├── calendar/
│ └── calendar-widget.tsx # Calendar-specific widget
├── news.tsx # News widget
├── flow.tsx # Duties/Tasks widget
├── email.tsx # Email widget
├── parole.tsx # Chat messages widget
└── quote-card.tsx # Quote widget
app/api/
├── calendars/
│ ├── route.ts # GET /api/calendars
│ └── [id]/
│ └── events/
│ └── route.ts # GET /api/calendars/[id]/events
├── news/
│ └── route.ts # GET /api/news
├── leantime/
│ └── tasks/
│ └── route.ts # GET /api/leantime/tasks
├── courrier/
│ ├── route.ts # GET /api/courrier
│ └── refresh/
│ └── route.ts # POST /api/courrier/refresh
└── rocket-chat/
└── messages/
└── route.ts # GET /api/rocket-chat/messages
🔄 Update Flow Diagrams
Notification Update Flow
User Action / Polling
↓
useNotifications Hook
↓
API Route (/api/notifications or /api/notifications/count)
↓
NotificationService.getInstance()
↓
Check Redis Cache
├─ Cache Hit → Return cached data
└─ Cache Miss → Fetch from Adapters
↓
LeantimeAdapter (and other adapters)
↓
Transform & Aggregate
↓
Store in Redis Cache
↓
Return to API
↓
Return to Hook
↓
Update Component State
Widget Update Flow
Component Mount / User Click Refresh
↓
useEffect / onClick Handler
↓
fetch() API Call
├─ With refresh=true (manual)
└─ Without refresh (initial)
↓
API Route Handler
├─ Check Cache (if applicable)
├─ Fetch from External Service
└─ Return Data
↓
Update Component State
├─ setLoading(false)
├─ setData(response)
└─ setError(null)
↓
Re-render Component
🎯 Key Features Summary
Notification System
- ✅ Multi-source aggregation (adapter pattern)
- ✅ Redis caching with TTL
- ✅ Background refresh scheduling
- ✅ Polling mechanism (60s interval)
- ✅ Rate limiting (5s minimum)
- ✅ Mark as read / Mark all as read
- ✅ Cache invalidation on updates
- ✅ Error handling and retry
- ✅ Source badges and links
Widget System
- ✅ Manual refresh buttons
- ✅ Auto-refresh/polling (widget-specific intervals)
- ✅ Session-based loading
- ✅ Error handling
- ✅ Loading states
- ✅ Empty states
- ✅ Responsive design
📝 Notes
-
Notification Sources: Currently only Leantime adapter is implemented. Other adapters (Nextcloud, Gitea, Dolibarr, Moodle) are commented out in the service.
-
Cache Strategy:
- Notification counts: 30 seconds TTL
- Notification lists: 5 minutes TTL
- Widget data: Varies by widget (some use API-level caching)
-
Polling Intervals:
- Notifications: 60 seconds
- Calendar widget: 5 minutes
- Parole widget: 30 seconds
- Other widgets: On mount only
-
Authentication: All notification and widget APIs require authentication via NextAuth session.
-
Error Handling: All components implement error states with retry mechanisms.
🔍 Debugging
- Use
/api/debug/notificationsto test notification system - Check browser console for detailed logs (all components log extensively)
- Check Redis cache keys:
notifications:count:{userId},notifications:list:{userId}:{page}:{limit}
Last Updated: Generated from codebase analysis