personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add JavaScript error handling to app system

Add comprehensive error handling infrastructure to the new app template
system, matching the functionality from the legacy base.html template.

Changes:
- Create convey/static/error-handler.js as standalone error handling module
- Captures window.error and unhandledrejection events
- Updates status icon to red (🔴) with red glow on any JS error
- Displays error log panel at bottom of viewport with error details
- Provides window.showError() for manual error display via modal
- HTML-escapes all error text for security

- Update convey/templates/app.html to include error handling
- Load error-handler.js FIRST before all other scripts to catch early errors
- Add error modal HTML structure for manual error display
- Add #error-log div for automatic error logging at bottom

- Update convey/static/app.css with error handling styles
- Add .status-icon.error style (red box-shadow glow)
- Add #error-log styles (fixed bottom panel, dark theme, monospace)

Error state takes precedence: status icon becomes red with glow when any
JS error occurs, regardless of WebSocket connection state. Error log shows
detailed messages: "❌ message @ file:line" for errors and "⚠️ Promise:
reason" for unhandled rejections.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

+112
+23
convey/static/app.css
··· 97 97 background: rgba(0,0,0,0.05); 98 98 } 99 99 100 + .facet-bar .status-icon.error { 101 + box-shadow: 0 0 4px 2px red; 102 + border-radius: 4px; 103 + } 104 + 100 105 /* Status Pane */ 101 106 .status-pane { 102 107 position: fixed; ··· 366 371 gap: 12px; 367 372 overflow: hidden; 368 373 } 374 + 375 + /* Error log display */ 376 + #error-log { 377 + display: none; 378 + position: fixed; 379 + bottom: 0; 380 + left: 0; 381 + right: 0; 382 + background: #111; 383 + color: #eee; 384 + padding: 1em; 385 + font: 12px monospace; 386 + max-height: 30vh; 387 + overflow-y: auto; 388 + border-top: 2px solid #ff3b30; 389 + z-index: 9998; 390 + box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.5); 391 + }
+75
convey/static/error-handler.js
··· 1 + /** 2 + * Error Handler for App System 3 + * Captures JavaScript errors and provides visual feedback 4 + * 5 + * Features: 6 + * - Catches window errors and unhandled promise rejections 7 + * - Updates status icon to red with red glow on error 8 + * - Displays error log at bottom of viewport 9 + * - Provides modal for manual error display via window.showError() 10 + */ 11 + 12 + (function(){ 13 + const statusIcon = document.querySelector('.facet-bar .status-icon'); 14 + const errorLog = document.getElementById('error-log'); 15 + const errorModal = document.getElementById('errorModal'); 16 + const errorMessage = document.getElementById('errorMessage'); 17 + const closeButton = errorModal ? errorModal.querySelector('.close') : null; 18 + 19 + // Escape HTML to prevent XSS 20 + function escapeHtml(text) { 21 + return String(text).replace(/</g, '&lt;').replace(/>/g, '&gt;'); 22 + } 23 + 24 + // Log error to bottom panel 25 + function logError(text) { 26 + if (errorLog) { 27 + errorLog.insertAdjacentHTML( 28 + 'beforeend', 29 + escapeHtml(text) + '<br>' 30 + ); 31 + errorLog.style.display = 'block'; 32 + } 33 + } 34 + 35 + // Mark status icon as error state (red with glow) 36 + function markError() { 37 + if (statusIcon) { 38 + statusIcon.textContent = '🔴'; 39 + statusIcon.classList.add('error'); 40 + } 41 + } 42 + 43 + // Global error handler 44 + window.addEventListener('error', (e) => { 45 + markError(); 46 + logError(`❌ ${e.message} @ ${e.filename}:${e.lineno}`); 47 + }); 48 + 49 + // Unhandled promise rejection handler 50 + window.addEventListener('unhandledrejection', (e) => { 51 + markError(); 52 + logError(`⚠️ Promise: ${e.reason}`); 53 + }); 54 + 55 + // Modal controls 56 + if (errorModal && closeButton && errorMessage) { 57 + // Provide global function for manual error display 58 + window.showError = (text) => { 59 + errorMessage.textContent = text; 60 + errorModal.style.display = 'block'; 61 + }; 62 + 63 + // Close button 64 + closeButton.onclick = () => { 65 + errorModal.style.display = 'none'; 66 + }; 67 + 68 + // Click outside to close 69 + window.addEventListener('click', (e) => { 70 + if (e.target === errorModal) { 71 + errorModal.style.display = 'none'; 72 + } 73 + }); 74 + } 75 + })();
+14
convey/templates/app.html
··· 7 7 <link rel="stylesheet" href="{{ url_for('review.static', filename='review.css') }}"> 8 8 <link rel="stylesheet" href="{{ url_for('review.static', filename='app.css') }}"> 9 9 10 + <!-- Error handling FIRST - catches all subsequent errors --> 11 + <script src="{{ url_for('review.static', filename='error-handler.js') }}"></script> 12 + 10 13 <!-- Embed facets data for immediate client-side access --> 11 14 <script> 12 15 window.facetsData = {{ facets|tojson|safe }}; ··· 313 316 margin-right: 0; 314 317 } 315 318 </style> 319 + 320 + <!-- Error Modal --> 321 + <div id="errorModal" class="modal"> 322 + <div class="modal-content"> 323 + <span class="close">&times;</span> 324 + <pre id="errorMessage"></pre> 325 + </div> 326 + </div> 327 + 328 + <!-- Error Log Display --> 329 + <div id="error-log"></div> 316 330 317 331 </body> 318 332 </html>