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

Configure Feed

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

v4

+789 -130
+789 -130
dashboard.html
··· 3 3 <head> 4 4 <meta charset="UTF-8"> 5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 - <title>Instance Dashboard</title> 6 + <title>Cluster Dashboard</title> 7 7 <style> 8 8 * { 9 9 margin: 0; ··· 42 42 font-size: 14px; 43 43 } 44 44 45 - .instances-list { 45 + .clusters-list { 46 46 display: flex; 47 47 flex-direction: column; 48 48 gap: 16px; 49 49 max-width: 100%; 50 50 } 51 51 52 - .instance-card { 52 + .cluster-card { 53 53 background: white; 54 54 border-radius: 12px; 55 - padding: 16px 20px; 56 55 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); 57 56 transition: all 0.3s ease; 58 57 border: 1px solid #e8e8e8; 58 + overflow: hidden; 59 + } 60 + 61 + .cluster-card:hover { 62 + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); 63 + border-color: #d0d0d0; 64 + } 65 + 66 + .cluster-header { 67 + padding: 16px 20px; 59 68 display: flex; 60 69 align-items: center; 61 70 gap: 20px; 71 + cursor: pointer; 72 + user-select: none; 62 73 } 63 74 64 - .instance-card:hover { 65 - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); 66 - border-color: #d0d0d0; 75 + .cluster-header:hover { 76 + background: #f9f9f9; 77 + } 78 + 79 + .expand-icon { 80 + width: 24px; 81 + height: 24px; 82 + display: flex; 83 + align-items: center; 84 + justify-content: center; 85 + font-size: 18px; 86 + transition: transform 0.3s ease; 87 + color: #666; 88 + flex-shrink: 0; 89 + } 90 + 91 + .cluster-card.expanded .expand-icon { 92 + transform: rotate(180deg); 67 93 } 68 94 69 95 .heartbeat { ··· 108 134 } 109 135 } 110 136 111 - .instance-name { 137 + .cluster-name { 112 138 font-size: 16px; 113 139 font-weight: 600; 114 140 color: #1a1a1a; ··· 181 207 background: linear-gradient(90deg, #8b5cf6 0%, #6d28d9 100%); 182 208 } 183 209 184 - .add-subinstance-btn { 210 + .menu-container { 211 + position: relative; 212 + flex-shrink: 0; 213 + margin-left: auto; 214 + } 215 + 216 + .menu-button { 185 217 background: none; 186 218 border: 2px solid #e8e8e8; 187 219 width: 36px; ··· 194 226 justify-content: center; 195 227 transition: all 0.2s ease; 196 228 color: #999; 197 - flex-shrink: 0; 198 - margin-left: auto; 229 + padding: 0; 199 230 } 200 231 201 - .add-subinstance-btn:hover { 232 + .menu-button:hover { 202 233 background: #f9f9f9; 203 234 border-color: #d0d0d0; 204 235 color: #1a1a1a; 205 236 } 206 237 207 - .add-subinstance-btn:active { 238 + .menu-button:active { 208 239 background: #efefef; 209 240 transform: scale(0.95); 210 241 } 211 242 243 + .menu-dropdown { 244 + position: absolute; 245 + top: 100%; 246 + right: 0; 247 + background: white; 248 + border: 1px solid #e8e8e8; 249 + border-radius: 8px; 250 + margin-top: 8px; 251 + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); 252 + min-width: 160px; 253 + opacity: 0; 254 + visibility: hidden; 255 + transform: translateY(-8px); 256 + transition: all 0.2s ease; 257 + z-index: 1000; 258 + } 259 + 260 + .menu-dropdown.active { 261 + opacity: 1; 262 + visibility: visible; 263 + transform: translateY(0); 264 + } 265 + 266 + .menu-item { 267 + display: flex; 268 + align-items: center; 269 + gap: 12px; 270 + padding: 12px 16px; 271 + border: none; 272 + background: none; 273 + cursor: pointer; 274 + font-size: 14px; 275 + color: #1a1a1a; 276 + width: 100%; 277 + text-align: left; 278 + transition: background 0.2s ease; 279 + } 280 + 281 + .menu-item:hover { 282 + background: #f9f9f9; 283 + } 284 + 285 + .menu-item:first-child { 286 + border-radius: 8px 8px 0 0; 287 + } 288 + 289 + .menu-item:last-child { 290 + border-radius: 0 0 8px 8px; 291 + } 292 + 293 + .menu-item.danger { 294 + color: #ef4444; 295 + } 296 + 297 + .menu-item.danger:hover { 298 + background: #fee2e2; 299 + } 300 + 301 + .menu-item-icon { 302 + font-size: 16px; 303 + display: flex; 304 + align-items: center; 305 + justify-content: center; 306 + width: 20px; 307 + } 308 + 309 + .cluster-content { 310 + max-height: 0; 311 + overflow: hidden; 312 + transition: max-height 0.3s ease; 313 + } 314 + 315 + .cluster-card.expanded .cluster-content { 316 + max-height: 1000px; 317 + } 318 + 319 + .instances-container { 320 + padding: 0 20px 20px 20px; 321 + border-top: 1px solid #f0f0f0; 322 + display: flex; 323 + flex-direction: column; 324 + gap: 12px; 325 + } 326 + 327 + .instance-item { 328 + padding: 12px 16px; 329 + background: #f9f9f9; 330 + border-radius: 8px; 331 + border: 1px solid #f0f0f0; 332 + display: flex; 333 + align-items: center; 334 + gap: 16px; 335 + } 336 + 337 + .instance-name-small { 338 + font-size: 14px; 339 + font-weight: 500; 340 + color: #1a1a1a; 341 + min-width: 120px; 342 + flex-shrink: 0; 343 + } 344 + 345 + .metrics-container-small { 346 + display: flex; 347 + align-items: center; 348 + gap: 16px; 349 + flex: 1; 350 + } 351 + 352 + .metric-small { 353 + display: flex; 354 + flex-direction: column; 355 + gap: 2px; 356 + min-width: 100px; 357 + } 358 + 359 + .metric-label-small { 360 + font-size: 10px; 361 + font-weight: 600; 362 + color: #999; 363 + text-transform: uppercase; 364 + letter-spacing: 0.4px; 365 + } 366 + 367 + .metric-content-small { 368 + display: flex; 369 + align-items: center; 370 + gap: 6px; 371 + } 372 + 373 + .metric-value-small { 374 + font-size: 14px; 375 + font-weight: 600; 376 + color: #1a1a1a; 377 + min-width: 35px; 378 + } 379 + 380 + .metric-bar-small { 381 + width: 50px; 382 + height: 4px; 383 + background: #e8e8e8; 384 + border-radius: 2px; 385 + overflow: hidden; 386 + } 387 + 388 + .metric-bar-fill-small { 389 + height: 100%; 390 + border-radius: 2px; 391 + } 392 + 212 393 /* Responsive design */ 213 394 @media (max-width: 1400px) { 214 - .instance-card { 395 + .cluster-header { 215 396 flex-wrap: wrap; 216 397 padding: 12px 16px; 217 398 } ··· 222 403 margin-top: 8px; 223 404 } 224 405 225 - .instance-name { 406 + .cluster-name { 226 407 order: 1; 227 408 } 228 409 229 - .add-subinstance-btn { 410 + .menu-container { 230 411 order: 3; 231 412 margin-left: 0; 232 413 margin-top: 8px; ··· 234 415 } 235 416 236 417 @media (max-width: 768px) { 237 - .instance-card { 418 + .cluster-header { 238 419 flex-wrap: wrap; 239 420 padding: 12px 16px; 240 421 } ··· 259 440 <body> 260 441 <div class="container"> 261 442 <div class="header"> 262 - <h1>Instance Dashboard</h1> 263 - <p>Monitor your system instances in real-time</p> 443 + <h1>Cluster Dashboard</h1> 444 + <p>Monitor your system clusters and instances in real-time</p> 264 445 </div> 265 446 266 - <div class="instances-list"> 267 - <!-- Instance 1 --> 268 - <div class="instance-card"> 269 - <div class="heartbeat healthy">♥</div> 270 - <span class="instance-name">API Server</span> 271 - 272 - <div class="metrics-container"> 273 - <div class="metric"> 274 - <div class="metric-label">Usage</div> 275 - <div class="metric-content"> 276 - <div class="metric-value">62%</div> 277 - <div class="metric-bar"> 278 - <div class="metric-bar-fill usage" style="width: 62%"></div> 447 + <div class="clusters-list"> 448 + <!-- Cluster 1 --> 449 + <div class="cluster-card"> 450 + <div class="cluster-header" onclick="toggleCluster(this)"> 451 + <div class="expand-icon">▼</div> 452 + <div class="heartbeat healthy">♥</div> 453 + <span class="cluster-name">API Cluster</span> 454 + 455 + <div class="metrics-container"> 456 + <div class="metric"> 457 + <div class="metric-label">Usage</div> 458 + <div class="metric-content"> 459 + <div class="metric-value">62%</div> 460 + <div class="metric-bar"> 461 + <div class="metric-bar-fill usage" style="width: 62%"></div> 462 + </div> 279 463 </div> 280 464 </div> 281 - </div> 282 465 283 - <div class="metric"> 284 - <div class="metric-label">Saturation</div> 285 - <div class="metric-content"> 286 - <div class="metric-value">28%</div> 287 - <div class="metric-bar"> 288 - <div class="metric-bar-fill saturation" style="width: 28%"></div> 466 + <div class="metric"> 467 + <div class="metric-label">Saturation</div> 468 + <div class="metric-content"> 469 + <div class="metric-value">28%</div> 470 + <div class="metric-bar"> 471 + <div class="metric-bar-fill saturation" style="width: 28%"></div> 472 + </div> 473 + </div> 474 + </div> 475 + 476 + <div class="metric"> 477 + <div class="metric-label">Error Rate</div> 478 + <div class="metric-content"> 479 + <div class="metric-value">0.2%</div> 480 + <div class="metric-bar"> 481 + <div class="metric-bar-fill error" style="width: 2%"></div> 482 + </div> 483 + </div> 484 + </div> 485 + 486 + <div class="metric"> 487 + <div class="metric-label">Latency</div> 488 + <div class="metric-content"> 489 + <div class="metric-value">45ms</div> 490 + <div class="metric-bar"> 491 + <div class="metric-bar-fill latency" style="width: 45%"></div> 492 + </div> 289 493 </div> 290 494 </div> 291 495 </div> 292 496 293 - <div class="metric"> 294 - <div class="metric-label">Error Rate</div> 295 - <div class="metric-content"> 296 - <div class="metric-value">0.2%</div> 297 - <div class="metric-bar"> 298 - <div class="metric-bar-fill error" style="width: 2%"></div> 299 - </div> 497 + <div class="menu-container"> 498 + <button class="menu-button" onclick="toggleMenu(event)">☰</button> 499 + <div class="menu-dropdown"> 500 + <button class="menu-item" onclick="action('backup', 'API Cluster')"> 501 + <span class="menu-item-icon">💾</span> 502 + <span>Trigger Backup</span> 503 + </button> 504 + <button class="menu-item" onclick="action('reboot', 'API Cluster')"> 505 + <span class="menu-item-icon">🔄</span> 506 + <span>Reboot</span> 507 + </button> 508 + <button class="menu-item danger" onclick="action('delete', 'API Cluster')"> 509 + <span class="menu-item-icon">🗑️</span> 510 + <span>Delete</span> 511 + </button> 300 512 </div> 301 513 </div> 514 + </div> 302 515 303 - <div class="metric"> 304 - <div class="metric-label">Latency</div> 305 - <div class="metric-content"> 306 - <div class="metric-value">45ms</div> 307 - <div class="metric-bar"> 308 - <div class="metric-bar-fill latency" style="width: 45%"></div> 516 + <div class="cluster-content"> 517 + <div class="instances-container"> 518 + <div class="instance-item"> 519 + <span class="instance-name-small">api-instance-1</span> 520 + <div class="metrics-container-small"> 521 + <div class="metric-small"> 522 + <div class="metric-label-small">Usage</div> 523 + <div class="metric-content-small"> 524 + <div class="metric-value-small">58%</div> 525 + <div class="metric-bar-small"> 526 + <div class="metric-bar-fill-small usage" style="width: 58%"></div> 527 + </div> 528 + </div> 529 + </div> 530 + <div class="metric-small"> 531 + <div class="metric-label-small">Saturation</div> 532 + <div class="metric-content-small"> 533 + <div class="metric-value-small">25%</div> 534 + <div class="metric-bar-small"> 535 + <div class="metric-bar-fill-small saturation" style="width: 25%"></div> 536 + </div> 537 + </div> 538 + </div> 539 + <div class="metric-small"> 540 + <div class="metric-label-small">Error Rate</div> 541 + <div class="metric-content-small"> 542 + <div class="metric-value-small">0.1%</div> 543 + <div class="metric-bar-small"> 544 + <div class="metric-bar-fill-small error" style="width: 1%"></div> 545 + </div> 546 + </div> 547 + </div> 548 + <div class="metric-small"> 549 + <div class="metric-label-small">Latency</div> 550 + <div class="metric-content-small"> 551 + <div class="metric-value-small">42ms</div> 552 + <div class="metric-bar-small"> 553 + <div class="metric-bar-fill-small latency" style="width: 42%"></div> 554 + </div> 555 + </div> 556 + </div> 557 + </div> 558 + </div> 559 + 560 + <div class="instance-item"> 561 + <span class="instance-name-small">api-instance-2</span> 562 + <div class="metrics-container-small"> 563 + <div class="metric-small"> 564 + <div class="metric-label-small">Usage</div> 565 + <div class="metric-content-small"> 566 + <div class="metric-value-small">65%</div> 567 + <div class="metric-bar-small"> 568 + <div class="metric-bar-fill-small usage" style="width: 65%"></div> 569 + </div> 570 + </div> 571 + </div> 572 + <div class="metric-small"> 573 + <div class="metric-label-small">Saturation</div> 574 + <div class="metric-content-small"> 575 + <div class="metric-value-small">30%</div> 576 + <div class="metric-bar-small"> 577 + <div class="metric-bar-fill-small saturation" style="width: 30%"></div> 578 + </div> 579 + </div> 580 + </div> 581 + <div class="metric-small"> 582 + <div class="metric-label-small">Error Rate</div> 583 + <div class="metric-content-small"> 584 + <div class="metric-value-small">0.3%</div> 585 + <div class="metric-bar-small"> 586 + <div class="metric-bar-fill-small error" style="width: 3%"></div> 587 + </div> 588 + </div> 589 + </div> 590 + <div class="metric-small"> 591 + <div class="metric-label-small">Latency</div> 592 + <div class="metric-content-small"> 593 + <div class="metric-value-small">48ms</div> 594 + <div class="metric-bar-small"> 595 + <div class="metric-bar-fill-small latency" style="width: 48%"></div> 596 + </div> 597 + </div> 598 + </div> 599 + </div> 600 + </div> 601 + 602 + <div class="instance-item"> 603 + <span class="instance-name-small">api-instance-3</span> 604 + <div class="metrics-container-small"> 605 + <div class="metric-small"> 606 + <div class="metric-label-small">Usage</div> 607 + <div class="metric-content-small"> 608 + <div class="metric-value-small">63%</div> 609 + <div class="metric-bar-small"> 610 + <div class="metric-bar-fill-small usage" style="width: 63%"></div> 611 + </div> 612 + </div> 613 + </div> 614 + <div class="metric-small"> 615 + <div class="metric-label-small">Saturation</div> 616 + <div class="metric-content-small"> 617 + <div class="metric-value-small">28%</div> 618 + <div class="metric-bar-small"> 619 + <div class="metric-bar-fill-small saturation" style="width: 28%"></div> 620 + </div> 621 + </div> 622 + </div> 623 + <div class="metric-small"> 624 + <div class="metric-label-small">Error Rate</div> 625 + <div class="metric-content-small"> 626 + <div class="metric-value-small">0.2%</div> 627 + <div class="metric-bar-small"> 628 + <div class="metric-bar-fill-small error" style="width: 2%"></div> 629 + </div> 630 + </div> 631 + </div> 632 + <div class="metric-small"> 633 + <div class="metric-label-small">Latency</div> 634 + <div class="metric-content-small"> 635 + <div class="metric-value-small">45ms</div> 636 + <div class="metric-bar-small"> 637 + <div class="metric-bar-fill-small latency" style="width: 45%"></div> 638 + </div> 639 + </div> 640 + </div> 309 641 </div> 310 642 </div> 311 643 </div> 312 644 </div> 645 + </div> 313 646 314 - <button class="add-subinstance-btn" title="Add subinstance">+</button> 315 - </div> 647 + <!-- Cluster 2 --> 648 + <div class="cluster-card"> 649 + <div class="cluster-header" onclick="toggleCluster(this)"> 650 + <div class="expand-icon">▼</div> 651 + <div class="heartbeat warning">♥</div> 652 + <span class="cluster-name">Database Cluster</span> 653 + 654 + <div class="metrics-container"> 655 + <div class="metric"> 656 + <div class="metric-label">Usage</div> 657 + <div class="metric-content"> 658 + <div class="metric-value">85%</div> 659 + <div class="metric-bar"> 660 + <div class="metric-bar-fill usage" style="width: 85%"></div> 661 + </div> 662 + </div> 663 + </div> 664 + 665 + <div class="metric"> 666 + <div class="metric-label">Saturation</div> 667 + <div class="metric-content"> 668 + <div class="metric-value">72%</div> 669 + <div class="metric-bar"> 670 + <div class="metric-bar-fill saturation" style="width: 72%"></div> 671 + </div> 672 + </div> 673 + </div> 316 674 317 - <!-- Instance 2 --> 318 - <div class="instance-card"> 319 - <div class="heartbeat warning">♥</div> 320 - <span class="instance-name">Database</span> 321 - 322 - <div class="metrics-container"> 323 - <div class="metric"> 324 - <div class="metric-label">Usage</div> 325 - <div class="metric-content"> 326 - <div class="metric-value">85%</div> 327 - <div class="metric-bar"> 328 - <div class="metric-bar-fill usage" style="width: 85%"></div> 675 + <div class="metric"> 676 + <div class="metric-label">Error Rate</div> 677 + <div class="metric-content"> 678 + <div class="metric-value">1.5%</div> 679 + <div class="metric-bar"> 680 + <div class="metric-bar-fill error" style="width: 15%"></div> 681 + </div> 329 682 </div> 330 683 </div> 331 - </div> 332 684 333 - <div class="metric"> 334 - <div class="metric-label">Saturation</div> 335 - <div class="metric-content"> 336 - <div class="metric-value">72%</div> 337 - <div class="metric-bar"> 338 - <div class="metric-bar-fill saturation" style="width: 72%"></div> 685 + <div class="metric"> 686 + <div class="metric-label">Latency</div> 687 + <div class="metric-content"> 688 + <div class="metric-value">125ms</div> 689 + <div class="metric-bar"> 690 + <div class="metric-bar-fill latency" style="width: 70%"></div> 691 + </div> 339 692 </div> 340 693 </div> 341 694 </div> 342 695 343 - <div class="metric"> 344 - <div class="metric-label">Error Rate</div> 345 - <div class="metric-content"> 346 - <div class="metric-value">1.5%</div> 347 - <div class="metric-bar"> 348 - <div class="metric-bar-fill error" style="width: 15%"></div> 349 - </div> 696 + <div class="menu-container"> 697 + <button class="menu-button" onclick="toggleMenu(event)">☰</button> 698 + <div class="menu-dropdown"> 699 + <button class="menu-item" onclick="action('backup', 'Database Cluster')"> 700 + <span class="menu-item-icon">💾</span> 701 + <span>Trigger Backup</span> 702 + </button> 703 + <button class="menu-item" onclick="action('reboot', 'Database Cluster')"> 704 + <span class="menu-item-icon">🔄</span> 705 + <span>Reboot</span> 706 + </button> 707 + <button class="menu-item danger" onclick="action('delete', 'Database Cluster')"> 708 + <span class="menu-item-icon">🗑️</span> 709 + <span>Delete</span> 710 + </button> 350 711 </div> 351 712 </div> 713 + </div> 352 714 353 - <div class="metric"> 354 - <div class="metric-label">Latency</div> 355 - <div class="metric-content"> 356 - <div class="metric-value">125ms</div> 357 - <div class="metric-bar"> 358 - <div class="metric-bar-fill latency" style="width: 70%"></div> 715 + <div class="cluster-content"> 716 + <div class="instances-container"> 717 + <div class="instance-item"> 718 + <span class="instance-name-small">db-primary</span> 719 + <div class="metrics-container-small"> 720 + <div class="metric-small"> 721 + <div class="metric-label-small">Usage</div> 722 + <div class="metric-content-small"> 723 + <div class="metric-value-small">88%</div> 724 + <div class="metric-bar-small"> 725 + <div class="metric-bar-fill-small usage" style="width: 88%"></div> 726 + </div> 727 + </div> 728 + </div> 729 + <div class="metric-small"> 730 + <div class="metric-label-small">Saturation</div> 731 + <div class="metric-content-small"> 732 + <div class="metric-value-small">75%</div> 733 + <div class="metric-bar-small"> 734 + <div class="metric-bar-fill-small saturation" style="width: 75%"></div> 735 + </div> 736 + </div> 737 + </div> 738 + <div class="metric-small"> 739 + <div class="metric-label-small">Error Rate</div> 740 + <div class="metric-content-small"> 741 + <div class="metric-value-small">1.2%</div> 742 + <div class="metric-bar-small"> 743 + <div class="metric-bar-fill-small error" style="width: 12%"></div> 744 + </div> 745 + </div> 746 + </div> 747 + <div class="metric-small"> 748 + <div class="metric-label-small">Latency</div> 749 + <div class="metric-content-small"> 750 + <div class="metric-value-small">120ms</div> 751 + <div class="metric-bar-small"> 752 + <div class="metric-bar-fill-small latency" style="width: 68%"></div> 753 + </div> 754 + </div> 755 + </div> 756 + </div> 757 + </div> 758 + 759 + <div class="instance-item"> 760 + <span class="instance-name-small">db-replica-1</span> 761 + <div class="metrics-container-small"> 762 + <div class="metric-small"> 763 + <div class="metric-label-small">Usage</div> 764 + <div class="metric-content-small"> 765 + <div class="metric-value-small">82%</div> 766 + <div class="metric-bar-small"> 767 + <div class="metric-bar-fill-small usage" style="width: 82%"></div> 768 + </div> 769 + </div> 770 + </div> 771 + <div class="metric-small"> 772 + <div class="metric-label-small">Saturation</div> 773 + <div class="metric-content-small"> 774 + <div class="metric-value-small">70%</div> 775 + <div class="metric-bar-small"> 776 + <div class="metric-bar-fill-small saturation" style="width: 70%"></div> 777 + </div> 778 + </div> 779 + </div> 780 + <div class="metric-small"> 781 + <div class="metric-label-small">Error Rate</div> 782 + <div class="metric-content-small"> 783 + <div class="metric-value-small">1.8%</div> 784 + <div class="metric-bar-small"> 785 + <div class="metric-bar-fill-small error" style="width: 18%"></div> 786 + </div> 787 + </div> 788 + </div> 789 + <div class="metric-small"> 790 + <div class="metric-label-small">Latency</div> 791 + <div class="metric-content-small"> 792 + <div class="metric-value-small">130ms</div> 793 + <div class="metric-bar-small"> 794 + <div class="metric-bar-fill-small latency" style="width: 72%"></div> 795 + </div> 796 + </div> 797 + </div> 798 + </div> 799 + </div> 800 + 801 + <div class="instance-item"> 802 + <span class="instance-name-small">db-replica-2</span> 803 + <div class="metrics-container-small"> 804 + <div class="metric-small"> 805 + <div class="metric-label-small">Usage</div> 806 + <div class="metric-content-small"> 807 + <div class="metric-value-small">85%</div> 808 + <div class="metric-bar-small"> 809 + <div class="metric-bar-fill-small usage" style="width: 85%"></div> 810 + </div> 811 + </div> 812 + </div> 813 + <div class="metric-small"> 814 + <div class="metric-label-small">Saturation</div> 815 + <div class="metric-content-small"> 816 + <div class="metric-value-small">72%</div> 817 + <div class="metric-bar-small"> 818 + <div class="metric-bar-fill-small saturation" style="width: 72%"></div> 819 + </div> 820 + </div> 821 + </div> 822 + <div class="metric-small"> 823 + <div class="metric-label-small">Error Rate</div> 824 + <div class="metric-content-small"> 825 + <div class="metric-value-small">1.5%</div> 826 + <div class="metric-bar-small"> 827 + <div class="metric-bar-fill-small error" style="width: 15%"></div> 828 + </div> 829 + </div> 830 + </div> 831 + <div class="metric-small"> 832 + <div class="metric-label-small">Latency</div> 833 + <div class="metric-content-small"> 834 + <div class="metric-value-small">125ms</div> 835 + <div class="metric-bar-small"> 836 + <div class="metric-bar-fill-small latency" style="width: 70%"></div> 837 + </div> 838 + </div> 839 + </div> 359 840 </div> 360 841 </div> 361 842 </div> 362 843 </div> 844 + </div> 363 845 364 - <button class="add-subinstance-btn" title="Add subinstance">+</button> 365 - </div> 846 + <!-- Cluster 3 --> 847 + <div class="cluster-card"> 848 + <div class="cluster-header" onclick="toggleCluster(this)"> 849 + <div class="expand-icon">▼</div> 850 + <div class="heartbeat critical">♥</div> 851 + <span class="cluster-name">Cache Cluster</span> 852 + 853 + <div class="metrics-container"> 854 + <div class="metric"> 855 + <div class="metric-label">Usage</div> 856 + <div class="metric-content"> 857 + <div class="metric-value">92%</div> 858 + <div class="metric-bar"> 859 + <div class="metric-bar-fill usage" style="width: 92%"></div> 860 + </div> 861 + </div> 862 + </div> 863 + 864 + <div class="metric"> 865 + <div class="metric-label">Saturation</div> 866 + <div class="metric-content"> 867 + <div class="metric-value">88%</div> 868 + <div class="metric-bar"> 869 + <div class="metric-bar-fill saturation" style="width: 88%"></div> 870 + </div> 871 + </div> 872 + </div> 873 + 874 + <div class="metric"> 875 + <div class="metric-label">Error Rate</div> 876 + <div class="metric-content"> 877 + <div class="metric-value">5.8%</div> 878 + <div class="metric-bar"> 879 + <div class="metric-bar-fill error" style="width: 58%"></div> 880 + </div> 881 + </div> 882 + </div> 366 883 367 - <!-- Instance 3 --> 368 - <div class="instance-card"> 369 - <div class="heartbeat critical">♥</div> 370 - <span class="instance-name">Cache Service</span> 371 - 372 - <div class="metrics-container"> 373 - <div class="metric"> 374 - <div class="metric-label">Usage</div> 375 - <div class="metric-content"> 376 - <div class="metric-value">92%</div> 377 - <div class="metric-bar"> 378 - <div class="metric-bar-fill usage" style="width: 92%"></div> 884 + <div class="metric"> 885 + <div class="metric-label">Latency</div> 886 + <div class="metric-content"> 887 + <div class="metric-value">340ms</div> 888 + <div class="metric-bar"> 889 + <div class="metric-bar-fill latency" style="width: 95%"></div> 890 + </div> 379 891 </div> 380 892 </div> 381 893 </div> 382 894 383 - <div class="metric"> 384 - <div class="metric-label">Saturation</div> 385 - <div class="metric-content"> 386 - <div class="metric-value">88%</div> 387 - <div class="metric-bar"> 388 - <div class="metric-bar-fill saturation" style="width: 88%"></div> 895 + <div class="menu-container"> 896 + <button class="menu-button" onclick="toggleMenu(event)">☰</button> 897 + <div class="menu-dropdown"> 898 + <button class="menu-item" onclick="action('backup', 'Cache Cluster')"> 899 + <span class="menu-item-icon">💾</span> 900 + <span>Trigger Backup</span> 901 + </button> 902 + <button class="menu-item" onclick="action('reboot', 'Cache Cluster')"> 903 + <span class="menu-item-icon">🔄</span> 904 + <span>Reboot</span> 905 + </button> 906 + <button class="menu-item danger" onclick="action('delete', 'Cache Cluster')"> 907 + <span class="menu-item-icon">🗑️</span> 908 + <span>Delete</span> 909 + </button> 910 + </div> 911 + </div> 912 + </div> 913 + 914 + <div class="cluster-content"> 915 + <div class="instances-container"> 916 + <div class="instance-item"> 917 + <span class="instance-name-small">cache-1</span> 918 + <div class="metrics-container-small"> 919 + <div class="metric-small"> 920 + <div class="metric-label-small">Usage</div> 921 + <div class="metric-content-small"> 922 + <div class="metric-value-small">91%</div> 923 + <div class="metric-bar-small"> 924 + <div class="metric-bar-fill-small usage" style="width: 91%"></div> 925 + </div> 926 + </div> 927 + </div> 928 + <div class="metric-small"> 929 + <div class="metric-label-small">Saturation</div> 930 + <div class="metric-content-small"> 931 + <div class="metric-value-small">86%</div> 932 + <div class="metric-bar-small"> 933 + <div class="metric-bar-fill-small saturation" style="width: 86%"></div> 934 + </div> 935 + </div> 936 + </div> 937 + <div class="metric-small"> 938 + <div class="metric-label-small">Error Rate</div> 939 + <div class="metric-content-small"> 940 + <div class="metric-value-small">5.5%</div> 941 + <div class="metric-bar-small"> 942 + <div class="metric-bar-fill-small error" style="width: 55%"></div> 943 + </div> 944 + </div> 945 + </div> 946 + <div class="metric-small"> 947 + <div class="metric-label-small">Latency</div> 948 + <div class="metric-content-small"> 949 + <div class="metric-value-small">335ms</div> 950 + <div class="metric-bar-small"> 951 + <div class="metric-bar-fill-small latency" style="width: 94%"></div> 952 + </div> 953 + </div> 954 + </div> 389 955 </div> 390 956 </div> 391 - </div> 392 957 393 - <div class="metric"> 394 - <div class="metric-label">Error Rate</div> 395 - <div class="metric-content"> 396 - <div class="metric-value">5.8%</div> 397 - <div class="metric-bar"> 398 - <div class="metric-bar-fill error" style="width: 58%"></div> 958 + <div class="instance-item"> 959 + <span class="instance-name-small">cache-2</span> 960 + <div class="metrics-container-small"> 961 + <div class="metric-small"> 962 + <div class="metric-label-small">Usage</div> 963 + <div class="metric-content-small"> 964 + <div class="metric-value-small">93%</div> 965 + <div class="metric-bar-small"> 966 + <div class="metric-bar-fill-small usage" style="width: 93%"></div> 967 + </div> 968 + </div> 969 + </div> 970 + <div class="metric-small"> 971 + <div class="metric-label-small">Saturation</div> 972 + <div class="metric-content-small"> 973 + <div class="metric-value-small">89%</div> 974 + <div class="metric-bar-small"> 975 + <div class="metric-bar-fill-small saturation" style="width: 89%"></div> 976 + </div> 977 + </div> 978 + </div> 979 + <div class="metric-small"> 980 + <div class="metric-label-small">Error Rate</div> 981 + <div class="metric-content-small"> 982 + <div class="metric-value-small">6.2%</div> 983 + <div class="metric-bar-small"> 984 + <div class="metric-bar-fill-small error" style="width: 62%"></div> 985 + </div> 986 + </div> 987 + </div> 988 + <div class="metric-small"> 989 + <div class="metric-label-small">Latency</div> 990 + <div class="metric-content-small"> 991 + <div class="metric-value-small">345ms</div> 992 + <div class="metric-bar-small"> 993 + <div class="metric-bar-fill-small latency" style="width: 96%"></div> 994 + </div> 995 + </div> 996 + </div> 399 997 </div> 400 998 </div> 401 - </div> 402 999 403 - <div class="metric"> 404 - <div class="metric-label">Latency</div> 405 - <div class="metric-content"> 406 - <div class="metric-value">340ms</div> 407 - <div class="metric-bar"> 408 - <div class="metric-bar-fill latency" style="width: 95%"></div> 1000 + <div class="instance-item"> 1001 + <span class="instance-name-small">cache-3</span> 1002 + <div class="metrics-container-small"> 1003 + <div class="metric-small"> 1004 + <div class="metric-label-small">Usage</div> 1005 + <div class="metric-content-small"> 1006 + <div class="metric-value-small">92%</div> 1007 + <div class="metric-bar-small"> 1008 + <div class="metric-bar-fill-small usage" style="width: 92%"></div> 1009 + </div> 1010 + </div> 1011 + </div> 1012 + <div class="metric-small"> 1013 + <div class="metric-label-small">Saturation</div> 1014 + <div class="metric-content-small"> 1015 + <div class="metric-value-small">88%</div> 1016 + <div class="metric-bar-small"> 1017 + <div class="metric-bar-fill-small saturation" style="width: 88%"></div> 1018 + </div> 1019 + </div> 1020 + </div> 1021 + <div class="metric-small"> 1022 + <div class="metric-label-small">Error Rate</div> 1023 + <div class="metric-content-small"> 1024 + <div class="metric-value-small">5.8%</div> 1025 + <div class="metric-bar-small"> 1026 + <div class="metric-bar-fill-small error" style="width: 58%"></div> 1027 + </div> 1028 + </div> 1029 + </div> 1030 + <div class="metric-small"> 1031 + <div class="metric-label-small">Latency</div> 1032 + <div class="metric-content-small"> 1033 + <div class="metric-value-small">340ms</div> 1034 + <div class="metric-bar-small"> 1035 + <div class="metric-bar-fill-small latency" style="width: 95%"></div> 1036 + </div> 1037 + </div> 1038 + </div> 409 1039 </div> 410 1040 </div> 411 1041 </div> 412 1042 </div> 413 - 414 - <button class="add-subinstance-btn" title="Add subinstance">+</button> 415 1043 </div> 416 1044 </div> 417 1045 </div> 418 1046 419 1047 <script> 420 - // Add event listeners to the plus buttons 421 - document.querySelectorAll('.add-subinstance-btn').forEach(btn => { 422 - btn.addEventListener('click', function(e) { 423 - e.preventDefault(); 424 - const instanceName = this.closest('.instance-card') 425 - .querySelector('.instance-name').textContent; 426 - alert(`Add subinstance to "${instanceName}"`); 427 - // Replace with actual implementation 1048 + function toggleCluster(header) { 1049 + const card = header.closest('.cluster-card'); 1050 + card.classList.toggle('expanded'); 1051 + } 1052 + 1053 + function toggleMenu(event) { 1054 + event.stopPropagation(); 1055 + const button = event.currentTarget; 1056 + const dropdown = button.nextElementSibling; 1057 + 1058 + // Close all other menus 1059 + document.querySelectorAll('.menu-dropdown.active').forEach(menu => { 1060 + if (menu !== dropdown) { 1061 + menu.classList.remove('active'); 1062 + } 1063 + }); 1064 + 1065 + dropdown.classList.toggle('active'); 1066 + } 1067 + 1068 + function action(type, clusterName) { 1069 + const actionNames = { 1070 + 'backup': 'Backup triggered', 1071 + 'reboot': 'Reboot initiated', 1072 + 'delete': 'Delete confirmation' 1073 + }; 1074 + 1075 + alert(`${actionNames[type]} for "${clusterName}"`); 1076 + 1077 + // Close the menu 1078 + document.querySelectorAll('.menu-dropdown').forEach(menu => { 1079 + menu.classList.remove('active'); 1080 + }); 1081 + } 1082 + 1083 + // Close menus when clicking outside 1084 + document.addEventListener('click', () => { 1085 + document.querySelectorAll('.menu-dropdown.active').forEach(menu => { 1086 + menu.classList.remove('active'); 428 1087 }); 429 1088 }); 430 1089 </script>