diff --git a/admin_server.py b/admin_server.py index f72c406..4c3aa63 100644 --- a/admin_server.py +++ b/admin_server.py @@ -24,6 +24,7 @@ from typing import Optional from fastapi import FastAPI, HTTPException, Query, Request, UploadFile, File from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse, StreamingResponse +from fastapi.staticfiles import StaticFiles from pydantic import BaseModel from cantaloupe_sync import router as cantaloupe_router, create_sync_tables @@ -354,6 +355,20 @@ app.add_middleware( # Mount Cantaloupe sync routes app.include_router(cantaloupe_router) +# Serve admin frontend SPA (single index.html, no external assets needed) +from fastapi.responses import FileResponse + +FRONTEND_INDEX = Path(__file__).parent / "static" / "index.html" + + +@app.get("/") +@app.get("/{full_path:path}") +async def serve_frontend(full_path: str = ""): + """Serve the admin SPA — all routes return index.html.""" + if FRONTEND_INDEX.is_file(): + return FileResponse(str(FRONTEND_INDEX)) + return JSONResponse({"detail": "Frontend not found"}, status_code=404) + # ─── Auth Middleware ──────────────────────────────────────────────────────── diff --git a/static/index.html b/static/index.html index dcd7a06..07968b2 100644 --- a/static/index.html +++ b/static/index.html @@ -532,6 +532,62 @@ .sidebar .sidebar-header .sh-icon { font-size: 22px; } .main { margin-left: 56px; padding: 16px; max-width: calc(100vw - 56px); } } + + /* ═══════════════════════════════════════════════════════════════════════ + CANTALOUPE SYNC + ═══════════════════════════════════════════════════════════════════════ */ + .cs-diff-summary { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); + gap: 8px; + margin-bottom: 14px; + } + .cs-diff-badge { + background: var(--card2); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + padding: 12px; + text-align: center; + } + .cs-diff-badge .csd-val { font-size: 24px; font-weight: 800; } + .cs-diff-badge .csd-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text2); margin-top: 2px; } + .cs-diff-badge.add .csd-val { color: var(--green); } + .cs-diff-badge.chg .csd-val { color: var(--amber); } + .cs-diff-badge.rem .csd-val { color: var(--red); } + .cs-diff-badge.unc .csd-val { color: var(--text2); } + + .cs-batch-row { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 12px; + border-bottom: 1px solid rgba(255,255,255,0.04); + cursor: pointer; + transition: background 0.1s; + font-size: 13px; + } + .cs-batch-row:hover { background: rgba(255,255,255,0.03); } + .cs-batch-row .csb-status { width: 80px; flex-shrink: 0; } + .cs-batch-row .csb-time { width: 160px; flex-shrink: 0; color: var(--text2); } + .cs-batch-row .csb-rows { width: 80px; text-align: right; flex-shrink: 0; font-variant-numeric: tabular-nums; } + .cs-batch-row .csb-chevron { font-size: 11px; color: var(--text2); transition: transform 0.2s; flex-shrink: 0; } + .cs-batch-row.expanded .csb-chevron { transform: rotate(90deg); } + + .cs-batch-detail { + display: none; + padding: 0 12px 14px 36px; + border-bottom: 1px solid rgba(255,255,255,0.05); + } + .cs-batch-detail.open { display: block; } + + .cs-changes-table { width: 100%; border-collapse: collapse; font-size: 12px; margin-top: 8px; } + .cs-changes-table th { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border); color: var(--text2); font-size: 10px; text-transform: uppercase; letter-spacing: 0.03em; } + .cs-changes-table td { padding: 6px 8px; border-bottom: 1px solid rgba(255,255,255,0.03); vertical-align: middle; } + .cs-changes-table .cs-old { color: var(--red); max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + .cs-changes-table .cs-new { color: var(--green); max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + .cs-changes-table .cs-arrow { color: var(--text2); padding: 0 4px; } + + .cs-actions { display: flex; gap: 8px; margin-top: 12px; } @@ -581,6 +637,9 @@ + + + +