v27.5: Revert to legacy HTML/JS/CSS UI as primary interface

- lab_api.py: Flip serving priority — ui/ folder (legacy) served first, React dist/ only as fallback
- Legacy UI has full features: card images, mana costs, type grouping, collection filters, EDHREC recs, ratio dashboard, commander portraits, 3-column deck builder
- React SPA was causing blank pages and missing functionality
- Installer no longer builds or bundles React dist/
- All 7 pages work: Batch Sim, Collection, Deck Builder, Auto Gen, Simulator, Coach, Training
This commit is contained in:
KoalaTrapLord committed 2026-03-12 04:32:33 +00:00
1 parent f5dae81193
commit 5f606fee22
1 file changed
+8 -11
+8 -11
View File
@@ -8230,31 +8230,28 @@ async def ml_tournament_results():
# Static File Serving (React SPA) — MUST be after all API routes # Static File Serving (React SPA) — MUST be after all API routes
# ══════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════
# React SPA: serve from frontend/commander-ai-lab-ui/dist (built with Vite) # UI Serving: legacy HTML/JS/CSS pages (primary) or React SPA (fallback)
_spa_dir = Path(__file__).parent / "frontend" / "commander-ai-lab-ui" / "dist"
_legacy_ui_dir = Path(__file__).parent / "ui" _legacy_ui_dir = Path(__file__).parent / "ui"
_spa_dir = Path(__file__).parent / "frontend" / "commander-ai-lab-ui" / "dist"
if _spa_dir.exists(): if _legacy_ui_dir.exists():
# Serve static assets (JS, CSS, images) from the SPA dist folder # Primary: serve the proven multi-page HTML/JS/CSS UI
app.mount("/", StaticFiles(directory=str(_legacy_ui_dir), html=True), name="ui")
elif _spa_dir.exists():
# Fallback: React SPA (only if legacy ui/ folder is missing)
_spa_assets = _spa_dir / "assets" _spa_assets = _spa_dir / "assets"
if _spa_assets.exists(): if _spa_assets.exists():
app.mount("/assets", StaticFiles(directory=str(_spa_assets)), name="spa-assets") app.mount("/assets", StaticFiles(directory=str(_spa_assets)), name="spa-assets")
# SPA catch-all: serve index.html for all non-API routes (client-side routing)
@app.get("/{full_path:path}") @app.get("/{full_path:path}")
async def _spa_catchall(full_path: str): async def _spa_catchall(full_path: str):
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
# If the exact file exists in dist, serve it
requested_file = _spa_dir / full_path requested_file = _spa_dir / full_path
if full_path and requested_file.exists() and requested_file.is_file(): if full_path and requested_file.exists() and requested_file.is_file():
return FileResponse(str(requested_file)) return FileResponse(str(requested_file))
# Otherwise serve index.html (let React Router handle it)
return FileResponse(str(_spa_dir / "index.html")) return FileResponse(str(_spa_dir / "index.html"))
elif _legacy_ui_dir.exists():
# Fallback: legacy HTML files
app.mount("/", StaticFiles(directory=str(_legacy_ui_dir), html=True), name="ui")
# ══════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════
# Startup # Startup