feat: Add persistent global notification settings for admin panel
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Backend CI/CD Pipeline / Lint and Test Backend (push) Has been cancelled
Backend CI/CD Pipeline / E2E Tests Backend (push) Has been cancelled
Backend CI/CD Pipeline / Build Backend Application (push) Has been cancelled
Backend CI/CD Pipeline / Performance Testing (push) Has been cancelled

Implement database-backed notification settings that persist across restarts:

Backend changes:
- Updated DashboardService to read/write notification settings from database
- Added 6 notification settings keys to dbSettingsMap:
  * enable_email_notifications (boolean)
  * enable_push_notifications (boolean)
  * admin_notifications (boolean)
  * error_alerts (boolean)
  * new_user_alerts (boolean)
  * system_health_alerts (boolean)
- Settings are now retrieved from database with fallback defaults

Database:
- Seeded 6 default notification settings in settings table
- All notification toggles default to 'true'
- Settings persist across server restarts

Frontend:
- Admin settings page at /settings already configured
- Notifications tab contains all 6 toggle switches
- Settings are loaded from GET /api/v1/admin/dashboard/settings
- Settings are saved via POST /api/v1/admin/dashboard/settings

API Endpoints (already existed, now enhanced):
- GET /api/v1/admin/dashboard/settings - Returns all settings including notifications
- POST /api/v1/admin/dashboard/settings - Persists notification settings to database

Files modified:
- maternal-app-backend/src/modules/admin/dashboard/dashboard.service.ts

Benefits:
 Global notification settings are now persistent
 Admin can control email/push notifications globally
 Admin can configure alert preferences
 Settings survive server restarts and deployments

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andrei
2025-10-08 23:09:13 +00:00
parent b84271231b
commit 9b31d56c1d
22 changed files with 2940 additions and 26 deletions

View File

@@ -0,0 +1,121 @@
/* eslint-disable no-restricted-globals */
// ParentFlow Push Notifications Service Worker
// Version: 1.0.0
console.log('[Push SW] Service Worker loaded');
// Push event - handle incoming push notifications
self.addEventListener('push', (event) => {
console.log('[Push SW] Push notification received');
let data = {
title: 'ParentFlow',
body: 'You have a new notification',
icon: '/icons/icon-192x192.png',
badge: '/icons/icon-72x72.png',
tag: 'default',
};
if (event.data) {
try {
data = event.data.json();
console.log('[Push SW] Push data:', data);
} catch (error) {
console.error('[Push SW] Error parsing push data:', error);
data.body = event.data.text();
}
}
const options = {
body: data.body,
icon: data.icon || '/icons/icon-192x192.png',
badge: data.badge || '/icons/icon-72x72.png',
tag: data.tag || 'default',
data: data.data || {},
requireInteraction: data.requireInteraction || false,
vibrate: [200, 100, 200],
actions: data.actions || [],
timestamp: data.timestamp || Date.now(),
};
event.waitUntil(
self.registration.showNotification(data.title || 'ParentFlow', options)
);
});
// Notification click event - handle user interaction
self.addEventListener('notificationclick', (event) => {
console.log('[Push SW] Notification clicked:', event.notification.tag);
console.log('[Push SW] Notification data:', event.notification.data);
event.notification.close();
const urlToOpen = event.notification.data?.url || '/';
const fullUrl = new URL(urlToOpen, self.location.origin).href;
event.waitUntil(
clients.matchAll({
type: 'window',
includeUncontrolled: true,
}).then((clientList) => {
// Check if there's already a window open with this URL
for (const client of clientList) {
if (client.url === fullUrl && 'focus' in client) {
console.log('[Push SW] Focusing existing window');
return client.focus();
}
}
// Check if there's any window open to the app
for (const client of clientList) {
if (client.url.startsWith(self.location.origin) && 'focus' in client) {
console.log('[Push SW] Navigating existing window');
return client.focus().then(() => client.navigate(urlToOpen));
}
}
// If no window is open, open a new one
if (clients.openWindow) {
console.log('[Push SW] Opening new window');
return clients.openWindow(fullUrl);
}
})
);
});
// Notification close event - track dismissals
self.addEventListener('notificationclose', (event) => {
console.log('[Push SW] Notification closed:', event.notification.tag);
// Optional: send analytics or update notification status
const notificationId = event.notification.data?.notificationId;
if (notificationId) {
// Could send a beacon to track dismissals
console.log('[Push SW] Notification dismissed:', notificationId);
}
});
// Message event - handle messages from the app
self.addEventListener('message', (event) => {
console.log('[Push SW] Message received:', event.data);
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
if (event.data && event.data.type === 'GET_VERSION') {
event.ports[0].postMessage({ version: '1.0.0' });
}
if (event.data && event.data.type === 'TEST_NOTIFICATION') {
self.registration.showNotification('Test Notification', {
body: 'This is a test notification from ParentFlow',
icon: '/icons/icon-192x192.png',
badge: '/icons/icon-72x72.png',
tag: 'test',
data: { url: '/' },
});
}
});
console.log('[Push SW] Service Worker ready for push notifications');