Skip to content

feat(frontend): confirm before deleting folders, with multi-select for bulk cleanup - #1426

Open
prawnsgupta wants to merge 3 commits into
AOSSIE-Org:mainfrom
prawnsgupta:fix/939-folder-delete-confirmation
Open

feat(frontend): confirm before deleting folders, with multi-select for bulk cleanup#1426
prawnsgupta wants to merge 3 commits into
AOSSIE-Org:mainfrom
prawnsgupta:fix/939-folder-delete-confirmation

Conversation

@prawnsgupta

@prawnsgupta prawnsgupta commented Jul 27, 2026

Copy link
Copy Markdown

Fixes #939

The problem

Deleting a folder in Settings → Folder Management happens the instant the trash icon is clicked. There is no warning and no way back — the folder row, its images, and their tags and face data are removed together (images and image_classes both cascade off folders), so a single misclick costs the whole indexing pass for that folder.

Following up on the review of #955

@rahulharpal1603 — this takes the direction you laid out when you reviewed #955, rather than the plain per-folder dialog that PR used. Your two objections were:

  1. A dialog per deletion is friction during bulk cleanup, since adding a parent folder lists all its nested folders. So folders can now be multi-selected and removed through one confirmation — clearing a directory tree is one dialog, not one per folder. The /folders/delete-folders endpoint already accepted a list of ids, so this needed no backend change; the mutation now passes the whole selection in a single request.
  2. A confirmation on top of the existing post-delete dialog is repetitive. Confirmed — useMutationFeedback defaults showSuccess: true and dispatches showInfoDialog, so deleting currently pops a "Folder Deleted" modal. With an explicit confirmation in front and the rows disappearing from the list, that success modal is now switched off for deletion. Errors are still surfaced. This is a one-line change if you would rather keep it.

What it does

  • The trash icon and the bulk action both open the shared ConfirmDialog with destructive styling.
  • The single-folder confirmation names the folder; the bulk one names the count.
  • Both state that the action cannot be undone, and that the photos themselves stay on disk — deletion only clears the library entry and its cascaded rows, never the filesystem, and it seemed worth saying so rather than leaving users to guess.
  • Select all is deliberately scoped to the folders currently on screen, so using View More afterwards cannot silently widen a selection the user already made.

Demo

screen-recording-2026-07-27-162914_k8weeNKP.mp4

Notes for review

  • No new dependency. There is no checkbox primitive in components/ui and @radix-ui/react-checkbox is not installed, so the selection boxes are native <input type="checkbox"> styled with the existing tokens. Happy to add the Radix primitive instead if you would prefer the consistency.
  • The icon-only delete button had no accessible name; it now carries an aria-label, which is also what the tests select it by.
  • deleteFolder(id) became deleteFolders(ids) in useFolderOperations. FolderManagementCard was its only consumer, so nothing else needed touching.

Tests

Added frontend/src/components/__tests__/FolderManagementCard.test.tsx — 15 tests over both flows: that clicking delete confirms instead of deleting, that cancelling deletes nothing, that the folder actually clicked is the one removed, that the confirmation can be reopened, and for bulk, that the count is right, that the button appears and disappears with the selection, and that confirming removes every selected folder in a single call.

Verified they catch the original bug: restoring the immediate-delete onClick fails 6 of them.

Frontend suite green, tsc --noEmit, ESLint and Prettier all clean. Merged latest main to clear the conflict — the delete-confirmation rows now sit on top of the new indexing-status states (isIndexingPending, the interrupted badge), reconciled in FolderManagementCard.

@rohan-pandeyy let me know for any other changes, if not feel free to merge the PR.

Deleting a folder from Folder Management happened the moment the trash
icon was clicked, so a misclick permanently removed the folder along with
its tags, faces and indexing data.

Deletion now goes through the shared ConfirmDialog. The confirmation names
the folder, states that it cannot be undone, and makes clear that the
photos themselves stay on disk, since deletion only clears the library
entry and its cascaded rows rather than touching the filesystem.

