UNPKG

realtimecursor

Version:

Real-time collaboration system with cursor tracking and approval workflow

222 lines (201 loc) 6.81 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>RealtimeCursor</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; margin: 0; padding: 0; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; } .container { max-width: 800px; padding: 2rem; background-color: white; border-radius: 10px; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); } h1 { color: #4a5568; margin-bottom: 1rem; } p { color: #718096; line-height: 1.6; margin-bottom: 1.5rem; } .button { display: inline-block; background-color: #4299e1; color: white; padding: 0.75rem 1.5rem; border-radius: 5px; text-decoration: none; font-weight: 600; transition: background-color 0.2s; margin: 0.5rem; } .button:hover { background-color: #3182ce; } .status { margin-top: 1rem; padding: 1rem; border-radius: 5px; } .status.online { background-color: #c6f6d5; color: #2f855a; } .status.offline { background-color: #fed7d7; color: #c53030; } .login-form { margin-top: 2rem; text-align: left; } .form-group { margin-bottom: 1rem; } label { display: block; margin-bottom: 0.5rem; font-weight: 500; } input { width: 100%; padding: 0.75rem; border: 1px solid #e2e8f0; border-radius: 5px; font-size: 1rem; } </style> </head> <body> <div class="container"> <h1>RealtimeCursor</h1> <p>A powerful real-time collaboration platform with live cursor tracking, approval workflows, and GitHub-style history.</p> <div id="status" class="status">Checking backend status...</div> <div> <a href="#" class="button" id="create-admin-button">Create Admin Users</a> <a href="#" class="button" id="health-check-button">Check Health</a> </div> <div class="login-form"> <h2>Login</h2> <div class="form-group"> <label for="email">Email</label> <input type="email" id="email" value="superadmin@example.com"> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" id="password" value="SuperAdmin123!"> </div> <button id="login-button" class="button">Login</button> <div id="login-result"></div> </div> </div> <script> // Get the backend URL from the URL parameter or use default const urlParams = new URLSearchParams(window.location.search); const apiUrl = urlParams.get('api') || 'https://realtime-1.onrender.com'; const statusElement = document.getElementById('status'); const createAdminButton = document.getElementById('create-admin-button'); const healthCheckButton = document.getElementById('health-check-button'); const loginButton = document.getElementById('login-button'); const loginResultElement = document.getElementById('login-result'); // Check health endpoint async function checkHealth() { try { statusElement.textContent = "Checking backend status..."; statusElement.className = "status"; const response = await fetch(`${apiUrl}/health`); const data = await response.json(); if (data.status === 'OK') { statusElement.textContent = `Backend is online! ${apiUrl}`; statusElement.className = "status online"; } else { statusElement.textContent = `Backend returned unexpected response: ${JSON.stringify(data)}`; statusElement.className = "status offline"; } } catch (error) { statusElement.textContent = `Backend is offline or unreachable: ${error.message}`; statusElement.className = "status offline"; } } // Create admin users async function createAdminUsers() { try { statusElement.textContent = "Creating admin users..."; statusElement.className = "status"; const response = await fetch(`${apiUrl}/create-default-admins`, { method: 'POST' }); const data = await response.json(); if (data.success) { statusElement.textContent = `Admin users created: ${JSON.stringify(data.results)}`; statusElement.className = "status online"; } else { statusElement.textContent = `Failed to create admin users: ${data.message || JSON.stringify(data)}`; statusElement.className = "status offline"; } } catch (error) { statusElement.textContent = `Error creating admin users: ${error.message}`; statusElement.className = "status offline"; } } // Login async function login() { try { const email = document.getElementById('email').value; const password = document.getElementById('password').value; loginResultElement.textContent = "Logging in..."; const response = await fetch(`${apiUrl}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const data = await response.json(); if (data.success) { loginResultElement.textContent = `Login successful! Token: ${data.token.substring(0, 20)}...`; localStorage.setItem('authToken', data.token); localStorage.setItem('user', JSON.stringify(data.user)); } else { loginResultElement.textContent = `Login failed: ${data.message || JSON.stringify(data)}`; } } catch (error) { loginResultElement.textContent = `Login error: ${error.message}`; } } // Add event listeners createAdminButton.addEventListener('click', (e) => { e.preventDefault(); createAdminUsers(); }); healthCheckButton.addEventListener('click', (e) => { e.preventDefault(); checkHealth(); }); loginButton.addEventListener('click', (e) => { e.preventDefault(); login(); }); // Check health on page load checkHealth(); // Set button URLs createAdminButton.href = `${apiUrl}/create-default-admins`; healthCheckButton.href = `${apiUrl}/health`; </script> </body> </html>