$(document).ready(function () { function cleanupStaleModalState() { if (!document.querySelector('.modal.show')) { document.querySelectorAll('.modal-backdrop').forEach(function (backdrop) { backdrop.remove(); }); document.body.classList.remove('modal-open'); document.body.style.removeProperty('padding-right'); document.body.style.removeProperty('overflow'); } } function getNotificationBadge() { return document.getElementById('notification-badge'); } function updateNotificationBadge(count) { const badge = getNotificationBadge(); if (!badge) { return; } const safeCount = Math.max(0, parseInt(count || 0, 10)); badge.dataset.count = String(safeCount); badge.classList.toggle('d-none', safeCount === 0); } function incrementNotificationBadge() { const badge = getNotificationBadge(); if (!badge) { return; } const current = parseInt(badge.dataset.count || '0', 10); updateNotificationBadge(current + 1); } function markNotificationRead(notificationId) { if (!notificationId || !window.notificationsReadUrlTemplate) { return; } fetch(window.notificationsReadUrlTemplate.replace('__id__', String(notificationId)), { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'), 'Accept': 'application/json', }, keepalive: true, }) .then(function (response) { if (!response.ok) { return null; } return response.json(); }) .then(function (data) { if (data && typeof data.unread !== 'undefined') { updateNotificationBadge(data.unread); } }) .catch(function () { // noop }); } function appendWsPopup(notification) { const container = document.getElementById('ws-notification-container'); if (!container || !notification) { return; } const popup = document.createElement('div'); popup.className = 'ws-notification-popup'; popup.dataset.id = String(notification.id || ''); const safeTitle = notification.title || 'Уведомление'; const bodyHtml = notification.message_html || notification.message || ''; popup.innerHTML = '
' + '' + safeTitle + '' + '' + '
' + '
' + bodyHtml + '
'; const closeBtn = popup.querySelector('.ws-notification-close'); if (closeBtn) { closeBtn.addEventListener('click', function (event) { event.stopPropagation(); markNotificationRead(notification.id); popup.remove(); }); } container.appendChild(popup); } cleanupStaleModalState(); window.addEventListener('pageshow', cleanupStaleModalState); if ($('.main-alert').length) { setTimeout(function () { $('.main-alert').fadeTo(2000, 500).slideUp(500, function () { $('.main-alert').slideUp(500); }); }, 3000); } const user = localStorage.getItem('user'); if (user > 0) { const socket = new WebSocket(localStorage.getItem('socketAddress')); socket.onopen = function () { console.log('[WS] Connected. Listen messages for user ' + user); }; socket.onmessage = function (event) { const received = JSON.parse(event.data); if (parseInt(received.data.user_id, 10) !== parseInt(user, 10)) { return; } const action = received.data.action; if (action === 'persistent_notification') { incrementNotificationBadge(); appendWsPopup(received.data.notification); return; } if (action !== 'message') { return; } if (received.data.payload.download) { document.location.href = '/storage/export/' + received.data.payload.download; } if (received.data.payload.link) { document.location.href = received.data.payload.link; setTimeout(function () { document.location.reload(); }, 2000); } setTimeout(function () { if (received.data.payload.error) { $('.alerts').append(''); } else { $('.alerts').append(''); } setTimeout(function () { $('.main-alert2').fadeTo(2000, 500).slideUp(500, function () { $('.main-alert2').slideUp(500); }); }, 3000); }, 1000); }; socket.onclose = function (event) { if (event.wasClean) { console.log('[WS] Closed clear, code=' + event.code + ' reason=' + event.reason); } else { console.log('[WS] Connection lost', event); } }; socket.onerror = function (error) { console.log('[error]', error); }; } });