Folders can also be selected with checkboxes and removed together through
a single "Delete selected (N)" confirmation, so clearing out a directory
tree does not mean dismissing one dialog per folder. Select all is scoped
to the folders currently on screen so "View More" cannot silently widen
the selection. The delete mutation now takes a list of ids and sends them
in one request, which the /folders/delete-folders endpoint already
supported.

The success dialog that used to appear after a deletion is gone: the user
has just confirmed the action and the folders disappear from the list, so
a second modal only added a click. Errors are still reported.

The icon-only delete button also gains an aria-label, so it has an
accessible name and the confirmation can be reached by keyboard and
screen reader.

Adds tests covering both flows: that clicking delete confirms rather than
deleting, that cancelling deletes nothing, that the right folder is
removed, and that a bulk confirmation deletes every selected folder in a
single call.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Folder deletion now requires confirmation, supports selecting multiple folders, and sends selected folder IDs through a batch deletion hook. Tests cover single-folder and bulk deletion, cancellation, reopening, selection counts, and select-all behavior.

Changes

Folder deletion flow

Layer / File(s) Summary
Batch deletion hook
frontend/src/hooks/useFolderOperations.tsx
The deletion mutation accepts folder ID arrays, ignores empty requests, and exposes batch deletion and pending-state fields.
Selection and confirmation UI
frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx
The folder card adds individual and select-all checkboxes, conditional bulk deletion, confirmation state, dynamic dialog text, and batch deletion wiring.
Deletion interaction tests
frontend/src/components/__tests__/FolderManagementCard.test.tsx
Tests cover confirmation, cancellation, reopening, bulk selection, select-all behavior, deletion counts, and batch calls.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested labels: TypeScript/JavaScript

Sequence Diagram(s)

sequenceDiagram
  participant FolderManagementCard
  participant ConfirmDialog
  participant useFolderOperations
  FolderManagementCard->>ConfirmDialog: Open deletion confirmation
  ConfirmDialog->>FolderManagementCard: Confirm selected folder IDs
  FolderManagementCard->>useFolderOperations: deleteFolders(folderIds)
  useFolderOperations->>FolderManagementCard: Expose deleteFoldersPending state
Loading

Poem

I’m a bunny with folders in line,
Now warnings make deleting just fine.
Select one or a few,
Confirm what you do,
And hop through the batch by design!

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR adds an irreversible confirmation dialog and explicit confirmation before folder deletion, satisfying #939.
Out of Scope Changes check ✅ Passed The multi-select bulk delete and test updates are aligned with the stated PR objectives and not obviously out of scope.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: folder deletion confirmation and bulk multi-select cleanup.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@rohan-pandeyy

Copy link
Copy Markdown
Member

@prawnsgupta Could you upload the demo video to the PR instead of the issue's comment section? It'll make the review process much easier.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This PR has merge conflicts.

Please resolve the merge conflicts before review.

Your PR will only be reviewed by a maintainer after all conflicts have been resolved.

📺 Watch this video to understand why conflicts occur and how to resolve them:
https://www.youtube.com/watch?v=Sqsz1-o7nXk

Reconcile the folder delete-confirmation UI with the indexing-status work that landed on main: rows now use isIndexingPending() and show the new "interrupted" badge, while keeping the multi-select and single batch confirm dialog from this branch.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
frontend/src/components/__tests__/FolderManagementCard.test.tsx (2)

1-3: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Test file sits under components/__tests__ but exercises a page component.

Consider frontend/src/pages/SettingsPage/components/__tests__/FolderManagementCard.test.tsx so the test lives next to its subject.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/__tests__/FolderManagementCard.test.tsx` around lines
1 - 3, Move the FolderManagementCard test from the generic components test
directory into the SettingsPage/components/__tests__ directory alongside the
FolderManagementCard subject, preserving its existing imports and test behavior.

17-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the visible-scoping guarantee of "Select all".

With only 3 mock folders and a default visibleFoldersCount of 6, every folder is always visible, so the branch that keeps hidden folders out of the selection is never exercised — precisely the behavior the PR calls out. A fixture of 7+ folders plus a "View More" case would lock it in.

Also applies to: 217-232

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/__tests__/FolderManagementCard.test.tsx` around lines
17 - 21, Add test coverage in FolderManagementCard tests for the Select all
behavior when more than the default visibleFoldersCount of 6 folders exist.
Expand the mockFolders fixture to at least 7 folders and add a View More
scenario verifying Select all selects only currently visible folders while
hidden folders remain unselected.
frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx (1)

