Files
led-editor/src/static/login.html
Jimmy 9f28eabd2d Rename UI to LED Editor and improve mobile editor layout
Use "LED Editor" in page titles and the home heading. On narrow
viewports, make the file tree an off-canvas drawer with backdrop,
hamburger toggle, Escape to close, and auto-close after opening a
file. Add safe-area and tap-target tweaks, cache-bust static assets.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 03:16:35 +12:00

121 lines
3.8 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sign in — LED Editor</title>
<link rel="icon" href="data:,">
<style>
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: linear-gradient(135deg, #0f172a, #1e293b);
color: #e2e8f0;
}
.card {
width: min(400px, 92vw);
background: rgba(15, 23, 42, 0.85);
border: 1px solid rgba(148, 163, 184, 0.25);
border-radius: 14px;
padding: 2rem;
}
h1 { margin: 0 0 1rem 0; font-size: 1.4rem; }
label { display: block; font-size: 0.85rem; color: #94a3b8; margin-bottom: 0.35rem; }
input {
width: 100%;
padding: 0.55rem 0.65rem;
border-radius: 8px;
border: 1px solid #64748b;
background: #0f172a;
color: #e2e8f0;
margin-bottom: 1rem;
}
button {
width: 100%;
padding: 0.65rem;
border: none;
border-radius: 8px;
background: #3b82f6;
color: #fff;
font-weight: 600;
cursor: pointer;
margin-bottom: 0.75rem;
}
button:disabled { opacity: 0.6; cursor: not-allowed; }
.err { color: #fca5a5; font-size: 0.9rem; margin-bottom: 0.75rem; min-height: 1.2em; }
a { color: #93c5fd; }
.links { font-size: 0.9rem; margin-top: 1rem; }
</style>
</head>
<body>
<main class="card">
<h1>Sign in</h1>
<div id="err" class="err"></div>
<form id="form">
<label for="username">Username</label>
<input id="username" name="username" autocomplete="username" required />
<label for="password">Password</label>
<input id="password" type="password" name="password" autocomplete="current-password" required />
<button type="submit" id="submit">Sign in</button>
</form>
<div class="links">
<a href="/">Home</a>
· <a id="register-link" href="/register">Create account</a>
</div>
</main>
<script>
const params = new URLSearchParams(window.location.search);
const next = params.get("next") || "/editor";
(async function checkStatus() {
try {
const r = await fetch("/api/auth/status");
const s = await r.json();
if (!s.auth_enabled) {
document.getElementById("err").textContent = "Sign-in is disabled (AUTH_ENABLED is not set).";
document.getElementById("form").style.display = "none";
}
if (!s.register_open) {
const link = document.getElementById("register-link");
link.style.display = "none";
}
} catch (_e) {}
})();
document.getElementById("form").addEventListener("submit", async (e) => {
e.preventDefault();
const err = document.getElementById("err");
const btn = document.getElementById("submit");
err.textContent = "";
btn.disabled = true;
try {
const body = {
username: document.getElementById("username").value.trim(),
password: document.getElementById("password").value,
};
const res = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "include",
body: JSON.stringify(body),
});
if (!res.ok) {
const j = await res.json().catch(() => ({}));
err.textContent = j.detail || res.statusText || "Login failed";
return;
}
window.location.href = next.startsWith("/") ? next : "/editor";
} catch (ex) {
err.textContent = String(ex.message || ex);
} finally {
btn.disabled = false;
}
});
</script>
</body>
</html>