mio dashboard docs.kosmonum.space/mio/
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

v1

+442
+442
dashboard.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8"> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 + <title>Instance Dashboard</title> 7 + <style> 8 + * { 9 + margin: 0; 10 + padding: 0; 11 + box-sizing: border-box; 12 + } 13 + 14 + body { 15 + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; 16 + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); 17 + min-height: 100vh; 18 + padding: 40px 20px; 19 + } 20 + 21 + .container { 22 + max-width: 1200px; 23 + margin: 0 auto; 24 + } 25 + 26 + .header { 27 + margin-bottom: 40px; 28 + } 29 + 30 + .header h1 { 31 + font-size: 32px; 32 + color: #1a1a1a; 33 + font-weight: 600; 34 + margin-bottom: 8px; 35 + } 36 + 37 + .header p { 38 + color: #666; 39 + font-size: 14px; 40 + } 41 + 42 + .instances-grid { 43 + display: grid; 44 + grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); 45 + gap: 20px; 46 + } 47 + 48 + .instance-card { 49 + background: white; 50 + border-radius: 12px; 51 + padding: 20px; 52 + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); 53 + transition: all 0.3s ease; 54 + border: 1px solid #e8e8e8; 55 + } 56 + 57 + .instance-card:hover { 58 + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); 59 + border-color: #d0d0d0; 60 + } 61 + 62 + .instance-header { 63 + display: flex; 64 + align-items: center; 65 + gap: 12px; 66 + margin-bottom: 20px; 67 + justify-content: space-between; 68 + } 69 + 70 + .instance-name-group { 71 + display: flex; 72 + align-items: center; 73 + gap: 12px; 74 + flex: 1; 75 + } 76 + 77 + .heartbeat { 78 + width: 24px; 79 + height: 24px; 80 + display: flex; 81 + align-items: center; 82 + justify-content: center; 83 + font-size: 20px; 84 + animation: heartbeat 1.5s ease-in-out infinite; 85 + } 86 + 87 + .heartbeat.healthy { 88 + color: #10b981; 89 + } 90 + 91 + .heartbeat.warning { 92 + color: #f59e0b; 93 + } 94 + 95 + .heartbeat.critical { 96 + color: #ef4444; 97 + } 98 + 99 + @keyframes heartbeat { 100 + 0%, 100% { 101 + transform: scale(1); 102 + opacity: 1; 103 + } 104 + 25% { 105 + transform: scale(1.2); 106 + opacity: 0.8; 107 + } 108 + 50% { 109 + transform: scale(1); 110 + opacity: 1; 111 + } 112 + 75% { 113 + transform: scale(1.1); 114 + opacity: 0.9; 115 + } 116 + } 117 + 118 + .instance-name { 119 + font-size: 16px; 120 + font-weight: 600; 121 + color: #1a1a1a; 122 + } 123 + 124 + .add-subinstance-btn { 125 + background: none; 126 + border: 2px solid #e8e8e8; 127 + width: 32px; 128 + height: 32px; 129 + border-radius: 8px; 130 + cursor: pointer; 131 + font-size: 18px; 132 + display: flex; 133 + align-items: center; 134 + justify-content: center; 135 + transition: all 0.2s ease; 136 + color: #999; 137 + } 138 + 139 + .add-subinstance-btn:hover { 140 + background: #f9f9f9; 141 + border-color: #d0d0d0; 142 + color: #1a1a1a; 143 + } 144 + 145 + .add-subinstance-btn:active { 146 + background: #efefef; 147 + transform: scale(0.95); 148 + } 149 + 150 + .metrics-grid { 151 + display: grid; 152 + grid-template-columns: repeat(2, 1fr); 153 + gap: 16px; 154 + } 155 + 156 + .metric { 157 + background: #f9f9f9; 158 + border-radius: 8px; 159 + padding: 12px; 160 + border: 1px solid #f0f0f0; 161 + } 162 + 163 + .metric-label { 164 + font-size: 12px; 165 + font-weight: 600; 166 + color: #666; 167 + text-transform: uppercase; 168 + letter-spacing: 0.5px; 169 + margin-bottom: 8px; 170 + } 171 + 172 + .metric-value { 173 + font-size: 20px; 174 + font-weight: 700; 175 + color: #1a1a1a; 176 + margin-bottom: 6px; 177 + } 178 + 179 + .metric-bar { 180 + width: 100%; 181 + height: 6px; 182 + background: #e8e8e8; 183 + border-radius: 3px; 184 + overflow: hidden; 185 + } 186 + 187 + .metric-bar-fill { 188 + height: 100%; 189 + border-radius: 3px; 190 + transition: width 0.3s ease; 191 + } 192 + 193 + .metric-bar-fill.usage { 194 + background: linear-gradient(90deg, #3b82f6 0%, #1e40af 100%); 195 + } 196 + 197 + .metric-bar-fill.saturation { 198 + background: linear-gradient(90deg, #f59e0b 0%, #d97706 100%); 199 + } 200 + 201 + .metric-bar-fill.error { 202 + background: linear-gradient(90deg, #ef4444 0%, #dc2626 100%); 203 + } 204 + 205 + .metric-bar-fill.latency { 206 + background: linear-gradient(90deg, #8b5cf6 0%, #6d28d9 100%); 207 + } 208 + 209 + .metric-description { 210 + font-size: 11px; 211 + color: #999; 212 + margin-top: 4px; 213 + } 214 + 215 + .status-badge { 216 + display: inline-block; 217 + padding: 4px 8px; 218 + border-radius: 4px; 219 + font-size: 11px; 220 + font-weight: 600; 221 + text-transform: uppercase; 222 + } 223 + 224 + .status-badge.healthy { 225 + background: #d1fae5; 226 + color: #065f46; 227 + } 228 + 229 + .status-badge.warning { 230 + background: #fef3c7; 231 + color: #92400e; 232 + } 233 + 234 + .status-badge.critical { 235 + background: #fee2e2; 236 + color: #7f1d1d; 237 + } 238 + 239 + /* Responsive design */ 240 + @media (max-width: 768px) { 241 + .instances-grid { 242 + grid-template-columns: 1fr; 243 + } 244 + 245 + .metrics-grid { 246 + grid-template-columns: 1fr; 247 + } 248 + 249 + .header h1 { 250 + font-size: 24px; 251 + } 252 + } 253 + </style> 254 + </head> 255 + <body> 256 + <div class="container"> 257 + <div class="header"> 258 + <h1>Instance Dashboard</h1> 259 + <p>Monitor your system instances in real-time</p> 260 + </div> 261 + 262 + <div class="instances-grid"> 263 + <!-- Instance 1 --> 264 + <div class="instance-card"> 265 + <div class="instance-header"> 266 + <div class="instance-name-group"> 267 + <div class="heartbeat healthy">♥</div> 268 + <span class="instance-name">API Server</span> 269 + </div> 270 + <button class="add-subinstance-btn" title="Add subinstance">+</button> 271 + </div> 272 + 273 + <div class="metrics-grid"> 274 + <!-- Usage --> 275 + <div class="metric"> 276 + <div class="metric-label">Usage</div> 277 + <div class="metric-value">62%</div> 278 + <div class="metric-bar"> 279 + <div class="metric-bar-fill usage" style="width: 62%"></div> 280 + </div> 281 + <div class="metric-description">CPU & Memory</div> 282 + </div> 283 + 284 + <!-- Saturation --> 285 + <div class="metric"> 286 + <div class="metric-label">Saturation</div> 287 + <div class="metric-value">28%</div> 288 + <div class="metric-bar"> 289 + <div class="metric-bar-fill saturation" style="width: 28%"></div> 290 + </div> 291 + <div class="metric-description">Queue depth</div> 292 + </div> 293 + 294 + <!-- Error Rate --> 295 + <div class="metric"> 296 + <div class="metric-label">Error Rate</div> 297 + <div class="metric-value">0.2%</div> 298 + <div class="metric-bar"> 299 + <div class="metric-bar-fill error" style="width: 2%"></div> 300 + </div> 301 + <div class="metric-description">Per minute</div> 302 + </div> 303 + 304 + <!-- Latency --> 305 + <div class="metric"> 306 + <div class="metric-label">Latency</div> 307 + <div class="metric-value">45ms</div> 308 + <div class="metric-bar"> 309 + <div class="metric-bar-fill latency" style="width: 45%"></div> 310 + </div> 311 + <div class="metric-description">P99</div> 312 + </div> 313 + </div> 314 + </div> 315 + 316 + <!-- Instance 2 --> 317 + <div class="instance-card"> 318 + <div class="instance-header"> 319 + <div class="instance-name-group"> 320 + <div class="heartbeat warning">♥</div> 321 + <span class="instance-name">Database</span> 322 + </div> 323 + <button class="add-subinstance-btn" title="Add subinstance">+</button> 324 + </div> 325 + 326 + <div class="metrics-grid"> 327 + <div class="metric"> 328 + <div class="metric-label">Usage</div> 329 + <div class="metric-value">85%</div> 330 + <div class="metric-bar"> 331 + <div class="metric-bar-fill usage" style="width: 85%"></div> 332 + </div> 333 + <div class="metric-description">CPU & Memory</div> 334 + </div> 335 + 336 + <div class="metric"> 337 + <div class="metric-label">Saturation</div> 338 + <div class="metric-value">72%</div> 339 + <div class="metric-bar"> 340 + <div class="metric-bar-fill saturation" style="width: 72%"></div> 341 + </div> 342 + <div class="metric-description">Queue depth</div> 343 + </div> 344 + 345 + <div class="metric"> 346 + <div class="metric-label">Error Rate</div> 347 + <div class="metric-value">1.5%</div> 348 + <div class="metric-bar"> 349 + <div class="metric-bar-fill error" style="width: 15%"></div> 350 + </div> 351 + <div class="metric-description">Per minute</div> 352 + </div> 353 + 354 + <div class="metric"> 355 + <div class="metric-label">Latency</div> 356 + <div class="metric-value">125ms</div> 357 + <div class="metric-bar"> 358 + <div class="metric-bar-fill latency" style="width: 70%"></div> 359 + </div> 360 + <div class="metric-description">P99</div> 361 + </div> 362 + </div> 363 + </div> 364 + 365 + <!-- Instance 3 --> 366 + <div class="instance-card"> 367 + <div class="instance-header"> 368 + <div class="instance-name-group"> 369 + <div class="heartbeat critical">♥</div> 370 + <span class="instance-name">Cache Service</span> 371 + </div> 372 + <button class="add-subinstance-btn" title="Add subinstance">+</button> 373 + </div> 374 + 375 + <div class="metrics-grid"> 376 + <div class="metric"> 377 + <div class="metric-label">Usage</div> 378 + <div class="metric-value">92%</div> 379 + <div class="metric-bar"> 380 + <div class="metric-bar-fill usage" style="width: 92%"></div> 381 + </div> 382 + <div class="metric-description">CPU & Memory</div> 383 + </div> 384 + 385 + <div class="metric"> 386 + <div class="metric-label">Saturation</div> 387 + <div class="metric-value">88%</div> 388 + <div class="metric-bar"> 389 + <div class="metric-bar-fill saturation" style="width: 88%"></div> 390 + </div> 391 + <div class="metric-description">Queue depth</div> 392 + </div> 393 + 394 + <div class="metric"> 395 + <div class="metric-label">Error Rate</div> 396 + <div class="metric-value">5.8%</div> 397 + <div class="metric-bar"> 398 + <div class="metric-bar-fill error" style="width: 58%"></div> 399 + </div> 400 + <div class="metric-description">Per minute</div> 401 + </div> 402 + 403 + <div class="metric"> 404 + <div class="metric-label">Latency</div> 405 + <div class="metric-value">340ms</div> 406 + <div class="metric-bar"> 407 + <div class="metric-bar-fill latency" style="width: 95%"></div> 408 + </div> 409 + <div class="metric-description">P99</div> 410 + </div> 411 + </div> 412 + </div> 413 + </div> 414 + </div> 415 + 416 + <script> 417 + // Add event listeners to the plus buttons 418 + document.querySelectorAll('.add-subinstance-btn').forEach(btn => { 419 + btn.addEventListener('click', function(e) { 420 + e.preventDefault(); 421 + const instanceName = this.closest('.instance-card') 422 + .querySelector('.instance-name').textContent; 423 + alert(`Add subinstance to "${instanceName}"`); 424 + // Replace with actual implementation 425 + }); 426 + }); 427 + 428 + // Example: Update metrics dynamically (simulated) 429 + function updateMetrics() { 430 + document.querySelectorAll('.metric-value').forEach(el => { 431 + const currentValue = parseInt(el.textContent); 432 + const randomChange = (Math.random() - 0.5) * 10; 433 + const newValue = Math.max(0, Math.min(100, currentValue + randomChange)); 434 + el.textContent = Math.round(newValue) + (el.textContent.includes('%') ? '%' : el.textContent.match(/ms|%/)[0] || ''); 435 + }); 436 + } 437 + 438 + // Optional: Update every 5 seconds 439 + // setInterval(updateMetrics, 5000); 440 + </script> 441 + </body> 442 + </html>