feat: soft-delete and undo/restore for local-workspace items
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped

Backend:
- DELETE /api/local-workspace/items/{id} now soft-deletes (sets deleted_at
  instead of hard DELETE) — items go to trash, not permanently gone
- New POST /api/local-workspace/items/{id}/restore to undo a delete
- _load_workspace_pages() and _load_children() now filter deleted_at IS NULL
  so soft-deleted items disappear from sidebar and tree queries

Frontend:
- undoDelete() now calls the restore API per item (single or bulk)
- bulkDelete() now shows the same undo banner as context menu delete
- All delete paths (ctxMenu, bulk, modal) use the same soft-delete + undo flow
This commit is contained in:
2026-07-16 10:28:17 -04:00
parent 631c106b01
commit 8c0b55635c
3 changed files with 45 additions and 20 deletions
+25 -4
View File
@@ -567,11 +567,20 @@ window._wsInitData = (function() {
if (ids.length === 0) return;
if (!confirm('Delete ' + ids.length + ' selected items?')) return;
var self = this;
// Soft-delete all selected items
for (var i=0; i<ids.length; i++) {
await fetch('/api/local-workspace/items/' + ids[i], { method: 'DELETE' });
}
this.clearSelection();
this._reloadAfterAction();
// Show undo banner for bulk delete
this.undoItemId = ids.join(',');
this.undoMessage = 'Deleted ' + ids.length + ' item(s)';
this.undoVisible = true;
this.undoTimeout = setTimeout(function() {
self.undoVisible = false;
self.undoItemId = null;
}, 5000);
},
clearSelection() {
for (var k in this.selectedIds) delete this.selectedIds[k];
@@ -1223,11 +1232,23 @@ window._wsInitData = (function() {
undoDelete() {
if (this.undoTimeout) clearTimeout(this.undoTimeout);
this.undoVisible = false;
var id = this.undoItemId;
if (!id) return;
// Recreate the item (we can't really undo a DELETE, so reload)
this._reloadAfterAction();
var ids = (this.undoItemId || '').toString().split(',');
this.undoItemId = null;
if (!ids.length || !ids[0]) return;
// Restore via API (soft-delete undo) — single or bulk
var self = this;
var restored = 0;
var total = ids.length;
function restoreOne(i) {
if (i >= total) {
self._reloadAfterAction();
return;
}
fetch('/api/local-workspace/items/' + ids[i] + '/restore', { method: 'POST' })
.then(function(r) { if (r.ok) restored++; })
.finally(function() { restoreOne(i + 1); });
}
restoreOne(0);
},
_removeFromTree(nodes, id) {
for (var i=0; i<nodes.length; i++) {