Update app.js
This commit is contained in:
@@ -8,6 +8,7 @@ const ROUTES = {
|
||||
instances: "/admin/instance",
|
||||
backup: "/admin/backup-repo",
|
||||
servers: "/admin/server",
|
||||
seats: "/server",
|
||||
keys: "/admin/key",
|
||||
crm: "/crm",
|
||||
};
|
||||
@@ -918,6 +919,31 @@ async function serversLoadData() {
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
/* ─── Fetch seat data ─────────────────────────────────────── */
|
||||
let seatMap = {};
|
||||
try {
|
||||
const seatRes = await fetch("https://n8n.derez.ai/webhook/server");
|
||||
if (seatRes.ok) {
|
||||
const seatJson = await seatRes.json();
|
||||
const seatArr = Array.isArray(seatJson)
|
||||
? Array.isArray(seatJson[0]?.data)
|
||||
? seatJson[0].data
|
||||
: seatJson
|
||||
: [];
|
||||
for (const s of seatArr) {
|
||||
if (s.server) seatMap[s.server.toLowerCase().trim()] = s;
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
/* seat data is optional */
|
||||
}
|
||||
|
||||
/* ─── Merge seats into server data ─────────────────────────── */
|
||||
for (const sv of serversData) {
|
||||
const key = (sv.server?.name ?? "").toLowerCase().trim();
|
||||
sv.seats = seatMap[key] || null;
|
||||
}
|
||||
|
||||
if (serversData.length === 0) throw new Error("No server data in response");
|
||||
currentServerIdx = 0;
|
||||
serversRenderTabs();
|
||||
@@ -1090,9 +1116,6 @@ function serversRenderDashboard(idx) {
|
||||
<div style="font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.07em;margin-top:3px">Score</div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="font-size:13px;color:var(--text-muted);line-height:1.65;border-top:1px solid var(--border);padding-top:12px;margin:0">
|
||||
${escHtml(summary.short_summary)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- ─ CPU / Memory / Disk ───────────────────────────────── -->
|
||||
@@ -1174,26 +1197,46 @@ function serversRenderDashboard(idx) {
|
||||
<div style="font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.07em;margin-bottom:6px">Exposed Ports</div>
|
||||
<div>${portsHtml}</div>
|
||||
<div style="font-size:12px;color:var(--text-muted);margin-top:8px">Vuln score: ${security.vulnerability_score ?? "—"}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
${
|
||||
security.risk_flags?.length
|
||||
? `
|
||||
<div style="margin-top:12px;padding-top:10px;border-top:1px solid var(--border);display:flex;gap:6px;flex-wrap:wrap">
|
||||
${security.risk_flags.map((f) => `<span class="badge badge-medium">${escHtml(f)}</span>`).join("")}
|
||||
</div>`
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title" style="margin-bottom:14px">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
|
||||
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>
|
||||
</svg>
|
||||
Containers
|
||||
<div class="card">
|
||||
<div class="card-title" style="margin-bottom:14px">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 3v18"/>
|
||||
</svg>
|
||||
Seats
|
||||
</div>
|
||||
${
|
||||
s.seats
|
||||
? `
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:14px">
|
||||
<div>
|
||||
<div class="dash-stat">${s.seats.Seats ?? "—"}</div>
|
||||
<div class="dash-stat-sub">Total</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="dash-stat">${s.seats["Seats taken"] ?? "—"}</div>
|
||||
<div class="dash-stat-sub">Taken</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="dash-stat" style="color:${(s.seats["Seats Available"] ?? 0) < 2 ? "var(--danger)" : (s.seats["Seats Available"] ?? 0) < 10 ? "var(--warning)" : "var(--success)"}">${s.seats["Seats Available"] ?? "—"}</div>
|
||||
<div class="dash-stat-sub">Available</div>
|
||||
</div>
|
||||
</div>`
|
||||
: `<div class="text-muted" style="font-size:13px;padding:8px 0">No seat data available</div>`
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title" style="margin-bottom:14px">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
|
||||
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>
|
||||
</svg>
|
||||
Containers
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:14px">
|
||||
<div>
|
||||
<div class="dash-stat" style="color:${containers.running > 0 ? "var(--success)" : "var(--text-muted)"}">${containers.running}</div>
|
||||
|
||||
Reference in New Issue
Block a user