feat(planner): add widget layout saving and scratchpad note functionality
feat(notifications): implement real-time live sync for mail, Jira, and calendar updates fix(database): add new columns for widget layout and last check timestamps fix(schema): update users table schema to include new fields for widget layout and last checks feat(microsoft): enhance Microsoft integration with demo email data and inbox fetching feat(jira): add listener for live updates on Jira tickets
This commit is contained in:
+102
-2
@@ -408,13 +408,113 @@
|
||||
}
|
||||
};
|
||||
|
||||
// 7b. Real-time Live Sync (Mail, Jira & Agenda)
|
||||
let lastKnownMailId = localStorage.getItem('fociz_last_mail_id') || '';
|
||||
let lastKnownJiraKey = localStorage.getItem('fociz_last_jira_key') || '';
|
||||
let lastCalendarHash = '';
|
||||
let isLiveSyncRunning = false;
|
||||
let isInitialLiveSync = true;
|
||||
|
||||
async function checkLiveSync() {
|
||||
if (isLiveSyncRunning) return;
|
||||
isLiveSyncRunning = true;
|
||||
try {
|
||||
const url = `/api/live_sync.php?last_mail_id=${encodeURIComponent(lastKnownMailId)}&last_jira_key=${encodeURIComponent(lastKnownJiraKey)}&calendar_hash=${encodeURIComponent(lastCalendarHash)}`;
|
||||
const res = await fetch(url, { cache: 'no-store' });
|
||||
if (res.status === 401) return;
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
if (data && data.success) {
|
||||
// Update mail badge in navigatie
|
||||
const mailBadge = document.getElementById('navMailBadge');
|
||||
if (mailBadge && typeof data.mail?.unread_count !== 'undefined') {
|
||||
if (data.mail.unread_count > 0) {
|
||||
mailBadge.innerText = data.mail.unread_count;
|
||||
mailBadge.classList.remove('hidden');
|
||||
} else {
|
||||
mailBadge.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// E-mail melding
|
||||
if (!isInitialLiveSync && data.mail?.has_new && data.mail.new_mail) {
|
||||
const m = data.mail.new_mail;
|
||||
sendBrowserNotification(
|
||||
`✉️ Nieuwe mail: ${m.from_name}`,
|
||||
`${m.subject} • ${m.received_human || 'Zojuist'}`,
|
||||
m.web_link || '/mail.php',
|
||||
`fociz-mail-${m.id}`
|
||||
);
|
||||
}
|
||||
|
||||
// Jira ticket melding
|
||||
if (!isInitialLiveSync && data.jira?.has_new && data.jira.new_issue) {
|
||||
const j = data.jira.new_issue;
|
||||
sendBrowserNotification(
|
||||
`⚡ Nieuw Jira ticket: [${j.key}]`,
|
||||
`${j.summary} (${j.priority})`,
|
||||
j.url || '/jira.php',
|
||||
`fociz-jira-${j.key}`
|
||||
);
|
||||
}
|
||||
|
||||
// Dispatch custom event voor actieve pagina's
|
||||
if (data.mail?.has_new || (data.mail?.latest_id && data.mail.latest_id !== lastKnownMailId)) {
|
||||
window.dispatchEvent(new CustomEvent('fociz:mail-updated', { detail: data.mail }));
|
||||
}
|
||||
if (data.jira?.has_new || (data.jira?.newest_key && data.jira.newest_key !== lastKnownJiraKey)) {
|
||||
window.dispatchEvent(new CustomEvent('fociz:jira-updated', { detail: data.jira }));
|
||||
}
|
||||
if (data.calendar?.has_changes) {
|
||||
window.dispatchEvent(new CustomEvent('fociz:calendar-updated', { detail: data.calendar }));
|
||||
}
|
||||
|
||||
if (data.mail?.latest_id) {
|
||||
lastKnownMailId = data.mail.latest_id;
|
||||
localStorage.setItem('fociz_last_mail_id', lastKnownMailId);
|
||||
}
|
||||
if (data.jira?.newest_key) {
|
||||
lastKnownJiraKey = data.jira.newest_key;
|
||||
localStorage.setItem('fociz_last_jira_key', lastKnownJiraKey);
|
||||
}
|
||||
if (data.calendar?.hash) {
|
||||
lastCalendarHash = data.calendar.hash;
|
||||
}
|
||||
|
||||
isInitialLiveSync = false;
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
// Stil negeren bij netwerkvertraging
|
||||
} finally {
|
||||
isLiveSyncRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 10. Initialisatie
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
refreshEvents();
|
||||
// Polling interval elke 60 seconden
|
||||
checkLiveSync();
|
||||
|
||||
// Polling interval elke 60 seconden voor agenda evaluatie
|
||||
setInterval(refreshEvents, 60000);
|
||||
// Evaluatie interval elke 15 seconden
|
||||
// Evaluatie interval elke 15 seconden voor agenda popups
|
||||
setInterval(evaluateEvents, 15000);
|
||||
// Live sync interval elke 12 seconden voor instant mail, Jira & calendar updates
|
||||
setInterval(checkLiveSync, 12000);
|
||||
|
||||
window.addEventListener('focus', () => {
|
||||
checkLiveSync();
|
||||
refreshEvents();
|
||||
});
|
||||
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
checkLiveSync();
|
||||
refreshEvents();
|
||||
}
|
||||
});
|
||||
|
||||
updateDotStatus();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user