diff --git a/webapp/templates/imaging.html b/webapp/templates/imaging.html index 9162af1..d5a6a31 100644 --- a/webapp/templates/imaging.html +++ b/webapp/templates/imaging.html @@ -96,6 +96,23 @@ {% endif %} + {% if s.intune_device_id %} +
+ LAPS password QR (paste -> scan on bay) +
+ + + + +
+
+
+ {% endif %} + {% if s.log_tail %}
Log tail ({{ s.log_tail | length }} line{{ 's' if s.log_tail | length != 1 }}) @@ -202,5 +219,67 @@ document.addEventListener('click', function(e) { copyText(text).then(function() { flashCopied(btn, true); }) .catch(function(err) { console.error('copy failed:', err); flashCopied(btn, false); }); }); + +// LAPS password -> client-side QR. Password never leaves browser tab. +// Auto-clears input + QR after 60s so it doesn't linger on shared screens. +function renderLapsQR(card) { + var input = card.querySelector('.laps-input'); + var container = card.querySelector('.laps-qr-container'); + var makeBtn = card.querySelector('.laps-make-btn'); + var clearBtn = card.querySelector('.laps-clear-btn'); + var timerEl = card.querySelector('.laps-timer'); + var text = input.value; + if (!text) { input.focus(); return; } + try { + var qr = qrcode(0, 'M'); + qr.addData(text); + qr.make(); + var modules = qr.getModuleCount(); + var size = 280; + var cellSize = Math.max(1, Math.floor(size / (modules + 8))); + container.innerHTML = qr.createImgTag(cellSize, 4); + makeBtn.style.display = 'none'; + clearBtn.style.display = ''; + var remaining = 60; + timerEl.textContent = '(auto-clears in ' + remaining + 's)'; + if (card._lapsTimer) clearInterval(card._lapsTimer); + card._lapsTimer = setInterval(function() { + remaining--; + if (remaining <= 0) { clearLapsQR(card); return; } + timerEl.textContent = '(auto-clears in ' + remaining + 's)'; + }, 1000); + } catch (err) { + container.textContent = 'QR error: ' + err; + } +} +function clearLapsQR(card) { + var input = card.querySelector('.laps-input'); + var container = card.querySelector('.laps-qr-container'); + var makeBtn = card.querySelector('.laps-make-btn'); + var clearBtn = card.querySelector('.laps-clear-btn'); + var timerEl = card.querySelector('.laps-timer'); + if (card._lapsTimer) { clearInterval(card._lapsTimer); card._lapsTimer = null; } + input.value = ''; + container.innerHTML = ''; + timerEl.textContent = ''; + makeBtn.style.display = ''; + clearBtn.style.display = 'none'; +} +document.addEventListener('click', function(e) { + var card; + if (e.target.classList.contains('laps-make-btn')) { + card = e.target.closest('.laps-card'); + if (card) renderLapsQR(card); + } else if (e.target.classList.contains('laps-clear-btn')) { + card = e.target.closest('.laps-card'); + if (card) clearLapsQR(card); + } +}); +document.addEventListener('keydown', function(e) { + if (e.key === 'Enter' && e.target.classList.contains('laps-input')) { + var card = e.target.closest('.laps-card'); + if (card) { e.preventDefault(); renderLapsQR(card); } + } +}); {% endblock %}