Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.d/1131-dashboard-upload-proxy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Changed
- (Dashboard) 헤더의 findings 파일 선택 컨트롤을 기존 `primary-action` 버튼으로 표시하고, 실제 파일 선택은 숨긴 네이티브 파일 입력이 계속 담당하도록 정리했습니다.
5 changes: 4 additions & 1 deletion scanner/dashboard/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@
<span class="logo"></span><span class="brand">AppGuardrail</span>
<span class="spacer"></span>
<span class="meta" id="src">no findings loaded</span>
<input type="file" id="file" accept="application/json,.json" aria-label="Upload findings file" style="margin-left:12px">
<input type="file" id="file" accept="application/json,.json" hidden>
<button type="button" id="header-browse-findings" class="primary-action" style="margin-left:12px">Upload findings file</button>
</header>
<p id="findings-summary" class="sr-only" role="status" aria-live="polite" aria-atomic="true"></p>
<main id="app" tabindex="-1"></main>
Expand Down Expand Up @@ -324,7 +325,9 @@ <h1>Dashboard</h1>
render();
}

const headerBrowseFindings = document.getElementById('header-browse-findings');
const fileInput = document.getElementById('file');
headerBrowseFindings.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', () => {
const selectedFile = fileInput.files?.[0];
fileInput.value = '';
Expand Down
2 changes: 1 addition & 1 deletion tests/test_dashboard_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_dashboard_rows_are_keyboard_accessible():
assert 'tabindex="0" role="button"' in html
assert 'title="View details for finding"' in html
assert "tbody tr:focus-visible" in html
assert "aria-label=\"Upload findings file\"" in html
assert ">Upload findings file</button>" in html
assert "aria-label=\"Search findings\"" in html
assert "aria-label=\"Filter by severity\"" in html
assert "tr.addEventListener('keydown'" in html
Expand Down
20 changes: 20 additions & 0 deletions tests/test_dashboard_upload_proxy_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Regression contract for the dashboard header findings-file picker proxy."""

from scanner.cli.appguardrail import dashboard_index_path


def test_header_upload_proxy_preserves_native_file_input_contract():
"""Visible button activation delegates to the hidden native picker boundary."""
html = dashboard_index_path().read_text(encoding="utf-8")

assert '<input type="file" id="file" accept="application/json,.json" hidden>' in html
assert (
'<button type="button" id="header-browse-findings" class="primary-action" '
'style="margin-left:12px">Upload findings file</button>' in html
)
assert "const headerBrowseFindings = document.getElementById('header-browse-findings');" in html
assert "const fileInput = document.getElementById('file');" in html
assert "headerBrowseFindings.addEventListener('click', () => fileInput.click());" in html
assert "const selectedFile = fileInput.files?.[0];" in html
assert "fileInput.value = '';" in html
assert "if(!selectedFile) return;" in html
Loading