Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions public/modules/ui/routes-overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,41 @@ function overviewRoutes() {
}

function triggerAllRoutesRemove() {
alertMessage.innerHTML = /* html */ `Are you sure you want to remove all routes? This action can't be undone`;
const toRemove = pack.routes.filter(route => !route.lock);
if (!toRemove.length) {
if (!pack.routes.length) {
tip("There are no routes to remove", false, "error");
} else {
tip("All routes are locked. Unlock routes to remove them, or use Lock all to unlock first.", false, "error");
}
return;
}

const lockedCount = pack.routes.length - toRemove.length;
alertMessage.innerHTML =
lockedCount > 0
? /* html */ `Remove all <b>unlocked</b> routes (${toRemove.length})? <b>${lockedCount}</b> locked route(s) will be kept. This cannot be undone.`
: /* html */ `Are you sure you want to remove all routes? This action can't be undone`;
Comment on lines +184 to +188
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The confirmation text/title are derived from toRemove/lockedCount computed before opening the #alert dialog, but the actual deletion list is recomputed inside the Remove handler. Because jQuery UI dialogs are non-modal by default, users can lock/unlock additional routes while the dialog is open, which can make the confirmed counts inaccurate and potentially delete more routes than the prompt indicated. Consider making this dialog modal (or otherwise preventing lock state changes while it’s open), or ensure the deletion always matches the exact set/count presented in the confirmation UI.

Copilot uses AI. Check for mistakes.

$("#alert").dialog({
resizable: false,
title: "Remove all routes",
title: lockedCount > 0 ? "Remove unlocked routes" : "Remove all routes",
buttons: {
Remove: function () {
pack.cells.routes = {};
pack.routes = [];
routes.selectAll("path").remove();

const routesToRemove = pack.routes.filter(route => !route.lock);
if (!routesToRemove.length) {
if (!pack.routes.length) {
tip("There are no routes to remove", false, "error");
} else {
tip("All routes are now locked; nothing was removed.", false, "error");
}
$(this).dialog("close");
return;
}
for (const route of routesToRemove) {
Routes.remove(route);
}
pack.cells.routes = Routes.buildLinks(pack.routes);
routesOverviewAddLines();
$(this).dialog("close");
},
Expand Down
2 changes: 1 addition & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5523,7 +5523,7 @@
class="icon-download"
></button>
<button id="routesLockAll" data-tip="Lock or unlock all routes" class="icon-lock"></button>
<button id="routesRemoveAll" data-tip="Remove all routes" class="icon-trash"></button>
<button id="routesRemoveAll" data-tip="Remove all unlocked routes (locked routes are kept)" class="icon-trash"></button>
<label for="routesSearch" data-tip="Filter by name or group" style="margin-left: 0.2em"
>Search: <input id="routesSearch" type="search"
/></label>
Expand Down
Loading