- Accessibility: dark ink (#00003d) on warning/success buttons, badges, and success alert - white text on #ff9500/#0ad64f failed WCAG AA (~2:1); dark-on-bright now passes. - Heading hierarchy: sidebar brand h1 -> div.brand-title (with matching CSS selector), and standardized all page-header titles to a single <h1> per page (8 templates were h2). - Prefix-safe modal JS: dashboard/backups/reports/enrollment delete+clone actions now build their form action from url_for(...'__K__'/'__F__').replace(...) instead of hardcoded paths, so they survive a URL-prefix mount.
207 lines
8.1 KiB
HTML
207 lines
8.1 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}{{ filename }} - Blancco Report{% endblock %}
|
|
|
|
{% set meta = data.meta or {} %}
|
|
{% set company = data.company or {} %}
|
|
{% set hw = data.hardware or {} %}
|
|
{% set sysinfo = hw.system or {} %}
|
|
{% set bios = hw.bios or {} %}
|
|
{% set memsum = hw.memory or {} %}
|
|
|
|
{# Bytes to human-readable GB / TB string, no decimals at MB scale #}
|
|
{% macro hbytes(n) -%}
|
|
{%- set n = (n | int) -%}
|
|
{%- if n >= 1099511627776 -%}
|
|
{{ "%.2f"|format(n / 1099511627776) }} TB
|
|
{%- elif n >= 1073741824 -%}
|
|
{{ "%.2f"|format(n / 1073741824) }} GB
|
|
{%- elif n >= 1048576 -%}
|
|
{{ "%.1f"|format(n / 1048576) }} MB
|
|
{%- else -%}
|
|
{{ n }} B
|
|
{%- endif -%}
|
|
{%- endmacro %}
|
|
|
|
{% block content %}
|
|
|
|
<div class="mb-2">
|
|
<a href="{{ url_for('blancco_reports') }}" class="pxe-btn-link" style="padding:0;">← All reports</a>
|
|
</div>
|
|
|
|
<div class="page-header">
|
|
<div>
|
|
<h1>Drive Erasure Certificate</h1>
|
|
<code class="mono" style="color:var(--text-light);">{{ filename }}</code>
|
|
</div>
|
|
<div class="header-actions">
|
|
<a href="{{ url_for('blancco_download_report', filename=filename) }}"
|
|
class="pxe-btn pxe-btn-ghost">
|
|
<i class="bi bi-download"></i> Download XML
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{# Hero summary: state badge + standard + drive count + erasure datetime #}
|
|
{% set first = (data.erasures or [{}])[0] %}
|
|
{% set overall_state = first.state or 'Unknown' %}
|
|
{% set overall_tone = 'success' if overall_state == 'Successful' else 'danger' if overall_state else 'secondary' %}
|
|
{% set overall_stat = 'success' if overall_state == 'Successful' else 'danger' if overall_state else '' %}
|
|
<div class="dashboard-grid mb-4">
|
|
<div class="stat-card {{ overall_stat }}">
|
|
<div class="label">Overall result</div>
|
|
<div class="value" style="font-size:1.5rem;">
|
|
<span class="badge badge-lg bg-{{ overall_tone }}">{{ overall_state }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="label">Erasure standard</div>
|
|
<div class="value" style="font-size:1.05rem;">{{ first.erasure_standard_name or '-' }}</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="label">Drives erased</div>
|
|
<div class="value">{{ data.erasures | length }}</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="label">Elapsed time</div>
|
|
<div class="value mono" style="font-size:1.5rem;">{{ first.elapsed_time or '-' }}</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="label">Erased at</div>
|
|
<div class="value mono" style="font-size:1rem;">{{ first.timestamp or meta.date or '-' }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="content-grid mb-3">
|
|
<div class="section-card">
|
|
<div class="section-title">Customer</div>
|
|
<dl class="row mb-0 small">
|
|
<dt class="col-sm-5">Business name</dt><dd class="col-sm-7">{{ company.business_name or '-' }}</dd>
|
|
<dt class="col-sm-5">Location</dt> <dd class="col-sm-7">{{ company.business_location or '-' }}</dd>
|
|
<dt class="col-sm-5">License holder</dt><dd class="col-sm-7">{{ company.customer_license or '-' }}</dd>
|
|
{% for k, v in company.items() %}
|
|
{% if k not in ['business_name','business_location','customer_license'] %}
|
|
<dt class="col-sm-5">{{ k|replace('_',' ')|title }}</dt><dd class="col-sm-7">{{ v }}</dd>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</dl>
|
|
</div>
|
|
<div class="section-card">
|
|
<div class="section-title">System</div>
|
|
<dl class="row mb-0 small">
|
|
<dt class="col-sm-5">Manufacturer</dt> <dd class="col-sm-7">{{ sysinfo.manufacturer or '-' }}</dd>
|
|
<dt class="col-sm-5">Model</dt> <dd class="col-sm-7">{{ sysinfo.model or '-' }}</dd>
|
|
<dt class="col-sm-5">Serial</dt> <dd class="col-sm-7"><code class="mono">{{ sysinfo.serial or '-' }}</code></dd>
|
|
<dt class="col-sm-5">Chassis</dt> <dd class="col-sm-7">{{ sysinfo.chassis_type or '-' }}</dd>
|
|
<dt class="col-sm-5">BIOS mode</dt> <dd class="col-sm-7">{{ sysinfo.bios_mode or '-' }} {% if sysinfo.secure_boot_state %}<span class="badge badge-secondary">SecureBoot {{ sysinfo.secure_boot_state }}</span>{% endif %}</dd>
|
|
<dt class="col-sm-5">BIOS vendor</dt> <dd class="col-sm-7">{{ bios.vendor or '-' }} {{ bios.version or '' }}</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
{# Per-drive cards: target details + step-by-step timeline #}
|
|
{% for er in data.erasures %}
|
|
{% set t = er.target or {} %}
|
|
{% set state = er.state or 'Unknown' %}
|
|
{% set tone = 'success' if state == 'Successful' else 'danger' if state else 'secondary' %}
|
|
{% set steps = (er.steps or {}).step %}
|
|
{% if steps is not iterable or steps is string or steps is mapping %}
|
|
{% set steps = [steps] if steps else [] %}
|
|
{% endif %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div>
|
|
<strong>Drive #{{ er.erasure_id or loop.index }}:</strong>
|
|
{{ t.vendor or '' }} {{ t.model or '(unknown drive)' }}
|
|
<code class="mono ms-2" style="color:var(--text-light);">{{ t.serial or '-' }}</code>
|
|
</div>
|
|
<span class="badge bg-{{ tone }}">{{ state }}</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3 mb-3">
|
|
<div class="col-md-3">
|
|
<div class="eyebrow">Interface</div>
|
|
<div>{{ t.interface_type or '-' }}</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="eyebrow">Capacity</div>
|
|
<div>{{ hbytes(t.capacity or 0) }}</div>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<div class="eyebrow">Health</div>
|
|
<div>{{ t.health or '-' }}</div>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<div class="eyebrow">Errors</div>
|
|
<div>{{ er.total_errors or 0 }}</div>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<div class="eyebrow">Sectors</div>
|
|
<div class="small">{{ er.processed_sectors or '-' }} / {{ t.sectors or '-' }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if steps %}
|
|
<div class="table-container">
|
|
<table class="table mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:3rem;">#</th>
|
|
<th>Step</th>
|
|
<th>Pattern</th>
|
|
<th>State</th>
|
|
<th>Elapsed</th>
|
|
<th>Errors</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for s in steps %}
|
|
<tr>
|
|
<td>{{ s.number or loop.index }}</td>
|
|
<td>{{ s.type or '-' }}</td>
|
|
<td class="small" style="color:var(--text-light);">{{ s.pattern or '-' }}</td>
|
|
<td>
|
|
<span class="badge bg-{{ 'success' if s.state == 'completed' else 'danger' if s.state else 'secondary' }}">
|
|
{{ s.state or '-' }}
|
|
</span>
|
|
</td>
|
|
<td><code class="mono">{{ s.elapsed_time or '-' }}</code></td>
|
|
<td>{{ s.errors or 0 }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<div class="card">
|
|
<div class="card-header">Document signing & provenance</div>
|
|
<div class="card-body">
|
|
<dl class="row mb-0 small">
|
|
<dt class="col-sm-3">Document ID</dt>
|
|
<dd class="col-sm-9"><code class="mono text-break">{{ meta.document_id or '-' }}</code></dd>
|
|
<dt class="col-sm-3">Product</dt>
|
|
<dd class="col-sm-9">{{ meta.product_name }} {{ meta.product_version }} (rev {{ meta.product_revision }})</dd>
|
|
<dt class="col-sm-3">Generated</dt>
|
|
<dd class="col-sm-9"><code class="mono">{{ meta.date or '-' }}</code></dd>
|
|
{% if data.license_consumption_ids %}
|
|
<dt class="col-sm-3">License consumption ID{{ 's' if data.license_consumption_ids|length > 1 }}</dt>
|
|
<dd class="col-sm-9">
|
|
{% for lc in data.license_consumption_ids %}<code class="mono d-block">{{ lc }}</code>{% endfor %}
|
|
</dd>
|
|
{% endif %}
|
|
<dt class="col-sm-3">Integrity hash</dt>
|
|
<dd class="col-sm-9">
|
|
<details>
|
|
<summary style="color:var(--text-light);cursor:pointer;">Show base64 signature ({{ meta.integrity|length if meta.integrity else 0 }} chars)</summary>
|
|
<code class="mono text-break d-block mt-2">{{ meta.integrity }}</code>
|
|
</details>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %}
|