Skip to content
Open
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
4 changes: 4 additions & 0 deletions .jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
## 2026-07-13 - Async Table Actions UX
**Learning:** Adding explicit loading and disabled states to table action buttons that invoke asynchronous processes helps prevent redundant API calls and visually assures the user that their request is being handled.
**Action:** Consistently apply `disabled` state and `Loading...` text changes to inline table action buttons linked to async workflows, and carefully preserve underlying DOM structures with `Array.from(btn.childNodes)` during the loading cycle to avoid rendering regressions.

## 2026-10-05 - Focus Management for Dynamic Content
**Learning:** When dynamic content like a side panel or detailed view is loaded asynchronously upon user action, screen readers and keyboard users may not notice the new content if focus remains on the triggering button. Moving focus to the title of the newly loaded content drastically improves discoverability and logical flow.
**Action:** Always programmatically move focus to a newly rendered panel's title (`tabindex="-1"`) when it is opened via user interaction, such as clicking a 'Details' button.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

### Added

- **μž‘μ—… 상세 μ˜μ—­ μ ‘κ·Όμ„± κ°œμ„ **:
- μ„Έμ…˜ 기둝의 빈 μƒνƒœ λ©”μ‹œμ§€μ— 'μ—…λ‘œλ“œν•˜μ—¬ μ‹œμž‘ν•˜λΌ'λŠ” μ•ˆλ‚΄λ₯Ό μΆ”κ°€ν•˜μ—¬ μ‚¬μš©μž 행동을 μœ λ„ν–ˆμŠ΅λ‹ˆλ‹€.
- 'Details' λ²„νŠΌ 클릭 μ‹œ μž‘μ—… 상세 νŒ¨λ„μ΄ 열릴 λ•Œ, νŒ¨λ„μ˜ 제λͺ© μš”μ†Œ(`tabindex="-1"`)둜 포컀슀λ₯Ό μžλ™μœΌλ‘œ μ΄λ™μ‹œμΌœ 슀크린 리더 및 ν‚€λ³΄λ“œ μ‚¬μš©μžμ˜ 탐색 κ²½ν—˜μ„ κ°œμ„ ν–ˆμŠ΅λ‹ˆλ‹€.
- **UI UX κ°œμ„ **: 'Details' λ²„νŠΌ 클릭 μ‹œ, μž‘μ—… 상세 정보 λ‘œλ“œ 쀑에 μ‚¬μš©μžκ°€ λͺ…μ‹œμ μΈ λ‘œλ”© μƒνƒœλ₯Ό 확인할 수 μžˆλ„λ‘ 'Loading...' ν…μŠ€νŠΈμ™€ λΉ„ν™œμ„±ν™” μƒνƒœλ₯Ό ν‘œμ‹œν•˜λ„λ‘ μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.
- **κ΄€λ¦¬μžμš© 단건 μž‘μ—… μ‚­μ œ 및 μž¬μ‹œλ„ API μΆ”κ°€**
- νŠΉμ • λ³€ν™˜ μž‘μ—…μ„ μ‚­μ œν•  수 μžˆλŠ” `DELETE /api/v1/admin/convert/jobs/{jobId}` μ—”λ“œν¬μΈνŠΈλ₯Ό μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,13 +299,13 @@ private static String demoShellHtml() {
</thead>
<tbody id="history-body"></tbody>
</table>
<p class="empty-state" id="empty-history">No documents submitted in this session.</p>
<p class="empty-state" id="empty-history">No documents submitted in this session. Upload a document above to begin.</p>
</div>

<aside class="job-detail" id="job-detail" aria-labelledby="job-detail-title" hidden>
<div class="job-detail__header">
<div>
<h3 id="job-detail-title" class="job-detail__title">Job detail</h3>
<h3 id="job-detail-title" class="job-detail__title" tabindex="-1">Job detail</h3>
<p class="job-detail__caption" id="job-detail-caption">Select a document to inspect operational evidence.</p>
</div>
<button type="button" class="btn btn-secondary btn-compact" id="retry-job-btn" hidden>Retry dead-lettered job</button>
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/static/assets/viewer/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const el = {
recoveryLatestInspected: document.getElementById("recovery-latest-inspected"),
recoveryStatus: document.getElementById("recovery-status"),
jobDetail: document.getElementById("job-detail"),
jobDetailTitle: document.getElementById("job-detail-title"),
jobDetailCaption: document.getElementById("job-detail-caption"),
jobDetailBody: document.getElementById("job-detail-body"),
retryJobBtn: document.getElementById("retry-job-btn"),
Expand Down Expand Up @@ -190,6 +191,7 @@ function renderJobDetail(detail) {
addDetailRow("Artifact", detail.convertedResourcePath);

el.retryJobBtn.hidden = !detail.deadLettered;
el.jobDetailTitle.focus();
}

function isNeedsAction(job) {
Expand Down
Loading