Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>ChickSense</title> | |
| <meta name="description" content="Automatic Health and Welfare Monitoring System for Chickens" /> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://rsms.me/inter/inter.css" /> | |
| <link rel="stylesheet" href="/static/css/style.css"> | |
| </head> | |
| <body class="p-4 lg:p-5"> | |
| <div class="max-w-screen-2x1 mx-auto"> | |
| <header class="flex flex-col md:flex-row justify-between items-start md:items-center mb-4 gap-3"> | |
| <div class="flex items-center gap-3"> | |
| <div class="w-12 h-12 bg-amber-100 rounded-lg flex items-center justify-center border border-amber-200" aria-hidden="true"> | |
| <img src="/static/assets/logo-.jpeg" alt="ChickSense Logo" class="rounded-lg"> | |
| </div> | |
| <div> | |
| <h1 class="text-xl md:text-2xl font-bold text-slate-800">ChickSense Dashboard</h1> | |
| <p id="datetime" class="text-xs md:text-sm text-slate-500" aria-live="polite">Loading Time...</p> | |
| </div> | |
| </div> | |
| </header> | |
| <main class="grid grid-cols-1 lg:grid-cols-12 gap-4"> | |
| <section class="lg:col-span-9 flex flex-col gap-4" aria-label="Video streams and controls"> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4" role="region"> | |
| <div class="card relative"> | |
| <div class="p-2"> | |
| <div class="aspect-video bg-slate-800 rounded-md"> | |
| <canvas id="video-canvas-0" class="w-full h-full rounded-md"></canvas> | |
| </div> | |
| <div class="cam-badge">CAM 1</div> | |
| </div> | |
| </div> | |
| <div class="card relative"> | |
| <div class="p-2"> | |
| <div class="aspect-video bg-slate-800 rounded-md"> | |
| <canvas id="video-canvas-1" class="w-full h-full rounded-md"></canvas> | |
| </div> | |
| <div class="cam-badge">CAM 2</div> | |
| </div> | |
| </div> | |
| <div class="card relative"> | |
| <div class="p-2"> | |
| <div class="aspect-video bg-slate-800 rounded-md"> | |
| <canvas id="video-canvas-2" class="w-full h-full rounded-md"></canvas> | |
| </div> | |
| <div class="cam-badge">CAM 3</div> | |
| </div> | |
| </div> | |
| <div class="card relative"> | |
| <div class="p-2"> | |
| <div class="aspect-video bg-slate-800 rounded-md"> | |
| <canvas id="video-canvas-3" class="w-full h-full rounded-md"></canvas> | |
| </div> | |
| <div class="cam-badge">CAM 4</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <div class="card" role="region"> | |
| <div class="card-header flex items-center justify-between"> | |
| <div class="flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-slate-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M6 13.5V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m12-3V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m-6-9V3.75m0 3.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 9.75V10.5" /> | |
| </svg> | |
| <h3 class="font-semibold text-slate-700 text-sm">View Controls</h3> | |
| </div> | |
| <button id="settings-button" title="Double-click to change camera URLs" class="p-1 text-slate-500 hover:text-blue-600 hover:bg-slate-300 rounded-md transition-colors"> | |
| <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <circle cx="12" cy="12" r="3"></circle> | |
| <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> | |
| </svg> | |
| </button> | |
| </div> | |
| <div id="toggle-controls" class="p-3 grid grid-cols-3 gap-3"> | |
| <button id="toggle-detected" data-control="show_detected" class="control-button flex items-center justify-center gap-2 p-2.5 rounded-lg text-xs md:text-sm font-medium" aria-pressed="true"> | |
| <svg class="w-6 h-6 icon-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"/> | |
| </svg> | |
| <svg class="w-6 h-6 icon-solid" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> | |
| <path fill-rule="evenodd" d="M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z" clip-rule="evenodd"/> | |
| </svg> | |
| <span>Detection</span> | |
| </button> | |
| </button> | |
| <button id="toggle-density" data-control="show_density" class="control-button flex items-center justify-center gap-2 p-2.5 rounded-lg text-xs md:text-sm font-medium" aria-pressed="false"> | |
| <svg class="w-6 h-6 icon-outline" xmlns="http://www.w3.org/2000/svg" | |
| viewBox="0 0 512 512" fill="none" stroke="currentColor" stroke-width="24"> | |
| <circle cx="256" cy="256" r="240"/> <circle cx="220" cy="120" r="64"/> <circle cx="356" cy="92" r="34"/> <circle cx="420" cy="160" r="26"/> <circle cx="120" cy="100" r="28"/> <circle cx="104" cy="196" r="44"/> <circle cx="208" cy="240" r="28"/> | |
| <circle cx="320" cy="236" r="44"/> <circle cx="420" cy="236" r="52"/> <circle cx="180" cy="372" r="88"/> <circle cx="300" cy="372" r="40"/> <circle cx="408" cy="372" r="52"/> | |
| <circle cx="272" cy="460" r="28"/> <circle cx="88" cy="288" r="20"/> | |
| </svg> | |
| <svg class="w-6 h-6 icon-solid" xmlns="http://www.w3.org/2000/svg" | |
| viewBox="0 0 512 512" fill="none" stroke="currentColor" stroke-width="24"> | |
| <circle cx="256" cy="256" r="240"/> <circle cx="220" cy="120" r="64"/> <circle cx="356" cy="92" r="34"/> <circle cx="420" cy="160" r="26"/> <circle cx="120" cy="100" r="28"/> <circle cx="104" cy="196" r="44"/> <circle cx="208" cy="240" r="28"/> | |
| <circle cx="320" cy="236" r="44"/> <circle cx="420" cy="236" r="52"/> <circle cx="180" cy="372" r="88"/> <circle cx="300" cy="372" r="40"/> <circle cx="408" cy="372" r="52"/> | |
| <circle cx="272" cy="460" r="28"/> <circle cx="88" cy="288" r="20"/> | |
| </svg> | |
| <span>Density</span> | |
| </button> | |
| <button id="toggle-inactive" data-control="show_inactive" class="control-button flex items-center justify-center gap-2 p-2.5 rounded-lg text-xs md:text-sm font-medium" aria-pressed="false"> | |
| <svg class="w-6 h-6 icon-outline" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z"/> | |
| </svg> | |
| <svg class="w-6 h-6 icon-solid" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"> | |
| <path fill-rule="evenodd" d="M12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75S17.385 2.25 12 2.25zM12.75 6a.75.75 0 00-1.5 0v6c0 .414.336.75.75.75h4.5a.75.75 0 000-1.5h-3.75V6z" clip-rule="evenodd"/> | |
| </svg> | |
| <span>Inactivity</span> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="card" role="region"> | |
| <div class="card-header flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-slate-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z" /> | |
| </svg> | |
| <h3 class="font-semibold text-slate-700 text-sm">System Log</h3> | |
| </div> | |
| <div id="system-log" class="p-4 text-xs text-slate-500 space-y-2 h-28 overflow-y-auto" role="log" aria-live="polite"></div> | |
| </div> | |
| </div> | |
| </section> | |
| <aside class="lg:col-span-3 flex flex-col gap-4" aria-label="Analysis and export panels"> | |
| <div class="card" role="region"> | |
| <div class="card-header flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-blue-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 010 3.75H5.625a1.875 1.875 0 010-3.75z" /> | |
| </svg> | |
| <h3 class="font-semibold text-slate-700 text-sm">Analysis Summary</h3> | |
| </div> | |
| <div class="p-4 space-y-3 text-sm"> | |
| <div class="flex items-center gap-3 p-2.5 bg-slate-50 rounded-lg"> | |
| <div class="w-9 h-9 bg-blue-100 text-blue-600 rounded-md flex items-center justify-center flex-shrink-0"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" /> | |
| </svg> | |
| </div> | |
| <div> | |
| <p class="text-slate-500 text-xs font-medium">Total Detected</p> | |
| <p id="detected-count" class="text-lg font-bold text-slate-800">0</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center gap-3 p-2.5 bg-slate-50 rounded-lg"> | |
| <div class="w-9 h-9 bg-amber-100 text-amber-600 rounded-md flex items-center justify-center flex-shrink-0"> | |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="none" stroke="currentColor" stroke-width="24"> | |
| <circle cx="256" cy="256" r="240"/> <circle cx="220" cy="120" r="64"/> <circle cx="356" cy="92" r="34"/> <circle cx="420" cy="160" r="26"/> <circle cx="120" cy="100" r="28"/> <circle cx="104" cy="196" r="44"/> | |
| <circle cx="208" cy="240" r="28"/> <circle cx="320" cy="236" r="44"/> <circle cx="420" cy="236" r="52"/> <circle cx="180" cy="372" r="88"/> <circle cx="300" cy="372" r="40"/> <circle cx="408" cy="372" r="52"/> | |
| <circle cx="272" cy="460" r="28"/> <circle cx="88" cy="288" r="20"/> | |
| </svg> | |
| </div> | |
| <div> | |
| <p class="text-slate-500 text-xs font-medium">Density Clusters</p> | |
| <p id="density-count" class="text-lg font-bold text-slate-800">0</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center gap-3 p-2.5 bg-slate-50 rounded-lg"> | |
| <div class="w-9 h-9 bg-red-100 text-red-600 rounded-md flex items-center justify-center flex-shrink-0"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" /> | |
| </svg> | |
| </div> | |
| <div> | |
| <p class="text-slate-500 text-xs font-medium">Inactive Chickens</p> | |
| <p id="inactive-count" class="text-lg font-bold text-slate-800">0</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card" role="region"> | |
| <div class="card-header flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-green-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M19.114 5.636a9 9 0 010 12.728M16.463 8.288a5.25 5.25 0 010 7.424M6.75 8.25l4.72-4.72a.75.75 0 011.28.53v15.88a.75.75 0 01-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.01 9.01 0 012.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75z" /> | |
| </svg> | |
| <h3 class="font-semibold text-slate-700 text-sm">Vocalization Analysis</h3> | |
| </div> | |
| <div id="vocalization-content" class="p-4"> | |
| </div> | |
| </div> | |
| <div class="card" role="region"> | |
| <div class="card-header flex items-center gap-2"> | |
| <svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-slate-600" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" /> | |
| </svg> | |
| <h3 class="font-semibold text-slate-700 text-sm">Export Metric Data (CSV)</h3> | |
| </div> | |
| <div class="p-4"> | |
| <button id="open-export-modal-btn" class="btn btn-primary w-full text-sm"> | |
| Export CSV | |
| </button> | |
| <p class="text-[11px] text-slate-500 mt-2 text-center">Export data by double-clicking the button above.</p> | |
| </div> | |
| </div> | |
| </aside> | |
| </main> | |
| </div> | |
| <div id="settings-modal" class="modal z-50" role="dialog" aria-labelledby="settings-modal-title" aria-hidden="true"> | |
| <div class="modal-backdrop"></div> | |
| <div class="modal-container"> | |
| <div class="card w-full max-w-lg"> | |
| <div class="card-header flex items-center justify-between"> | |
| <h3 id="settings-modal-title" class="font-semibold text-slate-700 text-sm">URL Settings</h3> | |
| <button class="modal-close-btn" aria-label="Close">β</button> | |
| </div> | |
| <div class="p-4 space-y-4 text-sm"> | |
| <div> | |
| <label for="cam1-url" class="block text-xs font-medium text-slate-600 mb-1">Camera 1 URL</label> | |
| <input type="text" id="cam1-url" class="modal-input" placeholder="Enter URL for Camera 1"> | |
| </div> | |
| <div> | |
| <label for="cam2-url" class="block text-xs font-medium text-slate-600 mb-1">Camera 2 URL</label> | |
| <input type="text" id="cam2-url" class="modal-input" placeholder="Enter URL for Camera 2"> | |
| </div> | |
| <div> | |
| <label for="cam3-url" class="block text-xs font-medium text-slate-600 mb-1">Camera 3 URL</label> | |
| <input type="text" id="cam3-url" class="modal-input" placeholder="Enter URL for Camera 3"> | |
| </div> | |
| <div> | |
| <label for="cam4-url" class="block text-xs font-medium text-slate-600 mb-1">Camera 4 URL</label> | |
| <input type="text" id="cam4-url" class="modal-input" placeholder="Enter URL for Camera 4"> | |
| </div> | |
| <hr class="border-slate-200"> | |
| <div> | |
| <label for="audio-url" class="block text-xs font-medium text-slate-600 mb-1">Audio URL</label> | |
| <input type="text" id="audio-url" class="modal-input" placeholder="Enter URL for Audio Source"> | |
| </div> | |
| <div class="flex justify-end gap-2 pt-2"> | |
| <button id="stop-all-streams-btn" class="btn bg-red-600 hover:bg-red-700 text-white text-sm">Stop All Streams</button> | |
| <button id="save-settings-btn" class="btn btn-primary text-sm">Save & Restart</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="export-modal" class="modal z-50" role="dialog" aria-labelledby="export-modal-title" aria-hidden="true"> | |
| <div class="modal-backdrop"></div> | |
| <div class="modal-container"> | |
| <div class="card w-full max-w-md"> | |
| <div class="card-header flex items-center justify-between"> | |
| <h3 id="export-modal-title" class="font-semibold text-slate-700 text-sm">Export Metric Data</h3> | |
| <button class="modal-close-btn" aria-label="Close">β</button> | |
| </div> | |
| <div class="p-4 space-y-3 text-sm"> | |
| <div> | |
| <label for="start-date" class="block text-xs font-medium text-slate-600 mb-1">Start Date</label> | |
| <input type="date" id="start-date" class="modal-input"> | |
| </div> | |
| <div> | |
| <label for="end-date" class="block text-xs font-medium text-slate-600 mb-1">End Date</label> | |
| <input type="date" id="end-date" class="modal-input"> | |
| </div> | |
| <div> | |
| <label for="camera-select" class="block text-xs font-medium text-slate-600 mb-1">Select Camera</label> | |
| <select id="camera-select" class="modal-input bg-white"> | |
| <option value="">All Cameras</option> | |
| <option value="1">Camera 1</option> | |
| <option value="2">Camera 2</option> | |
| <option value="3">Camera 3</option> | |
| <option value="4">Camera 4</option> | |
| </select> | |
| </div> | |
| <button id="download-csv-btn" class="btn btn-primary w-full">Download CSV</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="/static/js/app.js"></script> | |
| </body> | |
| </html> |