d01228a21e
- gui/main.py: FastAPI app with Jinja2 templates and static files - gui/state.py: shared application state (runner, template env) - gui/services/pos_runner.py: abstracted command execution layer with subprocess, SSE streaming, and sudo support - gui/routes/: 8 route modules (dashboard, install, compose, network, vbox, system, media, ssh) - gui/templates/: Bulma-based layout with sidebar navigation + section templates for all routes - gui/static/css/style.css: dark theme styling - gui/requirements.txt: fastapi, uvicorn, jinja2, python-multipart - 1- Start_GUI.sh: entry point with sudo cache, pip install, uvicorn launch Architecture: routes delegate to pos_runner which shells out to actual pos-* scripts — no logic duplication. SSE streaming for real-time output (install, compose up/down/logs, network scan, media).
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
from fastapi import APIRouter, Form, Query, Request
|
|
from fastapi.responses import HTMLResponse, StreamingResponse
|
|
|
|
from gui.state import runner, templates
|
|
|
|
router = APIRouter(prefix="/network")
|
|
|
|
|
|
@router.get("", response_class=HTMLResponse)
|
|
async def network_page(request: Request):
|
|
return templates.TemplateResponse(
|
|
"network/index.html", {"request": request, "active": "network"}
|
|
)
|
|
|
|
|
|
@router.get("/ip", response_class=HTMLResponse)
|
|
async def network_ip(request: Request):
|
|
code, out, err = await runner.run("pos network ip")
|
|
return templates.TemplateResponse(
|
|
"network/ip.html",
|
|
{"request": request, "active": "network", "output": out or err, "code": code},
|
|
)
|
|
|
|
|
|
@router.post("/checkport", response_class=HTMLResponse)
|
|
async def network_checkport(request: Request, target: str = Form(...)):
|
|
code, out, err = await runner.run(f"pos network checkport {target}")
|
|
return templates.TemplateResponse(
|
|
"network/checkport.html",
|
|
{
|
|
"request": request,
|
|
"active": "network",
|
|
"output": out or err,
|
|
"code": code,
|
|
"target": target,
|
|
},
|
|
)
|
|
|
|
|
|
@router.get("/scan", response_class=HTMLResponse)
|
|
async def network_scan_page(request: Request):
|
|
return templates.TemplateResponse(
|
|
"network/scan.html", {"request": request, "active": "network"}
|
|
)
|
|
|
|
|
|
@router.post("/scan/stream")
|
|
async def network_scan_stream(
|
|
target: str = Form(...), full: bool = Form(False), retries: int = Form(1)
|
|
):
|
|
async def generate():
|
|
cmd = f"pos network scan {target}"
|
|
if full:
|
|
cmd += " --full"
|
|
if retries > 1:
|
|
cmd += f" --retries {retries}"
|
|
async for event in runner.stream(cmd):
|
|
yield f"event: {event['event']}\ndata: {event['data']}\n\n"
|
|
|
|
return StreamingResponse(generate(), media_type="text/event-stream")
|