Product display name only — page titles, headers, email, browser notification, FastAPI app title. Repo, container_name, file paths, and infrastructure identifiers (truenas-burnin everywhere) stay put to avoid breaking deployment.
129 lines
5.2 KiB
HTML
129 lines
5.2 KiB
HTML
{% extends "layout.html" %}
|
|
|
|
{% block title %}NAS Burn-In — Dashboard{% endblock %}
|
|
|
|
{% block content %}
|
|
{% include "components/modal_start.html" %}
|
|
{% include "components/modal_batch.html" %}
|
|
{% include "components/modal_unlock.html" %}
|
|
|
|
<!-- Stats bar — drive counts updated live by app.js updateCounts(); sensor chips updated by SSE system-sensors event -->
|
|
<div class="stats-bar">
|
|
<div class="stat-card" data-stat-filter="all">
|
|
<span class="stat-value" id="stat-all">{{ drives | length }}</span>
|
|
<span class="stat-label">Drives</span>
|
|
</div>
|
|
<div class="stat-card stat-running" data-stat-filter="running">
|
|
<span class="stat-value" id="stat-running">0</span>
|
|
<span class="stat-label">Running</span>
|
|
</div>
|
|
<a class="stat-card stat-failed" href="/history?state=failed" data-stat-filter="failed">
|
|
<span class="stat-value" id="stat-failed">0</span>
|
|
<span class="stat-label">Failed</span>
|
|
</a>
|
|
<div class="stat-card stat-passed" data-stat-filter="passed">
|
|
<span class="stat-value" id="stat-passed">0</span>
|
|
<span class="stat-label">Passed</span>
|
|
</div>
|
|
<div class="stat-card stat-idle" data-stat-filter="idle">
|
|
<span class="stat-value" id="stat-idle">0</span>
|
|
<span class="stat-label">Idle</span>
|
|
</div>
|
|
|
|
{%- set st = poller.system_temps if (poller and poller.system_temps) else {} %}
|
|
{%- if st.get('cpu_c') is not none or st.get('pch_c') is not none %}
|
|
<div class="stats-bar-sep"></div>
|
|
{%- if st.get('cpu_c') is not none %}
|
|
<div class="stat-sensor" id="sensor-cpu">
|
|
<span class="stat-sensor-val {{ st.get('cpu_c') | temp_class }}" id="sensor-cpu-val">{{ st.get('cpu_c') }}°</span>
|
|
<span class="stat-sensor-label">CPU</span>
|
|
</div>
|
|
{%- endif %}
|
|
{%- if st.get('pch_c') is not none %}
|
|
<div class="stat-sensor" id="sensor-pch">
|
|
<span class="stat-sensor-val {{ st.get('pch_c') | temp_class }}" id="sensor-pch-val">{{ st.get('pch_c') }}°</span>
|
|
<span class="stat-sensor-label">PCH</span>
|
|
</div>
|
|
{%- endif %}
|
|
{%- endif %}
|
|
|
|
{%- set tp = poller.thermal_pressure if poller else 'ok' %}
|
|
<div class="stat-sensor stat-sensor-thermal stat-sensor-thermal-{{ tp }}"
|
|
id="sensor-thermal"
|
|
{% if not tp or tp == 'ok' %}hidden{% endif %}>
|
|
<span class="stat-sensor-val" id="sensor-thermal-val">
|
|
{%- if tp == 'warn' %}WARM{%- elif tp == 'crit' %}HOT{%- else %}OK{%- endif %}
|
|
</span>
|
|
<span class="stat-sensor-label">Thermal</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Failed drive banner — shown/hidden by JS when failed count > 0 -->
|
|
<div id="failed-banner" class="banner banner-error" hidden>
|
|
✕ <strong><span class="failed-count">0</span> drive(s)</strong> have failed tests —
|
|
<a href="/history?state=failed" style="color:inherit;text-decoration:underline">View history</a>
|
|
</div>
|
|
|
|
<div class="filter-bar" id="filter-bar">
|
|
<button class="filter-btn active" data-filter="all">
|
|
All <span class="badge">0</span>
|
|
</button>
|
|
<button class="filter-btn" data-filter="running">
|
|
Running <span class="badge">0</span>
|
|
</button>
|
|
<button class="filter-btn" data-filter="failed">
|
|
Failed <span class="badge">0</span>
|
|
</button>
|
|
<button class="filter-btn" data-filter="passed">
|
|
Passed <span class="badge">0</span>
|
|
</button>
|
|
<button class="filter-btn" data-filter="idle">
|
|
Idle <span class="badge">0</span>
|
|
</button>
|
|
|
|
<!-- Batch start bar (hidden until checkboxes are selected) -->
|
|
<div id="batch-bar" class="batch-bar" hidden>
|
|
<span class="batch-count-label"><span id="batch-count">0</span> selected</span>
|
|
<button class="btn-batch-start" id="batch-start-btn">Start Burn-In</button>
|
|
<button class="btn-batch-clear" id="batch-clear-btn">Clear</button>
|
|
</div>
|
|
|
|
<!-- Cancel all running burn-ins (shown by JS when any burn-in is active) -->
|
|
<button class="btn-cancel-all" id="cancel-all-btn" hidden title="Cancel all running and queued burn-in jobs">✕ Cancel All Burn-Ins</button>
|
|
</div>
|
|
|
|
<div class="table-wrap">
|
|
<div hx-ext="sse" sse-connect="/sse/drives">
|
|
<div id="drives-table-wrap" sse-swap="drives-update" hx-swap="innerHTML">
|
|
{% include "components/drives_table.html" %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Log Drawer (fixed, lives outside SSE swap area) -->
|
|
<div id="log-drawer" class="log-drawer" hidden>
|
|
<div class="drawer-header">
|
|
<div class="drawer-drive-info">
|
|
<span class="drawer-devname" id="drawer-devname">—</span>
|
|
<span class="drawer-drive-meta" id="drawer-drive-meta"></span>
|
|
</div>
|
|
<nav class="drawer-tabs">
|
|
<button class="drawer-tab active" data-tab="burnin">Burn-In</button>
|
|
<button class="drawer-tab" data-tab="smart">SMART</button>
|
|
<button class="drawer-tab" data-tab="events">Events</button>
|
|
</nav>
|
|
<div class="drawer-controls">
|
|
<label class="autoscroll-label">
|
|
<input type="checkbox" id="autoscroll-toggle" checked>
|
|
<span>Auto-scroll</span>
|
|
</label>
|
|
<button class="drawer-close" id="drawer-close-btn" title="Close (Esc)">✕</button>
|
|
</div>
|
|
</div>
|
|
<div class="drawer-body">
|
|
<div class="drawer-panel active" id="drawer-panel-burnin"></div>
|
|
<div class="drawer-panel" id="drawer-panel-smart"></div>
|
|
<div class="drawer-panel" id="drawer-panel-events"></div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|