hnsw-tuner / static /loading.html
raduvespa's picture
Initial HF Space
88f21af
Raw
History Blame Contribute Delete
4.63 kB
<!-- Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HNSWTuner Starting</title>
<style>
:root {
color-scheme: light;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
}
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background:
radial-gradient(circle at top, rgba(76, 132, 255, 0.16), transparent 40%),
linear-gradient(180deg, #f4f1ec 0%, #efe8de 100%);
color: #1f2933;
padding: 24px;
}
main {
width: min(100%, 680px);
background: rgba(255, 255, 255, 0.96);
border: 1px solid #d8dee4;
border-radius: 20px;
box-shadow: 0 24px 60px rgba(15, 23, 42, 0.12);
padding: 36px 32px;
}
h1 {
margin: 0 0 12px;
font-size: clamp(2rem, 4vw, 3rem);
line-height: 1.1;
}
p {
margin: 0 0 18px;
line-height: 1.6;
color: #52606d;
}
.status {
display: flex;
align-items: center;
gap: 14px;
margin-top: 24px;
font-weight: 600;
}
.status-text {
color: #243b53;
}
.pulse {
width: 14px;
height: 14px;
border-radius: 50%;
background: #2f6fed;
box-shadow: 0 0 0 0 rgba(47, 111, 237, 0.35);
animation: pulse 1.8s infinite;
}
.pulse.failed {
background: #c23b22;
box-shadow: none;
animation: none;
}
.details {
margin-top: 16px;
padding: 14px 16px;
background: #f8fafc;
border-radius: 12px;
color: #334e68;
white-space: pre-wrap;
word-break: break-word;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(47, 111, 237, 0.35);
}
70% {
box-shadow: 0 0 0 14px rgba(47, 111, 237, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(47, 111, 237, 0);
}
}
</style>
</head>
<body>
<main>
<h1>HNSWTuner is starting</h1>
<p>
Vespa and the demo dataset are bootstrapping in the background. This page will switch to the
full UI as soon as startup finishes.
</p>
<div class="status">
<div id="status-dot" class="pulse" aria-hidden="true"></div>
<div id="status-text" class="status-text">Checking startup status...</div>
</div>
<div id="status-message" class="details">Waiting for bootstrap...</div>
</main>
<script>
const statusText = document.getElementById("status-text");
const statusMessage = document.getElementById("status-message");
const statusDot = document.getElementById("status-dot");
let pollTimer = null;
function stopPolling() {
if (pollTimer !== null) {
clearInterval(pollTimer);
pollTimer = null;
}
}
async function pollStatus() {
try {
const response = await fetch("/status", { cache: "no-store" });
const status = await response.json();
statusMessage.textContent = status.message || "Waiting for bootstrap...";
if (status.state === "ready") {
stopPolling();
window.location.replace("/");
return;
}
if (status.state === "failed") {
stopPolling();
statusText.textContent = "Startup failed";
statusDot.classList.add("failed");
return;
}
statusText.textContent = "Startup in progress";
statusDot.classList.remove("failed");
} catch (error) {
statusText.textContent = "Waiting for status endpoint";
statusMessage.textContent = String(error);
}
}
pollStatus();
pollTimer = setInterval(pollStatus, 2000);
</script>
</body>
</html>