From 5241a192ee1bcf5f26e003a23eec80c2295593b8 Mon Sep 17 00:00:00 2001 From: doomedraven Date: Wed, 20 May 2026 06:32:44 +0000 Subject: [PATCH 01/27] hotkeys nativation for power users --- .prettierignore | 1 + web/static/js/cape-shortcuts.js | 119 ++++++++++++++++++++++++++++++++ web/templates/base.html | 45 ++++++++++++ web/templates/header.html | 7 +- 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 .prettierignore create mode 100644 web/static/js/cape-shortcuts.js diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000000..2d19fc766d9 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +*.html diff --git a/web/static/js/cape-shortcuts.js b/web/static/js/cape-shortcuts.js new file mode 100644 index 00000000000..656b6cf73bb --- /dev/null +++ b/web/static/js/cape-shortcuts.js @@ -0,0 +1,119 @@ +/** + * CAPEv2 Global Keyboard Shortcuts + * Enhances analyst workflow by providing keyboard navigation. + */ + +(function() { + 'use strict'; + + document.addEventListener('keydown', function(e) { + // Don't trigger if user is typing in an input or textarea + const activeElement = document.activeElement; + const isInput = activeElement.tagName === 'INPUT' || + activeElement.tagName === 'TEXTAREA' || + activeElement.isContentEditable; + + if (isInput && e.key !== 'Escape') { + return; + } + + // Global Key handlers + switch(e.key) { + case '/': + e.preventDefault(); + const globalSearch = document.getElementById('form_search'); + if (globalSearch) { + globalSearch.focus(); + globalSearch.select(); + } + break; + + case 'Escape': + if (isInput) { + activeElement.blur(); + } + // Close any open modals + $('.modal.show').modal('hide'); + break; + + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + if (e.altKey) { + e.preventDefault(); + const tabIndex = parseInt(e.key) - 1; + const tabs = $('#reportTabs .nav-link, #analysisTabs .nav-link'); + if (tabs[tabIndex]) { + tabs[tabIndex].click(); + } + } + break; + + case 'j': // Next Item + if (!isInput) navigateList(1); + break; + + case 'k': // Previous Item + if (!isInput) navigateList(-1); + break; + + case 'o': // Open/Expand + if (!isInput) { + const activeRow = $('.table-hover tbody tr.keyboard-active'); + if (activeRow.length) { + const link = activeRow.find('a').first(); + if (link.length) link[0].click(); + } + } + break; + + case '?': // Show help + if (!isInput) { + const helpModal = new bootstrap.Modal(document.getElementById('shortcutsHelpModal')); + helpModal.show(); + } + break; + } + }); + + /** + * Helper to navigate tables/lists via J/K + */ + function navigateList(direction) { + const rows = $('.table-hover tbody tr:visible, #diff-table tbody tr:visible'); + if (!rows.length) return; + + let currentIndex = rows.index($('.keyboard-active')); + let nextIndex = currentIndex + direction; + + if (currentIndex === -1 && direction === 1) nextIndex = 0; + if (nextIndex < 0) nextIndex = 0; + if (nextIndex >= rows.length) nextIndex = rows.length - 1; + + rows.removeClass('keyboard-active'); + const nextRow = $(rows[nextIndex]); + nextRow.addClass('keyboard-active'); + + // Scroll into view if needed + const rowTop = nextRow.offset().top; + const rowBottom = rowTop + nextRow.height(); + const winTop = $(window).scrollTop() + 100; // Header offset + const winBottom = $(window).scrollTop() + $(window).height(); + + if (rowTop < winTop || rowBottom > winBottom) { + $('html, body').animate({ + scrollTop: rowTop - 150 + }, 50); + } + } + + // Add visual feedback for keyboard navigation + const style = document.createElement('style'); + style.innerHTML = ` + .keyboard-active { + outline: 2px solid #3498db !important; + outline-offset: -2px; + background-color: rgba(52, 152, 219, 0.1) !important; + } + `; + document.head.appendChild(style); + +})(); diff --git a/web/templates/base.html b/web/templates/base.html index 68a60007927..c8b2bf0eadb 100644 --- a/web/templates/base.html +++ b/web/templates/base.html @@ -41,6 +41,7 @@ + +!-- Shortcuts Help Modal --> + {% block extra_scripts %}{% endblock %} diff --git a/web/templates/header.html b/web/templates/header.html index c3e7fdf7a1b..c14426f61f3 100644 --- a/web/templates/header.html +++ b/web/templates/header.html @@ -41,7 +41,12 @@ {% endif %} - + +
From 609a9497603a7fe496ea7d98cb645d3f7c0f8890 Mon Sep 17 00:00:00 2001 From: doomedraven Date: Wed, 20 May 2026 06:34:29 +0000 Subject: [PATCH 02/27] hotkeys nativation for power users --- web/templates/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/templates/base.html b/web/templates/base.html index c8b2bf0eadb..8c58a357a8e 100644 --- a/web/templates/base.html +++ b/web/templates/base.html @@ -49,7 +49,7 @@ $('[data-bs-toggle="popover"]').popover(); }) -!-- Shortcuts Help Modal --> +