Update app.js
This commit is contained in:
@@ -8,6 +8,7 @@ const ROUTES = {
|
|||||||
instances: "/admin/instance",
|
instances: "/admin/instance",
|
||||||
backup: "/admin/backup-repo",
|
backup: "/admin/backup-repo",
|
||||||
servers: "/admin/server",
|
servers: "/admin/server",
|
||||||
|
seats: "/server",
|
||||||
keys: "/admin/key",
|
keys: "/admin/key",
|
||||||
crm: "/crm",
|
crm: "/crm",
|
||||||
};
|
};
|
||||||
@@ -918,6 +919,31 @@ async function serversLoadData() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter(Boolean);
|
.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");
|
if (serversData.length === 0) throw new Error("No server data in response");
|
||||||
currentServerIdx = 0;
|
currentServerIdx = 0;
|
||||||
serversRenderTabs();
|
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 style="font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.07em;margin-top:3px">Score</div>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
|
|
||||||
<!-- ─ CPU / Memory / Disk ───────────────────────────────── -->
|
<!-- ─ 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 style="font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.07em;margin-bottom:6px">Exposed Ports</div>
|
||||||
<div>${portsHtml}</div>
|
<div>${portsHtml}</div>
|
||||||
<div style="font-size:12px;color:var(--text-muted);margin-top:8px">Vuln score: ${security.vulnerability_score ?? "—"}</div>
|
<div style="font-size:12px;color:var(--text-muted);margin-top:8px">Vuln score: ${security.vulnerability_score ?? "—"}</div>
|
||||||
|
</div>
|
||||||
</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">
|
||||||
<div class="card-title" style="margin-bottom:14px">
|
<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">
|
<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"/>
|
<rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 3v18"/>
|
||||||
<polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>
|
</svg>
|
||||||
</svg>
|
Seats
|
||||||
Containers
|
</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>
|
||||||
|
|
||||||
|
<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 style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:14px">
|
||||||
<div>
|
<div>
|
||||||
<div class="dash-stat" style="color:${containers.running > 0 ? "var(--success)" : "var(--text-muted)"}">${containers.running}</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