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
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:
121
maternal-web/public/push-sw.js
Normal file
121
maternal-web/public/push-sw.js
Normal 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');
|
||||
Reference in New Issue
Block a user