Mercurial
view mrjunejune/src/notes/login.html @ 279:b3b547563ec7
Add Google connector service and agent wiki
Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 22:22:36 -0700 |
| parents | 60a876c4587a |
| children |
line wrap: on
line source
<!DOCTYPE html> <html lang="en"> <head> {{/parts/base_head.html}} <title>Login | Notes</title> <style> .login-page { max-width: 400px; margin: 100px auto; padding: var(--zenbu-sys-padding-lg); } .login-box { background: #fff; border: 1px solid #ddd; border-radius: var(--zenbu-sys-radius-control); padding: var(--zenbu-sys-padding-xl); box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .login-box h1 { margin: 0 0 24px 0; font-size: var(--zenbu-sys-font-size-2xl); text-align: center; } .login-box label { display: block; margin-bottom: 8px; font-weight: 500; } .login-box input { width: 100%; min-height: var(--zenbu-control-height); padding: var(--zenbu-control-padding-block) var(--zenbu-control-padding-inline); border: 1px solid #ccc; border-radius: var(--zenbu-sys-radius-control-small); font-size: var(--zenbu-control-font-size); line-height: var(--zenbu-control-line-height); box-sizing: border-box; } .login-box input:focus { outline: none; border-color: #0078ff; } .login-box button { width: 100%; margin-top: 16px; background: #0078ff; color: white; border: none; border-radius: var(--zenbu-sys-radius-control-small); cursor: pointer; } .login-box zen-button { width: 100%; } .login-box button:hover { background: #0066dd; } .error-msg { color: #d32f2f; margin-top: 12px; text-align: center; display: none; } </style> </head> <body> {{/parts/header.html}} <main class="login-page"> <div class="login-box"> <h1>Notes Login</h1> <form id="login-form"> <zen-field appearance="plain" size="lg"> <label for="token">Access Token</label> <input type="password" id="token" placeholder="Enter your access token" required> </zen-field> <zen-button appearance="plain" size="lg"> <button type="submit">Login</button> </zen-button> <p class="error-msg" id="error-msg">Invalid token</p> </form> </div> </main> {{/parts/footer.html}} <script> // Check if already logged in const savedToken = localStorage.getItem('notes-auth-token'); if (savedToken) { window.location.href = '/notes/'; } document.getElementById('login-form').addEventListener('submit', async function(e) { e.preventDefault(); const token = document.getElementById('token').value.trim(); if (!token) return; // Verify token by trying to load a document try { const response = await fetch('/api/editor/load/index', { headers: { 'Authorization': 'Bearer ' + token } }); if (response.ok) { localStorage.setItem('notes-auth-token', token); // Redirect to originally requested page or /notes/ const returnUrl = new URLSearchParams(window.location.search).get('return') || '/notes/'; window.location.href = returnUrl; } else { document.getElementById('error-msg').style.display = 'block'; } } catch (err) { document.getElementById('error-msg').style.display = 'block'; } }); </script> </body> </html>