|
@@ -1,29 +1,67 @@
|
|
|
from fastapi import APIRouter
|
|
from fastapi import APIRouter
|
|
|
from fastapi.responses import HTMLResponse
|
|
from fastapi.responses import HTMLResponse
|
|
|
|
|
|
|
|
|
|
+from .exec_client import list_accounts
|
|
|
|
|
+
|
|
|
router = APIRouter(prefix="/dashboard", tags=["dashboard"])
|
|
router = APIRouter(prefix="/dashboard", tags=["dashboard"])
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/", response_class=HTMLResponse)
|
|
@router.get("/", response_class=HTMLResponse)
|
|
|
def dashboard_home():
|
|
def dashboard_home():
|
|
|
- return """<!doctype html>
|
|
|
|
|
|
|
+ accounts = list_accounts()
|
|
|
|
|
+
|
|
|
|
|
+ rows = "".join(
|
|
|
|
|
+ """
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td>{display_name}</td>
|
|
|
|
|
+ <td>{venue}</td>
|
|
|
|
|
+ <td>{venue_account_ref}</td>
|
|
|
|
|
+ <td>{description}</td>
|
|
|
|
|
+ <td>{enabled}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ """.strip().format(
|
|
|
|
|
+ display_name=(a.get("display_name") or "") if isinstance(a, dict) else "",
|
|
|
|
|
+ venue=(a.get("venue") or "") if isinstance(a, dict) else "",
|
|
|
|
|
+ venue_account_ref=(a.get("venue_account_ref") or "") if isinstance(a, dict) else "",
|
|
|
|
|
+ description=(a.get("description") or "") if isinstance(a, dict) else "",
|
|
|
|
|
+ enabled=("yes" if (a.get("enabled") if isinstance(a, dict) else False) else "no"),
|
|
|
|
|
+ )
|
|
|
|
|
+ for a in (accounts or [])
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ return f"""<!doctype html>
|
|
|
<html>
|
|
<html>
|
|
|
<head>
|
|
<head>
|
|
|
<meta charset=\"utf-8\" />
|
|
<meta charset=\"utf-8\" />
|
|
|
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />
|
|
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />
|
|
|
<title>Trader MCP Dashboard</title>
|
|
<title>Trader MCP Dashboard</title>
|
|
|
<style>
|
|
<style>
|
|
|
- body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial; margin: 2rem; }
|
|
|
|
|
- .card { max-width: 720px; padding: 1.25rem; border: 1px solid #e5e7eb; border-radius: 12px; }
|
|
|
|
|
- code { background: #f3f4f6; padding: 0.15rem 0.35rem; border-radius: 8px; }
|
|
|
|
|
- .muted { color: #6b7280; }
|
|
|
|
|
|
|
+ body {{ font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial; margin: 2rem; color: #111827; }}
|
|
|
|
|
+ .card {{ max-width: 980px; padding: 1.25rem; border: 1px solid #e5e7eb; border-radius: 12px; }}
|
|
|
|
|
+ .muted {{ color: #6b7280; }}
|
|
|
|
|
+ table {{ width: 100%; border-collapse: collapse; margin-top: 14px; }}
|
|
|
|
|
+ th, td {{ border-bottom: 1px solid #e5e7eb; padding: 10px 8px; text-align: left; vertical-align: top; }}
|
|
|
|
|
+ th {{ background: #f9fafb; }}
|
|
|
|
|
+ .pill {{ display:inline-block; padding:2px 10px; border-radius:999px; background:#f3f4f6; font-size: 0.9em; }}
|
|
|
</style>
|
|
</style>
|
|
|
</head>
|
|
</head>
|
|
|
<body>
|
|
<body>
|
|
|
<div class=\"card\">
|
|
<div class=\"card\">
|
|
|
<h1>Trader MCP Dashboard</h1>
|
|
<h1>Trader MCP Dashboard</h1>
|
|
|
- <p class=\"muted\">Scaffold page. Connect your trading widgets to MCP routes when you’re ready.</p>
|
|
|
|
|
- <p>Current: <code>GET /dashboard/</code></p>
|
|
|
|
|
|
|
+ <p class=\"muted\">exec-mcp accounts</p>
|
|
|
|
|
+
|
|
|
|
|
+ <table>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <th>name</th>
|
|
|
|
|
+ <th>venue</th>
|
|
|
|
|
+ <th>exchange account ref</th>
|
|
|
|
|
+ <th>description</th>
|
|
|
|
|
+ <th>enabled</th>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ {rows}
|
|
|
|
|
+ </table>
|
|
|
|
|
+
|
|
|
|
|
+ <p class=\"muted\" style=\"margin-top: 12px;\">Source: <span class=\"pill\">exec-mcp.list_accounts</span></p>
|
|
|
</div>
|
|
</div>
|
|
|
</body>
|
|
</body>
|
|
|
</html>"""
|
|
</html>"""
|