Spaces:
Sleeping
Sleeping
import gradio as gr, os, shutil, glob | |
from huggingface_hub import upload_file | |
# ---------- CONFIG ------------------------------------------------- | |
DATASET_REPO = "ruilongli/capture-data" | |
PENDING_DIR = "pending" | |
APPROVED_DIR = "approved" | |
ADMIN_KEY = os.getenv("ADMIN_KEY") # set in Space secrets | |
HF_TOKEN = os.getenv("HF_TOKEN") | |
for d in (PENDING_DIR, APPROVED_DIR): | |
os.makedirs(d, exist_ok=True) | |
# ------------------------------------------------------------------- | |
# -------- HELPERS -------------------------------------------------- | |
def list_pending(): # paths to files awaiting review | |
return sorted(glob.glob(f"{PENDING_DIR}/*")) | |
# -------- PUBLIC UPLOAD HANDLER ----------------------------------- | |
def handle_upload(tmp_path): | |
if not tmp_path: | |
return "❌ No file received." | |
fname = os.path.basename(tmp_path) | |
shutil.copy(tmp_path, os.path.join(PENDING_DIR, fname)) | |
return f"✅ `{fname}` uploaded for review!" | |
# -------- ADMIN ACTIONS ------------------------------------------- | |
def approve_files(_, selected_items): # no pw needed after login | |
if not selected_items: | |
return "⚠️ Nothing selected.", list_pending() | |
log_lines = [] | |
for item in selected_items: | |
file_path = item[0] if isinstance(item, (tuple, list)) else item | |
fname = os.path.basename(file_path) | |
upload_file( # 1) push to dataset repo | |
path_or_fileobj=file_path, | |
path_in_repo=f"images/{fname}", | |
repo_id=DATASET_REPO, | |
repo_type="dataset", | |
token=HF_TOKEN, | |
) | |
shutil.move(file_path, os.path.join(APPROVED_DIR, fname)) # 2) move | |
log_lines.append(f"✅ {fname}") | |
return "\n".join(log_lines), list_pending() | |
def refresh_files(_): # simply reload folder | |
return "🔁 List refreshed.", list_pending() | |
# -------- ADMIN LOGIN --------------------------------------------- | |
def admin_login(pw): | |
if pw != ADMIN_KEY: | |
return "🔒 Wrong key!", gr.update(visible=False) | |
return "✅ Logged in.", gr.update(visible=True) # show admin group | |
# -------------------- UI ------------------------------------------ | |
with gr.Blocks() as demo: | |
# -------- public uploader ---------- | |
gr.Markdown("## 🖼️ Anonymous Image Upload") | |
with gr.Row(): | |
up_comp = gr.File(type="filepath", file_types=["image"]) | |
up_msg = gr.Textbox(label="Status") | |
up_comp.upload(handle_upload, up_comp, up_msg) | |
# -------- admin login widgets ------- | |
with gr.Accordion("Admin login", open=False): | |
login_pw = gr.Textbox(label="Admin key", type="password") | |
login_btn = gr.Button("Log in") | |
login_msg = gr.Textbox(label="Login status", interactive=False) | |
# -------- admin panel (initially hidden) ----- | |
admin_panel = gr.Column(visible=False) | |
with admin_panel: | |
gr.Markdown("## 🔍 Admin review panel") | |
gallery = gr.Gallery( | |
label="Pending images", | |
value=list_pending(), | |
columns=[4], | |
height="auto", | |
interactive=False, | |
# selectable="multiple" | |
) | |
with gr.Row(): | |
approve_btn = gr.Button("Approve & publish", variant="primary") | |
refresh_btn = gr.Button("🔄 Refresh list", variant="secondary") | |
review_log = gr.Textbox(label="Log / Result", lines=6) | |
# ---- wiring ---- | |
login_btn.click(admin_login, login_pw, [login_msg, admin_panel]) | |
approve_btn.click( | |
fn=approve_files, | |
inputs=[login_pw, gallery], # pw unused but keeps signature | |
outputs=[review_log, gallery] | |
) | |
refresh_btn.click( | |
fn=refresh_files, | |
inputs=[login_pw], | |
outputs=[review_log, gallery] | |
) | |
demo.queue().launch() |