Webapp redesign phase 2: Overview and imaging floor
Imaging floor (/imaging, /imaging/tiles): - One line per PC: status chip, serial with machine number, hostname and IP, stage text with a segmented stage track, one action plus a '...' menu. Everything else (description, error, timestamps, Intune ID + QR, Set category / ARTS links, LAPS QR, log tail) is in the row's expandable body. - Order: failed, needs action (stage 7), in progress, done; log-only bays fold into one collapsed group. imaging_status.floor_state() and floor_order() compute this. - Status filter buttons with live counts next to the text filter. SSE refresh, expanded-row memory and LAPS handling are unchanged. - Stage text is never truncated; BIOS updates and erasing are bold. Overview (/): - Services popover, technician to-do line, the six most urgent floor rows (?limit=6 partial, refreshed every 15 s), and image cards with lint warnings, map errors and missing zips as separate chips. New, clone, delete and unattend stay on the cards' menus. Copy buttons are now handled once in static/app.js, with a fallback for plain-http pages where navigator.clipboard is unavailable.
This commit is contained in:
@@ -103,13 +103,30 @@ app.register_blueprint(images_unattend_views.bp) # Unattend review/save/undo
|
||||
@app.route("/")
|
||||
def dashboard():
|
||||
image_list = [images.image_status(it) for it in config.IMAGE_TYPES]
|
||||
for img in image_list:
|
||||
# Card details: OS, driver entries and lint, from the image pages.
|
||||
try:
|
||||
info = image_pages.header_info(img["image_type"])
|
||||
img["os_label"] = info["os_label"]
|
||||
img["driver_count"] = info["driver_count"]
|
||||
except Exception:
|
||||
img["os_label"], img["driver_count"] = "", 0
|
||||
img["lint"] = image_pages._lint_counts(img["image_type"])
|
||||
services = [system.service_status(s) for s in ("dnsmasq", "apache2", "smbd")]
|
||||
sessions, _hidden = imaging_status.hide_stale(imaging_status.list_sessions())
|
||||
floor = imaging_status.floor_order(sessions)
|
||||
real = [x for x in floor if x["floor_state"] != "logs"]
|
||||
counts = {k: sum(1 for x in real if x["floor_state"] == k) for k in ("failed", "action", "running", "done")}
|
||||
return render_template(
|
||||
"dashboard.html",
|
||||
images=image_list,
|
||||
services=services,
|
||||
image_types=config.IMAGE_TYPES,
|
||||
friendly_names=config.FRIENDLY_NAMES,
|
||||
sessions=real[:6],
|
||||
more=max(0, len(real) - 6),
|
||||
floor_counts=counts,
|
||||
compact=True,
|
||||
)
|
||||
|
||||
|
||||
@@ -845,7 +862,7 @@ def imaging_dashboard():
|
||||
hidden = 0
|
||||
if not show_all:
|
||||
sessions, hidden = imaging_status.hide_stale(sessions)
|
||||
return render_template("imaging.html", sessions=sessions, hidden=hidden,
|
||||
return render_template("imaging.html", sessions=imaging_status.floor_order(sessions), hidden=hidden,
|
||||
show_all=show_all, window_hours=imaging_status.ACTIVE_WINDOW_HOURS)
|
||||
|
||||
|
||||
@@ -857,7 +874,15 @@ def imaging_tiles_partial():
|
||||
sessions = imaging_status.list_sessions()
|
||||
if request.args.get("all") != "1":
|
||||
sessions, _hidden = imaging_status.hide_stale(sessions)
|
||||
return render_template("_imaging_tiles.html", sessions=sessions)
|
||||
sessions = imaging_status.floor_order(sessions)
|
||||
# ?limit=N (the Overview): the first N PCs, log-only bays left out.
|
||||
limit = request.args.get("limit", type=int)
|
||||
more = 0
|
||||
if limit:
|
||||
real = [x for x in sessions if x["floor_state"] != "logs"]
|
||||
more = max(0, len(real) - limit)
|
||||
sessions = real[:limit]
|
||||
return render_template("_imaging_tiles.html", sessions=sessions, more=more, compact=bool(limit))
|
||||
|
||||
|
||||
def _sessions_hash() -> str:
|
||||
|
||||
Reference in New Issue
Block a user