Adding: - health endpoint - extended /api/config - frontend extension of backend server viz
144 lines
No EOL
4.1 KiB
HTML
144 lines
No EOL
4.1 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>NOMYO Router Dashboard</title>
|
||
<style>
|
||
body{font-family:Arial,Helvetica,sans-serif;background:#f7f7f7;color:#333;padding:20px;}
|
||
h1{margin-top:0;}
|
||
table{border-collapse:collapse;width:100%;margin-bottom:20px;}
|
||
th,td{border:1px solid #ddd;padding:8px;}
|
||
th{background:#333;color:#fff;}
|
||
tr:nth-child(even){background:#f2f2f2;}
|
||
.endpoint{font-weight:bold;}
|
||
.model{font-family:monospace;}
|
||
.loading{color:#999;}
|
||
|
||
/* NEW STYLES */
|
||
.tables-wrapper{
|
||
display:flex;
|
||
gap:1rem;
|
||
margin-top:1rem;
|
||
}
|
||
.table-container{
|
||
width:50%;
|
||
}
|
||
/* Ensure the heading aligns nicely inside each container */
|
||
.table-container h2{
|
||
margin:0 0 0.5rem 0;
|
||
}
|
||
/* ---- NEW STYLES FOR PORTRAIT (height > width) ---- */
|
||
@media (orientation: portrait) {
|
||
/* Stack the two tables vertically */
|
||
.tables-wrapper {
|
||
flex-direction: column; /* instead of the default row */
|
||
}
|
||
.table-container {
|
||
width: 100%; /* full width when stacked */
|
||
}
|
||
/* Put the “Running Models” table first */
|
||
.table-container:nth-child(2) { /* the PS table is the 2nd child */
|
||
order: -1;
|
||
}
|
||
/* Keep the other table after it (default order 0) */
|
||
.table-container:nth-child(1) {
|
||
order: 0;
|
||
}
|
||
}
|
||
/* Add a tiny status‑style section */
|
||
.status-ok { color: #006400; font-weight: bold; } /* dark green */
|
||
.status-error{ color: #8B0000; font-weight: bold; } /* dark red */
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<a href="https://www.nomyo.ai" target="_blank"><img src="./static/228394408.png" width="100px" height="100px"></a><h1>Router Dashboard</h1>
|
||
|
||
<div class="tables-wrapper">
|
||
<div class="table-container">
|
||
<h2>Available Models (Tags)</h2>
|
||
<table id="tags-table">
|
||
<thead><tr><th>Model</th><th>Digest</th></tr></thead>
|
||
<tbody id="tags-body">
|
||
<tr><td colspan="2" class="loading">Loading…</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="table-container">
|
||
<h2>Running Models (PS)</h2>
|
||
<table id="ps-table">
|
||
<thead><tr><th>Model</th><th>Digest</th></tr></thead>
|
||
<tbody id="ps-body">
|
||
<tr><td colspan="2" class="loading">Loading…</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<h2>Configured Endpoints</h2>
|
||
<table id="endpoints-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Endpoint</th>
|
||
<th>Status</th>
|
||
<th>Version</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="endpoints-body">
|
||
<tr><td colspan="3" class="loading">Loading…</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<script>
|
||
async function fetchJSON(url){
|
||
const resp = await fetch(url);
|
||
if(!resp.ok){ throw new Error(`Failed ${url}: ${resp.status}`); }
|
||
return await resp.json();
|
||
}
|
||
|
||
async function loadEndpoints(){
|
||
try{
|
||
const data = await fetchJSON('/api/config');
|
||
const body = document.getElementById('endpoints-body');
|
||
// Map each endpoint object to a table row
|
||
body.innerHTML = data.endpoints.map(e => {
|
||
const statusClass = e.status === 'ok' ? 'status-ok' : 'status-error';
|
||
const version = e.version || 'N/A';
|
||
return `
|
||
<tr>
|
||
<td class="endpoint">${e.url}</td>
|
||
<td class="status ${statusClass}">${e.status}</td>
|
||
<td class="version">${version}</td>
|
||
</tr>`;
|
||
}).join('');
|
||
}catch(e){
|
||
console.error(e);
|
||
const body = document.getElementById('endpoints-body');
|
||
body.innerHTML = `<tr><td colspan="3" class="loading">Failed to load endpoints</td></tr>`;
|
||
}
|
||
}
|
||
|
||
async function loadTags(){
|
||
try{
|
||
const data = await fetchJSON('/api/tags');
|
||
const body = document.getElementById('tags-body');
|
||
body.innerHTML = data.models.map(m=>`<tr><td class="model">${m.name}</td><td>${m.digest}</td></tr>`).join('');
|
||
}catch(e){ console.error(e); }
|
||
}
|
||
|
||
async function loadPS(){
|
||
try{
|
||
const data = await fetchJSON('/api/ps');
|
||
const body = document.getElementById('ps-body');
|
||
body.innerHTML = data.models.map(m=>`<tr><td class="model">${m.name}</td><td>${m.digest}</td></tr>`).join('');
|
||
}catch(e){ console.error(e); }
|
||
}
|
||
|
||
window.addEventListener('load', ()=>{
|
||
loadEndpoints();
|
||
loadTags();
|
||
loadPS();
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |