Initial commit: Infrastructure host tracking app
build-and-push / build-and-push (push) Successful in 1m26s
build-and-push / build-and-push (push) Successful in 1m26s
Fastify + node:sqlite single-process app with vanilla JS UI for looking up hosts by hardware ID, hostname, or asset ID. Includes per-host network interface tracking, sites/rooms/server-types CRUD, Docker packaging, and a Gitea Actions workflow that runs tests then builds and pushes to gitea.thewrightserver.net/josh/infrastructure. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Infrastructure</title>
|
||||
<link rel="stylesheet" href="/app.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="topbar">
|
||||
<a class="brand" href="/" data-nav>Infrastructure</a>
|
||||
<div class="topbar-actions">
|
||||
<button id="new-host-btn" class="btn btn-primary">+ New host</button>
|
||||
<button id="manage-btn" class="btn btn-ghost">Manage</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="main">
|
||||
<section id="hero" class="hero">
|
||||
<h1 class="hero-title">Find a host</h1>
|
||||
<p class="hero-sub">Search by hostname, hardware ID, or asset ID.</p>
|
||||
<form id="lookup-form" class="search-row" autocomplete="off">
|
||||
<input
|
||||
id="search-input"
|
||||
type="text"
|
||||
class="search-input"
|
||||
placeholder="Hostname, hardware ID, or asset ID…"
|
||||
autocomplete="off"
|
||||
autofocus
|
||||
/>
|
||||
<button type="submit" id="lookup-btn" class="btn btn-primary">Lookup</button>
|
||||
</form>
|
||||
<div id="hero-empty-state" class="hero-empty"></div>
|
||||
</section>
|
||||
|
||||
<section id="results" class="results" hidden>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Hostname</th>
|
||||
<th>Hardware ID</th>
|
||||
<th>Asset ID</th>
|
||||
<th class="actions-col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="results-body"></tbody>
|
||||
</table>
|
||||
<div id="results-empty" class="results-empty" hidden>No hosts match.</div>
|
||||
</section>
|
||||
|
||||
<section id="detail" class="detail" hidden></section>
|
||||
</main>
|
||||
|
||||
<!-- Host modal -->
|
||||
<div id="host-modal" class="modal" hidden>
|
||||
<div class="modal-card">
|
||||
<div class="modal-header">
|
||||
<h2 id="host-modal-title">New host</h2>
|
||||
<button class="modal-close" data-close-modal="host-modal">×</button>
|
||||
</div>
|
||||
<div id="host-error" class="banner banner-error" hidden></div>
|
||||
<form id="host-form" class="form">
|
||||
<label class="field">
|
||||
<span>Hostname</span>
|
||||
<input name="hostname" type="text" required maxlength="253" autocomplete="off" />
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Hardware ID</span>
|
||||
<input name="hardware_id" type="text" required maxlength="100" autocomplete="off" />
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Asset ID</span>
|
||||
<input name="asset_id" type="text" required maxlength="100" autocomplete="off" />
|
||||
</label>
|
||||
<div class="field-row">
|
||||
<label class="field">
|
||||
<span>Site</span>
|
||||
<select name="site_id" required></select>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Room</span>
|
||||
<select name="room_id" required></select>
|
||||
</label>
|
||||
</div>
|
||||
<label class="field">
|
||||
<span>Position</span>
|
||||
<input name="position" type="text" maxlength="100" placeholder="e.g. R3-U12" autocomplete="off" />
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Server Type</span>
|
||||
<select name="server_type_id" required></select>
|
||||
</label>
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-ghost" data-close-modal="host-modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Manage modal -->
|
||||
<div id="manage-modal" class="modal" hidden>
|
||||
<div class="modal-card modal-card-wide">
|
||||
<div class="modal-header">
|
||||
<h2>Manage</h2>
|
||||
<button class="modal-close" data-close-modal="manage-modal">×</button>
|
||||
</div>
|
||||
<div class="tabs">
|
||||
<button class="tab tab-active" data-tab="sites">Sites</button>
|
||||
<button class="tab" data-tab="rooms">Rooms</button>
|
||||
<button class="tab" data-tab="server-types">Server Types</button>
|
||||
</div>
|
||||
<div id="manage-body" class="manage-body"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/app.js" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user