(data)
| 11716 | console.debug('Attack logs unchanged; skipping DOM update'); |
| 11717 | return attackLogsCache; |
| 11718 | } |
| 11719 | |
| 11720 | if (!response.ok) { |
| 11721 | throw new Error(`HTTP error! status: ${response.status}`); |
| 11722 | } |
| 11723 | |
| 11724 | const data = await response.json(); |
| 11725 | attackLogsCache = data; |
| 11726 | attackLogsETag = response.headers.get('ETag') || attackLogsETag; |
| 11727 | displayAttackLogs(data); |
| 11728 | return data; |
| 11729 | } catch (error) { |
| 11730 | console.error('Error loading attack logs:', error); |
| 11731 | |
| 11732 | if (!attackLogsCache) { |
| 11733 | document.getElementById('attack-logs-container').innerHTML = ` |
| 11734 | <div class="text-center text-red-400 py-8"> |
| 11735 | <svg class="w-12 h-12 mx-auto mb-3 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 11736 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path> |
| 11737 | </svg> |
| 11738 | <p>Error loading attack logs</p> |
| 11739 | <p class="text-sm text-gray-500 mt-2">${error.message}</p> |
| 11740 | </div> |
| 11741 | `; |
| 11742 | } |
| 11743 | |
| 11744 | return attackLogsCache; |
| 11745 | } finally { |
| 11746 | attackLogsInFlight = null; |
| 11747 | } |
| 11748 | })(); |
| 11749 | |
| 11750 | return attackLogsInFlight; |
| 11751 | } |
| 11752 | |
| 11753 | function filterAttackLogs(status) { |
| 11754 | currentAttackFilter = status; |
| 11755 | |
| 11756 | // Update filter button styles |
| 11757 | document.querySelectorAll('.attack-filter-btn').forEach(btn => { |
| 11758 | if (btn.getAttribute('data-filter') === status) { |
| 11759 | btn.classList.add('ring-2', 'ring-white'); |
| 11760 | } else { |
| 11761 | btn.classList.remove('ring-2', 'ring-white'); |
| 11762 | } |
| 11763 | }); |
| 11764 | |
| 11765 | // Re-display with filter |
| 11766 | if (attackLogsCache) { |
no test coverage detected