botui/ui/suite/monitoring/monitoring.html

1381 lines
44 KiB
HTML
Raw Normal View History

2025-12-03 18:42:22 -03:00
<div class="monitoring-container" id="monitoring-app">
<header class="monitoring-header">
<h2>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
class="header-icon"
>
<circle
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="1.</h2>5"
fill="none"
opacity="0.3"
/>
<circle
cx="12"
cy="12"
r="6.5"
stroke="currentColor"
stroke-width="1.5"
fill="none"
opacity="0.6"
/>
<circle cx="12" cy="12" r="2" fill="currentColor" />
<line
x1="12"
y1="2"
x2="12"
y2="5"
stroke="currentColor"
stroke-width="1.5"
/>
<line
x1="12"
y1="19"
x2="12"
y2="22"
stroke="currentColor"
stroke-width="1.5"
/>
<line
x1="2"
y1="12"
x2="5"
y2="12"
stroke="currentColor"
stroke-width="1.5"
/>
<line
x1="19"
y1="12"
x2="22"
y2="12"
stroke="currentColor"
stroke-width="1.5"
/>
</svg>
Monitoring Dashboard
</h2>
<div class="header-actions">
<button class="view-toggle" id="view-toggle" title="Toggle View">
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<rect x="3" y="3" width="7" height="7" />
<rect x="14" y="3" width="7" height="7" />
<rect x="3" y="14" width="7" height="7" />
<rect x="14" y="14" width="7" height="7" />
</svg>
</button>
<span
class="last-updated"
hx-get="/api/ui/monitoring/timestamp"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 5s"
hx-swap="innerHTML"
>--</span
>
</div>
</header>
<!-- Live System Visualization -->
<div class="live-visualization" id="live-view">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1200 650"
class="live-svg"
>
<defs>
<!-- Gradients -->
<linearGradient
id="bgGradient"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop
offset="0%"
style="stop-color: var(--bg-dark, #0f172a)"
/>
<stop
offset="50%"
style="stop-color: var(--bg-surface, #1e293b)"
/>
<stop
offset="100%"
style="stop-color: var(--bg-dark, #0f172a)"
/>
</linearGradient>
<linearGradient
id="coreGlow"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop offset="0%" style="stop-color: #3b82f6" />
<stop offset="50%" style="stop-color: #6366f1" />
<stop offset="100%" style="stop-color: #8b5cf6" />
</linearGradient>
<linearGradient
id="greenGlow"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop offset="0%" style="stop-color: #10b981" />
<stop offset="100%" style="stop-color: #22c55e" />
</linearGradient>
<linearGradient
id="dbGradient"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop offset="0%" style="stop-color: #3b82f6" />
<stop offset="100%" style="stop-color: #1d4ed8" />
</linearGradient>
<linearGradient
id="vectorGradient"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop offset="0%" style="stop-color: #8b5cf6" />
<stop offset="100%" style="stop-color: #6d28d9" />
</linearGradient>
<linearGradient
id="storageGradient"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop offset="0%" style="stop-color: #f59e0b" />
<stop offset="100%" style="stop-color: #d97706" />
</linearGradient>
<linearGradient
id="aiGradient"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop offset="0%" style="stop-color: #ec4899" />
<stop offset="100%" style="stop-color: #db2777" />
</linearGradient>
<linearGradient
id="cacheGradient"
x1="0%"
y1="0%"
x2="100%"
y2="100%"
>
<stop offset="0%" style="stop-color: #06b6d4" />
<stop offset="100%" style="stop-color: #0891b2" />
</linearGradient>
<!-- Glow filter -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="coloredBlur" />
<feMerge>
<feMergeNode in="coloredBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<!-- Background -->
<rect width="100%" height="100%" fill="url(#bgGradient)" />
<!-- Subtle grid -->
<g opacity="0.06" stroke="#64748b" stroke-width="0.5">
<line x1="0" y1="162" x2="1200" y2="162" />
<line x1="0" y1="325" x2="1200" y2="325" />
<line x1="0" y1="487" x2="1200" y2="487" />
<line x1="300" y1="0" x2="300" y2="650" />
<line x1="600" y1="0" x2="600" y2="650" />
<line x1="900" y1="0" x2="900" y2="650" />
</g>
<!-- ==================== CENTRAL CORE: BotServer ==================== -->
<g transform="translate(600, 325)" class="core-node">
<!-- Outer rotating ring -->
<circle
r="85"
fill="none"
stroke="url(#coreGlow)"
stroke-width="2"
stroke-dasharray="10 5"
opacity="0.4"
class="rotate-slow"
/>
<!-- Middle pulsing ring -->
<circle
r="65"
fill="none"
stroke="url(#coreGlow)"
stroke-width="3"
opacity="0.6"
class="pulse-ring"
/>
<!-- Core background -->
<circle
r="50"
fill="#1e293b"
stroke="url(#coreGlow)"
stroke-width="3"
filter="url(#glow)"
/>
<!-- Bot icon -->
<g fill="#f8fafc">
<rect
x="-22"
y="-18"
width="44"
height="32"
rx="7"
fill="url(#coreGlow)"
opacity="0.9"
/>
<circle cx="-9" cy="-4" r="4.5" fill="#f8fafc" />
<circle cx="9" cy="-4" r="4.5" fill="#f8fafc" />
<path
d="M-10 9 Q0 16 10 9"
stroke="#f8fafc"
stroke-width="2.5"
fill="none"
/>
<rect
x="-2.5"
y="-32"
width="5"
height="11"
rx="2.5"
fill="url(#coreGlow)"
/>
<circle
cx="0"
cy="-35"
r="4.5"
fill="url(#coreGlow)"
class="antenna-pulse"
/>
</g>
<text
y="72"
text-anchor="middle"
fill="#f8fafc"
font-family="system-ui"
font-size="13"
font-weight="600"
>
BotServer
</text>
<text
y="88"
text-anchor="middle"
fill="#10b981"
font-family="system-ui"
font-size="10"
class="status-text"
>
● Running
</text>
</g>
<!-- ==================== LEFT: Data Layer ==================== -->
<!-- PostgreSQL -->
<g
transform="translate(150, 185)"
class="service-node"
data-service="postgresql"
>
<circle
r="42"
fill="#1e293b"
stroke="url(#dbGradient)"
stroke-width="2"
filter="url(#glow)"
/>
<g transform="translate(-14, -16)">
<ellipse
cx="14"
cy="0"
rx="16"
ry="5.5"
fill="url(#dbGradient)"
/>
<path
d="M-2 0 L-2 18 Q14 27 30 18 L30 0"
fill="url(#dbGradient)"
opacity="0.8"
/>
<ellipse
cx="14"
cy="18"
rx="16"
ry="5.5"
fill="url(#dbGradient)"
/>
<line
x1="-2"
y1="6"
x2="30"
y2="6"
stroke="#1e40af"
stroke-width="1"
/>
<line
x1="-2"
y1="12"
x2="30"
y2="12"
stroke="#1e40af"
stroke-width="1"
/>
</g>
<text
y="58"
text-anchor="middle"
fill="#f8fafc"
font-family="system-ui"
font-size="11"
font-weight="500"
>
PostgreSQL
</text>
<circle
cx="32"
cy="-32"
r="5"
class="status-dot running"
data-status="postgresql"
/>
</g>
<!-- Qdrant -->
<g
transform="translate(150, 325)"
class="service-node"
data-service="qdrant"
>
<circle
r="42"
fill="#1e293b"
stroke="url(#vectorGradient)"
stroke-width="2"
filter="url(#glow)"
/>
<g fill="url(#vectorGradient)">
<polygon points="0,-20 17,10 -17,10" opacity="0.9" />
<polygon points="0,-11 11,6 -11,6" fill="#1e293b" />
<circle cx="0" cy="-20" r="3.5" />
<circle cx="17" cy="10" r="3.5" />
<circle cx="-17" cy="10" r="3.5" />
</g>
<text
y="58"
text-anchor="middle"
fill="#f8fafc"
font-family="system-ui"
font-size="11"
font-weight="500"
>
Qdrant
</text>
<circle
cx="32"
cy="-32"
r="5"
class="status-dot running"
data-status="qdrant"
/>
</g>
<!-- MinIO -->
<g
transform="translate(150, 465)"
class="service-node"
data-service="drive"
>
<circle
r="42"
fill="#1e293b"
stroke="url(#storageGradient)"
stroke-width="2"
filter="url(#glow)"
/>
<g fill="url(#storageGradient)">
<rect x="-20" y="-16" width="40" height="32" rx="4" />
<rect
x="-16"
y="-12"
width="32"
height="24"
rx="2"
fill="#1e293b"
/>
<rect
x="-12"
y="-8"
width="24"
height="7"
rx="1"
fill="#fcd34d"
opacity="0.4"
/>
<rect
x="-12"
y="2"
width="24"
height="7"
rx="1"
fill="#fcd34d"
opacity="0.4"
/>
<circle cx="8" cy="-4.5" r="1.8" fill="#fbbf24" />
<circle cx="8" cy="5.5" r="1.8" fill="#fbbf24" />
</g>
<text
y="58"
text-anchor="middle"
fill="#f8fafc"
font-family="system-ui"
font-size="11"
font-weight="500"
>
MinIO
</text>
<circle
cx="32"
cy="-32"
r="5"
class="status-dot running"
data-status="drive"
/>
</g>
<!-- ==================== RIGHT: Services ==================== -->
<!-- BotModels -->
<g
transform="translate(1050, 185)"
class="service-node"
data-service="botmodels"
>
<circle
r="42"
fill="#1e293b"
stroke="url(#aiGradient)"
stroke-width="2"
filter="url(#glow)"
/>
<g>
<circle
cx="0"
cy="-7"
r="12"
fill="none"
stroke="url(#aiGradient)"
stroke-width="2"
/>
<circle
cx="0"
cy="-7"
r="5"
fill="url(#aiGradient)"
class="ai-pulse"
/>
<path
d="M-16 10 L0 -2 L16 10"
stroke="url(#aiGradient)"
stroke-width="2"
fill="none"
/>
<path
d="M-10 16 L0 7 L10 16"
stroke="url(#aiGradient)"
stroke-width="2"
fill="none"
/>
</g>
<text
y="58"
text-anchor="middle"
fill="#f8fafc"
font-family="system-ui"
font-size="11"
font-weight="500"
>
BotModels
</text>
<circle
cx="32"
cy="-32"
r="5"
class="status-dot running"
data-status="botmodels"
/>
</g>
<!-- Cache -->
<g
transform="translate(1050, 325)"
class="service-node"
data-service="cache"
>
<circle
r="42"
fill="#1e293b"
stroke="url(#cacheGradient)"
stroke-width="2"
filter="url(#glow)"
/>
<g fill="url(#cacheGradient)">
<rect x="-18" y="-16" width="36" height="32" rx="3" />
<rect
x="-14"
y="-12"
width="28"
height="24"
rx="2"
fill="#1e293b"
/>
<text
x="0"
y="5"
text-anchor="middle"
font-family="system-ui"
font-size="16"
fill="#22d3ee"
>
</text>
</g>
<text
y="58"
text-anchor="middle"
fill="#f8fafc"
font-family="system-ui"
font-size="11"
font-weight="500"
>
Cache
</text>
<circle
cx="32"
cy="-32"
r="5"
class="status-dot running"
data-status="cache"
/>
</g>
<!-- Vault -->
<g
transform="translate(1050, 465)"
class="service-node"
data-service="vault"
>
<circle
r="42"
fill="#1e293b"
stroke="url(#greenGlow)"
stroke-width="2"
filter="url(#glow)"
/>
<g fill="url(#greenGlow)">
<rect x="-16" y="-9" width="32" height="25" rx="4" />
<rect
x="-12"
y="-5"
width="24"
height="17"
rx="2"
fill="#1e293b"
/>
<circle cx="0" cy="3.5" r="5" fill="url(#greenGlow)" />
<rect
x="-1.5"
y="3.5"
width="3"
height="7"
fill="url(#greenGlow)"
/>
<path
d="M-9 -16 L0 -23 L9 -16"
stroke="url(#greenGlow)"
stroke-width="2.5"
fill="none"
/>
</g>
<text
y="58"
text-anchor="middle"
fill="#f8fafc"
font-family="system-ui"
font-size="11"
font-weight="500"
>
Vault
</text>
<circle
cx="32"
cy="-32"
r="5"
class="status-dot running"
data-status="vault"
/>
</g>
<!-- ==================== ANIMATED CONNECTION LINES ==================== -->
<!-- Left connections -->
<g class="connection-lines" stroke-width="2" fill="none">
<path
d="M192 185 Q400 185 510 300"
stroke="#3b82f6"
opacity="0.25"
class="connection-path"
/>
<circle r="3.5" fill="#60a5fa" class="data-packet">
<animateMotion
dur="3s"
repeatCount="indefinite"
path="M192 185 Q400 185 510 300"
/>
</circle>
<path
d="M192 325 L510 325"
stroke="#8b5cf6"
opacity="0.25"
class="connection-path"
/>
<circle r="3.5" fill="#a78bfa" class="data-packet">
<animateMotion
dur="2.5s"
repeatCount="indefinite"
path="M192 325 L510 325"
/>
</circle>
<path
d="M192 465 Q400 465 510 350"
stroke="#f59e0b"
opacity="0.25"
class="connection-path"
/>
<circle r="3.5" fill="#fcd34d" class="data-packet">
<animateMotion
dur="3.5s"
repeatCount="indefinite"
path="M192 465 Q400 465 510 350"
/>
</circle>
</g>
<!-- Right connections -->
<g class="connection-lines" stroke-width="2" fill="none">
<path
d="M690 300 Q800 185 1008 185"
stroke="#ec4899"
opacity="0.25"
class="connection-path"
/>
<circle r="3.5" fill="#f472b6" class="data-packet">
<animateMotion
dur="2s"
repeatCount="indefinite"
path="M690 300 Q800 185 1008 185"
/>
</circle>
<path
d="M690 325 L1008 325"
stroke="#06b6d4"
opacity="0.25"
class="connection-path"
/>
<circle r="3.5" fill="#22d3ee" class="data-packet">
<animateMotion
dur="1.5s"
repeatCount="indefinite"
path="M690 325 L1008 325"
/>
</circle>
<path
d="M690 350 Q800 465 1008 465"
stroke="#10b981"
opacity="0.25"
class="connection-path"
/>
<circle r="3.5" fill="#34d399" class="data-packet">
<animateMotion
dur="4s"
repeatCount="indefinite"
path="M690 350 Q800 465 1008 465"
/>
</circle>
</g>
<!-- ==================== METRICS PANELS ==================== -->
<!-- Sessions -->
<g transform="translate(330, 50)">
<rect
x="0"
y="0"
width="150"
height="75"
rx="10"
fill="#1e293b"
stroke="#334155"
stroke-width="1"
/>
<text
x="12"
y="22"
fill="#64748b"
font-family="system-ui"
font-size="9"
font-weight="500"
>
ACTIVE SESSIONS
</text>
<text
x="12"
y="52"
fill="#f8fafc"
font-family="system-ui"
font-size="28"
font-weight="700"
hx-get="/api/ui/monitoring/metric/sessions"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 5s"
hx-swap="innerHTML"
>
--
</text>
<text
x="138"
y="62"
fill="#10b981"
font-family="system-ui"
font-size="10"
text-anchor="end"
hx-get="/api/ui/monitoring/trend/sessions"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 5s"
hx-swap="innerHTML"
>
↑ 0%
</text>
</g>
<!-- Messages -->
<g transform="translate(500, 50)">
<rect
x="0"
y="0"
width="150"
height="75"
rx="10"
fill="#1e293b"
stroke="#334155"
stroke-width="1"
/>
<text
x="12"
y="22"
fill="#64748b"
font-family="system-ui"
font-size="9"
font-weight="500"
>
MESSAGES TODAY
</text>
<text
x="12"
y="52"
fill="#f8fafc"
font-family="system-ui"
font-size="28"
font-weight="700"
hx-get="/api/ui/monitoring/metric/messages"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 10s"
hx-swap="innerHTML"
>
--
</text>
<text
x="138"
y="62"
fill="#94a3b8"
font-family="system-ui"
font-size="10"
text-anchor="end"
hx-get="/api/ui/monitoring/rate/messages"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 10s"
hx-swap="innerHTML"
>
0/hr
</text>
</g>
<!-- Response Time -->
<g transform="translate(670, 50)">
<rect
x="0"
y="0"
width="150"
height="75"
rx="10"
fill="#1e293b"
stroke="#334155"
stroke-width="1"
/>
<text
x="12"
y="22"
fill="#64748b"
font-family="system-ui"
font-size="9"
font-weight="500"
>
AVG RESPONSE
</text>
<text
x="12"
y="52"
fill="#f8fafc"
font-family="system-ui"
font-size="28"
font-weight="700"
hx-get="/api/ui/monitoring/metric/response_time"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 10s"
hx-swap="innerHTML"
>
--
</text>
<text
x="138"
y="62"
fill="#94a3b8"
font-family="system-ui"
font-size="10"
text-anchor="end"
>
ms
</text>
</g>
<!-- ==================== RESOURCE BARS ==================== -->
<g
transform="translate(330, 545)"
hx-get="/api/ui/monitoring/resources/bars"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 15s"
hx-swap="innerHTML"
>
<!-- CPU -->
<g transform="translate(0, 0)">
<text
x="0"
y="11"
fill="#94a3b8"
font-family="system-ui"
font-size="9"
font-weight="500"
>
CPU
</text>
<rect
x="35"
y="2"
width="90"
height="12"
rx="4"
fill="#334155"
/>
<rect
x="35"
y="2"
width="58"
height="12"
rx="4"
fill="url(#coreGlow)"
class="resource-fill"
/>
<text
x="132"
y="12"
fill="#f8fafc"
font-family="system-ui"
font-size="10"
font-weight="500"
>
65%
</text>
</g>
<!-- Memory -->
<g transform="translate(160, 0)">
<text
x="0"
y="11"
fill="#94a3b8"
font-family="system-ui"
font-size="9"
font-weight="500"
>
MEM
</text>
<rect
x="35"
y="2"
width="90"
height="12"
rx="4"
fill="#334155"
/>
<rect
x="35"
y="2"
width="65"
height="12"
rx="4"
fill="url(#greenGlow)"
class="resource-fill"
/>
<text
x="132"
y="12"
fill="#f8fafc"
font-family="system-ui"
font-size="10"
font-weight="500"
>
72%
</text>
</g>
<!-- GPU -->
<g transform="translate(320, 0)">
<text
x="0"
y="11"
fill="#94a3b8"
font-family="system-ui"
font-size="9"
font-weight="500"
>
GPU
</text>
<rect
x="35"
y="2"
width="90"
height="12"
rx="4"
fill="#334155"
/>
<rect
x="35"
y="2"
width="40"
height="12"
rx="4"
fill="url(#vectorGradient)"
class="resource-fill"
/>
<text
x="132"
y="12"
fill="#f8fafc"
font-family="system-ui"
font-size="10"
font-weight="500"
>
45%
</text>
</g>
<!-- Disk -->
<g transform="translate(480, 0)">
<text
x="0"
y="11"
fill="#94a3b8"
font-family="system-ui"
font-size="9"
font-weight="500"
>
DISK
</text>
<rect
x="35"
y="2"
width="90"
height="12"
rx="4"
fill="#334155"
/>
<rect
x="35"
y="2"
width="25"
height="12"
rx="4"
fill="url(#storageGradient)"
class="resource-fill"
/>
<text
x="132"
y="12"
fill="#f8fafc"
font-family="system-ui"
font-size="10"
font-weight="500"
>
28%
</text>
</g>
</g>
<!-- ==================== ACTIVITY TICKER ==================== -->
<g transform="translate(330, 590)">
<rect
x="0"
y="0"
width="490"
height="36"
rx="8"
fill="#1e293b"
stroke="#334155"
stroke-width="1"
/>
<circle
cx="16"
cy="18"
r="4"
fill="#10b981"
class="pulse-dot"
/>
<text
x="30"
y="22"
fill="#94a3b8"
font-family="system-ui"
font-size="11"
hx-get="/api/ui/monitoring/activity/latest"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 5s"
hx-swap="innerHTML"
>
System monitoring active...
</text>
</g>
<!-- ==================== LEGEND ==================== -->
<g transform="translate(50, 600)">
<g transform="translate(0, 0)">
<circle r="4" fill="#10b981" />
<text
x="10"
y="4"
fill="#94a3b8"
font-family="system-ui"
font-size="9"
>
Running
</text>
</g>
<g transform="translate(70, 0)">
<circle r="4" fill="#f59e0b" />
<text
x="10"
y="4"
fill="#94a3b8"
font-family="system-ui"
font-size="9"
>
Warning
</text>
</g>
<g transform="translate(140, 0)">
<circle r="4" fill="#ef4444" />
<text
x="10"
y="4"
fill="#94a3b8"
font-family="system-ui"
font-size="9"
>
Stopped
</text>
</g>
</g>
</svg>
</div>
<!-- Grid View (hidden by default) -->
<div class="monitoring-grid" id="grid-view" style="display: none">
<!-- Sessions Panel -->
<div
class="monitor-panel"
hx-get="/api/ui/monitoring/sessions"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 5s"
hx-swap="innerHTML"
>
<div class="panel-header">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
class="panel-icon"
>
<circle
cx="12"
cy="8"
r="4"
stroke="currentColor"
stroke-width="1.5"
/>
<path
d="M4 20c0-4 4-6 8-6s8 2 8 6"
stroke="currentColor"
stroke-width="1.5"
/>
</svg>
<span>Sessions</span>
</div>
<div class="tree-view">
<div class="tree-node">
<span class="tree-branch"></span>
<span class="tree-label">Loading...</span>
</div>
</div>
</div>
<!-- Messages Panel -->
<div
class="monitor-panel"
hx-get="/api/ui/monitoring/messages"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 10s"
hx-swap="innerHTML"
>
<div class="panel-header">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
class="panel-icon"
>
<path
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
stroke="currentColor"
stroke-width="1.5"
/>
</svg>
<span>Messages</span>
</div>
<div class="tree-view">
<div class="tree-node">
<span class="tree-branch"></span>
<span class="tree-label">Loading...</span>
</div>
</div>
</div>
<!-- Resources Panel -->
<div
class="monitor-panel resources-panel"
hx-get="/api/ui/monitoring/resources"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 15s"
hx-swap="innerHTML"
>
<div class="panel-header">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
class="panel-icon"
>
<rect
x="4"
y="4"
width="16"
height="16"
rx="2"
stroke="currentColor"
stroke-width="1.5"
/>
<line
x1="4"
y1="12"
x2="20"
y2="12"
stroke="currentColor"
stroke-width="1"
/>
<line
x1="12"
y1="4"
x2="12"
y2="20"
stroke="currentColor"
stroke-width="1"
/>
</svg>
<span>Resources</span>
</div>
<div class="tree-view">
<div class="tree-node">
<span class="tree-branch"></span>
<span class="tree-label">Loading...</span>
</div>
</div>
</div>
<!-- Services Panel -->
<div
class="monitor-panel services-panel"
hx-get="/api/ui/monitoring/services"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 30s"
hx-swap="innerHTML"
>
<div class="panel-header">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
class="panel-icon"
>
<rect
x="2"
y="3"
width="20"
height="4"
rx="1"
stroke="currentColor"
stroke-width="1.5"
/>
<rect
x="2"
y="10"
width="20"
height="4"
rx="1"
stroke="currentColor"
stroke-width="1.5"
/>
<rect
x="2"
y="17"
width="20"
height="4"
rx="1"
stroke="currentColor"
stroke-width="1.5"
/>
</svg>
<span>Services</span>
</div>
<div class="tree-view">
<div class="tree-node">
<span class="tree-branch"></span>
<span class="tree-label">Loading...</span>
</div>
</div>
</div>
<!-- Bots Panel -->
<div
class="monitor-panel bots-panel"
hx-get="/api/ui/monitoring/bots"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 30s"
hx-swap="innerHTML"
>
<div class="panel-header">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
class="panel-icon"
>
<rect
x="4"
y="4"
width="16"
height="14"
rx="3"
stroke="currentColor"
stroke-width="1.5"
/>
<circle cx="9" cy="10" r="1.5" fill="currentColor" />
<circle cx="15" cy="10" r="1.5" fill="currentColor" />
<path
d="M9 14 Q12 16 15 14"
stroke="currentColor"
stroke-width="1.5"
fill="none"
/>
</svg>
<span>Active Bots</span>
</div>
<div class="tree-view">
<div class="tree-node">
<span class="tree-branch"></span>
<span class="tree-label">Loading...</span>
</div>
</div>
</div>
</div>
<!-- Hidden service status updater -->
<div
id="service-status-container"
style="display: none"
hx-get="/api/ui/monitoring/services/status"
2025-12-03 18:42:22 -03:00
hx-trigger="load, every 30s"
hx-swap="innerHTML"
></div>
<link rel="stylesheet" href="monitoring.css" />
<script src="monitoring.js"></script>
2025-12-03 18:42:22 -03:00
</div>