feat(review): inline file uploader instead of redirect home

When a user lands on Review without an upload, show a file uploader
on the page itself and auto-run the analyzer once a file is picked,
rather than bouncing them to the home page with a "Back to home"
button.

Auto-analyze is the right default here: the user is already on the
Review page, so they've implicitly committed to a scan. Stashing the
bytes in the same session-state keys the home page uses keeps the
rest of the flow (encoding picker, gate, tool pages) unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-16 19:57:01 +00:00
parent db5ec084da
commit fc6c22c6a7
2 changed files with 55 additions and 11 deletions

View File

@@ -286,15 +286,51 @@ st.caption(
"the rest before applying."
)
# Pre-flight: nothing to review without an upload.
# Pre-flight: if nothing has been uploaded yet, let the user upload
# directly from this page instead of bouncing them back to the home
# screen. Once a file is picked, we auto-run the analyzer (the user is
# already on the Review page — they've implicitly committed to a scan),
# stash the result, and rerun so the rest of the page picks it up.
findings: list[Finding] = st.session_state.get("home_findings") or []
upload_name = st.session_state.get("home_uploaded_name")
if not upload_name:
st.warning("No file uploaded. Go back to the home page and upload a CSV or Excel file first.")
if st.button("Back to home"):
st.switch_page("app.py")
st.stop()
st.info(
"Upload a CSV or Excel file to begin reviewing. The analyzer runs "
"locally and your data never leaves this computer."
)
review_upload = st.file_uploader(
"Choose a file",
type=["csv", "tsv", "xlsx", "xls"],
key="review_upload",
help="Drag-and-drop or browse for a CSV, TSV, or Excel file.",
)
if review_upload is None:
st.stop()
# New file → stash bytes + size + name, drop any stale state, then
# run the analyzer. The rerun at the bottom lets the rest of this
# page render with the upload in place.
same_file = (
st.session_state.get("home_uploaded_name") == review_upload.name
and st.session_state.get("home_uploaded_size") == review_upload.size
)
if not same_file:
st.session_state["home_uploaded_name"] = review_upload.name
st.session_state["home_uploaded_size"] = review_upload.size
st.session_state["home_uploaded_bytes"] = review_upload.getvalue()
st.session_state.pop("home_findings", None)
st.session_state.pop("home_skipped", None)
st.session_state.pop("review_decisions", None)
st.session_state.pop("normalization_result", None)
st.session_state.pop("normalization_for", None)
st.session_state.pop("encoding_override", None)
if st.session_state.get("home_findings") is None:
with st.spinner("Analyzing…"):
st.session_state["home_findings"] = _run_analysis_with_override(None)
st.session_state["home_skipped"] = False
st.rerun()
# ---- Encoding picker --------------------------------------------------------
#