truenas-burnin/app/templates/components/drives_table.html
Brandon Walter b73b5251ae Initial commit — TrueNAS Burn-In Dashboard v0.5.0
Full-stack burn-in orchestration dashboard (Stages 1–6d complete):
FastAPI backend, SQLite/WAL, SSE live dashboard, mock TrueNAS server,
SMTP/webhook notifications, batch burn-in, settings UI, audit log,
stats page, cancel SMART/burn-in, drag-to-reorder stages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 00:08:29 -05:00

174 lines
7.3 KiB
HTML

{%- macro smart_cell(smart) -%}
<div class="smart-cell">
{%- if smart.state == 'running' -%}
<div class="progress-wrap">
<div class="progress-bar">
<div class="progress-fill" style="width:{{ smart.percent or 0 }}%"></div>
</div>
<span class="progress-pct">{{ smart.percent or 0 }}%</span>
</div>
{%- if smart.eta_seconds %}
<div class="eta-text">{{ smart.eta_seconds | format_eta }}</div>
{%- endif %}
{%- elif smart.state == 'passed' -%}
<span class="chip chip-passed">Passed</span>
{%- elif smart.state == 'failed' -%}
<span class="chip chip-failed" title="{{ smart.error_text or '' }}">Failed</span>
{%- elif smart.state == 'aborted' -%}
<span class="chip chip-aborted">Aborted</span>
{%- else -%}
<span class="cell-empty"></span>
{%- endif -%}
</div>
{%- endmacro -%}
{%- macro burnin_cell(bi) -%}
<div class="burnin-cell">
{%- if bi is none -%}
<span class="cell-empty"></span>
{%- elif bi.state == 'queued' -%}
<span class="chip chip-queued">Queued</span>
{%- elif bi.state == 'running' -%}
<div class="progress-wrap">
<div class="progress-bar">
<div class="progress-fill progress-fill-green" style="width:{{ bi.percent or 0 }}%"></div>
</div>
<span class="progress-pct">{{ bi.percent or 0 }}%</span>
</div>
<div class="burnin-meta">
{%- if bi.stage_name %}
<span class="stage-name">{{ bi.stage_name | replace('_', ' ') | title }}</span>
{%- endif %}
{%- if bi.started_at %}
<span class="elapsed-timer" data-started="{{ bi.started_at }}">{{ bi.started_at | format_elapsed }}</span>
{%- endif %}
</div>
{%- elif bi.state == 'passed' -%}
<span class="chip chip-passed">Passed</span>
{%- elif bi.state == 'failed' -%}
<span class="chip chip-failed">Failed{% if bi.stage_name %} ({{ bi.stage_name | replace('_',' ') }}){% endif %}</span>
{%- elif bi.state == 'cancelled' -%}
<span class="chip chip-aborted">Cancelled</span>
{%- elif bi.state == 'unknown' -%}
<span class="chip chip-unknown">Unknown</span>
{%- else -%}
<span class="cell-empty"></span>
{%- endif -%}
</div>
{%- endmacro -%}
<table>
<thead>
<tr>
<th class="col-check">
<input type="checkbox" id="select-all-cb" class="drive-cb" title="Select all idle drives">
</th>
<th class="col-drive">Drive</th>
<th class="col-serial">Serial</th>
<th class="col-size">Size</th>
<th class="col-temp">Temp</th>
<th class="col-health">Health</th>
<th class="col-smart">Short SMART</th>
<th class="col-smart">Long SMART</th>
<th class="col-burnin">Burn-In</th>
<th class="col-actions">Actions</th>
</tr>
</thead>
<tbody id="drives-tbody">
{%- if drives %}
{%- for drive in drives %}
{%- set bi_active = drive.burnin and drive.burnin.state in ('queued', 'running') %}
{%- set short_busy = drive.smart_short and drive.smart_short.state == 'running' %}
{%- set long_busy = drive.smart_long and drive.smart_long.state == 'running' %}
{%- set selectable = not bi_active and not short_busy and not long_busy %}
<tr data-status="{{ drive.status }}" id="drive-{{ drive.id }}">
<td class="col-check">
{%- if selectable %}
<input type="checkbox" class="drive-checkbox" data-drive-id="{{ drive.id }}">
{%- endif %}
</td>
<td class="col-drive">
<span class="drive-name">{{ drive.devname }}</span>
<span class="drive-model">{{ drive.model or "Unknown" }}</span>
{%- if drive.location %}
<span class="drive-location"
data-drive-id="{{ drive.id }}"
data-field="location"
title="Click to edit location">{{ drive.location }}</span>
{%- else %}
<span class="drive-location drive-location-empty"
data-drive-id="{{ drive.id }}"
data-field="location"
title="Click to set location">+ location</span>
{%- endif %}
</td>
<td class="col-serial mono">{{ drive.serial or "—" }}</td>
<td class="col-size">{{ drive.size_bytes | format_bytes }}</td>
<td class="col-temp">
{%- if drive.temperature_c is not none %}
<span class="temp {{ drive.temperature_c | temp_class }}">{{ drive.temperature_c }}°C</span>
{%- else %}
<span class="cell-empty"></span>
{%- endif %}
</td>
<td class="col-health">
<span class="chip chip-{{ drive.smart_health | lower }}">{{ drive.smart_health }}</span>
</td>
<td class="col-smart">{{ smart_cell(drive.smart_short) }}</td>
<td class="col-smart">{{ smart_cell(drive.smart_long) }}</td>
<td class="col-burnin">{{ burnin_cell(drive.burnin) }}</td>
<td class="col-actions">
<div class="action-group">
{%- if bi_active %}
<!-- Burn-in running/queued: only show cancel -->
<button class="btn-action btn-cancel"
data-job-id="{{ drive.burnin.id }}">✕ Burn-In</button>
{%- else %}
<!-- Short SMART: show cancel if running, else start button -->
{%- if short_busy %}
<button class="btn-action btn-cancel-smart"
data-drive-id="{{ drive.id }}"
data-test-type="short"
title="Cancel Short SMART test">✕ Short</button>
{%- else %}
<button class="btn-action btn-smart-short{% if long_busy %} btn-disabled{% endif %}"
data-drive-id="{{ drive.id }}"
data-test-type="SHORT"
{% if long_busy %}disabled{% endif %}
title="Start Short SMART test">Short</button>
{%- endif %}
<!-- Long SMART: show cancel if running, else start button -->
{%- if long_busy %}
<button class="btn-action btn-cancel-smart"
data-drive-id="{{ drive.id }}"
data-test-type="long"
title="Cancel Long SMART test">✕ Long</button>
{%- else %}
<button class="btn-action btn-smart-long{% if short_busy %} btn-disabled{% endif %}"
data-drive-id="{{ drive.id }}"
data-test-type="LONG"
{% if short_busy %}disabled{% endif %}
title="Start Long SMART test (~several hours)">Long</button>
{%- endif %}
<!-- Burn-In -->
<button class="btn-action btn-start{% if short_busy or long_busy %} btn-disabled{% endif %}"
data-drive-id="{{ drive.id }}"
data-devname="{{ drive.devname }}"
data-serial="{{ drive.serial or '' }}"
data-model="{{ drive.model or 'Unknown' }}"
data-size="{{ drive.size_bytes | format_bytes }}"
data-health="{{ drive.smart_health }}"
{% if short_busy or long_busy %}disabled{% endif %}
title="Start Burn-In">Burn-In</button>
{%- endif %}
</div>
</td>
</tr>
{%- endfor %}
{%- else %}
<tr>
<td colspan="10" class="empty-state">No drives found. Waiting for first poll…</td>
</tr>
{%- endif %}
</tbody>
</table>