added initial roadmap and implementation

This commit is contained in:
2026-03-11 22:23:16 +02:00
parent 39b97a6db5
commit c0792f2e1d
62 changed files with 12410 additions and 1 deletions

169
web/index.html Normal file
View File

@@ -0,0 +1,169 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MadBase Admin Dashboard</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
h1, h2 { border-bottom: 1px solid #ccc; padding-bottom: 10px; }
.card { border: 1px solid #eee; padding: 15px; margin-bottom: 15px; border-radius: 4px; }
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 8px; border-bottom: 1px solid #eee; }
button { background: #ff4444; color: white; border: none; padding: 5px 10px; cursor: pointer; border-radius: 4px; }
button:hover { background: #cc0000; }
pre { background: #f5f5f5; padding: 10px; overflow: auto; }
</style>
</head>
<body>
<h1>MadBase Admin Dashboard</h1>
<div class="card">
<h2>Projects</h2>
<table id="projects-table">
<thead><tr><th>ID</th><th>Name</th><th>Status</th><th>Action</th></tr></thead>
<tbody></tbody>
</table>
<div style="margin-top: 10px;">
<input type="text" id="new-project-name" placeholder="New Project Name">
<button onclick="createProject()" style="background: #44cc44;">Create Project</button>
</div>
</div>
<div class="card">
<h2>Features</h2>
<button onclick="testDB()" style="background: #0088cc;">Test DB Connection</button>
<button onclick="fetchBuckets()" style="background: #ffaa00;">List Storage Buckets</button>
<div id="feature-output" style="margin-top: 10px; padding: 10px; background: #eee; min-height: 50px;"></div>
</div>
<div class="card">
<h2>Users (Global)</h2>
<table id="users-table">
<thead><tr><th>ID</th><th>Email</th><th>Created At</th><th>Action</th></tr></thead>
<tbody></tbody>
</table>
</div>
<div class="card">
<h2>System Metrics</h2>
<pre id="metrics-output">Loading...</pre>
</div>
<script>
const API_BASE = '/platform/v1';
async function testDB() {
// Check health
try {
const res = await fetch('/');
const text = await res.text();
document.getElementById('feature-output').innerHTML = `Gateway Status: ${text}`;
} catch (e) {
document.getElementById('feature-output').innerHTML = `<span style="color:red">Connection Failed</span>`;
}
}
async function fetchBuckets() {
// Needs Auth... but this is Admin Dashboard.
// Admin API doesn't expose Storage listing directly yet.
// We can add a proxy or just check health for now.
document.getElementById('feature-output').innerHTML = "Storage Browser: Requires authenticated user context (Not implemented in Admin UI yet)";
}
async function rotateKey(id) {
if (!confirm('Rotate keys for this project? Old keys will stop working.')) return;
try {
await fetch(`${API_BASE}/projects/${id}/keys`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({})
});
fetchProjects();
alert('Keys rotated!');
} catch (e) { alert('Error rotating keys'); }
}
async function fetchProjects() {
try {
const res = await fetch(`${API_BASE}/projects`);
const projects = await res.json();
const tbody = document.querySelector('#projects-table tbody');
tbody.innerHTML = projects.map(p => `
<tr>
<td>${p.id}</td>
<td>${p.name}</td>
<td>${p.status}</td>
<td>
<button onclick="deleteProject('${p.id}')">Delete</button>
<button onclick="rotateKey('${p.id}')" style="background:orange;">Rotate Key</button>
</td>
</tr>
`).join('');
} catch (e) { console.error(e); }
}
async function createProject() {
const name = document.getElementById('new-project-name').value;
if (!name) return;
try {
await fetch(`${API_BASE}/projects`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, owner_id: null })
});
document.getElementById('new-project-name').value = '';
fetchProjects();
} catch (e) { alert('Error creating project'); }
}
async function deleteProject(id) {
if (!confirm('Are you sure?')) return;
try {
await fetch(`${API_BASE}/projects/${id}`, { method: 'DELETE' });
fetchProjects();
} catch (e) { alert('Error deleting project'); }
}
async function fetchUsers() {
try {
const res = await fetch(`${API_BASE}/users`);
const users = await res.json();
const tbody = document.querySelector('#users-table tbody');
tbody.innerHTML = users.map(u => `
<tr>
<td>${u.id}</td>
<td>${u.email}</td>
<td>${new Date(u.created_at).toLocaleString()}</td>
<td><button onclick="deleteUser('${u.id}')">Delete</button></td>
</tr>
`).join('');
} catch (e) { console.error(e); }
}
async function deleteUser(id) {
if (!confirm('Are you sure?')) return;
try {
await fetch(`${API_BASE}/users/${id}`, { method: 'DELETE' });
fetchUsers();
} catch (e) { alert('Error deleting user'); }
}
async function fetchMetrics() {
try {
const res = await fetch('/metrics');
const text = await res.text();
// Show only madbase metrics or summary
document.getElementById('metrics-output').textContent = text.split('\n').filter(l => !l.startsWith('#') && l.trim()).slice(0, 10).join('\n') + '\n...';
} catch (e) {
document.getElementById('metrics-output').textContent = 'Error loading metrics';
}
}
fetchProjects();
fetchUsers();
fetchMetrics();
setInterval(fetchMetrics, 5000);
</script>
</body>
</html>