window.CockpitLive = (function () { var ws = null; var reconnectTimer = null; function startPolling(fn, intervalMs) { intervalMs = intervalMs || 30000; fn(); var id = setInterval(fn, intervalMs); return function () { clearInterval(id); }; } function eventFingerprint(data) { var ev = (data && data.events) || []; if (!ev.length) return ''; return ev.slice(0, 5).map(function (e) { return String(e.created_at || '') + '#' + String(e.agent_name || '') + '#' + String(e.title || e.event_type || ''); }).join('|'); } function connectFeed(onMessage) { if (typeof WebSocket === 'undefined') return function () {}; var proto = location.protocol === 'https:' ? 'wss:' : 'ws:'; var lastFp = ''; var booted = false; function connect() { try { ws = new WebSocket(proto + '//' + location.host + '/ws/feed'); ws.onmessage = function (ev) { try { var data = JSON.parse(ev.data); var fp = eventFingerprint(data); if (!booted) { booted = true; lastFp = fp; if (onMessage) onMessage(data, { reason: 'connect' }); return; } if (fp && fp !== lastFp) { lastFp = fp; if (onMessage) onMessage(data, { reason: 'events' }); } } catch (e) {} }; ws.onclose = function () { booted = false; lastFp = ''; reconnectTimer = setTimeout(connect, 5000); }; } catch (e) { reconnectTimer = setTimeout(connect, 5000); } } connect(); return function () { if (reconnectTimer) clearTimeout(reconnectTimer); if (ws) { try { ws.close(); } catch (e) {} ws = null; } }; } function updateLiveBadge(el, at) { if (!el) return; el.textContent = 'Live ยท ' + (at || new Date().toLocaleTimeString('nl-NL', { hour: '2-digit', minute: '2-digit' })); } function renderAgentFeed(container, events) { if (!container || !events) return; container.innerHTML = events.slice(0, 12).map(function (ev) { var t = (ev.created_at || '').substring(11, 16); return '
Nog geen events.
'; } return { startPolling: startPolling, connectFeed: connectFeed, updateLiveBadge: updateLiveBadge, renderAgentFeed: renderAgentFeed }; })();