Spaces:
Running
Running
| """Admin review console — list submissions, view review timeline, add reviews. | |
| Submissions are immutable. Each review is stored as its own file under | |
| ``reviews/<submission>/``; a submission can be reviewed many times by different | |
| people. The "current status" shown here is the most recent review's status. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import streamlit as st | |
| from lib.schema import VALID_STATUSES | |
| from lib.storage import ( | |
| ADMIN_PASSWORD, | |
| add_review, | |
| check_admin_password, | |
| hf_configured, | |
| list_submissions, | |
| ) | |
| st.set_page_config(page_title="TDB Intake — Admin", page_icon="🔍", layout="wide") | |
| STATUS_EMOJI = { | |
| "pending": "🟡", | |
| "reviewed": "🟢", | |
| "needs_fix": "🔴", | |
| } | |
| def status_badge(status: str) -> str: | |
| return f"{STATUS_EMOJI.get(status, '⚪')} {status}" | |
| # ------------- auth ------------------------------------------------------ | |
| if "admin_authed" not in st.session_state: | |
| st.session_state.admin_authed = False | |
| st.title("Admin — Review submissions") | |
| if not ADMIN_PASSWORD: | |
| st.warning("`ADMIN_PASSWORD` is not set on the server — admin is open to anyone.") | |
| st.session_state.admin_authed = True | |
| if not st.session_state.admin_authed: | |
| with st.form("auth"): | |
| pw = st.text_input("Admin password", type="password") | |
| if st.form_submit_button("Continue"): | |
| if check_admin_password(pw): | |
| st.session_state.admin_authed = True | |
| st.rerun() | |
| else: | |
| st.error("Wrong password.") | |
| st.stop() | |
| # ------------- load list ------------------------------------------------- | |
| if not hf_configured: | |
| st.info("ℹ️ Reading from `./data/` (local dev mode).") | |
| cols = st.columns([3, 1]) | |
| with cols[0]: | |
| status_filter = st.multiselect( | |
| "Filter by status", | |
| options=VALID_STATUSES, | |
| default=[], | |
| placeholder="Show all", | |
| ) | |
| with cols[1]: | |
| if st.button("Refresh", use_container_width=True): | |
| st.rerun() | |
| try: | |
| items = list_submissions() | |
| except Exception as e: | |
| st.error(f"Failed to list submissions: {e}") | |
| st.stop() | |
| if status_filter: | |
| items = [s for s in items if s["status"] in status_filter] | |
| st.caption(f"{len(items)} submission(s)") | |
| if not items: | |
| st.info("No submissions match this filter.") | |
| st.stop() | |
| # ------------- list display ---------------------------------------------- | |
| for s in items: | |
| n_reviews = s.get("review_count", 0) | |
| review_tag = f" · 💬 {n_reviews}" if n_reviews else " · no reviews yet" | |
| label = ( | |
| f"{STATUS_EMOJI.get(s['status'], '⚪')} " | |
| f"**{s['trial_id']}** — {s['username']} · " | |
| f"_{s['submittedAt']}_{review_tag}" | |
| ) | |
| with st.expander(label): | |
| meta_c1, meta_c2 = st.columns(2) | |
| with meta_c1: | |
| st.markdown( | |
| f"**Current status:** {status_badge(s.get('status', 'pending'))} \n" | |
| f"**Submitted:** {s.get('submittedAt', '')} \n" | |
| f"**Last reviewed:** {s.get('reviewedAt', '') or '—'}" | |
| ) | |
| with meta_c2: | |
| st.markdown( | |
| f"**File:** `{s.get('submissionId', '')}` \n" | |
| f"**Last reviewer:** {s.get('reviewer', '') or '—'}" | |
| ) | |
| # ---- Review timeline ----------------------------------------- | |
| reviews = s.get("reviews") or [] | |
| st.markdown(f"#### Review history ({len(reviews)})") | |
| if not reviews: | |
| st.caption("No reviews yet.") | |
| else: | |
| for rev in reversed(reviews): # newest first | |
| st.markdown( | |
| f"- {status_badge(rev.get('status', ''))} — " | |
| f"**{rev.get('reviewer') or 'anon'}** " | |
| f"· _{rev.get('at', '')}_" | |
| + (f" \n {rev.get('note')}" if rev.get("note") else "") | |
| ) | |
| # ---- Add a review -------------------------------------------- | |
| st.markdown("#### Add a review") | |
| with st.form(f"review_{s['submissionId']}"): | |
| new_status = st.radio( | |
| "Status", | |
| options=VALID_STATUSES, | |
| index=VALID_STATUSES.index(s.get("status", "pending")) | |
| if s.get("status") in VALID_STATUSES | |
| else 0, | |
| horizontal=True, | |
| ) | |
| rc1, rc2 = st.columns([1, 2]) | |
| with rc1: | |
| reviewer = st.text_input("Your name", placeholder="e.g., Dr. Smith") | |
| with rc2: | |
| note = st.text_input("Comment", placeholder="optional") | |
| if st.form_submit_button("Add review", type="primary"): | |
| if not reviewer.strip(): | |
| st.error("Please enter your name.") | |
| else: | |
| try: | |
| add_review( | |
| s["submissionId"], | |
| status=new_status, | |
| reviewer=reviewer.strip(), | |
| note=note.strip(), | |
| ) | |
| st.success("Review added.") | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Failed to add review: {e}") | |
| with st.expander("Raw submission JSON"): | |
| st.code(json.dumps(s.get("submission", {}), indent=2, ensure_ascii=False), language="json") | |