Enhance service worker with update handling and improve task scheduling format

This commit is contained in:
2025-01-29 21:57:04 +01:00
parent 502938b8cf
commit a9dfb8d54d
3 changed files with 84 additions and 29 deletions

View File

@@ -3,6 +3,24 @@ if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js') navigator.serviceWorker.register('/service-worker.js')
.then(registration => { .then(registration => {
console.log('ServiceWorker registration successful with scope: ', registration.scope); console.log('ServiceWorker registration successful with scope: ', registration.scope);
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// New update available
console.log('New content is available; please refresh.');
if (confirm('New version available. Do you want to update?')) {
window.location.reload();
}
} else {
// Content is cached for offline use
console.log('Content is cached for offline use.');
}
}
};
};
}) })
.catch(error => { .catch(error => {
console.log('ServiceWorker registration failed: ', error); console.log('ServiceWorker registration failed: ', error);

View File

@@ -1,28 +1,51 @@
self.addEventListener('install', (event) => { const CACHE_NAME = 'org-todo-pwa-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/style.css',
'/app.js',
'/manifest.json'
];
self.addEventListener('install', event => {
event.waitUntil( event.waitUntil(
caches.open('task-manager-cache').then((cache) => { caches.open(CACHE_NAME)
return cache.addAll([ .then(cache => {
'/', return cache.addAll(urlsToCache);
'/index.html', })
'/style.css', );
'/app.js', self.skipWaiting(); // Force the waiting service worker to become the active service worker
'/manifest.json', });
'/icons/icon-192x192.png',
'/icons/icon-512x512.png' self.addEventListener('activate', event => {
]); event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== CACHE_NAME) {
return caches.delete(cacheName);
}
})
);
}) })
); );
self.clients.claim(); // Take control of all clients immediately
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
if (response) {
return response;
}
return fetch(event.request);
})
);
}); });
self.addEventListener('fetch', (event) => { self.addEventListener('message', event => {
if (event.request.url.includes('/get-tags') || event.request.url.includes('/save-tags')) { if (event.data === 'skipWaiting') {
// Bypass cache for tags endpoints self.skipWaiting();
event.respondWith(fetch(event.request));
} else {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
return cachedResponse || fetch(event.request);
})
);
} }
}); });

View File

@@ -15,16 +15,30 @@ if (!fs.existsSync(dataDir)) {
// Ensure the tags.json file exists // Ensure the tags.json file exists
const tagsFilePath = path.join(dataDir, 'tags.json'); const tagsFilePath = path.join(dataDir, 'tags.json');
if (!fs.existsSync(tagsFilePath)) { if (!fs.existsSync(tagsFilePath)) {
fs.writeFileSync(tagsFilePath, JSON.stringify([]));} fs.writeFileSync(tagsFilePath, JSON.stringify([]));
}
// Protect the /add-task endpoint with authentication // Protect the /add-task endpoint with authentication
router.post('/add-task', auth, async (req, res) => { router.post('/add-task', auth, async (req, res) => {
const { subject, description, scheduled } = req.body; const { subject, description, scheduled } = req.body;
const currentDateTime = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''); const currentDateTime = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
// Format the scheduled date and time for Org mode
const scheduledDate = new Date(scheduled);
const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
const dayName = dayNames[scheduledDate.getUTCDay()];
let formattedScheduled;
if (scheduledDate.getUTCHours() === 0 && scheduledDate.getUTCMinutes() === 0) {
// No time provided, format without time
formattedScheduled = `<${scheduledDate.getUTCFullYear()}-${String(scheduledDate.getUTCMonth() + 1).padStart(2, '0')}-${String(scheduledDate.getUTCDate()).padStart(2, '0')} ${dayName}>`;
} else {
// Time provided, format with time
formattedScheduled = `<${scheduledDate.getUTCFullYear()}-${String(scheduledDate.getUTCMonth() + 1).padStart(2, '0')}-${String(scheduledDate.getUTCDate()).padStart(2, '0')} ${dayName} ${String(scheduledDate.getUTCHours()).padStart(2, '0')}:${String(scheduledDate.getUTCMinutes()).padStart(2, '0')}>`;
}
let orgFormattedData = `* TODO ${subject} let orgFormattedData = `* TODO ${subject}
SCHEDULED: <${scheduled}> SCHEDULED: ${formattedScheduled}
:LOGBOOK: :LOGBOOK:
- State "TODO" from "TODO" [${currentDateTime}] - State "TODO" from "TODO" [${currentDateTime}]
:END: :END:
@@ -33,7 +47,7 @@ router.post('/add-task', auth, async (req, res) => {
if (description) { if (description) {
orgFormattedData = `* TODO ${subject} orgFormattedData = `* TODO ${subject}
${description} ${description}
SCHEDULED: <${scheduled}> SCHEDULED: ${formattedScheduled}
:LOGBOOK: :LOGBOOK:
- State "TODO" from "TODO" [${currentDateTime}] - State "TODO" from "TODO" [${currentDateTime}]
:END: :END:
@@ -43,10 +57,10 @@ router.post('/add-task', auth, async (req, res) => {
const filePath = path.join(dataDir, 'tasks.org'); const filePath = path.join(dataDir, 'tasks.org');
try { try {
await fs.promises.appendFile(filePath, orgFormattedData); await fs.promises.appendFile(filePath, orgFormattedData);
res.send({ message: 'Task added successfully!' }); res.json({ message: 'Task added successfully' });
} catch (err) { } catch (error) {
logger.error('Error writing to file:', err); logger.error('Error writing to tasks.org file:', error);
res.status(500).send('Error writing to file.'); res.status(500).json({ message: 'Error adding task' });
} }
}); });