diff --git a/.env.example b/.env.example index 6ff6b38..1b20dec 100644 --- a/.env.example +++ b/.env.example @@ -24,7 +24,7 @@ SMS_ENABLED=false DATABASE_URL=sqlite:///./mcm.db # ── TUI Web-Modus (textual serve) ────────────────────────── -# Starten: .venv/bin/python -m textual serve --host 0.0.0.0 --port $WEB_PORT tui_standalone.py +# Starten: python serve_tui.py --host 0.0.0.0 --port $WEB_PORT WEB_PORT=8001 # ── Benutzer-Authentifizierung ────────────────────────────────────────────── diff --git a/README.md b/README.md index 59a3f3b..12894fa 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ DEFAULT_ADMIN_PASSWORD=admin .venv/bin/python main_api_only.py # TUI als Browser-App (Terminal 2) -.venv/bin/python -m textual serve --host 0.0.0.0 --port 8001 tui_standalone.py +python serve_tui.py ``` Dann im Browser öffnen: `http://:8001` diff --git a/requirements.txt b/requirements.txt index a40c190..ddc18fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,3 +14,4 @@ python-dotenv>=1.0.0 httpx>=0.27.0 python-jose[cryptography]>=3.3.0 bcrypt>=4.0.0 +textual-serve>=1.1.0 diff --git a/serve_tui.py b/serve_tui.py new file mode 100644 index 0000000..f5e34e0 --- /dev/null +++ b/serve_tui.py @@ -0,0 +1,41 @@ +"""MCM TUI Web-Server via textual-serve. + +Startet einen Web-Server, der die TUI pro Browser-Verbindung als Subprocess ausführt. +Voraussetzung: MCM API-Server muss bereits laufen (python main_api_only.py). + +Verwendung: + python serve_tui.py [--host 0.0.0.0] [--port 8001] +""" + +import asyncio +import sys + +from textual_serve.server import Server + +from config import settings + + +def main() -> None: + import argparse + + parser = argparse.ArgumentParser(description="MCM TUI Web-Server") + parser.add_argument("--host", default="0.0.0.0", help="Host (default: 0.0.0.0)") + parser.add_argument( + "--port", type=int, default=settings.web_port, help=f"Port (default: {settings.web_port})" + ) + args = parser.parse_args() + + # Pfad zum Python-Interpreter im venv, damit alle Pakete verfügbar sind + python = sys.executable + command = f"{python} tui_standalone.py" + + print(f"MCM TUI Web-Server startet auf http://{args.host}:{args.port}") + print(f"Subprocess-Befehl: {command}") + print("Ctrl+C zum Beenden.") + + server = Server(command=command, host=args.host, port=args.port, title="MCM – MultiCustomerMessenger") + asyncio.run(server.serve()) + + +if __name__ == "__main__": + main() diff --git a/tui_standalone.py b/tui_standalone.py index 4bf50cc..501ed16 100644 --- a/tui_standalone.py +++ b/tui_standalone.py @@ -1,20 +1,20 @@ -"""MCM TUI – Standalone Entry Point für textual serve. +"""MCM TUI – Standalone Entry Point. -Startet nur die TUI (kein API-Server, keine Channels). -Die TUI spricht via HTTP gegen den laufenden MCM-API-Server. +Wird von serve_tui.py per textual-serve als Subprocess pro Browser-Session gestartet. +Kann auch direkt im Terminal gestartet werden. Verwendung: - # API-Server muss bereits laufen: - python main_api_only.py + # Direkt im Terminal: + python tui_standalone.py - # TUI im Browser starten: - .venv/bin/python -m textual serve --host 0.0.0.0 --port 8001 tui_standalone.py - - # Dann im Browser öffnen: http://:8001 + # Als Browser-App via serve_tui.py: + python serve_tui.py """ from tui.app import MCMApp -# textual serve erwartet eine Klasse oder Factory-Funktion, -# keine bereits instanziierte App. +# Für textual serve (ältere Variante) – Klasse als Factory app = MCMApp + +if __name__ == "__main__": + MCMApp().run()