Adds status page for websockets

sync
Laurent 10 months ago
parent ab1713b29e
commit ae51d0c5c8
  1. 4
      crm/templates/crm/add_prospect.html
  2. 38
      sync/consumers.py
  3. 1
      sync/routing.py
  4. 76
      tournaments/templates/tournaments/admin/status.html
  5. 1
      tournaments/urls.py
  6. 3
      tournaments/views.py

@ -1,4 +1,6 @@
{% extends "crm/base.html" %} {% block content %}
{% extends "crm/base.html" %}
{% block content %}
<div class="container padding-bottom">
<div class="grid-x padding-bottom">
<div class="cell medium-6 large-6 my-block bubble">

@ -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):

@ -5,6 +5,7 @@ from . import consumers
websocket_urlpatterns = [
re_path(r"ws/user/(?P<user_id>[\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<room_name>\w+)/$", consumers.ChatConsumer.as_asgi()),
]

@ -0,0 +1,76 @@
<!-- templates/status.html -->
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Status</title>
<style>
.status-card {
border: 1px solid #ddd;
padding: 20px;
margin: 20px;
border-radius: 8px;
max-width: 500px;
}
.status-indicator {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 10px;
}
.connected { background-color: #4CAF50; }
.disconnected { background-color: #f44336; }
</style>
</head>
<body>
<div class="status-card">
<h2>WebSocket Status</h2>
<div>
<span class="status-indicator" id="connection-indicator"></span>
<span id="connection-status">Connecting...</span>
</div>
<div>
<p>Active Connections: <span id="active-connections">0</span></p>
<p>Channel Layer Type: <span id="channel-layer-type">-</span></p>
<p>Last Updated: <span id="last-updated">-</span></p>
</div>
</div>
<script>
const statusSocket = new WebSocket(
'ws://' + window.location.host + '/ws/status/'
);
function updateConnectionStatus(connected) {
const indicator = document.getElementById('connection-indicator');
const status = document.getElementById('connection-status');
indicator.className = 'status-indicator ' + (connected ? 'connected' : 'disconnected');
status.textContent = connected ? 'Connected' : 'Disconnected';
}
statusSocket.onopen = function(e) {
updateConnectionStatus(true);
};
statusSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
document.getElementById('active-connections').textContent = data.active_connections;
document.getElementById('channel-layer-type').textContent = data.channel_layer_type;
document.getElementById('last-updated').textContent = new Date().toLocaleTimeString();
};
statusSocket.onclose = function(e) {
updateConnectionStatus(false);
// Try to reconnect every 5 seconds
setTimeout(function() {
window.location.reload();
}, 5000);
};
statusSocket.onerror = function(e) {
updateConnectionStatus(false);
};
</script>
</body>
</html>

@ -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'),
]

@ -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')

Loading…
Cancel
Save