From 3784ec7ca7e5e590d3b92c6d2c1c33172939728f Mon Sep 17 00:00:00 2001 From: chris Date: Wed, 11 Feb 2026 19:58:15 -0500 Subject: [PATCH] chore: version service worker cache --- Dockerfile | 4 ++++ public/js/main.js | 13 ++++++++++--- public/sw.js | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 79d8a3e..e62e7b1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,10 @@ RUN npm install --omit=dev # Copy all project files, including the 'public' directory, into the container COPY . . +# Bake a cache-busting version into the service worker +ARG APP_VERSION=dev +RUN sed -i "s/__APP_VERSION__/${APP_VERSION}/g" public/sw.js + # Make port 3000 available EXPOSE 3000 diff --git a/public/js/main.js b/public/js/main.js index 36d41d2..ee55c37 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -15,7 +15,8 @@ import { renderArchiveView, renderTimeOffHistoryView, updatePendingRequestsList, - renderEditTimeOffModal + renderEditTimeOffModal, + renderCalendarView } from './ui.js'; // --- STATE MANAGEMENT --- @@ -55,7 +56,7 @@ async function subscribeToNotifications() { applicationServerKey: urlBase64ToUint8Array(publicVapidKey) }); - const res = await apiCall(' /subscribe', 'POST', subscription); + const res = await apiCall('/subscribe', 'POST', subscription); // If the subscription is saved successfully, set a flag so we don't do it again if (res.success) { @@ -262,6 +263,9 @@ function handleAdminDashboardClick(e) { case 'view-notes-btn': handleViewNotesClick(); return; + case 'view-calendar-btn': + renderCalendarView(); + return; } if (target.classList.contains('approve-request-btn') || target.classList.contains('deny-request-btn')) { @@ -463,6 +467,9 @@ function setupTabbedInterface() { panel.classList.add('hidden'); }); document.getElementById(`tab-content-${tabTarget}`).classList.remove('hidden'); + if (tabTarget === 'calendar') { + renderCalendarView(); + } }); } @@ -483,4 +490,4 @@ document.addEventListener('visibilitychange', () => { } }); -initializeApp(); \ No newline at end of file +initializeApp(); diff --git a/public/sw.js b/public/sw.js index 986b130..9e31102 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1,6 +1,7 @@ -// public/sw.js - CORRECTED +// public/sw.js -const CACHE_NAME = 'timepulse-v1'; +const APP_VERSION = '__APP_VERSION__'; +const CACHE_NAME = `timepulse-${APP_VERSION}`; const filesToCache = [ '/', '/index.html', '/style/style.css', '/js/main.js', '/js/ui.js', '/js/api.js', '/js/utils.js', '/manifest.json', @@ -32,8 +33,33 @@ self.addEventListener('fetch', event => { if (event.request.method !== 'GET' || event.request.url.includes('/api/')) { return; } + + const url = new URL(event.request.url); + + if (event.request.mode === 'navigate' || url.pathname === '/' || url.pathname.endsWith('/index.html')) { + event.respondWith( + fetch(event.request) + .then(response => { + const responseClone = response.clone(); + caches.open(CACHE_NAME).then(cache => cache.put(event.request, responseClone)); + return response; + }) + .catch(() => caches.match(event.request)) + ); + return; + } + event.respondWith( - caches.match(event.request).then(response => response || fetch(event.request)) + caches.match(event.request).then(cached => { + const fetchPromise = fetch(event.request).then(response => { + if (response && response.ok) { + const responseClone = response.clone(); + caches.open(CACHE_NAME).then(cache => cache.put(event.request, responseClone)); + } + return response; + }); + return cached || fetchPromise; + }) ); }); @@ -51,4 +77,4 @@ self.addEventListener('push', e => { body: 'You have a new update.' }); } -}); \ No newline at end of file +});