Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Quantum API Dashboard</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700&family=Major+Mono+Display&display=swap'); | |
| :root { | |
| --primary-hue: 210; | |
| --primary-saturation: 80%; | |
| --primary-lightness: 50%; | |
| } | |
| body { | |
| font-family: 'Orbitron', sans-serif; | |
| background: radial-gradient(circle at center, #0f172a 0%, #020617 100%); | |
| overflow: hidden; | |
| color: #e2e8f0; | |
| touch-action: none; | |
| } | |
| .dashboard { | |
| position: relative; | |
| width: 100vw; | |
| height: 100vh; | |
| perspective: 2000px; | |
| transform-style: preserve-3d; | |
| } | |
| .button-3d { | |
| position: absolute; | |
| width: 140px; | |
| height: 140px; | |
| border-radius: 20px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: move; | |
| user-select: none; | |
| transform-style: preserve-3d; | |
| transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); | |
| box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5); | |
| z-index: 10; | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(5px); | |
| background: linear-gradient(145deg, rgba(255,255,255,0.1), rgba(255,255,255,0.05)); | |
| } | |
| .button-3d:hover { | |
| transform: translateY(-8px) rotateX(15deg) scale(1.05); | |
| box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.6); | |
| z-index: 20; | |
| } | |
| .button-3d:active { | |
| transform: translateY(0) rotateX(0) scale(0.98); | |
| } | |
| .button-3d::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| border-radius: inherit; | |
| background: linear-gradient(135deg, rgba(255,255,255,0.2) 0%, transparent 50%); | |
| opacity: 0; | |
| transition: opacity 0.3s; | |
| } | |
| .button-3d:hover::before { | |
| opacity: 1; | |
| } | |
| .button-icon { | |
| font-size: 3rem; | |
| margin-bottom: 12px; | |
| text-shadow: 0 4px 8px rgba(0,0,0,0.4); | |
| transition: all 0.3s; | |
| } | |
| .button-label { | |
| font-size: 1rem; | |
| font-weight: 600; | |
| text-shadow: 0 2px 4px rgba(0,0,0,0.4); | |
| text-align: center; | |
| max-width: 90%; | |
| word-break: break-word; | |
| } | |
| .button-status { | |
| position: absolute; | |
| bottom: 10px; | |
| right: 10px; | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| background: #4ade80; | |
| box-shadow: 0 0 10px #4ade80; | |
| } | |
| .modal { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba(2, 6, 23, 0.95); | |
| backdrop-filter: blur(20px); | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| z-index: 1000; | |
| opacity: 0; | |
| pointer-events: none; | |
| transition: opacity 0.4s, transform 0.4s; | |
| transform: scale(0.9); | |
| } | |
| .modal-content { | |
| background: linear-gradient(145deg, rgba(30, 41, 59, 0.9), rgba(15, 23, 42, 0.9)); | |
| border-radius: 24px; | |
| width: 85%; | |
| max-width: 800px; | |
| max-height: 90vh; | |
| overflow-y: auto; | |
| padding: 2.5rem; | |
| box-shadow: 0 35px 60px -15px rgba(0, 0, 0, 0.7); | |
| border: 1px solid rgba(255, 255, 255, 0.15); | |
| transform: translateY(30px); | |
| transition: transform 0.4s; | |
| position: relative; | |
| } | |
| .modal.active { | |
| opacity: 1; | |
| pointer-events: all; | |
| transform: scale(1); | |
| } | |
| .modal.active .modal-content { | |
| transform: translateY(0); | |
| } | |
| .control-panel { | |
| position: fixed; | |
| bottom: 3rem; | |
| right: 3rem; | |
| z-index: 500; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1rem; | |
| } | |
| .control-button { | |
| width: 70px; | |
| height: 70px; | |
| border-radius: 50%; | |
| background: linear-gradient(145deg, hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)), | |
| hsl(var(--primary-hue), calc(var(--primary-saturation) - 10%), calc(var(--primary-lightness) - 10%))); | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| font-size: 1.8rem; | |
| color: white; | |
| box-shadow: 0 15px 25px -5px rgba(0, 0, 0, 0.4); | |
| cursor: pointer; | |
| transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .control-button::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(45deg, rgba(255,255,255,0.2) 0%, transparent 100%); | |
| opacity: 0; | |
| transition: opacity 0.3s; | |
| } | |
| .control-button:hover { | |
| transform: translateY(-5px) scale(1.1); | |
| box-shadow: 0 20px 30px -5px rgba(0, 0, 0, 0.5); | |
| } | |
| .control-button:hover::after { | |
| opacity: 1; | |
| } | |
| .control-button:active { | |
| transform: translateY(0) scale(0.98); | |
| } | |
| .grid-lines { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background-image: | |
| linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px); | |
| background-size: 60px 60px; | |
| z-index: 0; | |
| opacity: 0.7; | |
| } | |
| .particles { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: 1; | |
| pointer-events: none; | |
| } | |
| .particle { | |
| position: absolute; | |
| width: 2px; | |
| height: 2px; | |
| background: rgba(255,255,255,0.5); | |
| border-radius: 50%; | |
| animation: float 15s infinite linear; | |
| } | |
| @keyframes float { | |
| 0% { | |
| transform: translateY(0) translateX(0); | |
| opacity: 0; | |
| } | |
| 10% { | |
| opacity: 1; | |
| } | |
| 90% { | |
| opacity: 1; | |
| } | |
| 100% { | |
| transform: translateY(-100vh) translateX(20px); | |
| opacity: 0; | |
| } | |
| } | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 10px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: rgba(255, 255, 255, 0.05); | |
| border-radius: 10px; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| border-radius: 10px; | |
| } | |
| /* Form elements */ | |
| input, textarea, select { | |
| background-color: rgba(15, 23, 42, 0.7); | |
| border: 1px solid rgba(255, 255, 255, 0.15); | |
| border-radius: 12px; | |
| padding: 0.9rem 1.2rem; | |
| color: white; | |
| width: 100%; | |
| margin-bottom: 1rem; | |
| transition: all 0.3s; | |
| font-family: 'Orbitron', sans-serif; | |
| } | |
| input:focus, textarea:focus, select:focus { | |
| outline: none; | |
| border-color: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| box-shadow: 0 0 0 3px hsla(var(--primary-hue), var(--primary-saturation), var(--primary-lightness), 0.3); | |
| background-color: rgba(15, 23, 42, 0.9); | |
| } | |
| .form-label { | |
| display: block; | |
| margin-bottom: 0.7rem; | |
| font-weight: 600; | |
| font-size: 0.95rem; | |
| letter-spacing: 0.5px; | |
| } | |
| .btn { | |
| background: linear-gradient(145deg, hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)), | |
| hsl(var(--primary-hue), calc(var(--primary-saturation) - 10%), calc(var(--primary-lightness) - 10%))); | |
| color: white; | |
| border: none; | |
| padding: 1rem 2rem; | |
| border-radius: 12px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); | |
| font-family: 'Orbitron', sans-serif; | |
| letter-spacing: 0.5px; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .btn::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(45deg, rgba(255,255,255,0.2) 0%, transparent 100%); | |
| opacity: 0; | |
| transition: opacity 0.3s; | |
| } | |
| .btn:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 15px 25px -5px rgba(0, 0, 0, 0.4); | |
| } | |
| .btn:hover::after { | |
| opacity: 1; | |
| } | |
| .btn:active { | |
| transform: translateY(0); | |
| } | |
| .btn-secondary { | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(10px); | |
| } | |
| .btn-secondary:hover { | |
| background: rgba(255, 255, 255, 0.15); | |
| } | |
| .color-option { | |
| width: 30px; | |
| height: 30px; | |
| border-radius: 50%; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| border: 2px solid transparent; | |
| } | |
| .color-option:hover { | |
| transform: scale(1.1); | |
| } | |
| .color-option.active { | |
| transform: scale(1.2); | |
| border: 2px solid white; | |
| box-shadow: 0 0 10px rgba(255,255,255,0.5); | |
| } | |
| .tab { | |
| padding: 0.8rem 1.5rem; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| font-weight: 500; | |
| background: transparent; | |
| color: rgba(255,255,255,0.7); | |
| } | |
| .tab.active { | |
| background: rgba(255,255,255,0.1); | |
| color: white; | |
| font-weight: 600; | |
| } | |
| .tab:hover:not(.active) { | |
| background: rgba(255,255,255,0.05); | |
| } | |
| .tab-content { | |
| display: none; | |
| } | |
| .tab-content.active { | |
| display: block; | |
| animation: fadeIn 0.4s; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .response-tabs { | |
| display: flex; | |
| border-bottom: 1px solid rgba(255,255,255,0.1); | |
| margin-bottom: 1.5rem; | |
| } | |
| .response-tab { | |
| padding: 0.7rem 1.5rem; | |
| cursor: pointer; | |
| border-bottom: 3px solid transparent; | |
| transition: all 0.3s; | |
| font-size: 0.9rem; | |
| color: rgba(255,255,255,0.7); | |
| } | |
| .response-tab.active { | |
| border-bottom: 3px solid hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| color: white; | |
| } | |
| .response-tab:hover:not(.active) { | |
| color: white; | |
| } | |
| .response-content { | |
| display: none; | |
| } | |
| .response-content.active { | |
| display: block; | |
| } | |
| .code-block { | |
| background: rgba(0,0,0,0.3); | |
| border-radius: 8px; | |
| padding: 1rem; | |
| font-family: 'Major Mono Display', monospace; | |
| font-size: 0.85rem; | |
| line-height: 1.6; | |
| overflow-x: auto; | |
| margin-bottom: 1rem; | |
| } | |
| .connection-line { | |
| position: absolute; | |
| background: rgba(255,255,255,0.2); | |
| height: 2px; | |
| transform-origin: left center; | |
| z-index: 5; | |
| pointer-events: none; | |
| } | |
| .connection-line::after { | |
| content: ''; | |
| position: absolute; | |
| right: 0; | |
| top: 50%; | |
| width: 10px; | |
| height: 10px; | |
| background: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| border-radius: 50%; | |
| transform: translateY(-50%); | |
| box-shadow: 0 0 10px hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| } | |
| .connection-mode { | |
| position: absolute; | |
| background: rgba(15, 23, 42, 0.9); | |
| border: 1px solid rgba(255,255,255,0.2); | |
| padding: 0.3rem 0.6rem; | |
| border-radius: 20px; | |
| font-size: 0.7rem; | |
| z-index: 6; | |
| pointer-events: none; | |
| transform: translate(-50%, -50%); | |
| } | |
| .mini-map { | |
| position: fixed; | |
| bottom: 3rem; | |
| left: 3rem; | |
| width: 200px; | |
| height: 200px; | |
| background: rgba(15, 23, 42, 0.7); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| border-radius: 8px; | |
| z-index: 500; | |
| overflow: hidden; | |
| backdrop-filter: blur(5px); | |
| } | |
| .mini-map-viewport { | |
| position: absolute; | |
| border: 2px solid hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| background: rgba(59, 130, 246, 0.2); | |
| z-index: 2; | |
| } | |
| .mini-map-content { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| transform-origin: 0 0; | |
| } | |
| .mini-map-button { | |
| position: absolute; | |
| width: 6px; | |
| height: 6px; | |
| border-radius: 50%; | |
| transform: translate(-50%, -50%); | |
| } | |
| .context-menu { | |
| position: absolute; | |
| background: rgba(30, 41, 59, 0.95); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| border-radius: 8px; | |
| box-shadow: 0 10px 25px -5px rgba(0,0,0,0.5); | |
| z-index: 1000; | |
| backdrop-filter: blur(10px); | |
| display: none; | |
| overflow: hidden; | |
| } | |
| .context-menu-item { | |
| padding: 0.8rem 1.5rem; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.8rem; | |
| } | |
| .context-menu-item:hover { | |
| background: rgba(255,255,255,0.1); | |
| } | |
| .context-menu-item i { | |
| width: 20px; | |
| text-align: center; | |
| } | |
| .dashboard-overlay { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: 5; | |
| pointer-events: none; | |
| } | |
| .dashboard-title { | |
| position: absolute; | |
| top: 2rem; | |
| left: 2rem; | |
| font-size: 1.8rem; | |
| font-weight: 700; | |
| z-index: 10; | |
| background: linear-gradient(to right, #fff, #aaa); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| text-shadow: 0 2px 10px rgba(0,0,0,0.3); | |
| } | |
| .dashboard-subtitle { | |
| position: absolute; | |
| top: 4.5rem; | |
| left: 2rem; | |
| font-size: 1rem; | |
| color: rgba(255,255,255,0.7); | |
| z-index: 10; | |
| max-width: 300px; | |
| } | |
| .dashboard-bg { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: radial-gradient(circle at 20% 30%, hsla(var(--primary-hue), 50%, 30%, 0.3) 0%, transparent 50%), | |
| radial-gradient(circle at 80% 70%, hsla(calc(var(--primary-hue) + 60), 50%, 30%, 0.3) 0%, transparent 50%); | |
| z-index: 0; | |
| transition: all 1s; | |
| } | |
| .connection-mode-selector { | |
| position: absolute; | |
| top: 0; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| background: rgba(30, 41, 59, 0.9); | |
| border-radius: 0 0 8px 8px; | |
| padding: 0.5rem 1rem; | |
| display: flex; | |
| gap: 0.5rem; | |
| z-index: 100; | |
| border: 1px solid rgba(255,255,255,0.1); | |
| border-top: none; | |
| } | |
| .connection-mode-btn { | |
| padding: 0.3rem 0.8rem; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| font-size: 0.8rem; | |
| transition: all 0.2s; | |
| } | |
| .connection-mode-btn.active { | |
| background: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| color: white; | |
| } | |
| .connection-mode-btn:not(.active):hover { | |
| background: rgba(255,255,255,0.1); | |
| } | |
| .button-tags { | |
| position: absolute; | |
| top: 10px; | |
| left: 10px; | |
| display: flex; | |
| gap: 5px; | |
| flex-wrap: wrap; | |
| max-width: 80%; | |
| } | |
| .button-tag { | |
| background: rgba(0,0,0,0.3); | |
| border-radius: 4px; | |
| padding: 2px 6px; | |
| font-size: 0.6rem; | |
| color: rgba(255,255,255,0.8); | |
| white-space: nowrap; | |
| } | |
| .button-actions { | |
| position: absolute; | |
| top: 10px; | |
| right: 10px; | |
| display: none; | |
| gap: 5px; | |
| } | |
| .button-3d:hover .button-actions { | |
| display: flex; | |
| } | |
| .button-action { | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 4px; | |
| background: rgba(0,0,0,0.3); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 0.7rem; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| } | |
| .button-action:hover { | |
| background: rgba(255,255,255,0.2); | |
| } | |
| .button-group { | |
| position: absolute; | |
| border: 2px dashed rgba(255,255,255,0.3); | |
| border-radius: 8px; | |
| z-index: 4; | |
| background: rgba(59, 130, 246, 0.1); | |
| display: none; | |
| } | |
| .button-group.active { | |
| display: block; | |
| } | |
| .button-group-label { | |
| position: absolute; | |
| top: -25px; | |
| left: 0; | |
| background: rgba(30, 41, 59, 0.9); | |
| padding: 0.3rem 0.6rem; | |
| border-radius: 4px; | |
| font-size: 0.8rem; | |
| white-space: nowrap; | |
| } | |
| .dashboard-toolbar { | |
| position: absolute; | |
| top: 2rem; | |
| right: 2rem; | |
| display: flex; | |
| gap: 1rem; | |
| z-index: 10; | |
| } | |
| .toolbar-btn { | |
| padding: 0.5rem 1rem; | |
| border-radius: 6px; | |
| background: rgba(255,255,255,0.1); | |
| backdrop-filter: blur(5px); | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| font-size: 0.9rem; | |
| } | |
| .toolbar-btn:hover { | |
| background: rgba(255,255,255,0.2); | |
| } | |
| .toolbar-btn.active { | |
| background: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| color: white; | |
| } | |
| .search-bar { | |
| position: absolute; | |
| top: 2rem; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 300px; | |
| z-index: 10; | |
| } | |
| .search-input { | |
| width: 100%; | |
| padding: 0.7rem 1.2rem; | |
| border-radius: 30px; | |
| background: rgba(30, 41, 59, 0.8); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| color: white; | |
| font-size: 0.9rem; | |
| transition: all 0.3s; | |
| backdrop-filter: blur(5px); | |
| } | |
| .search-input:focus { | |
| outline: none; | |
| border-color: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| box-shadow: 0 0 0 3px hsla(var(--primary-hue), var(--primary-saturation), var(--primary-lightness), 0.3); | |
| width: 400px; | |
| } | |
| .search-results { | |
| position: absolute; | |
| top: 100%; | |
| left: 0; | |
| width: 100%; | |
| background: rgba(30, 41, 59, 0.95); | |
| border-radius: 0 0 12px 12px; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| display: none; | |
| box-shadow: 0 10px 25px -5px rgba(0,0,0,0.5); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| border-top: none; | |
| z-index: 100; | |
| } | |
| .search-result-item { | |
| padding: 0.8rem 1.2rem; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| border-bottom: 1px solid rgba(255,255,255,0.05); | |
| } | |
| .search-result-item:hover { | |
| background: rgba(255,255,255,0.1); | |
| } | |
| .search-result-item:last-child { | |
| border-bottom: none; | |
| } | |
| .search-result-icon { | |
| margin-right: 0.8rem; | |
| color: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| } | |
| .search-input.active + .search-results { | |
| display: block; | |
| } | |
| .dashboard-stats { | |
| position: absolute; | |
| bottom: 2rem; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| display: flex; | |
| gap: 1.5rem; | |
| background: rgba(30, 41, 59, 0.8); | |
| border-radius: 30px; | |
| padding: 0.7rem 1.5rem; | |
| z-index: 10; | |
| backdrop-filter: blur(5px); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| } | |
| .stat-item { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| } | |
| .stat-value { | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| color: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| } | |
| .stat-label { | |
| font-size: 0.7rem; | |
| opacity: 0.8; | |
| margin-top: 0.2rem; | |
| } | |
| .dashboard-help { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| background: rgba(30, 41, 59, 0.95); | |
| border-radius: 16px; | |
| padding: 2rem; | |
| max-width: 600px; | |
| width: 80%; | |
| max-height: 80vh; | |
| overflow-y: auto; | |
| z-index: 1000; | |
| box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.7); | |
| border: 1px solid rgba(255, 255, 255, 0.15); | |
| display: none; | |
| } | |
| .dashboard-help.active { | |
| display: block; | |
| animation: fadeIn 0.4s; | |
| } | |
| .help-close { | |
| position: absolute; | |
| top: 1rem; | |
| right: 1rem; | |
| cursor: pointer; | |
| font-size: 1.2rem; | |
| color: rgba(255,255,255,0.7); | |
| transition: all 0.2s; | |
| } | |
| .help-close:hover { | |
| color: white; | |
| } | |
| .help-section { | |
| margin-bottom: 2rem; | |
| } | |
| .help-title { | |
| font-size: 1.5rem; | |
| margin-bottom: 1rem; | |
| color: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| } | |
| .help-content { | |
| line-height: 1.6; | |
| color: rgba(255,255,255,0.8); | |
| } | |
| .help-shortcut { | |
| display: flex; | |
| justify-content: space-between; | |
| padding: 0.8rem 0; | |
| border-bottom: 1px solid rgba(255,255,255,0.1); | |
| } | |
| .help-shortcut:last-child { | |
| border-bottom: none; | |
| } | |
| .shortcut-keys { | |
| display: flex; | |
| gap: 0.5rem; | |
| } | |
| .shortcut-key { | |
| background: rgba(255,255,255,0.1); | |
| padding: 0.3rem 0.6rem; | |
| border-radius: 4px; | |
| font-family: 'Major Mono Display', monospace; | |
| } | |
| .api-visualizer { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: 1000; | |
| display: none; | |
| } | |
| .api-visualizer.active { | |
| display: block; | |
| } | |
| .visualizer-canvas { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .visualizer-controls { | |
| position: absolute; | |
| bottom: 2rem; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| display: flex; | |
| gap: 1rem; | |
| z-index: 1001; | |
| } | |
| .visualizer-btn { | |
| padding: 0.8rem 1.5rem; | |
| border-radius: 30px; | |
| background: rgba(30, 41, 59, 0.8); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| color: white; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| backdrop-filter: blur(5px); | |
| } | |
| .visualizer-btn:hover { | |
| background: rgba(255,255,255,0.1); | |
| } | |
| .visualizer-btn i { | |
| margin-right: 0.5rem; | |
| } | |
| .dashboard-tour { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: 10000; | |
| pointer-events: none; | |
| } | |
| .tour-highlight { | |
| position: absolute; | |
| border-radius: 8px; | |
| box-shadow: 0 0 0 9999px rgba(0,0,0,0.8), 0 0 0 3px hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| z-index: 10001; | |
| transition: all 0.3s; | |
| } | |
| .tour-tooltip { | |
| position: absolute; | |
| background: rgba(30, 41, 59, 0.95); | |
| border-radius: 8px; | |
| padding: 1.5rem; | |
| max-width: 300px; | |
| box-shadow: 0 10px 25px -5px rgba(0,0,0,0.5); | |
| border: 1px solid rgba(255,255,255,0.1); | |
| z-index: 10002; | |
| pointer-events: auto; | |
| } | |
| .tour-tooltip-title { | |
| font-size: 1.2rem; | |
| margin-bottom: 0.8rem; | |
| color: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| } | |
| .tour-tooltip-content { | |
| margin-bottom: 1.5rem; | |
| line-height: 1.5; | |
| } | |
| .tour-tooltip-footer { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .tour-progress { | |
| font-size: 0.8rem; | |
| opacity: 0.7; | |
| } | |
| .tour-btn { | |
| padding: 0.5rem 1rem; | |
| border-radius: 4px; | |
| background: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| color: white; | |
| cursor: pointer; | |
| transition: all 0.2s; | |
| } | |
| .tour-btn:hover { | |
| opacity: 0.9; | |
| } | |
| .tour-btn-secondary { | |
| background: rgba(255,255,255,0.1); | |
| } | |
| .dashboard-loading { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: #0f172a; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| z-index: 10000; | |
| } | |
| .loading-spinner { | |
| width: 50px; | |
| height: 50px; | |
| border: 5px solid rgba(255,255,255,0.1); | |
| border-radius: 50%; | |
| border-top-color: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| animation: spin 1s linear infinite; | |
| margin-bottom: 1.5rem; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| .loading-text { | |
| font-size: 1.2rem; | |
| letter-spacing: 2px; | |
| background: linear-gradient(to right, #fff, #aaa); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .loading-progress { | |
| width: 200px; | |
| height: 4px; | |
| background: rgba(255,255,255,0.1); | |
| border-radius: 2px; | |
| margin-top: 1.5rem; | |
| overflow: hidden; | |
| } | |
| .loading-progress-bar { | |
| height: 100%; | |
| background: hsl(var(--primary-hue), var(--primary-saturation), var(--primary-lightness)); | |
| width: 0%; | |
| transition: width 0.3s; | |
| } | |
| /* Responsive adjustments */ | |
| @media (max-width: 768px) { | |
| .dashboard-title, .dashboard-subtitle { | |
| left: 1rem; | |
| } | |
| .dashboard-toolbar { | |
| right: 1rem; | |
| top: 1rem; | |
| } | |
| .control-panel { | |
| right: 1rem; | |
| bottom: 1rem; | |
| } | |
| .mini-map { | |
| left: 1rem; | |
| bottom: 1rem; | |
| width: 150px; | |
| height: 150px; | |
| } | |
| .dashboard-stats { | |
| bottom: 1rem; | |
| padding: 0.5rem 1rem; | |
| gap: 1rem; | |
| } | |
| .search-bar { | |
| top: 1rem; | |
| width: 200px; | |
| } | |
| .search-input:focus { | |
| width: 250px; | |
| } | |
| .modal-content { | |
| width: 90%; | |
| padding: 1.5rem; | |
| } | |
| .button-3d { | |
| width: 100px; | |
| height: 100px; | |
| } | |
| .button-icon { | |
| font-size: 2rem; | |
| } | |
| .button-label { | |
| font-size: 0.8rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="dashboard-loading"> | |
| <div class="loading-spinner"></div> | |
| <div class="loading-text">QUANTUM DASHBOARD</div> | |
| <div class="loading-progress"> | |
| <div class="loading-progress-bar" id="loadingBar"></div> | |
| </div> | |
| </div> | |
| <div class="dashboard" id="dashboard"> | |
| <div class="dashboard-bg"></div> | |
| <div class="grid-lines"></div> | |
| <div class="particles" id="particles"></div> | |
| <div class="dashboard-overlay"></div> | |
| <div class="dashboard-title">Quantum API Dashboard</div> | |
| <div class="dashboard-subtitle">Visualize, connect and manage your API ecosystem in 3D space</div> | |
| <div class="dashboard-toolbar"> | |
| <div class="toolbar-btn" id="groupModeBtn"> | |
| <i class="fas fa-object-group"></i> Group Mode | |
| </div> | |
| <div class="toolbar-btn" id="connectionModeBtn"> | |
| <i class="fas fa-plug"></i> Connect APIs | |
| </div> | |
| <div class="toolbar-btn" id="visualizerBtn"> | |
| <i class="fas fa-project-diagram"></i> Visualizer | |
| </div> | |
| <div class="toolbar-btn" id="helpBtn"> | |
| <i class="fas fa-question-circle"></i> Help | |
| </div> | |
| </div> | |
| <div class="search-bar"> | |
| <input type="text" class="search-input" placeholder="Search APIs, endpoints, tags..." id="searchInput"> | |
| <div class="search-results" id="searchResults"></div> | |
| </div> | |
| <div class="dashboard-stats"> | |
| <div class="stat-item"> | |
| <div class="stat-value" id="apiCount">0</div> | |
| <div class="stat-label">APIs</div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-value" id="connectionCount">0</div> | |
| <div class="stat-label">Connections</div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-value" id="groupCount">0</div> | |
| <div class="stat-label">Groups</div> | |
| </div> | |
| <div class="stat-item"> | |
| <div class="stat-value" id="statusValue">100%</div> | |
| <div class="stat-label">Status</div> | |
| </div> | |
| </div> | |
| <!-- 3D Buttons will be added here dynamically --> | |
| <!-- Connection lines will be added here dynamically --> | |
| <!-- Button groups will be added here dynamically --> | |
| <!-- Connection mode selector (hidden by default) --> | |
| <div class="connection-mode-selector" id="connectionModeSelector" style="display: none;"> | |
| <div class="connection-mode-btn active" data-mode="sequential">Sequential</div> | |
| <div class="connection-mode-btn" data-mode="parallel">Parallel</div> | |
| <div class="connection-mode-btn" data-mode="conditional">Conditional</div> | |
| <div class="connection-mode-btn" data-mode="fallback">Fallback</div> | |
| </div> | |
| <!-- Control Panel --> | |
| <div class="control-panel"> | |
| <div class="control-button" id="settingsButton"> | |
| <i class="fas fa-cog"></i> | |
| </div> | |
| <div class="control-button" id="addButton"> | |
| <i class="fas fa-plus"></i> | |
| </div> | |
| <div class="control-button" id="minimapButton"> | |
| <i class="fas fa-map"></i> | |
| </div> | |
| </div> | |
| <!-- Mini Map --> | |
| <div class="mini-map" id="miniMap" style="display: none;"> | |
| <div class="mini-map-content" id="miniMapContent"></div> | |
| <div class="mini-map-viewport" id="miniMapViewport"></div> | |
| </div> | |
| </div> | |
| <!-- Context Menu --> | |
| <div class="context-menu" id="contextMenu"> | |
| <div class="context-menu-item" data-action="edit"> | |
| <i class="fas fa-edit"></i> Edit | |
| </div> | |
| <div class="context-menu-item" data-action="delete"> | |
| <i class="fas fa-trash"></i> Delete | |
| </div> | |
| <div class="context-menu-item" data-action="duplicate"> | |
| <i class="fas fa-copy"></i> Duplicate | |
| </div> | |
| <div class="context-menu-item" data-action="test"> | |
| <i class="fas fa-bolt"></i> Test API | |
| </div> | |
| <div class="context-menu-item" data-action="document"> | |
| <i class="fas fa-book"></i> Documentation | |
| </div> | |
| <div class="context-menu-item" data-action="group"> | |
| <i class="fas fa-object-group"></i> Create Group | |
| </div> | |
| </div> | |
| <!-- Settings Modal --> | |
| <div class="modal" id="settingsModal"> | |
| <div class="modal-content"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h2 class="text-2xl font-bold">Dashboard Settings</h2> | |
| <button class="text-gray-400 hover:text-white" id="closeSettings"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="response-tabs mb-6"> | |
| <div class="response-tab active" data-tab="appearance">Appearance</div> | |
| <div class="response-tab" data-tab="behavior">Behavior</div> | |
| <div class="response-tab" data-tab="shortcuts">Shortcuts</div> | |
| <div class="response-tab" data-tab="importexport">Import/Export</div> | |
| </div> | |
| <div class="tab-content active" data-tab-content="appearance"> | |
| <div class="mb-8"> | |
| <h3 class="text-xl font-semibold mb-4">Color Theme</h3> | |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6"> | |
| <div class="color-theme-option" data-theme="blue"> | |
| <div class="color-theme-preview bg-blue-500"></div> | |
| <div class="color-theme-label">Ocean</div> | |
| </div> | |
| <div class="color-theme-option" data-theme="purple"> | |
| <div class="color-theme-preview bg-purple-500"></div> | |
| <div class="color-theme-label">Royal</div> | |
| </div> | |
| <div class="color-theme-option" data-theme="green"> | |
| <div class="color-theme-preview bg-green-500"></div> | |
| <div class="color-theme-label">Emerald</div> | |
| </div> | |
| <div class="color-theme-option" data-theme="red"> | |
| <div class="color-theme-preview bg-red-500"></div> | |
| <div class="color-theme-label">Ruby</div> | |
| </div> | |
| <div class="color-theme-option" data-theme="yellow"> | |
| <div class="color-theme-preview bg-yellow-500"></div> | |
| <div class="color-theme-label">Gold</div> | |
| </div> | |
| <div class="color-theme-option" data-theme="pink"> | |
| <div class="color-theme-preview bg-pink-500"></div> | |
| <div class="color-theme-label">Rose</div> | |
| </div> | |
| <div class="color-theme-option" data-theme="indigo"> | |
| <div class="color-theme-preview bg-indigo-500"></div> | |
| <div class="color-theme-label">Sapphire</div> | |
| </div> | |
| <div class="color-theme-option" data-theme="teal"> | |
| <div class="color-theme-preview bg-teal-500"></div> | |
| <div class="color-theme-label">Aqua</div> | |
| </div> | |
| </div> | |
| <h3 class="text-xl font-semibold mb-4">Dashboard Appearance</h3> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6"> | |
| <div> | |
| <label class="form-label">Background Intensity</label> | |
| <input type="range" id="bgIntensity" min="0" max="100" value="50" class="w-full"> | |
| </div> | |
| <div> | |
| <label class="form-label">Grid Visibility</label> | |
| <select id="gridVisibility" class="bg-gray-800"> | |
| <option value="visible">Visible</option> | |
| <option value="hidden">Hidden</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="form-label">Particle Density</label> | |
| <input type="range" id="particleDensity" min="0" max="100" value="30" class="w-full"> | |
| </div> | |
| <div> | |
| <label class="form-label">Animation Speed</label> | |
| <select id="animationSpeed" class="bg-gray-800"> | |
| <option value="slow">Slow</option> | |
| <option value="normal" selected>Normal</option> | |
| <option value="fast">Fast</option> | |
| </select> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex space-x-3"> | |
| <button class="btn">Save Changes</button> | |
| <button class="btn btn-secondary">Reset Defaults</button> | |
| </div> | |
| </div> | |
| <div class="tab-content" data-tab-content="behavior"> | |
| <div class="mb-8"> | |
| <h3 class="text-xl font-semibold mb-4">Interaction Settings</h3> | |
| <div class="space-y-4 mb-6"> | |
| <div class="flex items-center justify-between"> | |
| <label class="form-label">Enable Hover Effects</label> | |
| <label class="switch"> | |
| <input type="checkbox" checked> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <label class="form-label">Enable Dragging</label> | |
| <label class="switch"> | |
| <input type="checkbox" checked> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <label class="form-label">Enable Context Menu</label> | |
| <label class="switch"> | |
| <input type="checkbox" checked> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <label class="form-label">Auto-arrange on Add</label> | |
| <label class="switch"> | |
| <input type="checkbox"> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| </div> | |
| <h3 class="text-xl font-semibold mb-4">API Behavior</h3> | |
| <div class="space-y-4 mb-6"> | |
| <div class="flex items-center justify-between"> | |
| <label class="form-label">Auto-test on Click</label> | |
| <label class="switch"> | |
| <input type="checkbox"> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <label class="form-label">Show Response by Default</label> | |
| <label class="switch"> | |
| <input type="checkbox"> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <label class="form-label">Cache Responses</label> | |
| <label class="switch"> | |
| <input type="checkbox" checked> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex space-x-3"> | |
| <button class="btn">Save Changes</button> | |
| <button class="btn btn-secondary">Reset Defaults</button> | |
| </div> | |
| </div> | |
| <div class="tab-content" data-tab-content="shortcuts"> | |
| <div class="mb-8"> | |
| <h3 class="text-xl font-semibold mb-4">Keyboard Shortcuts</h3> | |
| <div class="space-y-2"> | |
| <div class="help-shortcut"> | |
| <div>Add New API</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">Ctrl</span> | |
| <span class="shortcut-key">N</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Toggle Group Mode</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">G</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Toggle Connection Mode</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">C</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Open Settings</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">Ctrl</span> | |
| <span class="shortcut-key">,</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Search APIs</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">Ctrl</span> | |
| <span class="shortcut-key">K</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Toggle Mini Map</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">M</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex space-x-3"> | |
| <button class="btn">Save Changes</button> | |
| <button class="btn btn-secondary">Reset Defaults</button> | |
| </div> | |
| </div> | |
| <div class="tab-content" data-tab-content="importexport"> | |
| <div class="mb-8"> | |
| <h3 class="text-xl font-semibold mb-4">Import Configuration</h3> | |
| <div class="mb-6"> | |
| <label class="form-label">Import JSON Configuration</label> | |
| <textarea class="w-full h-32 font-mono text-sm" id="importJson" placeholder="Paste your JSON configuration here..."></textarea> | |
| </div> | |
| <div class="mb-6"> | |
| <label class="form-label">Or Upload File</label> | |
| <div class="border-2 border-dashed border-gray-700 rounded-lg p-8 text-center"> | |
| <i class="fas fa-file-upload text-3xl mb-2 text-gray-500"></i> | |
| <p class="text-gray-400 mb-4">Drag & drop your JSON file here, or click to browse</p> | |
| <button class="btn btn-secondary">Select File</button> | |
| </div> | |
| </div> | |
| <h3 class="text-xl font-semibold mb-4">Export Configuration</h3> | |
| <div class="mb-6"> | |
| <label class="form-label">Current Configuration</label> | |
| <textarea class="w-full h-32 font-mono text-sm" id="exportJson" readonly></textarea> | |
| </div> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <button class="btn btn-secondary">Copy to Clipboard</button> | |
| <button class="btn">Download JSON</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- API Browser Modal --> | |
| <div class="modal" id="apiModal"> | |
| <div class="modal-content"> | |
| <div class="flex justify-between items-center mb-6"> | |
| <h2 class="text-2xl font-bold" id="apiModalTitle">API Endpoint</h2> | |
| <button class="text-gray-400 hover:text-white" id="closeApiModal"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="mb-4"> | |
| <div class="flex items-center space-x-2 mb-2"> | |
| <span class="px-3 py-1 rounded-full bg-green-100 text-green-800 text-sm" id="apiMethod">GET</span> | |
| <span class="text-gray-300 text-sm truncate" id="apiUrl">https://api.val.town/v1/run/...</span> | |
| </div> | |
| <p class="text-gray-400" id="apiDescription">Accessing this API endpoint</p> | |
| </div> | |
| <div class="response-tabs mb-6"> | |
| <div class="response-tab active" data-tab="request">Request</div> | |
| <div class="response-tab" data-tab="documentation">Documentation</div> | |
| <div class="response-tab" data-tab="history">History</div> | |
| <div class="response-tab" data-tab="settings">Settings</div> | |
| </div> | |
| <div class="tab-content active" data-tab-content="request"> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Request Parameters</h3> | |
| <div class="space-y-3" id="parametersContainer"> | |
| <div class="flex items-center space-x-2"> | |
| <input type="text" placeholder="Parameter" class="flex-1" value="user_id"> | |
| <input type="text" placeholder="Value" class="flex-1" value="12345"> | |
| <button class="text-red-400 hover:text-red-300"> | |
| <i class="fas fa-trash"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <button class="text-blue-400 hover:text-blue-300 text-sm mt-2 flex items-center" id="addParameter"> | |
| <i class="fas fa-plus mr-1"></i> Add Parameter | |
| </button> | |
| </div> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Headers</h3> | |
| <div class="space-y-3" id="headersContainer"> | |
| <div class="flex items-center space-x-2"> | |
| <input type="text" value="Content-Type" class="flex-1 bg-gray-800"> | |
| <input type="text" value="application/json" class="flex-1 bg-gray-800"> | |
| <button class="text-red-400 hover:text-red-300"> | |
| <i class="fas fa-trash"></i> | |
| </button> | |
| </div> | |
| <div class="flex items-center space-x-2"> | |
| <input type="text" value="Authorization" class="flex-1 bg-gray-800"> | |
| <input type="text" placeholder="Bearer token..." class="flex-1"> | |
| <button class="text-red-400 hover:text-red-300"> | |
| <i class="fas fa-trash"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <button class="text-blue-400 hover:text-blue-300 text-sm mt-2 flex items-center" id="addHeader"> | |
| <i class="fas fa-plus mr-1"></i> Add Header | |
| </button> | |
| </div> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Request Body</h3> | |
| <textarea class="w-full h-32 font-mono text-sm" id="requestBody" placeholder="Enter JSON body..."></textarea> | |
| </div> | |
| <div class="flex justify-end space-x-3"> | |
| <button class="btn btn-secondary" id="testRequest"> | |
| <i class="fas fa-bolt mr-2"></i> Test Request | |
| </button> | |
| <button class="btn" id="sendRequest"> | |
| <i class="fas fa-paper-plane mr-2"></i> Send | |
| </button> | |
| </div> | |
| <div class="mt-8 border-t border-gray-700 pt-6" id="responseSection" style="display: none;"> | |
| <div class="response-tabs mb-4"> | |
| <div class="response-tab active" data-response-tab="body">Body</div> | |
| <div class="response-tab" data-response-tab="headers">Headers</div> | |
| <div class="response-tab" data-response-tab="cookies">Cookies</div> | |
| <div class="response-tab" data-response-tab="timing">Timing</div> | |
| </div> | |
| <div class="response-content active" data-response-content="body"> | |
| <div class="flex items-center space-x-2 mb-3"> | |
| <span class="px-3 py-1 rounded-full bg-green-100 text-green-800 text-sm">200 OK</span> | |
| <span class="text-gray-400 text-sm">1.2s</span> | |
| <span class="text-gray-400 text-sm">2.4 KB</span> | |
| </div> | |
| <pre class="bg-gray-800 p-4 rounded-lg overflow-x-auto text-sm font-mono" id="responseBody">{ | |
| "status": "success", | |
| "data": { | |
| "user_id": 12345, | |
| "name": "John Doe", | |
| "email": "john@example.com" | |
| } | |
| }</pre> | |
| </div> | |
| <div class="response-content" data-response-content="headers"> | |
| <div class="code-block"> | |
| HTTP/1.1 200 OK<br> | |
| Content-Type: application/json<br> | |
| Content-Length: 2345<br> | |
| Date: Wed, 21 Oct 2023 07:28:00 GMT<br> | |
| Server: nginx/1.18.0<br> | |
| Cache-Control: no-cache<br> | |
| Connection: keep-alive | |
| </div> | |
| </div> | |
| <div class="response-content" data-response-content="cookies"> | |
| <div class="code-block"> | |
| No cookies received | |
| </div> | |
| </div> | |
| <div class="response-content" data-response-content="timing"> | |
| <div class="code-block"> | |
| DNS Lookup: 120ms<br> | |
| TCP Connection: 80ms<br> | |
| TLS Handshake: 220ms<br> | |
| Request Sent: 5ms<br> | |
| Waiting (TTFB): 350ms<br> | |
| Content Download: 15ms<br> | |
| <br> | |
| Total: 790ms | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="tab-content" data-tab-content="documentation"> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Endpoint Description</h3> | |
| <div class="bg-gray-800 p-4 rounded-lg"> | |
| <p>This endpoint retrieves user profile information based on the provided user ID.</p> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Parameters</h3> | |
| <div class="overflow-x-auto"> | |
| <table class="w-full bg-gray-800 rounded-lg overflow-hidden"> | |
| <thead> | |
| <tr class="bg-gray-700"> | |
| <th class="p-3 text-left">Name</th> | |
| <th class="p-3 text-left">Type</th> | |
| <th class="p-3 text-left">Required</th> | |
| <th class="p-3 text-left">Description</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr class="border-b border-gray-700"> | |
| <td class="p-3">user_id</td> | |
| <td class="p-3">integer</td> | |
| <td class="p-3">Yes</td> | |
| <td class="p-3">The ID of the user to retrieve</td> | |
| </tr> | |
| <tr class="border-b border-gray-700"> | |
| <td class="p-3">fields</td> | |
| <td class="p-3">string</td> | |
| <td class="p-3">No</td> | |
| <td class="p-3">Comma-separated list of fields to return</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Response</h3> | |
| <div class="bg-gray-800 p-4 rounded-lg"> | |
| <h4 class="font-semibold mb-2">Success Response (200 OK)</h4> | |
| <pre class="font-mono text-sm">{ | |
| "status": "success", | |
| "data": { | |
| "user_id": 12345, | |
| "name": "John Doe", | |
| "email": "john@example.com", | |
| "created_at": "2023-01-15T08:30:00Z" | |
| } | |
| }</pre> | |
| <h4 class="font-semibold mt-4 mb-2">Error Response (404 Not Found)</h4> | |
| <pre class="font-mono text-sm">{ | |
| "status": "error", | |
| "message": "User not found", | |
| "code": 404 | |
| }</pre> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Example Code</h3> | |
| <div class="bg-gray-800 p-4 rounded-lg"> | |
| <h4 class="font-semibold mb-2">JavaScript (Fetch)</h4> | |
| <pre class="font-mono text-sm">fetch('https://api.example.com/users/12345') | |
| .then(response => response.json()) | |
| .then(data => console.log(data)) | |
| .catch(error => console.error('Error:', error));</pre> | |
| <h4 class="font-semibold mt-4 mb-2">cURL</h4> | |
| <pre class="font-mono text-sm">curl -X GET "https://api.example.com/users/12345" \ | |
| -H "Authorization: Bearer YOUR_TOKEN"</pre> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="tab-content" data-tab-content="history"> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Request History</h3> | |
| <div class="bg-gray-800 rounded-lg overflow-hidden"> | |
| <div class="history-item p-4 border-b border-gray-700"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <div class="flex items-center space-x-2"> | |
| <span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">200</span> | |
| <span class="text-sm">GET /users/12345</span> | |
| </div> | |
| <span class="text-xs text-gray-400">2 minutes ago</span> | |
| </div> | |
| <div class="text-xs text-gray-400 truncate">Response: {"status":"success","data":{"user_id":12345,"name":"John Doe"}}</div> | |
| </div> | |
| <div class="history-item p-4 border-b border-gray-700"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <div class="flex items-center space-x-2"> | |
| <span class="px-2 py-1 rounded-full bg-red-100 text-red-800 text-xs">404</span> | |
| <span class="text-sm">GET /users/99999</span> | |
| </div> | |
| <span class="text-xs text-gray-400">1 hour ago</span> | |
| </div> | |
| <div class="text-xs text-gray-400 truncate">Response: {"status":"error","message":"User not found"}</div> | |
| </div> | |
| <div class="history-item p-4"> | |
| <div class="flex justify-between items-center mb-2"> | |
| <div class="flex items-center space-x-2"> | |
| <span class="px-2 py-1 rounded-full bg-green-100 text-green-800 text-xs">200</span> | |
| <span class="text-sm">GET /users/12345</span> | |
| </div> | |
| <span class="text-xs text-gray-400">Yesterday</span> | |
| </div> | |
| <div class="text-xs text-gray-400 truncate">Response: {"status":"success","data":{"user_id":12345,"name":"John Doe"}}</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="tab-content" data-tab-content="settings"> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Endpoint Settings</h3> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="form-label">Endpoint Name</label> | |
| <input type="text" value="Get User Profile" class="w-full"> | |
| </div> | |
| <div> | |
| <label class="form-label">Endpoint URL</label> | |
| <input type="text" value="https://api.example.com/users/{user_id}" class="w-full"> | |
| </div> | |
| <div> | |
| <label class="form-label">HTTP Method</label> | |
| <select class="w-full"> | |
| <option>GET</option> | |
| <option>POST</option> | |
| <option>PUT</option> | |
| <option>DELETE</option> | |
| <option>PATCH</option> | |
| </select> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <label class="form-label">Cache Responses</label> | |
| <label class="switch"> | |
| <input type="checkbox" checked> | |
| <span class="slider"></span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <h3 class="text-lg font-semibold mb-3">Button Appearance</h3> | |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4"> | |
| <div> | |
| <label class="form-label">Icon</label> | |
| <select class="w-full"> | |
| <option value="fa-user">User</option> | |
| <option value="fa-database">Database</option> | |
| <option value="fa-plug">API</option> | |
| <option value="fa-bell">Notification</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="form-label">Color</label> | |
| <div class="flex space-x-2"> | |
| <div class="color-option bg-blue-500 active" data-color="blue"></div> | |
| <div class="color-option bg-purple-500" data-color="purple"></div> | |
| <div class="color-option bg-green-500" data-color="green"></div> | |
| <div class="color-option bg-red-500" data-color="red"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="flex space-x-3"> | |
| <button class="btn">Save Changes</button> | |
| <button class="btn btn-secondary">Reset</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Help Modal --> | |
| <div class="dashboard-help" id="helpModal"> | |
| <div class="help-close" id="closeHelp"> | |
| <i class="fas fa-times"></i> | |
| </div> | |
| <div class="help-section"> | |
| <h2 class="help-title">Quantum API Dashboard Guide</h2> | |
| <div class="help-content"> | |
| <p>Welcome to the Quantum API Dashboard, a revolutionary way to visualize, connect and manage your API ecosystem in 3D space.</p> | |
| </div> | |
| </div> | |
| <div class="help-section"> | |
| <h3 class="help-title">Getting Started</h3> | |
| <div class="help-content"> | |
| <p>To begin, add your first API endpoint by clicking the <strong>+</strong> button in the control panel. Configure the endpoint details and click "Add".</p> | |
| <p>You can then click on any API button to view and test the endpoint, or drag buttons to arrange them in your preferred layout.</p> | |
| </div> | |
| </div> | |
| <div class="help-section"> | |
| <h3 class="help-title">Key Features</h3> | |
| <div class="help-content"> | |
| <p><strong>3D Visualization:</strong> APIs are represented as interactive 3D buttons that respond to your mouse movements.</p> | |
| <p><strong>Connection Mode:</strong> Create visual connections between APIs to represent workflows and dependencies.</p> | |
| <p><strong>Grouping:</strong> Organize related APIs into logical groups for better organization.</p> | |
| <p><strong>Mini Map:</strong> Navigate large dashboards easily with the overview mini map.</p> | |
| <p><strong>Visualizer:</strong> See your API ecosystem in a dynamic 3D graph visualization.</p> | |
| </div> | |
| </div> | |
| <div class="help-section"> | |
| <h3 class="help-title">Keyboard Shortcuts</h3> | |
| <div class="help-content"> | |
| <div class="help-shortcut"> | |
| <div>Add New API</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">Ctrl</span> | |
| <span class="shortcut-key">N</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Toggle Group Mode</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">G</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Toggle Connection Mode</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">C</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Open Settings</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">Ctrl</span> | |
| <span class="shortcut-key">,</span> | |
| </div> | |
| </div> | |
| <div class="help-shortcut"> | |
| <div>Search APIs</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">Ctrl</span> | |
| <span class="shortcut-key">K</span> | |
| </div> | |
| </div> | |
| <!-- final shortcut row --> | |
| <div class="help-shortcut"> | |
| <div>Toggle Mini Map</div> | |
| <div class="shortcut-keys"> | |
| <span class="shortcut-key">M</span> | |
| </div> | |
| </div> | |
| </div> <!-- .help-content --> | |
| </div> <!-- .help-section (Keyboard Shortcuts) --> | |
| </div> <!-- #helpModal.dashboard-help --> | |
| <!-- ββββββββββββββββββββββ EXTRA STYLES & CORE SCRIPT ββββββββββββββββββββββ --> | |
| <style> | |
| /* Toggle-switch styling (used in Settings modal) */ | |
| .switch{position:relative;display:inline-block;width:42px;height:24px} | |
| .switch input{display:none} | |
| .slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;border-radius:24px; | |
| background:rgba(255,255,255,.2);transition:.4s} | |
| .slider:before{content:"";position:absolute;height:18px;width:18px;left:3px;bottom:3px; | |
| background:#fff;border-radius:50%;transition:.4s} | |
| .switch input:checked + .slider{ | |
| background:hsl(var(--primary-hue),var(--primary-saturation),var(--primary-lightness)) | |
| } | |
| .switch input:checked + .slider:before{transform:translateX(18px)} | |
| </style> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| /* βββ Loading screen βββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| const loader = document.querySelector('.dashboard-loading'); | |
| const bar = document.getElementById('loadingBar'); | |
| let pct = 0, id = setInterval(() => { | |
| pct += 4; | |
| bar.style.width = pct + '%'; | |
| if (pct >= 100) { clearInterval(id); | |
| loader.style.opacity = 0; | |
| setTimeout(() => loader.remove(), 400); | |
| } | |
| }, 30); | |
| /* βββ Modal toggles ββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| const toggleModal = (btnId, modalId, closeBtnId) => { | |
| const btn = document.getElementById(btnId); | |
| const modal = document.getElementById(modalId); | |
| const close = document.getElementById(closeBtnId); | |
| if (!btn || !modal) return; | |
| btn.addEventListener('click', () => modal.classList.add('active')); | |
| (close || modal).addEventListener('click', e => { | |
| if (e.target === modal || e.target === close) | |
| modal.classList.remove('active'); | |
| }); | |
| }; | |
| toggleModal('helpBtn', 'helpModal', 'closeHelp'); | |
| toggleModal('settingsButton','settingsModal', 'closeSettings'); | |
| /* βββ Tab & subtabs (Settings / API modal) ββββββββββββββββββββββββ */ | |
| document.querySelectorAll('.response-tab').forEach(tab => { | |
| tab.addEventListener('click', () => { | |
| const siblings = tab.parentElement.querySelectorAll('.response-tab'); | |
| siblings.forEach(t => t.classList.remove('active')); | |
| tab.classList.add('active'); | |
| const wrapper = tab.closest('.modal-content') || document; | |
| wrapper.querySelectorAll('.tab-content, .response-content') | |
| .forEach(c => c.classList.remove('active')); | |
| const attr = tab.dataset.tabContent ? 'tabContent' : | |
| tab.dataset.tab ? 'tab' : | |
| 'responseTab'; | |
| const selector = `[data-${attr.toLowerCase()}="${tab.dataset[attr]}"]`; | |
| const dest = wrapper.querySelector(selector); | |
| dest && dest.classList.add('active'); | |
| }); | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> |