diff --git a/crm/templates/crm/add_prospect.html b/crm/templates/crm/add_prospect.html index 0c60407..bb94611 100644 --- a/crm/templates/crm/add_prospect.html +++ b/crm/templates/crm/add_prospect.html @@ -1,4 +1,6 @@ -{% extends "crm/base.html" %} {% block content %} +{% extends "crm/base.html" %} + +{% block content %}
diff --git a/sync/consumers.py b/sync/consumers.py index d2c8825..7b9c7d0 100644 --- a/sync/consumers.py +++ b/sync/consumers.py @@ -2,6 +2,9 @@ import json from asgiref.sync import async_to_sync from channels.generic.websocket import WebsocketConsumer +from channels.layers import get_channel_layer +from collections import defaultdict +import threading class UserConsumer(WebsocketConsumer): def connect(self): @@ -40,6 +43,41 @@ class UserConsumer(WebsocketConsumer): # Send message to WebSocket self.send(text_data=message) +class StatusConsumer(WebsocketConsumer): + # Class variable to track connections + connections = defaultdict(int) + connections_lock = threading.Lock() + + def connect(self): + self.accept() + with self.connections_lock: + StatusConsumer.connections[self.channel_name] = 1 + self.send_status_update() + + def disconnect(self, close_code): + with self.connections_lock: + StatusConsumer.connections.pop(self.channel_name, None) + self.send_status_update() + + def send_status_update(self): + channel_layer = get_channel_layer() + async_to_sync(channel_layer.group_send)( + "status_group", + { + "type": "status_message", + "message": { + "active_connections": len(StatusConsumer.connections), + "channel_layer_type": channel_layer.__class__.__name__ + } + } + ) + + def receive(self, text_data): + # Handle any incoming messages if needed + pass + + def status_message(self, event): + self.send(text_data=json.dumps(event["message"])) # class ChatConsumer(WebsocketConsumer): # def connect(self): diff --git a/sync/routing.py b/sync/routing.py index 3456399..3ee21fd 100644 --- a/sync/routing.py +++ b/sync/routing.py @@ -5,6 +5,7 @@ from . import consumers websocket_urlpatterns = [ re_path(r"ws/user/(?P[\w-]+)/$", consumers.UserConsumer.as_asgi()), + re_path(r'ws/status/$', consumers.StatusConsumer.as_asgi()), # re_path(r"ws/chat/$", consumers.ChatConsumer.as_asgi()), # re_path(r"ws/chat/(?P\w+)/$", consumers.ChatConsumer.as_asgi()), ] diff --git a/tournaments/templates/tournaments/admin/status.html b/tournaments/templates/tournaments/admin/status.html new file mode 100644 index 0000000..70897bd --- /dev/null +++ b/tournaments/templates/tournaments/admin/status.html @@ -0,0 +1,76 @@ + + + + + WebSocket Status + + + +
+

WebSocket Status

+
+ + Connecting... +
+
+

Active Connections: 0

+

Channel Layer Type: -

+

Last Updated: -

+
+
+ + + + diff --git a/tournaments/urls.py b/tournaments/urls.py index 5670262..21128bb 100644 --- a/tournaments/urls.py +++ b/tournaments/urls.py @@ -39,4 +39,5 @@ urlpatterns = [ path('utils/xls-to-csv/', views.xls_to_csv, name='xls-to-csv'), path('mail-test/', views.simple_form_view, name='mail-test'), path('admin/tournament-import/', views.tournament_import_view, name='tournament_import'), + path('admin/status/', views.status_page, name='status_page'), ] diff --git a/tournaments/views.py b/tournaments/views.py index 44ce649..1a35329 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -575,3 +575,6 @@ def get_file_data(zip_file, file_path): except json.JSONDecodeError as e: print(f"JSON Error for {file_path}: {str(e)}") raise Exception(f"Invalid JSON in file {file_path}") + +def status_page(request): + return render(request, 'tournaments/admin/status.html')