feat: compact mail folder tree + right-click Ordner leeren

- MailFolderTree: compact styling matching AI assistant SessionList (py-1, text-sm, depth*12+8 padding, no space-y)
- Added right-click context menu on folders with "Ordner leeren" entry
- Backend: POST /mail/folders/{folder_id}/empty soft-deletes all mails in folder
- Frontend API: emptyFolder() function added to mail.ts
- Mail.tsx: onFolderEmptied callback reloads mails and folders
This commit is contained in:
Agent Zero
2026-07-20 09:25:43 +02:00
parent 35fcd2a9d4
commit 9063093a5a
4 changed files with 154 additions and 23 deletions
+44
View File
@@ -587,6 +587,50 @@ async def delete_folder(
await db.delete(folder)
# ─── Empty Folder (soft-delete all mails in folder) ───
@router.post("/folders/{folder_id}/empty")
async def empty_folder(
folder_id: str,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(require_permission("mail:delete")),
):
"""Soft-delete all mails in a folder (sets deleted_at = now()).
The mails remain in the database but are hidden from the normal list.
Returns the number of mails that were emptied.
"""
tenant_id = uuid.UUID(current_user["tenant_id"])
user_id = uuid.UUID(current_user["user_id"])
f_id = _parse_uuid(folder_id, "folder_id")
folder = (
await db.execute(
select(MailFolder).where(and_(MailFolder.id == f_id, MailFolder.tenant_id == tenant_id))
)
).scalar_one_or_none()
if not folder:
raise HTTPException(404, detail={"detail": "Folder not found", "code": "not_found"})
account = await _get_account(db, folder.account_id, tenant_id, user_id)
await _check_delegate_access(db, account, user_id, "delete")
# Soft-delete all non-deleted mails in this folder
result = await db.execute(
select(Mail).where(
and_(
Mail.folder_id == f_id,
Mail.tenant_id == tenant_id,
Mail.deleted_at.is_(None),
)
)
)
mails = result.scalars().all()
now = datetime.now(UTC)
for mail in mails:
mail.deleted_at = now
await db.flush()
return {"emptied_count": len(mails)}
# ─── Attachment Upload (F-MAIL-04) ───