Add connected technician tracking to dashboard
- Add ViewerInfo struct to track viewer name and connection time - Update session manager to track viewers with names - Update API to return viewer list for each session - Update dashboard to display "Mike Connected (3 min)" on machine bars - Update viewer.html to pass viewer_name parameter 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -673,6 +673,39 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Format duration since connection
|
||||
function formatDuration(connectedAt) {
|
||||
const now = new Date();
|
||||
const connected = new Date(connectedAt);
|
||||
const diffMs = now - connected;
|
||||
const diffMins = Math.floor(diffMs / 60000);
|
||||
const diffHours = Math.floor(diffMins / 60);
|
||||
|
||||
if (diffMins < 1) return 'just now';
|
||||
if (diffMins < 60) return diffMins + ' min';
|
||||
if (diffHours < 24) return diffHours + ' hr';
|
||||
return Math.floor(diffHours / 24) + ' day';
|
||||
}
|
||||
|
||||
// Format connected technicians display
|
||||
function formatViewers(viewers) {
|
||||
if (!viewers || viewers.length === 0) return '';
|
||||
|
||||
// Get names (filter out default "Technician" if there's a real name)
|
||||
const names = viewers.map(v => v.name || 'Technician');
|
||||
|
||||
// Find earliest connection for duration
|
||||
const earliest = viewers.reduce((min, v) => {
|
||||
const t = new Date(v.connected_at);
|
||||
return t < min ? t : min;
|
||||
}, new Date(viewers[0].connected_at));
|
||||
|
||||
const duration = formatDuration(earliest);
|
||||
const nameList = names.join(', ');
|
||||
|
||||
return nameList + ' Connected (' + duration + ')';
|
||||
}
|
||||
|
||||
function renderMachinesList() {
|
||||
const container = document.getElementById("machinesList");
|
||||
|
||||
@@ -697,13 +730,19 @@
|
||||
const isSelected = selectedMachine?.id === m.id;
|
||||
const statusColor = m.is_online ? 'hsl(142, 76%, 50%)' : 'hsl(0, 0%, 50%)';
|
||||
const statusText = m.is_online ? 'Online' : 'Offline';
|
||||
const viewersText = formatViewers(m.viewers);
|
||||
const viewersHtml = viewersText
|
||||
? '<div style="font-size: 11px; color: hsl(142, 76%, 50%); margin-left: auto; white-space: nowrap;">' + escapeHtml(viewersText) + '</div>'
|
||||
: '';
|
||||
|
||||
return '<div class="sidebar-item' + (isSelected ? ' active' : '') + '" onclick="selectMachine(\'' + m.id + '\')" style="margin-bottom: 8px; padding: 12px;">' +
|
||||
'<div style="display: flex; align-items: center; gap: 12px;">' +
|
||||
'<div style="width: 10px; height: 10px; border-radius: 50%; background: ' + statusColor + ';"></div>' +
|
||||
'<div>' +
|
||||
'<div style="display: flex; align-items: center; gap: 12px; width: 100%;">' +
|
||||
'<div style="width: 10px; height: 10px; border-radius: 50%; background: ' + statusColor + '; flex-shrink: 0;"></div>' +
|
||||
'<div style="flex: 1; min-width: 0;">' +
|
||||
'<div style="font-weight: 500;">' + (m.agent_name || m.agent_id.slice(0,8)) + '</div>' +
|
||||
'<div style="font-size: 12px; color: hsl(var(--muted-foreground));">' + statusText + ' • ' + started + '</div>' +
|
||||
'</div>' +
|
||||
viewersHtml +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}).join("") + '</div>';
|
||||
@@ -836,7 +875,8 @@
|
||||
}
|
||||
|
||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||
const wsUrl = `${protocol}//${window.location.host}/ws/viewer?session_id=${sessionId}`;
|
||||
const viewerName = user?.name || user?.email || "Technician";
|
||||
const wsUrl = `${protocol}//${window.location.host}/ws/viewer?session_id=${sessionId}&viewer_name=${encodeURIComponent(viewerName)}`;
|
||||
|
||||
console.log("Connecting chat to:", wsUrl);
|
||||
chatSocket = new WebSocket(wsUrl);
|
||||
|
||||
@@ -174,6 +174,10 @@
|
||||
window.close();
|
||||
}
|
||||
|
||||
// Get viewer name from localStorage (same as dashboard)
|
||||
const user = JSON.parse(localStorage.getItem('user') || 'null');
|
||||
const viewerName = user?.name || user?.email || 'Technician';
|
||||
|
||||
// State
|
||||
let ws = null;
|
||||
let canvas = document.getElementById('viewer-canvas');
|
||||
@@ -593,7 +597,7 @@
|
||||
|
||||
function connect() {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const wsUrl = `${protocol}//${window.location.host}/ws/viewer?session_id=${sessionId}`;
|
||||
const wsUrl = `${protocol}//${window.location.host}/ws/viewer?session_id=${sessionId}&viewer_name=${encodeURIComponent(viewerName)}`;
|
||||
|
||||
console.log('Connecting to:', wsUrl);
|
||||
updateStatus('connecting', 'Connecting...');
|
||||
|
||||
Reference in New Issue
Block a user