prvng_platform/crates/provisioning-daemon/admin/app.js

74 lines
2.5 KiB
JavaScript
Raw Normal View History

'use strict';
const tokenInput = document.getElementById('token');
const panels = {
health: document.getElementById('health'),
tools: document.getElementById('tools'),
stats: document.getElementById('stats'),
recent: document.getElementById('recent'),
};
function headers() {
const t = tokenInput.value.trim();
return t ? { 'Authorization': `Bearer ${t}` } : {};
}
async function fetchJson(path) {
const res = await fetch(path, { headers: headers() });
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
return res.json();
}
function render(panel, html) {
panels[panel].innerHTML = html;
}
async function showHealth() {
try {
const data = await fetchJson('/health');
render('health', `<pre>${JSON.stringify(data, null, 2)}</pre>`);
} catch (e) { render('health', `<p class="error">${e.message}</p>`); }
}
async function showTools() {
try {
const data = await fetchJson('/api/v1/tools');
const rows = data.tools.map(t =>
`<tr><td>${t.name}</td><td class="cat-${t.category.toLowerCase()}">${t.category}</td><td>${t.description}</td></tr>`
).join('');
render('tools', `<table><thead><tr><th>Name</th><th>Category</th><th>Description</th></tr></thead><tbody>${rows}</tbody></table>`);
} catch (e) { render('tools', `<p class="error">${e.message}</p>`); }
}
async function showStats() {
try {
const data = await fetchJson('/api/v1/state/stats');
render('stats', `<pre>${JSON.stringify(data, null, 2)}</pre>`);
} catch (e) { render('stats', `<p class="error">${e.message}</p>`); }
}
async function showRecent() {
try {
const data = await fetchJson('/api/v1/state/recent');
const rows = data.invocations.map(r =>
`<tr><td>${r.invoked_at}</td><td>${r.tool}</td><td>${r.duration_ms}ms</td><td>${r.outcome.status}</td></tr>`
).join('');
render('recent', `<table><thead><tr><th>When</th><th>Tool</th><th>Duration</th><th>Outcome</th></tr></thead><tbody>${rows}</tbody></table>`);
} catch (e) { render('recent', `<p class="error">${e.message}</p>`); }
}
const loaders = { health: showHealth, tools: showTools, stats: showStats, recent: showRecent };
document.querySelectorAll('nav button').forEach(btn => {
btn.addEventListener('click', () => {
const target = btn.dataset.panel;
document.querySelectorAll('nav button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
Object.values(panels).forEach(p => p.hidden = true);
panels[target].hidden = false;
loaders[target]();
});
});
document.querySelector('nav button[data-panel="health"]').click();