diff --git a/learn_sql_model/api/websocket.py b/learn_sql_model/api/websocket.py index aed8f6d..a066176 100644 --- a/learn_sql_model/api/websocket.py +++ b/learn_sql_model/api/websocket.py @@ -101,14 +101,19 @@ async def websocket_endpoint_hero_echo( ): config = get_config() await websocket.accept() + last_heros = None try: with config.database.engine.connect() as con: while True: data = await websocket.receive_text() hero = HeroUpdate.parse_raw(data) - heros = con.execute("SELECT * FROM hero").fetchall() - heros = Heros.parse_obj({"heros": heros}) + # heros = con.execute("SELECT * FROM hero").fetchall() + # heros = Heros.parse_obj({"heros": heros}) + heros = Heros.list(session=session) + if heros != last_heros: + await manager.broadcast(heros.json(), "heros") + last_heros = heros hero.update(session=session) console.print(heros) await websocket.send_text(heros.json()) @@ -119,21 +124,28 @@ async def websocket_endpoint_hero_echo( print("connection closed") -@web_socket_router.websocket("/ws-hero-update") -async def websocket_endpoint_hero_update( +@web_socket_router.websocket("/ws-heros'") +async def websocket_endpoint_heros( websocket: WebSocket, session: Session = Depends(get_session), ): + await manager.connect(websocket, "heros") await websocket.accept() + try: while True: - data = await websocket.receive_text() - hero = HeroUpdate.parse_raw(data) - print(hero) - hero.update(session=session) - print("hero is updated") + ... + # data = await websocket.receive_text() + # hero = HeroUpdate.parse_raw(data) + # heros = con.execute("SELECT * FROM hero").fetchall() + # heros = Heros.parse_obj({"heros": heros}) + # hero.update(session=session) + # console.print(heros) + # await websocket.send_text(heros.json()) except WebSocketDisconnect: print("disconnected") + manager.disconnect(websocket, "heros") except ConnectionClosed: + manager.disconnect(websocket, "heros") print("connection closed") diff --git a/learn_sql_model/cli/app.py b/learn_sql_model/cli/app.py index 197b9e0..6a3dac3 100644 --- a/learn_sql_model/cli/app.py +++ b/learn_sql_model/cli/app.py @@ -4,6 +4,7 @@ from typer.main import get_group from learn_sql_model.cli.api import api_app from learn_sql_model.cli.config import config_app +from learn_sql_model.cli.dashboard import dashboard_app from learn_sql_model.cli.hero import hero_app from learn_sql_model.cli.model import model_app from learn_sql_model.game.game import game_app @@ -18,6 +19,7 @@ app.add_typer(model_app, name="model") app.add_typer(api_app, name="api") app.add_typer(hero_app, name="hero") app.add_typer(game_app, name="game") +app.add_typer(dashboard_app, name="dashboard") def version_callback(value: bool) -> None: diff --git a/learn_sql_model/cli/dashboard.py b/learn_sql_model/cli/dashboard.py new file mode 100644 index 0000000..f9d925e --- /dev/null +++ b/learn_sql_model/cli/dashboard.py @@ -0,0 +1,65 @@ +from textual.app import App, ComposeResult +from textual.containers import ScrollableContainer +from textual.widgets import Footer, Header, Static +import typer + +from learn_sql_model.cli.common import verbose_callback +from learn_sql_model.models.hero import Heros + +dashboard_app = typer.Typer() + + +@dashboard_app.callback() +def config( + verbose: bool = typer.Option( + False, + callback=verbose_callback, + help="show the log messages", + ), +): + "dashboard cli" + + +class HeroName(Static): + """A stopwatch widget.""" + + +class DashboardApp(App): + """A Textual app to manage stopwatches.""" + + BINDINGS = [("d", "toggle_dark", "Toggle dark mode")] + + def compose(self) -> ComposeResult: + """Create child widgets for the app.""" + yield Header() + yield Footer() + yield ScrollableContainer(*[HeroName(hero.name) for hero in Heros.list().heros]) + + @property + def ws(self): + def connect(): + self._ws = create_connection( + f"ws://{config.api_client.url.replace('https://', '')}/ws-heros" + ) + + if not hasattr(self, "_ws"): + connect() + if not self._ws.connected: + connect() + return self._ws + + def action_toggle_dark(self) -> None: + """An action to toggle dark mode.""" + self.dark = not self.dark + + +@dashboard_app.command() +def run( + verbose: bool = typer.Option( + False, + callback=verbose_callback, + help="show the log messages", + ), +): + app = DashboardApp() + app.run() diff --git a/learn_sql_model/models/hero.py b/learn_sql_model/models/hero.py index dac0f78..4b0544b 100644 --- a/learn_sql_model/models/hero.py +++ b/learn_sql_model/models/hero.py @@ -5,7 +5,7 @@ import httpx from pydantic import BaseModel from sqlmodel import Field, Relationship, SQLModel, Session, select -from learn_sql_model.config import config, get_config +from learn_sql_model.config import config from learn_sql_model.models.pet import Pet @@ -79,10 +79,11 @@ class Heros(BaseModel): return Heros(heros=heros) if session is None: - engine = get_config().database.engine - with Session(engine) as session: - heros = get_heros(session, where, offset, limit) - return heros + + r = httpx.get(f"{config.api_client.url}/heros/") + if r.status_code != 200: + raise RuntimeError(f"{r.status_code}:\n {r.text}") + return Heros.parse_obj(r.json()) return get_heros(session, where, offset, limit)