feat(upload): bulk drag-and-drop upload on home page (#66) #74

Merged
marcel merged 13 commits from feature/66-bulk-upload-drop-zone into main 2026-03-26 12:00:09 +01:00
Owner

Summary

  • Adds POST /api/documents/quick-upload — accepts multiple files in one multipart request, creates one document per file (title = filename without extension, status = UPLOADED), returns { created: [...], errors: [...] } for partial-success handling
  • Fixes storeDocument() to strip the file extension from the title (was previously storing e.g. "scan001.pdf" as title)
  • Adds a compact drag-and-drop upload zone to the home page (WRITE_ALL users only), between the search card and the document list — supports drag-and-drop and click-to-select, validates MIME types client-side, shows per-file feedback, and refreshes the list via invalidateAll() after upload
  • i18n keys added for de/en/es

Test plan

  • Backend: ./mvnw test — all 179 tests pass (new tests cover 401/403/200/invalid-type for quick-upload endpoint, and title stripping in storeDocument)
  • Frontend: npm run check — no new errors
  • Manual: drop one PDF onto home page → document appears in list with title = filename without extension
  • Manual: drop multiple files at once → one document per file created
  • Manual: drop an unsupported file (e.g. .docx) → error message shown, no document created
  • Manual: mobile / no-drag: click the drop zone → file picker opens

Closes #66

🤖 Generated with Claude Code

## Summary - Adds `POST /api/documents/quick-upload` — accepts multiple files in one multipart request, creates one document per file (title = filename without extension, status = UPLOADED), returns `{ created: [...], errors: [...] }` for partial-success handling - Fixes `storeDocument()` to strip the file extension from the title (was previously storing e.g. `"scan001.pdf"` as title) - Adds a compact drag-and-drop upload zone to the home page (WRITE_ALL users only), between the search card and the document list — supports drag-and-drop and click-to-select, validates MIME types client-side, shows per-file feedback, and refreshes the list via `invalidateAll()` after upload - i18n keys added for de/en/es ## Test plan - [ ] Backend: `./mvnw test` — all 179 tests pass (new tests cover 401/403/200/invalid-type for quick-upload endpoint, and title stripping in storeDocument) - [ ] Frontend: `npm run check` — no new errors - [ ] Manual: drop one PDF onto home page → document appears in list with title = filename without extension - [ ] Manual: drop multiple files at once → one document per file created - [ ] Manual: drop an unsupported file (e.g. .docx) → error message shown, no document created - [ ] Manual: mobile / no-drag: click the drop zone → file picker opens Closes #66 🤖 Generated with [Claude Code](https://claude.com/claude-code)
marcel added 2 commits 2026-03-26 10:02:27 +01:00
Adds a new multipart endpoint that accepts multiple files and creates one
document per file without requiring any form metadata. Each document gets
title = filename-without-extension and status = UPLOADED.

- Fix storeDocument() to strip the file extension from the document title
- Validate content type (PDF/JPEG/PNG/TIFF) server-side; unsupported files
  are skipped and returned as per-file errors in QuickUploadResult
- Tests cover 401/403 auth, success path, and unsupported file type

Closes #66 (backend part)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(upload): add drag-and-drop bulk upload zone to home page
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m25s
CI / Backend Unit Tests (push) Successful in 2m26s
CI / E2E Tests (push) Has started running
CI / Unit & Component Tests (pull_request) Failing after 1m49s
CI / Backend Unit Tests (pull_request) Successful in 2m2s
CI / E2E Tests (pull_request) Failing after 30m19s
bbfef9a22d
Adds a compact, unobtrusive drop zone between the search card and the
document list. Only visible to users with WRITE_ALL permission.

- Drag-and-drop or click-to-select multiple files at once
- Client-side MIME type validation with per-file error messages
- POSTs to /api/documents/quick-upload; refreshes list via invalidateAll()
- Inline feedback: success count + per-file errors
- i18n keys added to de/en/es message files

Closes #66 (frontend part)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 10:09:31 +01:00
fix(upload): use border-ink/20 and primary color for drop zone visibility
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Failing after 1m59s
CI / Backend Unit Tests (pull_request) Successful in 2m16s
CI / E2E Tests (pull_request) Failing after 30m10s
50e3f948c7
In light mode, border-line-2 (#eeede8) was nearly invisible and
accent (#a1dcd8, mint) was too light for hover text. Switch to:
- border-ink/20 — navy-tinted dashed border, readable in both modes
- hover:border-primary / hover:text-primary — navy in light, mint in dark

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 2 commits 2026-03-26 10:20:21 +01:00
Adds window-level dragenter/dragleave/drop listeners that detect when
the user drags any file into the browser. The drop zone expands from
py-3 to py-10 with a softened highlight, giving a clear visual cue
that dropping is possible anywhere on the page.

Uses a drag-counter to correctly handle the dragenter/dragleave storm
that fires as the pointer moves across child elements.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(test): add invalidateAll to $app/navigation mock in home page spec
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 2m24s
CI / Backend Unit Tests (pull_request) Successful in 2m11s
CI / E2E Tests (pull_request) Has been cancelled
db103ca1ab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 10:33:04 +01:00
fix(search): sort document overview by createdAt DESC instead of documentDate ASC
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
6a663cefe6
Newly uploaded documents (from bulk drop-zone or Excel import) have no
documentDate, so they were sinking to the bottom. Sorting by createdAt
DESC puts the most recently added documents first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 10:38:43 +01:00
fix(upload): structured error codes for quick-upload, fix duplicate filename crash
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
963807ff05
- Switch errors from plain strings to { filename, code } objects so the
  frontend can show translated messages instead of raw exception text
- Add UNSUPPORTED_FILE_TYPE error code end-to-end (Java enum → errors.ts
  → de/en/es messages)
- Fix IncorrectResultSizeDataAccessException when a filename exists more
  than once in the DB: use findFirstByOriginalFilename instead of
  findByOriginalFilename in storeDocument()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 10:52:56 +01:00
feat(documents): add delete button to document edit form
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
91a29d501d
- DELETE /api/documents/{id} endpoint (204 No Content, WRITE_ALL required)
- DocumentService.deleteDocument() — throws 404 if not found, cascades
  via DB foreign keys (versions, annotations, comments all ON DELETE CASCADE)
- Delete form action in edit page server: redirects to / on success
- Two-step confirmation in the save bar: first click reveals inline
  "Wirklich löschen?" + confirm/cancel, avoiding native browser dialogs
- i18n key doc_delete_confirm added to de/en/es

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 11:00:22 +01:00
fix(documents): style delete button as red outlined button with inline trash icon
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
1413058ae7
Replace the subtle link-style delete trigger and broken degruyter icon
with a proper red outlined button and an inline SVG trash bin icon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 11:12:46 +01:00
fix(delete): add cascade deletes and fix SvelteKit named action conflict
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
0795e4099f
- Add V14 migration: ON DELETE CASCADE for document_tags and document_receivers
  so deleting a document removes its join-table rows automatically
- Rename default form action to 'update' in the edit page — SvelteKit forbids
  mixing a default action with named actions (was causing 500 on delete)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 11:14:54 +01:00
fix(dropzone): replace broken degruyter upload icon with inline SVG
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
9d5c57b49b
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 11:31:48 +01:00
feat(upload): warn on duplicate filename with link to existing document
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
d078ad8224
- storeDocument now returns StoreResult(document, isNew) to distinguish
  new uploads from updates to existing documents
- QuickUploadResult gains an `updated` list alongside `created`
- Frontend shows an amber warning with a "View document" link for duplicates
  instead of silently re-uploading and leaving the user confused

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel added 1 commit 2026-03-26 11:37:43 +01:00
feat(upload): show progress bar in drop zone during upload
Some checks failed
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Successful in 2m23s
CI / Backend Unit Tests (push) Successful in 2m13s
CI / E2E Tests (push) Failing after 29m59s
1ea84e4dc8
Replaces fetch with XMLHttpRequest to get upload progress events.
The drop zone shows a filling progress bar and percentage while
files are uploading, then reverts to the normal hint when done.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
marcel merged commit 1ea84e4dc8 into main 2026-03-26 12:00:09 +01:00
marcel deleted branch feature/66-bulk-upload-drop-zone 2026-03-26 12:00:13 +01:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#74