Webapp redesign: fixes from the functional regression test

- Unattend: a command's '...' menu stayed open after Move up/down and
  covered the next row's menu, so the next click could stage removing the
  wrong command. The menu now closes and focus returns to its button.
- '...' menus close on an outside click, on Escape and when another
  opens (static/app.js), for every page.
- Drivers: Remove asks to confirm again, as before the redesign. Long zip
  paths in a row body wrap (the page scrolled sideways at 390 px).
- Rollback review returns to the page it was opened from (Dell page or
  Updates overview), for both Cancel and the rollback itself.
- To-do: the ServiceNow period offers a year again (366 days).
- Imaging floor: a search that matches a log-only bay opens that group;
  its open state survives the live refresh. 'Clear all' states the
  number of session files it deletes, hidden finished ones included.
- Dashboard: the image key pattern is valid under the browser's v flag
  (client-side validation was silently skipped).
- Import: allowed_import_source() compares real paths, so
  '<upload dir>/../..' is refused. This path traversal predates the
  redesign; the import moves the source tree, so it mattered.
This commit is contained in:
cproudlock
2026-10-14 14:48:10 -04:00
parent 2bcc9d8016
commit 2ed2cbe2e9
11 changed files with 61 additions and 15 deletions

View File

@@ -23,7 +23,7 @@ function cancelImagingReload() {
{% if sessions %}
{% call ui.more('the imaging floor') %}
<form method="post" action="{{ url_for('imaging_delete_all') }}"
onsubmit="return confirm('Clear all {{ sessions|length }} imaging sessions? Every row is removed; PCs still imaging reappear on their next status push.');">
onsubmit="return confirm('Clear all {{ clear_count }} imaging session files{{ (', including ' ~ hidden ~ ' hidden finished') if hidden else '' }}? Every row is removed; PCs still imaging reappear on their next status push.');">
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="del">Clear all sessions</button>
</form>
@@ -363,11 +363,29 @@ document.addEventListener('keydown', function(e) {
document.querySelectorAll('#floor-filters [data-count]').forEach(function(n) {
n.textContent = counts[n.getAttribute('data-count')];
});
// A log-only bay that matches a search is shown: open its group.
var logs = document.querySelector('details.floor-logs');
if (logs) {
var hit = Array.prototype.some.call(logs.querySelectorAll('.imaging-card'), function (c) { return !c.hidden; });
if (q !== '' && hit) logs.open = true;
if (!hit) logs.hidden = true; else logs.hidden = false;
}
var none = document.getElementById('floor-nomatch');
if (none) none.hidden = visible > 0 || (q === '' && stateFilter === '');
}
function restoreLogsGroup() {
var g = document.querySelector('details.floor-logs');
if (!g) return;
try { if (sessionStorage.getItem('floor-logs-open') === '1') g.open = true; } catch (e) {}
if (!g._bound) {
g.addEventListener('toggle', function () { try { sessionStorage.setItem('floor-logs-open', g.open ? '1' : '0'); } catch (e) {} });
g._bound = true;
}
}
window.imagingPostSwapHooks = function() {
restoreLogsGroup();
restoreExpandedState();
autoRenderLapsQRs();
renderIntuneQRs();