Webapp redesign phase 4: Updates overview and rollback review

- GET /updates/: one card per updater (Dell, iPXE, Blancco, BPRT) with
  its state, a Check now / Open action and details in accordions; the
  shared download cap is a small popover.
- Dell applies list: one line per apply titled by its first change
  ('Latitude 5350 pack A11 to A12', model looked up in the maps) and
  'and n more'; the chip says how many written files are unchanged since
  the apply. The body lists every change, skipped item, error and file.
- dell_updates.file_status(): per file an apply wrote, unchanged /
  changed / missing by content hash, the same test rollback uses.
  describe(), history_view() and rollback_preview() build on it.
- GET /updates/dell/rollback/<id>: review a rollback before doing it,
  with the files that would be restored and a diff of each. The POST
  route is unchanged; both forms can return to the overview.
This commit is contained in:
cproudlock
2026-10-14 13:54:41 -04:00
parent 731d7b044d
commit cc1e76f3ab
6 changed files with 391 additions and 2 deletions

View File

@@ -28,7 +28,7 @@ def _render(preview=None, preview_keys=()):
scan=dell_updates.last_scan(),
prog=prog,
staged=items,
history=dell_updates.history()[:15],
history=dell_updates.history_view(15),
settings=updates_common.settings(),
preview=preview,
preview_keys=list(preview_keys),
@@ -157,6 +157,18 @@ def discard():
return _back()
@bp.route("/rollback/<apply_id>")
def rollback_review(apply_id):
"""Review a rollback before doing it: which files would be restored
(content unchanged since the apply) and the diff of each."""
try:
rec = dell_updates.rollback_preview(apply_id)
except ValueError:
flash("No apply with that id.", "warning")
return redirect(url_for("updates_overview"))
return render_template("updates_rollback.html", rec=rec)
@bp.route("/rollback", methods=["POST"])
def rollback():
apply_id = request.form.get("apply_id", "")
@@ -170,10 +182,14 @@ def rollback():
"on the share, unused.", "success")
for msg in refused:
flash(f"Not restored: {msg}.", "danger")
if request.form.get("next") == "overview":
return redirect(url_for("updates_overview"))
return _back()
@bp.route("/settings", methods=["POST"])
def save_settings():
save_speed_cap() # shared with the other Updates pages (views/__init__.py)
if request.form.get("next") == "overview":
return redirect(url_for("updates_overview"))
return _back()