120 lines
5.6 KiB
HTML
Executable File
120 lines
5.6 KiB
HTML
Executable File
|
||
|
||
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>System & Docker Status</title>
|
||
<style>
|
||
:root {
|
||
--bg: #0f172a; /* slate-900 */
|
||
--card: #111827; /* gray-900 */
|
||
--muted: #94a3b8; /* slate-400 */
|
||
--text: #e5e7eb; /* gray-200 */
|
||
--accent: #22d3ee; /* cyan-400 */
|
||
--accent2: #34d399; /* green-400 */
|
||
--danger: #f87171; /* red-400 */
|
||
}
|
||
* { box-sizing: border-box; }
|
||
body { margin:0; font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, 'Helvetica Neue', Arial, 'Noto Sans', 'Apple Color Emoji','Segoe UI Emoji'; background: var(--bg); color: var(--text); }
|
||
header { padding: 24px; border-bottom: 1px solid #1f2937; position: sticky; top: 0; background: linear-gradient(180deg, rgba(15,23,42,0.9), rgba(15,23,42,0.9)); backdrop-filter: blur(6px); z-index: 10; }
|
||
h1 { margin: 0 0 8px; font-size: 1.4rem; }
|
||
.sub { color: var(--muted); font-size: .9rem; }
|
||
|
||
.wrap { max-width: 1200px; margin: 0 auto; padding: 24px; }
|
||
|
||
/* Top grid for system */
|
||
.grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 16px; }
|
||
.card { background: var(--card); border: 1px solid #1f2937; border-radius: 12px; padding: 16px; }
|
||
.card h2 { margin: 0 0 8px; font-size: 1.1rem; }
|
||
|
||
.kpi { display:flex; align-items:center; gap: 16px; }
|
||
.ring { --size: 84px; width: var(--size); height: var(--size); border-radius: 50%; position: relative; display:grid; place-items:center; background: conic-gradient(var(--accent) var(--deg), #334155 var(--deg)); }
|
||
.ring::before { content:""; width: calc(var(--size) - 14px); height: calc(var(--size) - 14px); border-radius: 50%; background: var(--card); position: absolute; }
|
||
.ring span { position: relative; font-weight: 700; }
|
||
.legend { color: var(--muted); font-size: .9rem; }
|
||
|
||
.bar { height: 10px; background: #334155; border-radius: 999px; overflow: hidden; }
|
||
.bar > i { display:block; height: 100%; background: var(--accent2); width: 0; }
|
||
|
||
/* Container list */
|
||
.list { display:flex; flex-direction: column; gap: 12px; }
|
||
.row { display:grid; grid-template-columns: 2fr 1fr 2fr 1fr 120px; gap: 12px; align-items:center; padding: 12px; border-radius: 10px; background: #0b1220; border: 1px solid #1f2937; }
|
||
.row .name { font-weight: 600; }
|
||
.row .muted { color: var(--muted); font-size: .9rem; }
|
||
.status { padding: 2px 8px; border-radius: 999px; font-size: .8rem; display:inline-block; background: #064e3b; color: #a7f3d0; }
|
||
.status.stopped { background:#3f0a0a; color:#fecaca; }
|
||
|
||
.ports { display:flex; flex-wrap: wrap; gap: 6px; }
|
||
.port { padding: 4px 8px; border-radius: 999px; font-size: .8rem; background:#1f2937; color:#cbd5e1; border: 1px solid #334155; }
|
||
.badge { padding: 2px 6px; border-radius: 6px; font-size: .8rem; background:#1f2937; border: 1px solid #334155; }
|
||
|
||
.toolbar { display:flex; gap: 12px; align-items:center; margin-bottom: 12px; }
|
||
.toolbar input { background:#0b1220; border:1px solid #1f2937; color:var(--text); border-radius:8px; padding:8px 10px; }
|
||
.toolbar button { background:#111827; border:1px solid #1f2937; color:var(--text); border-radius:8px; padding:8px 12px; cursor:pointer; }
|
||
.toolbar button:hover { border-color:#334155; }
|
||
|
||
footer { color: var(--muted); padding: 24px; text-align:center; }
|
||
a { color: var(--accent); text-decoration: none; }
|
||
.small { font-size: .85rem; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<h1>System & Docker Status</h1>
|
||
<div class="sub">Last update: <span id="last-update">–</span> · Auto-refresh <span id="refresh-state">on</span></div>
|
||
</header>
|
||
|
||
<main class="wrap">
|
||
<section class="grid" id="system-grid">
|
||
<div class="card" style="grid-column: span 4;">
|
||
<h2>CPU</h2>
|
||
<div class="kpi">
|
||
<div class="ring" id="cpu-ring"><span id="cpu-percent">0%</span></div>
|
||
<div>
|
||
<div class="legend small">Load averages</div>
|
||
<div class="small">1m: <span id="load-1m">–</span></div>
|
||
<div class="small">5m: <span id="load-5m">–</span></div>
|
||
<div class="small">15m: <span id="load-15m">–</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card" style="grid-column: span 8;">
|
||
<h2>Memory</h2>
|
||
<div class="kpi" style="gap: 24px;">
|
||
<div style="min-width:220px">
|
||
<div class="legend">Used</div>
|
||
<div class="bar"><i id="mem-bar"></i></div>
|
||
<div class="small"><span id="mem-used">–</span> / <span id="mem-total">–</span> (<span id="mem-percent">–</span>)</div>
|
||
</div>
|
||
<div>
|
||
<div class="legend">Tip</div>
|
||
<div class="small">Keep memory usage under 80% to avoid OOM kills.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section style="margin-top: 24px;">
|
||
<div class="card">
|
||
<div class="toolbar">
|
||
<input id="search" type="search" placeholder="Filter containers by name or image…" />
|
||
<button id="toggle-refresh">Pause</button>
|
||
<span class="small" id="container-count"></span>
|
||
</div>
|
||
<div class="list" id="container-list"></div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<footer>
|
||
<div class="small">This page reads <code>data/status.json</code>. Place your status file under <code>./data</code> (mounted to <code>/app/public/data</code>).</div>
|
||
</footer>
|
||
|
||
<script src="js/status.js"></script>
|
||
</body>
|
||
</html>
|
||
``
|