S2S / frontend /dashboard.html
Krishnakkp's picture
feat: initial deployment to HF spaces
ecef9b0
Raw
History Blame Contribute Delete
13.1 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard - Voice Lab</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/dashboard.css">
</head>
<body>
<div class="landing-mesh" style="z-index: -2; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: radial-gradient(circle at 10% 20%, rgba(124, 58, 237, 0.08) 0%, transparent 40%), radial-gradient(circle at 90% 80%, rgba(37, 99, 235, 0.08) 0%, transparent 40%); pointer-events: none;"></div>
<canvas id="particles-canvas"></canvas>
<nav id="main-nav">
<a href="index.html" class="logo">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"></path><path d="M19 10v2a7 7 0 0 1-14 0v-2"></path><line x1="12" y1="19" x2="12" y2="22"></line></svg>
Voice Lab
</a>
<div class="nav-links" id="nav-links">
<a href="index.html">Home</a>
<a href="dashboard.html" class="active">Dashboard</a>
<a href="tts.html">TTS</a>
<a href="sts.html">STS</a>
<button id="logout-btn" class="btn btn-danger" style="padding: 0.4rem 1rem; font-size: 0.85rem;">Logout</button>
</div>
</nav>
<main style="max-width: 1100px; margin: 2rem auto; padding: 0 5%; position: relative; z-index: 10;">
<div class="page-header animate-fade-in" style="margin-bottom: 3rem; display: flex; justify-content: space-between; align-items: center;">
<div>
<h1 style="font-size: 2.5rem;"><span class="text-gradient">Welcome, <span id="user-display">User</span></span></h1>
<p style="color: var(--text-muted); font-size: 1.1rem; margin-top: 0.5rem;">Your Voice Lab Command Center</p>
</div>
<div class="spinner-orb" style="width: 50px; height: 50px; margin: 0;"></div>
</div>
<div class="dashboard-grid animate-slide-up stagger-1">
<div class="glass-panel stat-card">
<div class="stat-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"></path></svg>
</div>
<div class="stat-info">
<h4>Total Generations</h4>
<p id="total-generations-count">0</p>
</div>
</div>
<div class="glass-panel stat-card">
<div class="stat-icon" style="background: rgba(16, 185, 129, 0.1); color: var(--success);">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg>
</div>
<div class="stat-info">
<h4>System Status</h4>
<p id="system-status-text" style="font-size: 1.2rem; color: var(--success);">Online</p>
</div>
</div>
<div class="glass-panel stat-card">
<div class="stat-icon" style="background: rgba(244, 63, 94, 0.1); color: var(--accent);">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>
</div>
<div class="stat-info">
<h4>Compute Saved</h4>
<p id="compute-saved-text">0m</p>
</div>
</div>
</div>
<div class="dashboard-grid animate-slide-up stagger-2" style="grid-template-columns: 1fr 1fr; margin-top: 2rem;">
<!-- GPU Server Connection Panel -->
<div class="glass-panel" style="padding: 2rem; border-color: rgba(37, 99, 235, 0.3);">
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.5rem;">
<h3 style="font-size: 1.4rem; display: flex; align-items: center; gap: 0.5rem;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--secondary)" stroke-width="2"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect><rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect><line x1="6" y1="6" x2="6.01" y2="6"></line><line x1="6" y1="18" x2="6.01" y2="18"></line></svg>
GPU Inference Server
</h3>
<div id="colab-status-badge" style="padding: 0.3rem 0.8rem; border-radius: 100px; font-size: 0.8rem; font-weight: 600; background: rgba(244, 63, 94, 0.1); color: var(--accent); border: 1px solid var(--accent);">Disconnected</div>
</div>
<p style="color: var(--text-muted); font-size: 0.95rem; line-height: 1.5; margin-bottom: 1.5rem;">
Link your powerful Colab or local Gradio GPU server to enable blazing-fast Zero-Shot Voice Cloning and Speech-to-Speech generation.
</p>
<div style="display: flex; gap: 1rem;">
<input type="text" id="colab-url-input" placeholder="e.g. https://1234abcd.gradio.live" style="flex: 1; padding: 0.8rem 1.2rem; background: rgba(0,0,0,0.3); border: 1px solid var(--border); border-radius: 12px; color: white; font-family: inherit;">
<button id="connect-colab-btn" class="btn btn-glow" style="min-width: 120px;">Connect</button>
</div>
<div id="colab-info" style="margin-top: 1rem; font-size: 0.85rem; color: var(--text-dim);">
Currently falling back to Hugging Face Space (Slower).
</div>
</div>
<!-- Quick Actions Panel -->
<div class="glass-panel" style="padding: 2rem;">
<h3 style="font-size: 1.4rem; margin-bottom: 1.5rem; display: flex; align-items: center; gap: 0.5rem;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--primary)" stroke-width="2"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
Generative Workflows
</h3>
<p style="color: var(--text-muted); font-size: 0.95rem; line-height: 1.5; margin-bottom: 1.5rem;">
Jump right into your creative process. Start synthesizing text or cloning existing audio directly.
</p>
<div class="quick-actions" style="margin-top: 0; display: flex; flex-direction: column; gap: 1rem;">
<a href="tts.html" class="btn btn-glow" style="justify-content: flex-start; padding: 1rem 1.5rem;">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
Neural Text-to-Speech
</a>
<a href="sts.html" class="btn btn-outline" style="justify-content: flex-start; padding: 1rem 1.5rem; background: rgba(255,255,255,0.02);">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 0.5rem;"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"></path><path d="M19 10v2a7 7 0 0 1-14 0v-2"></path><line x1="12" y1="19" x2="12" y2="22"></line></svg>
Voice Cloning & STS
</a>
</div>
</div>
</div>
</main>
<script src="js/particles.js"></script>
<script src="js/toast.js"></script>
<script>
const API_URL = '';
document.addEventListener('DOMContentLoaded', async () => {
const token = localStorage.getItem('token');
if (!token) { window.location.href = 'auth.html'; return; }
document.getElementById('logout-btn').addEventListener('click', () => {
localStorage.removeItem('token');
window.location.href = 'index.html';
});
// Fetch User
try {
const res = await fetch(`${API_URL}/auth/me`, {
headers: {'Authorization': 'Bearer ' + token}
});
if (res.ok) {
const data = await res.json();
document.getElementById('user-display').textContent = data.username;
} else {
throw new Error();
}
} catch (e) {
localStorage.removeItem('token');
window.location.href = 'auth.html';
}
// GPU Server Logic
const colabInput = document.getElementById('colab-url-input');
const connectBtn = document.getElementById('connect-colab-btn');
const statusBadge = document.getElementById('colab-status-badge');
const colabInfo = document.getElementById('colab-info');
async function checkGPUStatus() {
try {
const res = await fetch(`${API_URL}/admin/status`);
if(res.ok) {
const data = await res.json();
if(data.using_colab && data.connected) {
statusBadge.textContent = 'Connected';
statusBadge.style.background = 'rgba(16, 185, 129, 0.1)';
statusBadge.style.color = 'var(--success)';
statusBadge.style.borderColor = 'var(--success)';
colabInfo.textContent = 'High-speed GPU instance active.';
colabInfo.style.color = 'var(--success)';
} else {
statusBadge.textContent = 'Disconnected';
statusBadge.style.background = 'rgba(244, 63, 94, 0.1)';
statusBadge.style.color = 'var(--accent)';
statusBadge.style.borderColor = 'var(--accent)';
colabInfo.textContent = data.space_connected ? 'Falling back to HF Space (Slower).' : 'No inference servers available.';
colabInfo.style.color = 'var(--text-dim)';
}
}
} catch(e) {
console.error("Failed to check status", e);
}
}
async function fetchStats() {
try {
const res = await fetch(`${API_URL}/admin/stats`, {
headers: {'Authorization': 'Bearer ' + token}
});
if(res.ok) {
const data = await res.json();
document.getElementById('total-generations-count').textContent = data.total_generations;
document.getElementById('compute-saved-text').textContent = data.compute_saved;
}
} catch(e) {
console.error("Failed to fetch stats", e);
}
}
// Initial Check
checkGPUStatus();
fetchStats();
connectBtn.addEventListener('click', async () => {
const url = colabInput.value.trim();
if(!url) { showToast('Please enter a valid Gradio URL', 'warning'); return; }
connectBtn.innerHTML = '<div class="spinner-orb" style="width:16px;height:16px;margin:0;"></div>';
connectBtn.disabled = true;
try {
const res = await fetch(`${API_URL}/admin/colab`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({ url: url })
});
if(res.ok) {
showToast('Successfully connected to GPU Server!', 'success');
setTimeout(checkGPUStatus, 1000); // give backend a second to verify
} else {
throw new Error('Failed to connect');
}
} catch(e) {
showToast(e.message, 'error');
} finally {
connectBtn.innerHTML = 'Connect';
connectBtn.disabled = false;
}
});
});
</script>
</body>
</html>