feat(backups): filter, preview, compare and bulk delete (v0.24.2-beta)
Closes #134.
Backups are /export compact output — plain RouterOS script, not the binary
.backup blob — which is what makes the reporter's "it's just a text, after
all" correct and most of this cheap.
- Filters: device, type, date range and free text over device name,
filename and notes. Dates are inclusive at both ends, because a picker
showing "to: 3 Sep" that stops at that day's first instant is a trap. - Preview in place, on row click. No round trip through the downloads
folder to see what a backup contains. - Compare any two, reusing the lineDiff that Config History already uses
rather than adding a second diff implementation. - Bulk delete, with selection and a confirmation that names what goes.
Two deliberate choices.
Bulk delete had to respect an existing invariant: a backup and its config
snapshot are one artifact, joined by ON DELETE CASCADE so they cannot drift
apart. Removing fifty in one click can therefore destroy restore points
nobody looked at. The confirmation is built from a server-side preview that
reports the backups per device and how many config snapshots will go with
them, and it is capped at 200 per call. The action is also site-scoped, so it
cannot reach into another site's history.
The Filename column is gone from the table but the filename is not gone: it
is the natural handle for a file — device and timestamp, the thing you would
quote to a colleague — so it moved to the preview and diff headers where you
are actually looking at that file, rather than being dropped.
Diff direction is extracted and tested. Selection order in a table is
whatever the user happened to click and carries no meaning, so the pair is
ordered oldest-first; rendered the other way round every addition reads as a
deletion, and nothing about the output looks wrong while it does.
Incidentally fixed: 'pre-upgrade' backups were labelled "Manual" in the table
because the badge only knew three types. Type wording now has one home.
The list query's placeholder counter is replaced by a bind() helper deriving
from params.length. The counter's final increment was dead, and whoever added
the next filter would have inherited a stale index.
Verified against 110 real backups: every filter and combination returns the
expected counts and partitions cleanly, preview and diff read real .rsc with
file_path withheld, and bulk delete removed three throwaway backups plus
their files and left the other 110 untouched. Guards checked: empty, missing,
non-numeric and injected ids, unknown ids, and the 200 cap.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Container image: ghcr.io/2gt-media-group-llc/mikrotik-manager:0.24.2-beta
Documentation: https://2gt-media-group-llc.github.io/mikrotik-manager/