File size: 4,203 Bytes
2795ce6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
// Create a notification container if it doesn't exist
function createNotificationContainer() {
let container = document.getElementById('notification-container');
if (!container) {
container = document.createElement('div');
container.id = 'notification-container';
container.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
max-width: 400px;
`;
document.body.appendChild(container);
}
return container;
}
// Show error notification
function showError(message) {
const container = createNotificationContainer();
// Create notification element
const notification = document.createElement('div');
notification.className = 'error-notification';
notification.style.cssText = `
background-color: #ff4444;
color: white;
padding: 15px;
margin-bottom: 10px;
border-radius: 4px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
position: relative;
animation: slideIn 0.3s ease-out;
`;
// Add close button
const closeButton = document.createElement('button');
closeButton.innerHTML = '×';
closeButton.style.cssText = `
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: white;
font-size: 20px;
cursor: pointer;
padding: 0 5px;
`;
// Add message
const messageText = document.createElement('div');
messageText.style.cssText = `
margin-right: 20px;
word-wrap: break-word;
`;
messageText.textContent = typeof message === 'object' ? message.message : message;
// Assemble notification
notification.appendChild(messageText);
notification.appendChild(closeButton);
// Add to container
container.appendChild(notification);
// Add close functionality
closeButton.onclick = () => {
notification.style.animation = 'slideOut 0.3s ease-out';
setTimeout(() => notification.remove(), 300);
};
// Auto-remove after 10 seconds
setTimeout(() => {
if (notification.parentNode) {
notification.style.animation = 'slideOut 0.3s ease-out';
setTimeout(() => notification.remove(), 300);
}
}, 10000);
}
// Add CSS animations
const style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes slideOut {
from { transform: translateX(0); opacity: 1; }
to { transform: translateX(100%); opacity: 0; }
}
`;
document.head.appendChild(style);
// Handle SSE notifications
function setupErrorNotifications() {
const eventSource = new EventSource('/notifications');
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
if (data.type === 'error') {
showError(data.message);
}
};
eventSource.onerror = function(error) {
console.error('EventSource failed:', error);
eventSource.close();
// Try to reconnect after 5 seconds
setTimeout(setupErrorNotifications, 5000);
};
}
// Handle AJAX errors
function handleAjaxError(error) {
let errorMessage = 'An error occurred';
if (error.response) {
try {
const data = error.response.data;
errorMessage = data.error || data.message || errorMessage;
} catch (e) {
errorMessage = error.response.statusText || errorMessage;
}
} else if (error.request) {
errorMessage = 'No response received from server';
} else {
errorMessage = error.message;
}
showError(errorMessage);
}
// Initialize error handling
document.addEventListener('DOMContentLoaded', function() {
setupErrorNotifications();
// Add global AJAX error handler
$(document).ajaxError(function(event, jqXHR, settings, error) {
handleAjaxError(error);
});
}); |