22
33from __future__ import annotations
44
5+ import json
56from collections .abc import AsyncIterator
67from contextlib import asynccontextmanager
7- from typing import TYPE_CHECKING , override
8+ from typing import TYPE_CHECKING , Any , override
89
910from channels .db import database_sync_to_async
1011from channels .generic .websocket import AsyncWebsocketConsumer
1112from django .urls import path
1213
13- from .models import Site
14+ from .models import Operation , Site
1415
1516if TYPE_CHECKING :
1617 from ..users .models import User
@@ -33,13 +34,65 @@ async def connect(self):
3334 async with self .close_on_error ():
3435 site_id = int (self .scope ["url_route" ]["kwargs" ]["site_id" ])
3536 site = await find_site (site_id , user )
37+
38+ # Listen for events for this site
3639 await self .channel_layer .group_add (
3740 site .channels_group_name (),
3841 self .channel_name ,
3942 )
4043
4144 await self .accept ()
42- await self .send (text_data = f'<p id="foo">site name: { site .name } </p>' )
45+ info = await self .gather_site_info (site )
46+ await self .send (text_data = f"<code id='site-info'>\n { json .dumps (info , indent = 4 )} </code>" )
47+
48+ @database_sync_to_async
49+ def gather_site_info (self , site : Site ) -> dict [str , Any ]:
50+ """Returns a dictionary with information about the site."""
51+ site .refresh_from_db ()
52+ info = {
53+ "name" : site .name ,
54+ "url" : site .sites_url ,
55+ "description" : site .description ,
56+ "purpose" : site .purpose ,
57+ "mode" : site .mode ,
58+ "users" : list (site .users .values_list ("username" , flat = True )),
59+ "is_being_served" : site .is_served ,
60+ }
61+
62+ if site .database is not None :
63+ # TODO
64+ pass
65+
66+ op = Operation .objects .filter (site = site ).first ()
67+ if op is not None :
68+ operation_info = {
69+ "type" : op .ty ,
70+ "created_time" : op .created_time .isoformat (),
71+ "started_time" : (
72+ op .started_time .isoformat () if op .started_time is not None else None
73+ ),
74+ "actions" : [],
75+ }
76+ for action in op .list_actions_in_order ():
77+ operation_info ["actions" ].append (
78+ {
79+ "slug" : action .slug ,
80+ "name" : action .name ,
81+ "started_time" : (
82+ action .started_time .isoformat ()
83+ if action .started_time is not None
84+ else None
85+ ),
86+ "result" : action .result ,
87+ "user_message" : action .user_message ,
88+ }
89+ )
90+ if self .scope ["user" ].is_superuser :
91+ operation_info ["actions" ][- 1 ]["message" ] = action .message
92+
93+ info ["operation" ] = operation_info
94+
95+ return info
4396
4497 @asynccontextmanager
4598 async def close_on_error (
0 commit comments