- Report view: the hero summarised only the first erasure, so a drive whose Purge failed and Clear fallback succeeded showed Failed while the list said Successful. It now uses the per-drive outcome (report_result) and lists the standards that wiped each drive. - To-do and ServiceNow: reports with no usable document id could never be ticked or cleared (400). They are now tracked by file name (file:<name>). - Imaging: the LAPS password field is masked, with a Show/Hide toggle. - Imaging: succeeded sessions not updated for ACTIVE_WINDOW_HOURS are hidden from the dashboard (failed and in-progress always stay), with Show all. - Enrollment: the active SFLD package can no longer be deleted, which left ppkg.conf pointing at a missing file; its row is marked Active. - Import: confirm before importing, saying upload-folder sources are moved and same-name files in the image are overwritten.
174 lines
8.4 KiB
HTML
174 lines
8.4 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Technician To-Do - PXE Server Manager{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="page-header">
|
|
<h1><i class="bi bi-clipboard-check"></i> Technician To-Do</h1>
|
|
<div class="header-actions">
|
|
<span class="badge badge-{{ 'warning' if todo.total else 'success' }} badge-lg">{{ todo.total }} open</span>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="text-muted">
|
|
Blancco wipes, reports, evidence packs and cloud uploads are automatic. These are the
|
|
CMMC playbook steps that still need a technician ({{ site }}). Mark each one done here once finished.
|
|
</p>
|
|
|
|
{# 1. ServiceNow #}
|
|
<div class="section-card">
|
|
<div class="section-title">1. Tick wipes on the Onsite Bin Management RITM (ENT-045 / ENT-159)</div>
|
|
{% if todo.servicenow %}
|
|
<p class="mb-2"><strong>{{ todo.servicenow }}</strong> wipe{{ 's' if todo.servicenow != 1 }} from the last 30 days still to tick in ServiceNow.</p>
|
|
<a href="{{ url_for('blancco_servicenow') }}" class="pxe-btn pxe-btn-primary"><i class="bi bi-list-check"></i> Open the tick list</a>
|
|
{% else %}
|
|
<p class="text-muted mb-0">All caught up.</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{# 2. Evidence packs #}
|
|
<div class="section-card">
|
|
<div class="section-title">2. Upload the monthly evidence pack to Box (ENT-056 / ENT-158)</div>
|
|
{% if todo.evidence %}
|
|
<p class="mb-2">Saved automatically on the 1st. Download it, upload it to the site's ENT-056 / ENT-158 evidence folders in Box, then mark it uploaded.</p>
|
|
<div class="table-container">
|
|
<table class="data-table">
|
|
<thead><tr><th>Month</th><th>File</th><th class="text-end">Actions</th></tr></thead>
|
|
<tbody>
|
|
{% for p in todo.evidence %}
|
|
<tr>
|
|
<td class="mono">{{ p.month }}</td>
|
|
<td class="mono">{{ p.file }}</td>
|
|
<td class="text-end text-nowrap">
|
|
<a href="{{ url_for('blancco_evidence_file', filename=p.file) }}" class="pxe-btn pxe-btn-secondary btn-row-action"><i class="bi bi-download"></i> Download</a>
|
|
<form method="post" action="{{ url_for('blancco_todo_mark', kind='evidence_uploaded', key=p.month) }}" style="display:inline;">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="pxe-btn pxe-btn-success btn-row-action">Mark uploaded</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted mb-0">No pack waiting. The next one is saved on the 1st of next month.</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{# 3. Failed wipes #}
|
|
<div class="section-card">
|
|
<div class="section-title">3. Destroy drives that failed to wipe (ENT-158 / ENT-159)</div>
|
|
{% if todo.failed %}
|
|
<p class="mb-2">Remove the drive, destroy it per site procedure, record the Certificate of Destruction and the destruction note on the RITM, then mark it here.</p>
|
|
<div class="table-container">
|
|
<table class="data-table">
|
|
<thead><tr><th>Serial</th><th>Model</th><th>Wiped</th><th>Failure</th><th class="text-end">Actions</th></tr></thead>
|
|
<tbody>
|
|
{% for it in todo.failed %}
|
|
<tr title="{{ it.file }}">
|
|
<td class="mono">{{ it.serial or '-' }}</td>
|
|
<td>{{ it.model or '-' }}</td>
|
|
<td class="mono text-nowrap">{{ it.when | local_dt }}</td>
|
|
<td class="small wrap">{{ it.note }}</td>
|
|
<td class="text-end text-nowrap">
|
|
<a href="{{ url_for('blancco_view_report', filename=it.file) }}" class="pxe-btn pxe-btn-secondary btn-row-action"><i class="bi bi-eye"></i> Report</a>
|
|
<form method="post" action="{{ url_for('blancco_todo_mark', kind='destroyed', key=it.key) }}" style="display:inline;">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="pxe-btn pxe-btn-success btn-row-action">COD recorded</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted mb-0">No failed wipes waiting for destruction.</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{# 4. Not in the cloud #}
|
|
<div class="section-card">
|
|
<div class="section-title">4. Reports that did not reach the Blancco cloud (ENT-056)</div>
|
|
{% if todo.not_in_cloud %}
|
|
<p class="mb-2">Auditors pull certificates from the Blancco Management Portal. Upload the report's XML there by hand, then mark it resolved.</p>
|
|
<div class="table-container">
|
|
<table class="data-table">
|
|
<thead><tr><th>Serial</th><th>Model</th><th>Wiped</th><th class="text-end">Actions</th></tr></thead>
|
|
<tbody>
|
|
{% for it in todo.not_in_cloud %}
|
|
<tr title="{{ it.file }}">
|
|
<td class="mono">{{ it.serial or '-' }}</td>
|
|
<td>{{ it.model or '-' }}</td>
|
|
<td class="mono text-nowrap">{{ it.when | local_dt }}</td>
|
|
<td class="text-end text-nowrap">
|
|
<a href="{{ url_for('blancco_download_report', filename=it.file) }}" class="pxe-btn pxe-btn-secondary btn-row-action"><i class="bi bi-download"></i> XML</a>
|
|
<form method="post" action="{{ url_for('blancco_todo_mark', kind='cloud_resolved', key=it.key) }}" style="display:inline;">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="pxe-btn pxe-btn-success btn-row-action">Resolved</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted mb-0">Every report with a known upload status reached the cloud.</p>
|
|
{% endif %}
|
|
</div>
|
|
{# 5. Hardware the server cannot image yet #}
|
|
<div class="section-card">
|
|
<div class="section-title">5. Add drivers / BIOS for new hardware</div>
|
|
{% if hardware %}
|
|
<p class="mb-2">These models booted WinPE here but the server has no Win11 driver pack or no BIOS entry for them.
|
|
Download the Dell driver pack and BIOS for the exact model below, add them, and they drop off this list.
|
|
<a href="{{ url_for('hardware_page') }}">Hardware coverage</a> shows every model.</p>
|
|
<div class="table-container">
|
|
<table class="data-table">
|
|
<thead><tr><th>Model (WMI)</th><th>System SKU</th><th>BIOS seen</th><th>Missing</th><th>Last seen</th><th class="text-end">Actions</th></tr></thead>
|
|
<tbody>
|
|
{% for r in hardware %}
|
|
<tr title="Serials: {{ r.serials | join(', ') }}">
|
|
<td class="mono">{{ r.model }}</td>
|
|
<td class="mono">{{ r.skus | join(', ') or '-' }}</td>
|
|
<td class="mono">{{ r.last_bios_version or '-' }}</td>
|
|
<td class="small wrap">
|
|
{% if r.missing %}Driver pack: {{ r.missing | join(', ') }}{% endif %}
|
|
{% if r.bios.status in ('none', 'file-missing') %}{% if r.missing %}<br>{% endif %}BIOS: {{ 'no manifest entry' if r.bios.status == 'none' else r.bios.file ~ ' not on server' }}{% endif %}
|
|
</td>
|
|
<td class="mono text-nowrap">{{ r.last_seen | local_dt }}</td>
|
|
<td class="text-end text-nowrap">
|
|
<button type="button" class="btn btn-sm btn-outline-secondary btn-row-action copy-btn" data-copy-text="{{ r.model }}">copy model</button>
|
|
<form method="post" action="{{ url_for('hardware_dismiss') }}" style="display:inline;">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<input type="hidden" name="model" value="{{ r.model }}">
|
|
<input type="hidden" name="next" value="{{ url_for('blancco_todo') }}">
|
|
<button type="submit" class="pxe-btn pxe-btn-ghost btn-row-action">Dismiss</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<p class="text-muted mb-0">Every model seen has a Win11 driver pack and a BIOS entry.</p>
|
|
{% endif %}
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_scripts %}
|
|
<script>
|
|
document.querySelectorAll('.copy-btn').forEach(function (b) {
|
|
b.addEventListener('click', function () {
|
|
var t = b.getAttribute('data-copy-text') || '';
|
|
var done = function () { var o = b.textContent; b.textContent = 'copied'; setTimeout(function () { b.textContent = o; }, 1200); };
|
|
if (navigator.clipboard && window.isSecureContext) { navigator.clipboard.writeText(t).then(done); return; }
|
|
var ta = document.createElement('textarea'); ta.value = t; document.body.appendChild(ta); ta.select();
|
|
try { document.execCommand('copy'); done(); } finally { document.body.removeChild(ta); }
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|