add real-time patient vital signs monitoring dashboard UI and backend integration
This commit is contained in:
@@ -210,6 +210,12 @@ def serve_dashboard_root():
|
|||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
|
|
||||||
|
from fastapi.responses import Response
|
||||||
|
@app.get("/favicon.ico", include_in_schema=False)
|
||||||
|
async def favicon():
|
||||||
|
return Response(status_code=204, media_type="image/x-icon")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# === WebSocket endpoint for live vitals ===
|
# === WebSocket endpoint for live vitals ===
|
||||||
@app.websocket("/ws/vitals")
|
@app.websocket("/ws/vitals")
|
||||||
|
|||||||
@@ -8,6 +8,17 @@
|
|||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;600;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🩺</text></svg>">
|
||||||
|
<script>
|
||||||
|
// Suppress browser extension message channel port errors inside telemetry embed
|
||||||
|
window.addEventListener('unhandledrejection', function(event) {
|
||||||
|
var msg = (event && event.reason && (event.reason.message || event.reason)) || '';
|
||||||
|
if (typeof msg === 'string' && msg.indexOf('A listener indicated an asynchronous response') !== -1) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* === CSS Reset & Base === */
|
/* === CSS Reset & Base === */
|
||||||
*, *::before, *::after {
|
*, *::before, *::after {
|
||||||
@@ -2801,6 +2812,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function stepContecMachineSweep(timestamp) {
|
function stepContecMachineSweep(timestamp) {
|
||||||
|
if (document.hidden) {
|
||||||
|
machLastFrameTime = timestamp;
|
||||||
|
requestAnimationFrame(stepContecMachineSweep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ctxMachEcg || !canvasMachEcg) {
|
if (!ctxMachEcg || !canvasMachEcg) {
|
||||||
requestAnimationFrame(stepContecMachineSweep);
|
requestAnimationFrame(stepContecMachineSweep);
|
||||||
return;
|
return;
|
||||||
@@ -4787,6 +4804,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function animateWaveforms() {
|
function animateWaveforms() {
|
||||||
|
if (isMinimal || document.hidden) {
|
||||||
|
requestAnimationFrame(animateWaveforms);
|
||||||
|
return;
|
||||||
|
}
|
||||||
waveformPhase += 0.05;
|
waveformPhase += 0.05;
|
||||||
|
|
||||||
// Generate idle waveforms for cards with no data
|
// Generate idle waveforms for cards with no data
|
||||||
|
|||||||
Reference in New Issue
Block a user