feat: add Fleet operations view
This commit is contained in:
1 parent
c6d01df31c
commit
786a1ab910
12 files changed
+1062
-148
No files matched your search
@@ -222,33 +222,72 @@ def _repairs_content() -> str:
|
||||
"""
|
||||
|
||||
|
||||
def _miners_content() -> str:
|
||||
def _miners_content(can_view_locations: bool) -> str:
|
||||
location_filters = """
|
||||
<div class="field"><label for="fleetSite">Site</label>
|
||||
<select id="fleetSite"><option value="">All sites</option></select></div>
|
||||
<div class="field"><label for="fleetRoom">Room</label>
|
||||
<select id="fleetRoom"><option value="">All rooms</option></select></div>
|
||||
""" if can_view_locations else ""
|
||||
return f"""
|
||||
<section class="panel" aria-labelledby="minerListTitle">
|
||||
<section class="panel fleet-panel" aria-labelledby="minerListTitle">
|
||||
<div class="panel-head">
|
||||
<div>
|
||||
<h2 id="minerListTitle">Miner inventory</h2>
|
||||
<p class="panel-copy">Real inventory records. Search matches the
|
||||
fields supported by the Inventory API.</p>
|
||||
</div>
|
||||
<span class="freshness">Up to 100 results</span>
|
||||
<div><h2 id="minerListTitle">Fleet</h2>
|
||||
<p class="panel-copy">Current miner identity, operating state, telemetry, and repair context.</p></div>
|
||||
<span class="freshness" id="fleetFreshness">Loading current fleet</span>
|
||||
</div>
|
||||
<form class="filter-bar" id="minerSearchForm" role="search">
|
||||
<div class="field">
|
||||
<label for="minerSearchInput">Search miners</label>
|
||||
<input id="minerSearchInput" type="search" autocomplete="off"
|
||||
placeholder="Asset ID, MAC, serial, model, or IP">
|
||||
<form class="fleet-filters" id="fleetFilters" role="search">
|
||||
<div class="field fleet-search"><label for="fleetQuery">Search miners</label>
|
||||
<input id="fleetQuery" type="search" autocomplete="off"
|
||||
placeholder="Asset ID, MAC, IP, model, or serial"></div>
|
||||
<div class="field"><label for="fleetLifecycle">Lifecycle</label>
|
||||
<select id="fleetLifecycle"><option value="">All lifecycle states</option>
|
||||
<option value="active">Active</option><option value="spare">Spare</option>
|
||||
<option value="in_repair">In repair</option><option value="retired">Retired</option></select></div>
|
||||
<div class="field"><label for="fleetModel">Model</label>
|
||||
<input id="fleetModel" type="text" autocomplete="off" placeholder="Any model"></div>
|
||||
<div class="field"><label for="fleetRuntime">Runtime</label>
|
||||
<select id="fleetRuntime"><option value="">All runtime states</option>
|
||||
<option value="online">Online</option><option value="offline">Offline</option>
|
||||
<option value="unknown">Unknown</option></select></div>
|
||||
<div class="field"><label for="fleetRepair">Repair</label>
|
||||
<select id="fleetRepair"><option value="">Any repair state</option>
|
||||
<option value="active">Active repair</option><option value="none">No active repair</option></select></div>
|
||||
<div class="field"><label for="fleetOperational">Operational state</label>
|
||||
<select id="fleetOperational"><option value="">All operational states</option>
|
||||
<option value="online">Online</option><option value="offline">Offline</option>
|
||||
<option value="unstable">Hash unstable</option><option value="repair">In repair</option>
|
||||
<option value="spare">Spare</option><option value="retired">Retired</option>
|
||||
<option value="unknown">Unknown</option></select></div>
|
||||
{location_filters}
|
||||
<div class="field"><label for="fleetTags">Tags</label>
|
||||
<input id="fleetTags" type="text" autocomplete="off" placeholder="Comma separated"></div>
|
||||
<label class="check-control" for="fleetProblems">
|
||||
<input id="fleetProblems" type="checkbox"> Problems only</label>
|
||||
<div class="fleet-filter-actions">
|
||||
<button class="command-button" type="submit">Apply</button>
|
||||
<button class="quiet-button" id="fleetReset" type="button">Reset</button>
|
||||
</div>
|
||||
<button class="command-button" type="submit">Search</button>
|
||||
</form>
|
||||
{_state_messages("miners")}
|
||||
<div class="table-wrap" data-view-state="ready" hidden>
|
||||
<table>
|
||||
<thead><tr><th>Asset ID</th><th>Current MAC</th><th>Model</th>
|
||||
<th>Lifecycle</th><th>Runtime</th><th>Location</th></tr></thead>
|
||||
<tbody id="minerRows"></tbody>
|
||||
</table>
|
||||
<div data-view-state="ready" hidden>
|
||||
<p class="fleet-result-summary" id="fleetResultSummary" aria-live="polite"></p>
|
||||
<div class="table-wrap fleet-table-wrap">
|
||||
<table class="fleet-table">
|
||||
<thead><tr><th>Miner</th><th>Operational</th><th>Model / Serial</th>
|
||||
<th>Network</th><th>Location</th><th>Hashrate</th><th>Power</th>
|
||||
<th>Max chip temp</th><th>Lifecycle / Repair</th><th>Actions</th></tr></thead>
|
||||
<tbody id="fleetRows"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="fleet-pagination" aria-label="Fleet pages">
|
||||
<button class="quiet-button" id="fleetPrevious" type="button" disabled>Previous</button>
|
||||
<label for="fleetLimit">Rows per page</label>
|
||||
<select id="fleetLimit"><option value="25">25</option><option value="50">50</option>
|
||||
<option value="100">100</option><option value="250">250</option></select>
|
||||
<button class="quiet-button" id="fleetNext" type="button" disabled>Next</button>
|
||||
</nav>
|
||||
</section>
|
||||
"""
|
||||
|
||||
@@ -297,11 +336,15 @@ def render_app_page(
|
||||
content = (
|
||||
_map_content(has_permission("locations.manage"))
|
||||
if view == "map"
|
||||
else _miners_content(has_permission("locations.view"))
|
||||
if view == "miners"
|
||||
else CONTENT[view]()
|
||||
)
|
||||
map_script = (
|
||||
page_script = (
|
||||
'<script src="/assets/minerops-mine-map.js" defer></script>'
|
||||
if view == "map"
|
||||
else '<script src="/assets/minerops-fleet.js" defer></script>'
|
||||
if view == "miners"
|
||||
else ""
|
||||
)
|
||||
return f"""<!doctype html>
|
||||
@@ -313,7 +356,8 @@ def render_app_page(
|
||||
<link rel="stylesheet" href="/assets/minerops-app.css">
|
||||
</head>
|
||||
<body data-view="{escape(view)}"
|
||||
data-can-view-miners="{str(can_view_miners).lower()}">
|
||||
data-can-view-miners="{str(can_view_miners).lower()}"
|
||||
data-can-view-locations="{str(has_permission("locations.view")).lower()}">
|
||||
<a class="skip-link" href="#mainContent">Skip to main content</a>
|
||||
<div class="app-shell">
|
||||
<header class="topbar">
|
||||
@@ -358,6 +402,6 @@ def render_app_page(
|
||||
</main>
|
||||
</div>
|
||||
<script src="/assets/minerops-app.js" defer></script>
|
||||
{map_script}
|
||||
{page_script}
|
||||
</body>
|
||||
</html>"""
|
||||
Reference in new issue
Block a user