96-101: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Deduplicate the deletion copy.

Both branches repeat the same trailing warning verbatim; only the subject differs.

♻️ Optional refactor
   const deletionDescription = () => {
-    if (foldersToDelete.length === 1) {
-      return `"${foldersToDelete[0].folder_path}" will be removed from your library along with its tags and indexing data. This cannot be undone, though the photos themselves stay on your disk.`;
-    }
-    return `${foldersToDelete.length} folders will be removed from your library along with their tags and indexing data. This cannot be undone, though the photos themselves stay on your disk.`;
+    const subject =
+      foldersToDelete.length === 1
+        ? `"${foldersToDelete[0].folder_path}" will be removed from your library along with its tags and indexing data.`
+        : `${foldersToDelete.length} folders will be removed from your library along with their tags and indexing data.`;
+    return `${subject} This cannot be undone, though the photos themselves stay on your disk.`;
   };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx` around
lines 96 - 101, Update deletionDescription to build the differing folder subject
separately, then append one shared warning message for both the single-folder
and multiple-folder cases. Preserve the existing wording and singular/plural
subjects.
frontend/src/hooks/useFolderOperations.tsx (1)

133-133: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename deleteFolderMutation to match its batch semantics.

The mutation, handler, and exposed state are all plural now; the singular variable name is the only leftover.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/hooks/useFolderOperations.tsx` at line 133, Rename
deleteFolderMutation to its plural batch-semantics name throughout the mutation
declaration, handlers, and exposed state in the surrounding folder operations
hook, preserving all existing behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx`:
- Around line 111-120: Update the “Select all” control in FolderManagementCard
so its label explicitly indicates it applies only to visible folders when
folders exceed visibleFoldersCount, while retaining “Select all” wording. Set
the checkbox’s indeterminate state when some, but not all, visible folders are
selected, and keep checked tied to allVisibleSelected. Use the existing
selection state and toggleSelectAllVisible behavior.

---

Nitpick comments:
In `@frontend/src/components/__tests__/FolderManagementCard.test.tsx`:
- Around line 1-3: Move the FolderManagementCard test from the generic
components test directory into the SettingsPage/components/__tests__ directory
alongside the FolderManagementCard subject, preserving its existing imports and
test behavior.
- Around line 17-21: Add test coverage in FolderManagementCard tests for the
Select all behavior when more than the default visibleFoldersCount of 6 folders
exist. Expand the mockFolders fixture to at least 7 folders and add a View More
scenario verifying Select all selects only currently visible folders while
hidden folders remain unselected.

In `@frontend/src/hooks/useFolderOperations.tsx`:
- Line 133: Rename deleteFolderMutation to its plural batch-semantics name
throughout the mutation declaration, handlers, and exposed state in the
surrounding folder operations hook, preserving all existing behavior.

In `@frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx`:
- Around line 96-101: Update deletionDescription to build the differing folder
subject separately, then append one shared warning message for both the
single-folder and multiple-folder cases. Preserve the existing wording and
singular/plural subjects.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2096e026-1fb1-442c-8a73-291c1613d0c7

📥 Commits

Reviewing files that changed from the base of the PR and between d9fb073 and 38cf847.

📒 Files selected for processing (3)
  • frontend/src/components/__tests__/FolderManagementCard.test.tsx
  • frontend/src/hooks/useFolderOperations.tsx
  • frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx

Comment thread frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx
It only spans folders currently on screen, so relabel it "Select all shown" and show an indeterminate state when some but not all visible folders are selected, instead of an empty checkbox.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request frontend good first issue Good for newcomers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Confirmation before deleating a folder

2 participants