From 1c361e138b792396adca2837fc6b77eac467a76a Mon Sep 17 00:00:00 2001 From: cproudlock Date: Thu, 14 May 2026 20:14:51 -0400 Subject: [PATCH] imaging: compact tile + search filter + stage 7 label tweak Tile shrunk for fleet density: - QR: 160px -> 96px - Drop big h4 for serial, use fs-6 strong instead - DeviceId + buttons + MAC + started time consolidated into one small grey row instead of three separate sections - Progress bar 1.2rem -> 0.7rem - mb-4 -> mb-2 between cards - card-body py-2 for tighter vertical rhythm Search: - Sticky search input above the card list - Filters live on serial, hostname, pctype, machinenumber, intune_device_id via lowercase substring match on a data-filter attribute - Visible-count badge updates as you type ("3/12") - Auto-refresh paused while query has text or while input is focused Stage 7 label: was "assign category" only, now "awaiting category / lockdown" to reflect that bays past category assignment are still waiting on the Intune-driven LAPS-prompt reboot before lockdown. Co-Authored-By: Claude Opus 4.7 (1M context) --- webapp/templates/imaging.html | 109 +++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 40 deletions(-) diff --git a/webapp/templates/imaging.html b/webapp/templates/imaging.html index aedd46c..cbd7dbf 100644 --- a/webapp/templates/imaging.html +++ b/webapp/templates/imaging.html @@ -18,12 +18,18 @@ window.addEventListener('DOMContentLoaded', scheduleImagingReload); {% block content %} -
+

Imaging Progress

Auto-refresh 15s. POST updates from imaging clients arrive at /imaging/status.
- {{ sessions|length }} session{{ 's' if sessions|length != 1 }} + {{ sessions|length }}/{{ sessions|length }} +
+ +
+
{% if not sessions %} @@ -43,8 +49,10 @@ window.addEventListener('DOMContentLoaded', scheduleImagingReload); 4: ('Apps installed', 'Type-specific scripts complete. Preparing for Intune enrollment.'), 5: ('Enrolling in Intune', 'PPKG installing - device joining Azure AD + Intune. ~5-10 min, reboot to follow.'), 6: ('Waiting on first Intune sync','Post-PPKG settle (~120s). Triggering Schedule #3 sync repeatedly.'), - 7: ('Registered - assign category','Device ID captured. Click "set category" to put bay in the right Intune group. Then wait for LAPS reboot.'), - 8: ('Imaging complete', 'Lockdown applied. Bay rebooted into ShopFloor session. Ready for production.') + 7: ('Registered - awaiting category / lockdown', + 'Device ID captured. If category not yet set in Intune, click "set category". Once set, bay waits for the Intune-driven LAPS-prompt reboot to apply lockdown.'), + 8: ('Imaging complete', + 'Lockdown applied. Bay rebooted into ShopFloor session. Ready for production.') } %} {% for s in sessions %} @@ -55,64 +63,57 @@ window.addEventListener('DOMContentLoaded', scheduleImagingReload); {% set is_done = s.status == 'succeeded' %} {% set border = 'danger' if is_failed else ('success' if is_done else 'primary') %} {% set friendly = stage_labels.get(stage_idx, ('Stage ' ~ stage_idx, '')) %} -
-
-
+
+
+
{% if s.intune_device_id %} -
{% else %} -
- waiting for Intune Device ID +
+ no DeviceId
{% endif %}
-
-

{{ s.serial or '(no serial)' }}

- {% if s.hostname_target %}{{ s.hostname_target }}{% endif %} +
+ {{ s.serial or '(no serial)' }} + {% if s.hostname_target %}{{ s.hostname_target }}{% endif %} {% if s.pctype %}{{ s.pctype }}{% endif %} {% if s.machinenumber %}#{{ s.machinenumber }}{% endif %} {{ s.status or 'in_progress' }}
-
-
-
- {{ friendly[0] }} - {{ stage_idx }}/{{ stage_total or '?' }} -
- {{ pct }}% +
+
+ {{ friendly[0] }} + {{ stage_idx }}/{{ stage_total or '?' }}
-
-
-
- {% if friendly[1] %}
{{ friendly[1] }}
{% endif %} + {{ pct }}% · last {{ s.last_updated or '-' }}
+
+
+
+ {% if friendly[1] %}
{{ friendly[1] }}
{% endif %} {% if s.intune_device_id %} -
- Intune: {{ s.intune_device_id }} - - set category + MAC {{ s.mac or '-' }} · started {{ s.started_at or '-' }}
{% endif %} - -
- started {{ s.started_at or '-' }} - · last {{ s.last_updated or '-' }} - {% if s.mac %}· MAC {{ s.mac }}{% endif %} - {% if s.current_stage %}· {{ s.current_stage }}{% endif %} -
@@ -325,5 +326,33 @@ window.addEventListener('DOMContentLoaded', function() { if (input && input.value) renderLapsQR(card, { skipPersist: true }); }); }); + +// Client-side filter: hide imaging-card elements whose data-filter doesn't +// match the search query. Live as user types. Pauses auto-reload while +// the input is focused or non-empty so typing isn't interrupted by refresh. +window.addEventListener('DOMContentLoaded', function() { + var search = document.getElementById('imaging-search'); + var counter = document.getElementById('visible-count'); + if (!search) return; + function applyFilter() { + var q = search.value.trim().toLowerCase(); + var visible = 0; + document.querySelectorAll('.imaging-card').forEach(function(card) { + var hay = card.getAttribute('data-filter') || ''; + var match = (q === '') || hay.indexOf(q) !== -1; + card.style.display = match ? '' : 'none'; + if (match) visible++; + }); + if (counter) counter.textContent = visible; + if (q !== '') { cancelImagingReload(); } + else { cancelImagingReload(); scheduleImagingReload(); } + } + search.addEventListener('input', applyFilter); + search.addEventListener('focus', cancelImagingReload); + search.addEventListener('blur', function() { + if (search.value.trim() === '') { cancelImagingReload(); scheduleImagingReload(); } + }); + applyFilter(); +}); {% endblock %}