mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-01-11 19:56:44 +00:00
feat: Implement service worker generation script and update build process for Dashboard
This commit is contained in:
parent
0a6cdd11af
commit
5eee900fd3
7 changed files with 620 additions and 7 deletions
144
Common/Scripts/generate-service-worker.js
Executable file
144
Common/Scripts/generate-service-worker.js
Executable file
|
|
@ -0,0 +1,144 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Universal Service Worker Generator for OneUptime Services
|
||||
*
|
||||
* This script can be used by any OneUptime service to generate
|
||||
* a service worker from a template with dynamic versioning.
|
||||
*
|
||||
* Usage:
|
||||
* node generate-service-worker.js [template-path] [output-path]
|
||||
*
|
||||
* Example:
|
||||
* node generate-service-worker.js sw.js.template public/sw.js
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
|
||||
// Default values
|
||||
const DEFAULT_APP_VERSION = '1.0.0';
|
||||
const DEFAULT_GIT_SHA = 'local';
|
||||
|
||||
/**
|
||||
* Get app version from environment or package.json
|
||||
*/
|
||||
function getAppVersion(packageJsonPath) {
|
||||
// First try environment variable (Docker build)
|
||||
if (process.env.APP_VERSION) {
|
||||
return process.env.APP_VERSION;
|
||||
}
|
||||
|
||||
// Fallback to package.json version
|
||||
try {
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||||
return packageJson.version || DEFAULT_APP_VERSION;
|
||||
} catch (error) {
|
||||
console.warn('Could not read package.json, using default version');
|
||||
return DEFAULT_APP_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get git SHA from environment
|
||||
*/
|
||||
function getGitSha() {
|
||||
// Try environment variable first (Docker build)
|
||||
if (process.env.GIT_SHA) {
|
||||
return process.env.GIT_SHA.substring(0, 8); // Short SHA
|
||||
}
|
||||
|
||||
// Try to get from git command if available
|
||||
try {
|
||||
const { execSync } = require('child_process');
|
||||
const gitSha = execSync('git rev-parse --short HEAD', { encoding: 'utf8' }).trim();
|
||||
return gitSha;
|
||||
} catch (error) {
|
||||
// Fallback to timestamp-based hash for local development
|
||||
const timestamp = Date.now().toString();
|
||||
const hash = crypto.createHash('md5').update(timestamp).digest('hex');
|
||||
return hash.substring(0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate service worker from template
|
||||
*/
|
||||
function generateServiceWorker(templatePath, outputPath, serviceName = 'OneUptime') {
|
||||
// Check if template exists
|
||||
if (!fs.existsSync(templatePath)) {
|
||||
console.error('❌ Service worker template not found:', templatePath);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Read template
|
||||
const template = fs.readFileSync(templatePath, 'utf8');
|
||||
|
||||
// Get version information
|
||||
const packageJsonPath = path.join(path.dirname(templatePath), 'package.json');
|
||||
const appVersion = getAppVersion(packageJsonPath);
|
||||
const gitSha = getGitSha();
|
||||
const buildTimestamp = new Date().toISOString();
|
||||
|
||||
console.log(`🔧 Generating service worker for ${serviceName}...`);
|
||||
console.log(` App Version: ${appVersion}`);
|
||||
console.log(` Git SHA: ${gitSha}`);
|
||||
console.log(` Build Time: ${buildTimestamp}`);
|
||||
|
||||
// Replace placeholders
|
||||
const generatedContent = template
|
||||
.replace(/\{\{APP_VERSION\}\}/g, appVersion)
|
||||
.replace(/\{\{GIT_SHA\}\}/g, gitSha)
|
||||
.replace(/\{\{BUILD_TIMESTAMP\}\}/g, buildTimestamp)
|
||||
.replace(/\{\{SERVICE_NAME\}\}/g, serviceName);
|
||||
|
||||
// Add generation comment at the top
|
||||
const header = `/*
|
||||
* Generated Service Worker for ${serviceName}
|
||||
*
|
||||
* Generated at: ${buildTimestamp}
|
||||
* App Version: ${appVersion}
|
||||
* Git SHA: ${gitSha}
|
||||
*
|
||||
* DO NOT EDIT THIS FILE DIRECTLY
|
||||
* Edit the template file instead and run the generator script
|
||||
*/
|
||||
|
||||
`;
|
||||
|
||||
const finalContent = header + generatedContent;
|
||||
|
||||
// Ensure output directory exists
|
||||
const outputDir = path.dirname(outputPath);
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Write generated service worker
|
||||
fs.writeFileSync(outputPath, finalContent, 'utf8');
|
||||
|
||||
console.log('✅ Service worker generated successfully:', outputPath);
|
||||
console.log(` Cache version: oneuptime-v${appVersion}-${gitSha}`);
|
||||
}
|
||||
|
||||
// Command line interface
|
||||
if (require.main === module) {
|
||||
const args = process.argv.slice(2);
|
||||
const templatePath = args[0] || 'sw.js.template';
|
||||
const outputPath = args[1] || 'public/sw.js';
|
||||
const serviceName = args[2] || path.basename(process.cwd());
|
||||
|
||||
try {
|
||||
// Resolve paths relative to current working directory
|
||||
const resolvedTemplatePath = path.resolve(templatePath);
|
||||
const resolvedOutputPath = path.resolve(outputPath);
|
||||
|
||||
generateServiceWorker(resolvedTemplatePath, resolvedOutputPath, serviceName);
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to generate service worker:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { generateServiceWorker, getAppVersion, getGitSha };
|
||||
4
Dashboard/.gitignore
vendored
4
Dashboard/.gitignore
vendored
|
|
@ -19,6 +19,10 @@ node_modules
|
|||
|
||||
env.js
|
||||
|
||||
# Note: public/sw.js is auto-generated from sw.js.template during build
|
||||
# but should be committed to ensure it exists for deployments
|
||||
# The file is regenerated with correct versions during Docker build
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@
|
|||
"version": "0.1.0",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev-build": "NODE_ENV=development node esbuild.config.js",
|
||||
"generate-sw": "node scripts/generate-sw.js",
|
||||
"dev-build": "npm run generate-sw && NODE_ENV=development node esbuild.config.js",
|
||||
"dev": "npx nodemon",
|
||||
"build": "NODE_ENV=production node esbuild.config.js",
|
||||
"analyze": "analyze=true NODE_ENV=production node esbuild.config.js",
|
||||
"build": "npm run generate-sw && NODE_ENV=production node esbuild.config.js",
|
||||
"analyze": "npm run generate-sw && analyze=true NODE_ENV=production node esbuild.config.js",
|
||||
"test": "react-app-rewired test",
|
||||
"eject": "echo 'esbuild does not require eject'",
|
||||
"compile": "tsc",
|
||||
"compile": "npm run generate-sw && tsc",
|
||||
"clear-modules": "rm -rf node_modules && rm package-lock.json && npm install",
|
||||
"start": "node --require ts-node/register Serve.ts",
|
||||
"audit": "npm audit --audit-level=low",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,25 @@
|
|||
/*
|
||||
* Generated Service Worker for OneUptime Dashboard
|
||||
*
|
||||
* Generated at: 2025-07-30T10:17:31.747Z
|
||||
* App Version: 0.1.0
|
||||
* Git SHA: 0a6cdd11af
|
||||
*
|
||||
* DO NOT EDIT THIS FILE DIRECTLY
|
||||
* Edit the template file instead and run the generator script
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generated Service Worker for OneUptime Dashboard
|
||||
*
|
||||
* Generated at: 2025-07-30T10:09:37.995Z
|
||||
* App Version: 0.1.0
|
||||
* Git SHA: 0a6cdd11af
|
||||
*
|
||||
* DO NOT EDIT THIS FILE DIRECTLY
|
||||
* Edit the template file instead and run the generator script
|
||||
*/
|
||||
|
||||
/* eslint-disable no-restricted-globals */
|
||||
|
||||
// OneUptime Progressive Web App Service Worker
|
||||
|
|
@ -5,8 +27,10 @@
|
|||
|
||||
console.log('[ServiceWorker] OneUptime PWA Service Worker Loaded');
|
||||
|
||||
// Cache configuration
|
||||
const CACHE_VERSION = 'oneuptime-v1.2.0'; // Update this when deploying new versions
|
||||
// Cache configuration - Updated dynamically during build
|
||||
// Version format: oneuptime-v{APP_VERSION}-{GIT_SHA}
|
||||
// This ensures cache invalidation on every deployment
|
||||
const CACHE_VERSION = 'oneuptime-v0.1.0-0a6cdd11af'; // Auto-generated version
|
||||
const STATIC_CACHE = `${CACHE_VERSION}-static`;
|
||||
const DYNAMIC_CACHE = `${CACHE_VERSION}-dynamic`;
|
||||
|
||||
|
|
@ -363,7 +387,7 @@ self.addEventListener('message', function(event) {
|
|||
if (event.data && event.data.type === 'SKIP_WAITING') {
|
||||
self.skipWaiting();
|
||||
} else if (event.data && event.data.type === 'GET_VERSION') {
|
||||
event.ports[0].postMessage({ version: 'oneuptime-pwa-no-cache' });
|
||||
event.ports[0].postMessage({ version: CACHE_VERSION });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
21
Dashboard/scripts/generate-sw-dev.sh
Executable file
21
Dashboard/scripts/generate-sw-dev.sh
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Development Service Worker Generation Script
|
||||
#
|
||||
# This script can be used during local development to test
|
||||
# the service worker generation with sample environment variables
|
||||
|
||||
echo "🔧 Generating service worker for local development..."
|
||||
|
||||
# Set sample environment variables for testing
|
||||
export APP_VERSION="1.0.0-dev"
|
||||
export GIT_SHA=$(git rev-parse --short HEAD 2>/dev/null || echo "local-dev")
|
||||
|
||||
echo "Using APP_VERSION: $APP_VERSION"
|
||||
echo "Using GIT_SHA: $GIT_SHA"
|
||||
|
||||
# Generate the service worker
|
||||
node scripts/generate-sw.js
|
||||
|
||||
echo "✅ Service worker generated for development"
|
||||
echo "🔍 Check public/sw.js to see the generated file"
|
||||
22
Dashboard/scripts/generate-sw.js
Executable file
22
Dashboard/scripts/generate-sw.js
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Dashboard Service Worker Generator
|
||||
*
|
||||
* This script generates the Dashboard service worker from a template,
|
||||
* using the universal generator from Common/Scripts.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const { generateServiceWorker } = require('../../Common/Scripts/generate-service-worker');
|
||||
|
||||
// Generate Dashboard service worker
|
||||
const templatePath = path.join(__dirname, '..', 'sw.js.template');
|
||||
const outputPath = path.join(__dirname, '..', 'public', 'sw.js');
|
||||
|
||||
try {
|
||||
generateServiceWorker(templatePath, outputPath, 'OneUptime Dashboard');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to generate Dashboard service worker:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
397
Dashboard/sw.js.template
Normal file
397
Dashboard/sw.js.template
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
/*
|
||||
* Generated Service Worker for OneUptime Dashboard
|
||||
*
|
||||
* Generated at: 2025-07-30T10:09:37.995Z
|
||||
* App Version: 0.1.0
|
||||
* Git SHA: 0a6cdd11af
|
||||
*
|
||||
* DO NOT EDIT THIS FILE DIRECTLY
|
||||
* Edit the template file instead and run the generator script
|
||||
*/
|
||||
|
||||
/* eslint-disable no-restricted-globals */
|
||||
|
||||
// OneUptime Progressive Web App Service Worker
|
||||
// Handles push notifications and caching for PWA functionality
|
||||
|
||||
console.log('[ServiceWorker] OneUptime PWA Service Worker Loaded');
|
||||
|
||||
// Cache configuration - Updated dynamically during build
|
||||
// Version format: oneuptime-v{APP_VERSION}-{GIT_SHA}
|
||||
// This ensures cache invalidation on every deployment
|
||||
const CACHE_VERSION = 'oneuptime-v0.1.0-0a6cdd11af'; // Auto-generated version
|
||||
const STATIC_CACHE = `${CACHE_VERSION}-static`;
|
||||
const DYNAMIC_CACHE = `${CACHE_VERSION}-dynamic`;
|
||||
|
||||
// Cache duration configuration (in milliseconds)
|
||||
const CACHE_DURATIONS = {
|
||||
static: 7 * 24 * 60 * 60 * 1000, // 7 days for static assets
|
||||
dynamic: 24 * 60 * 60 * 1000, // 1 day for dynamic content
|
||||
};
|
||||
|
||||
// Assets to cache immediately during install
|
||||
const STATIC_ASSETS = [
|
||||
'/dashboard/',
|
||||
'/dashboard/manifest.json',
|
||||
'/dashboard/offline.html',
|
||||
'/dashboard/assets/img/favicons/favicon.ico',
|
||||
'/dashboard/assets/img/favicons/android-chrome-192x192.png',
|
||||
'/dashboard/assets/img/favicons/android-chrome-512x512.png',
|
||||
// Add other critical assets as needed
|
||||
];
|
||||
|
||||
// Install event - cache static assets
|
||||
self.addEventListener('install', function(event) {
|
||||
console.log('[ServiceWorker] Installing...');
|
||||
|
||||
event.waitUntil(
|
||||
Promise.all([
|
||||
// Cache static assets
|
||||
caches.open(STATIC_CACHE).then(function(cache) {
|
||||
console.log('[ServiceWorker] Pre-caching static assets');
|
||||
return cache.addAll(STATIC_ASSETS.filter(url => url !== '/dashboard/'));
|
||||
}),
|
||||
|
||||
// Skip waiting to activate immediately
|
||||
self.skipWaiting()
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
// Activate event - clean up old caches
|
||||
self.addEventListener('activate', function(event) {
|
||||
console.log('[ServiceWorker] Activating...');
|
||||
|
||||
event.waitUntil(
|
||||
Promise.all([
|
||||
// Clean up old caches
|
||||
caches.keys().then(function(cacheNames) {
|
||||
return Promise.all(
|
||||
cacheNames.map(function(cacheName) {
|
||||
if (cacheName.startsWith('oneuptime-') &&
|
||||
!cacheName.startsWith(CACHE_VERSION)) {
|
||||
console.log('[ServiceWorker] Deleting old cache:', cacheName);
|
||||
return caches.delete(cacheName);
|
||||
}
|
||||
})
|
||||
);
|
||||
}),
|
||||
|
||||
// Claim all clients
|
||||
self.clients.claim()
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
// Fetch event - implement caching strategies
|
||||
self.addEventListener('fetch', function(event) {
|
||||
const request = event.request;
|
||||
const url = new URL(request.url);
|
||||
|
||||
// Skip non-GET requests
|
||||
if (request.method !== 'GET') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip chrome-extension and other non-http(s) requests
|
||||
if (!url.protocol.startsWith('http')) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.respondWith(handleRequest(request));
|
||||
});
|
||||
|
||||
// Request handling with different caching strategies
|
||||
async function handleRequest(request) {
|
||||
const url = new URL(request.url);
|
||||
const pathname = url.pathname;
|
||||
|
||||
try {
|
||||
// Strategy 1: Network First for HTML pages (with fallback)
|
||||
if (pathname.endsWith('/') || pathname.endsWith('.html') ||
|
||||
pathname === '/dashboard' || pathname.startsWith('/dashboard/') && !pathname.includes('.')) {
|
||||
return await networkFirstWithFallback(request, DYNAMIC_CACHE);
|
||||
}
|
||||
|
||||
// Strategy 2: Cache First for JavaScript, CSS, and other static assets
|
||||
if (pathname.includes('/dist/') || pathname.match(/\.(js|css|woff|woff2|ttf|otf|eot)$/)) {
|
||||
return await cacheFirstWithUpdate(request, STATIC_CACHE);
|
||||
}
|
||||
|
||||
// Strategy 3: Cache First for images and other media
|
||||
if (pathname.match(/\.(png|jpe?g|gif|svg|ico|webp|avif)$/)) {
|
||||
return await cacheFirstWithUpdate(request, STATIC_CACHE);
|
||||
}
|
||||
|
||||
|
||||
// Strategy 5: Network First for everything else
|
||||
return await networkFirstWithFallback(request, DYNAMIC_CACHE);
|
||||
|
||||
} catch (error) {
|
||||
console.error('[ServiceWorker] Request handling error:', error);
|
||||
|
||||
// Return offline page for navigation requests
|
||||
if (request.mode === 'navigate') {
|
||||
const offlineResponse = await caches.match('/dashboard/offline.html');
|
||||
if (offlineResponse) {
|
||||
return offlineResponse;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a basic offline response
|
||||
return new Response('Offline - Please check your internet connection', {
|
||||
status: 503,
|
||||
statusText: 'Service Unavailable',
|
||||
headers: { 'Content-Type': 'text/plain' }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Caching Strategy 1: Network First with Fallback (for HTML)
|
||||
async function networkFirstWithFallback(request, cacheName) {
|
||||
try {
|
||||
const networkResponse = await fetch(request);
|
||||
|
||||
if (networkResponse.ok) {
|
||||
// Cache successful responses
|
||||
const cache = await caches.open(cacheName);
|
||||
cache.put(request, networkResponse.clone());
|
||||
}
|
||||
|
||||
return networkResponse;
|
||||
} catch (error) {
|
||||
console.log('[ServiceWorker] Network failed, trying cache:', request.url);
|
||||
|
||||
const cachedResponse = await caches.match(request);
|
||||
if (cachedResponse) {
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Caching Strategy 2: Cache First with Background Update (for static assets)
|
||||
async function cacheFirstWithUpdate(request, cacheName) {
|
||||
const cachedResponse = await caches.match(request);
|
||||
|
||||
if (cachedResponse) {
|
||||
// Return cached version immediately
|
||||
|
||||
// Background update if cache is old
|
||||
const cacheDate = new Date(cachedResponse.headers.get('date') || 0);
|
||||
const now = new Date();
|
||||
const age = now.getTime() - cacheDate.getTime();
|
||||
|
||||
if (age > CACHE_DURATIONS.static) {
|
||||
// Background update - don't await
|
||||
updateCacheInBackground(request, cacheName);
|
||||
}
|
||||
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
// Not in cache, fetch from network
|
||||
try {
|
||||
const networkResponse = await fetch(request);
|
||||
|
||||
if (networkResponse.ok) {
|
||||
const cache = await caches.open(cacheName);
|
||||
cache.put(request, networkResponse.clone());
|
||||
}
|
||||
|
||||
return networkResponse;
|
||||
} catch (error) {
|
||||
console.error('[ServiceWorker] Failed to fetch asset:', request.url, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Background cache update
|
||||
async function updateCacheInBackground(request, cacheName) {
|
||||
try {
|
||||
const networkResponse = await fetch(request);
|
||||
|
||||
if (networkResponse.ok) {
|
||||
const cache = await caches.open(cacheName);
|
||||
await cache.put(request, networkResponse);
|
||||
console.log('[ServiceWorker] Background cache update:', request.url);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('[ServiceWorker] Background update failed:', request.url, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle push subscription changes
|
||||
self.addEventListener('pushsubscriptionchange', function(event) {
|
||||
console.log('[ServiceWorker] Push subscription changed:', event);
|
||||
|
||||
// Re-subscribe to push notifications
|
||||
event.waitUntil(
|
||||
self.registration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: null // This should be set by your application
|
||||
})
|
||||
.then(function(newSubscription) {
|
||||
console.log('[ServiceWorker] New push subscription:', newSubscription);
|
||||
// Send new subscription to your server
|
||||
return updatePushSubscription(newSubscription);
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('[ServiceWorker] Failed to resubscribe to push:', error);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// Handle push notifications
|
||||
self.addEventListener('push', function(event) {
|
||||
console.log('[ServiceWorker] Push received:', event);
|
||||
console.log('[ServiceWorker] Event data available:', !!event.data);
|
||||
|
||||
if (event.data) {
|
||||
try {
|
||||
const dataText = event.data.text();
|
||||
console.log('[ServiceWorker] Raw push data:', dataText);
|
||||
|
||||
const data = event.data.json();
|
||||
console.log('[ServiceWorker] Push data (parsed):', data);
|
||||
|
||||
const options = {
|
||||
body: data.body,
|
||||
icon: data.icon || '/dashboard/assets/img/favicons/android-chrome-192x192.png',
|
||||
badge: data.badge || '/dashboard/assets/img/favicons/favicon-32x32.png',
|
||||
tag: data.tag || 'oneuptime-notification',
|
||||
requireInteraction: data.requireInteraction || false,
|
||||
actions: data.actions || [],
|
||||
data: data.data || {},
|
||||
silent: false,
|
||||
renotify: true,
|
||||
vibrate: [100, 50, 100],
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
console.log('[ServiceWorker] Showing notification with options:', options);
|
||||
|
||||
event.waitUntil(
|
||||
self.registration.showNotification(data.title, options)
|
||||
.then(() => {
|
||||
console.log('[ServiceWorker] Notification shown successfully');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('[ServiceWorker] Error showing notification:', error);
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('[ServiceWorker] Error parsing push data:', error);
|
||||
const rawData = event.data ? event.data.text() : 'No data';
|
||||
console.log('[ServiceWorker] Raw event data:', rawData);
|
||||
|
||||
// Show fallback notification
|
||||
event.waitUntil(
|
||||
self.registration.showNotification('OneUptime Notification', {
|
||||
body: 'You have a new notification from OneUptime',
|
||||
icon: '/dashboard/assets/img/favicons/android-chrome-192x192.png',
|
||||
tag: 'oneuptime-fallback',
|
||||
data: { url: '/dashboard' }
|
||||
})
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.log('[ServiceWorker] Push event received but no data');
|
||||
|
||||
// Show default notification
|
||||
event.waitUntil(
|
||||
self.registration.showNotification('OneUptime', {
|
||||
body: 'You have a new notification',
|
||||
icon: '/dashboard/assets/img/favicons/android-chrome-192x192.png',
|
||||
tag: 'oneuptime-default',
|
||||
data: { url: '/dashboard' }
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle notification clicks
|
||||
self.addEventListener('notificationclick', function(event) {
|
||||
console.log('[ServiceWorker] Notification clicked:', event.notification.tag);
|
||||
event.notification.close();
|
||||
|
||||
const clickAction = event.action;
|
||||
const notificationData = event.notification.data || {};
|
||||
|
||||
let targetUrl = '/dashboard';
|
||||
|
||||
if (clickAction && notificationData[clickAction]) {
|
||||
// Handle action button clicks
|
||||
targetUrl = notificationData[clickAction].url || targetUrl;
|
||||
} else {
|
||||
// Handle main notification click
|
||||
targetUrl = notificationData.url ||
|
||||
notificationData.clickAction ||
|
||||
notificationData.link ||
|
||||
targetUrl;
|
||||
}
|
||||
|
||||
event.waitUntil(
|
||||
clients.matchAll({ type: 'window', includeUncontrolled: true })
|
||||
.then(function(clientList) {
|
||||
// Check if there's already a OneUptime window open
|
||||
for (let i = 0; i < clientList.length; i++) {
|
||||
const client = clientList[i];
|
||||
const clientUrl = new URL(client.url);
|
||||
|
||||
if (clientUrl.origin === self.location.origin && 'focus' in client) {
|
||||
// Navigate to the target URL and focus the window
|
||||
return client.navigate(targetUrl)
|
||||
.then(() => client.focus());
|
||||
}
|
||||
}
|
||||
|
||||
// If no OneUptime window is open, open a new one
|
||||
if (clients.openWindow) {
|
||||
return clients.openWindow(targetUrl);
|
||||
}
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('[ServiceWorker] Error handling notification click:', error);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// Handle notification close events
|
||||
self.addEventListener('notificationclose', function(event) {
|
||||
console.log('[ServiceWorker] Notification closed:', event.notification.tag);
|
||||
});
|
||||
|
||||
// Handle background sync - removed offline functionality
|
||||
self.addEventListener('sync', function(event) {
|
||||
console.log('[ServiceWorker] Background sync:', event.tag);
|
||||
// Background sync events can still be handled but no offline caching
|
||||
});
|
||||
|
||||
// Handle messages from the main thread
|
||||
self.addEventListener('message', function(event) {
|
||||
console.log('[ServiceWorker] Message received:', event.data);
|
||||
|
||||
if (event.data && event.data.type === 'SKIP_WAITING') {
|
||||
self.skipWaiting();
|
||||
} else if (event.data && event.data.type === 'GET_VERSION') {
|
||||
event.ports[0].postMessage({ version: CACHE_VERSION });
|
||||
}
|
||||
});
|
||||
|
||||
// Helper function to update push subscription
|
||||
function updatePushSubscription(subscription) {
|
||||
return fetch('/api/push-subscription', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(subscription)
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('[ServiceWorker] Error updating push subscription:', error);
|
||||
});
|
||||
}
|
||||
|
||||
console.log('[ServiceWorker] OneUptime PWA Service Worker Ready');
|
||||
Loading…
Add table
Reference in a new issue