fix: restore archive completion notification polling
Track monthly archive generation by generated_archive_id and poll notifications until completed/failed (up to timeout) instead of short PDF polling only. This restores completed ZIP notifications for calendar archive actions when generation takes longer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -28,6 +28,9 @@ const DASHBOARD_FETCH_TTL_MS = 30_000; // 30 sekundi
|
|||||||
let dbPromise = null;
|
let dbPromise = null;
|
||||||
let syncListenerStarted = false;
|
let syncListenerStarted = false;
|
||||||
let isSyncInProgress = false;
|
let isSyncInProgress = false;
|
||||||
|
const archiveNotificationPollers = new Map();
|
||||||
|
const ARCHIVE_NOTIFICATION_POLL_INTERVAL_MS = 10_000;
|
||||||
|
const ARCHIVE_NOTIFICATION_POLL_TIMEOUT_MS = 15 * 60 * 1000;
|
||||||
|
|
||||||
function isBrowser() {
|
function isBrowser() {
|
||||||
return typeof window !== 'undefined';
|
return typeof window !== 'undefined';
|
||||||
@@ -866,6 +869,70 @@ function _schedulePdfNotificationPolling() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _findCompletedArchiveNotification(notifications, generatedArchiveId) {
|
||||||
|
if (!generatedArchiveId || !Array.isArray(notifications)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return notifications.find((notification) => {
|
||||||
|
const metadata = notification?.metadata || {};
|
||||||
|
return metadata.entity_type === 'fleet_archive'
|
||||||
|
&& String(metadata.generated_archive_id || '') === String(generatedArchiveId)
|
||||||
|
&& ['completed', 'failed'].includes(String(metadata.stage || ''));
|
||||||
|
}) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _clearArchiveNotificationPoller(generatedArchiveId) {
|
||||||
|
const key = String(generatedArchiveId || '');
|
||||||
|
const handles = archiveNotificationPollers.get(key);
|
||||||
|
if (!handles) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.clearInterval(handles.intervalId);
|
||||||
|
window.clearTimeout(handles.timeoutId);
|
||||||
|
archiveNotificationPollers.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _scheduleArchiveNotificationPolling(generatedArchiveId = null) {
|
||||||
|
if (!isBrowser()) return;
|
||||||
|
if (!generatedArchiveId) {
|
||||||
|
[5000, 20000, 60000].forEach((delay) => {
|
||||||
|
setTimeout(() => _refreshNotificationsAsync(), delay);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = String(generatedArchiveId);
|
||||||
|
if (archiveNotificationPollers.has(key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pollOnce = async () => {
|
||||||
|
try {
|
||||||
|
const notificationModule = await import('./notificationStore.js');
|
||||||
|
await notificationModule.fetchNotifications();
|
||||||
|
const resolvedNotification = _findCompletedArchiveNotification(
|
||||||
|
notificationModule.$notifications.get(),
|
||||||
|
key
|
||||||
|
);
|
||||||
|
if (resolvedNotification) {
|
||||||
|
_clearArchiveNotificationPoller(key);
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
// silent — korisnik će i dalje vidjeti toast ili ručno osvježiti notifikacije
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const intervalId = window.setInterval(() => {
|
||||||
|
void pollOnce();
|
||||||
|
}, ARCHIVE_NOTIFICATION_POLL_INTERVAL_MS);
|
||||||
|
const timeoutId = window.setTimeout(() => {
|
||||||
|
_clearArchiveNotificationPoller(key);
|
||||||
|
}, ARCHIVE_NOTIFICATION_POLL_TIMEOUT_MS);
|
||||||
|
|
||||||
|
archiveNotificationPollers.set(key, { intervalId, timeoutId });
|
||||||
|
void pollOnce();
|
||||||
|
}
|
||||||
|
|
||||||
export async function downloadWorkOrderPdf(workOrderId) {
|
export async function downloadWorkOrderPdf(workOrderId) {
|
||||||
if (!workOrderId) {
|
if (!workOrderId) {
|
||||||
throw new Error('Work order ID je obavezan.');
|
throw new Error('Work order ID je obavezan.');
|
||||||
@@ -1030,7 +1097,7 @@ export async function downloadMonthlyServiceTasksArchive(year, month) {
|
|||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
showToast('ZIP arhiva servisnih taskova se generira u pozadini. Preuzimanje je dostupno kroz notifikaciju.', 'info');
|
showToast('ZIP arhiva servisnih taskova se generira u pozadini. Preuzimanje je dostupno kroz notifikaciju.', 'info');
|
||||||
_schedulePdfNotificationPolling();
|
_scheduleArchiveNotificationPolling(payload?.generated_archive_id || null);
|
||||||
return payload;
|
return payload;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showToast(err?.message || 'Pokretanje generiranja ZIP arhive servisnih taskova nije uspjelo.', 'error');
|
showToast(err?.message || 'Pokretanje generiranja ZIP arhive servisnih taskova nije uspjelo.', 'error');
|
||||||
@@ -1047,7 +1114,7 @@ export async function downloadMonthlyWorkOrdersArchive(year, month) {
|
|||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
showToast('ZIP arhiva putnih naloga se generira u pozadini. Preuzimanje je dostupno kroz notifikaciju.', 'info');
|
showToast('ZIP arhiva putnih naloga se generira u pozadini. Preuzimanje je dostupno kroz notifikaciju.', 'info');
|
||||||
_schedulePdfNotificationPolling();
|
_scheduleArchiveNotificationPolling(payload?.generated_archive_id || null);
|
||||||
return payload;
|
return payload;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showToast(err?.message || 'Pokretanje generiranja ZIP arhive putnih naloga nije uspjelo.', 'error');
|
showToast(err?.message || 'Pokretanje generiranja ZIP arhive putnih naloga nije uspjelo.', 'error');
|
||||||
|
|||||||
Reference in New Issue
Block a user