From c1f52e78fb0fe094aade4d38279c935f711981b9 Mon Sep 17 00:00:00 2001 From: Quinten Steenhuis Date: Wed, 7 Oct 2026 20:28:15 -0400 Subject: [PATCH 1/5] Keep upload navigation disabled until documents are ready --- efile_app/efile/static/js/upload-documents.js | 35 +++- .../templates/efile/upload_documents.html | 11 +- .../efile/tests/test_document_extractions.py | 22 +++ efile_app/efile/views/extraction_review.py | 2 +- efile_app/js-tests/upload-documents.test.js | 161 ++++++++++++++++++ 5 files changed, 219 insertions(+), 12 deletions(-) diff --git a/efile_app/efile/static/js/upload-documents.js b/efile_app/efile/static/js/upload-documents.js index c43473c9..af6f2b4c 100644 --- a/efile_app/efile/static/js/upload-documents.js +++ b/efile_app/efile/static/js/upload-documents.js @@ -33,6 +33,27 @@ const aiRememberChoice = document.getElementById("ai-remember-choice"); const selectedFiles = new Map(); let nextSelectionId = 0; + let uploading = false; + let analysisReady = form.dataset.hasLead === "true" && form.dataset.extractionPending !== "true"; + + function updateContinue() { + const disabled = uploading || !analysisReady; + continueButton.classList.toggle("disabled", disabled); + if (disabled) { + continueButton.setAttribute("aria-disabled", "true"); + continueButton.setAttribute("tabindex", "-1"); + continueButton.removeAttribute("href"); + } else { + continueButton.removeAttribute("aria-disabled"); + continueButton.removeAttribute("tabindex"); + continueButton.setAttribute("href", continueButton.dataset.continueUrl); + } + } + + continueButton.addEventListener("click", (event) => { + if (uploading || !analysisReady) event.preventDefault(); + }); + updateContinue(); // The "remember this" row is offered only after the filer changes the // setting, and only for the rest of this page load. Until then the account // preference is not this request's business, so it is left out of the post. @@ -169,6 +190,9 @@ form.addEventListener("submit", async (event) => { event.preventDefault(); + if (uploading) return; + uploading = true; + updateContinue(); errorBox.hidden = true; state.hidden = false; uploadButton.disabled = true; @@ -190,14 +214,16 @@ const result = await response.json(); if (!response.ok || !result.success) throw new Error(result.error || "Upload failed."); stateTitle.textContent = result.extraction_pending ? "Your documents are uploaded" : "Your documents are ready"; - let pendingDetail = "You can review your PDFs while we read your first file."; + let pendingDetail = "Please wait while we read your first file. You can continue when it is ready."; if (aiIsOff()) pendingDetail = "AI is off. We are looking for form and case numbers."; stateDetail.textContent = result.extraction_pending ? pendingDetail : "Review what we found before you continue."; window.setTimeout(() => window.location.reload(), 300); } catch (error) { - state.hidden = true; + uploading = false; + updateContinue(); + state.hidden = form.dataset.extractionPending !== "true" || analysisReady; errorBox.textContent = error.message; errorBox.hidden = false; uploadButton.disabled = false; @@ -250,9 +276,8 @@ stateDetail.textContent = result.total_pages > result.pages_analyzed ? `We read the first ${result.pages_analyzed} of ${result.total_pages} pages. ${nextPageNudge}` : nextPageNudge; - continueButton.classList.remove("disabled"); - continueButton.removeAttribute("aria-disabled"); - continueButton.removeAttribute("tabindex"); + analysisReady = true; + updateContinue(); const analyzingPill = document.querySelector(".status-pill--analyzing"); if (analyzingPill) { analyzingPill.classList.replace("status-pill--analyzing", "status-pill--ready"); diff --git a/efile_app/efile/templates/efile/upload_documents.html b/efile_app/efile/templates/efile/upload_documents.html index 30bcca7f..e562ffce 100644 --- a/efile_app/efile/templates/efile/upload_documents.html +++ b/efile_app/efile/templates/efile/upload_documents.html @@ -46,7 +46,9 @@ {% translate "Upload your court documents" %}