mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
edc56bc457
Introduce manual import workflow and download permission support. Adds a Prisma migration and schema field (users.download_access) to track per-user download access, and updates admin UI to toggle global and per-user download access. Implements new APIs: filesystem browse, manual-import endpoint, download-access settings, audiobook download-status, and on-demand download-token generation. Adds frontend components for manual import and related tests, plus documentation for the manual-import feature and the documentation-agent prompt. Key files: prisma/migrations/20260212000000_add_download_access_permission/migration.sql, prisma/schema.prisma, src/app/api/admin/filesystem/browse/route.ts, src/app/api/admin/manual-import/route.ts, src/app/api/admin/settings/download-access/route.ts, src/app/api/requests/[id]/download-token/route.ts, src/app/api/audiobooks/[asin]/download-status/route.ts, and updated admin users pages/components and permissions util.
4.8 KiB
4.8 KiB
Manual Import Feature — Acceptance Criteria
Status: ⏳ In Progress
Overview
Allow admins to manually import audiobook files from the server filesystem into RMAB's processing pipeline for a specific book.
Acceptance Criteria
AC-1: Manual Import Button (Frontend)
- "Manual Import" button visible on
AudiobookDetailsModalfor admin users only - Button hidden when book is in active processing states:
downloading,processing,searching - Button uses
FolderArrowDownIconfrom Heroicons - Clicking opens the file browser modal
AC-2: File Browser Modal — Phase 1 (Browse)
- Modal opens at
max-w-2xl, rounded-2xl, with header/breadcrumb/listing/footer regions - Root view shows two entry tiles: Downloads and Media Library (paths from
download_dirandmedia_dirconfig) - Each folder row shows: folder icon, name, metadata line (audio file count, subfolder count, total size)
- Blue
♪ Nbadge on folders containing audio files - Folder icon swaps to
FolderOpenIconon hover (150ms transition) - Single-click selects folder (only if it has audio files); double-click navigates into it
- Folders without audio files shown at reduced opacity, still navigable but not selectable
- Breadcrumb navigation with clickable segments, home icon for root, ellipsis collapse for deep paths
- Footer shows selected path (monospace), file stats, "Review Import →" button (only when valid selection)
- Directional slide animations: right when going deeper, left when going back
- Loading skeletons during directory fetch
- Empty state for empty directories
- Error state with "Try Again" for failed directory reads
- Dark mode support throughout
AC-3: File Browser Modal — Phase 2 (Confirm)
- Slide transition from browse to confirm phase
- Shows book context: cover thumbnail + title + author
- Shows selected folder: path (monospace) + stats in inset block
- Numbered "What will happen" list: (1) copy to media library, (2) tag metadata, (3) download cover art, (4) scan library
- "Back" button returns to browse phase
- "Start Import" primary button triggers the import
- Button shows loading state during API call
- Success: close modal, show success toast, trigger request list refresh
- Error: show error toast, stay on confirm screen
AC-4: Filesystem Browse API
GET /api/admin/filesystem/browse?path=...— admin-only endpoint- Returns directory listing:
{ entries: [{ name, type, audioFileCount, subfolderCount, totalSize }] } - If no
pathparam, returns root directories (download_dir, media_dir from config) - Path validation: must be within allowed root directories (prevent directory traversal)
- Handles permission errors gracefully
- Sorts: folders first, then alphabetical
AC-5: Manual Import API
POST /api/admin/manual-import— admin-only endpoint- Request body:
{ audiobookId: string, folderPath: string } - Path validation: folderPath must be within allowed roots
- Validates folder exists and contains audio files
- If no existing request: creates request (status:
processing) + queuesorganize_filesjob - If existing request (non-active state): updates status to
processing+ queuesorganize_filesjob - Returns:
{ success: true, requestId: string } - Proper error responses for: invalid path, no audio files, already processing, book not found
AC-6: Integration with Existing Pipeline
- The
organize_filesjob processes the manual import folder identically to download-client-delivered folders - Files are copied (not moved) to the media library
- Metadata tagging, cover art download, file hash generation all work as normal
- Library scan triggered after organization (if configured)
- Request status progresses: processing → downloaded → available (via scheduled scan)
AC-7: Docker Build
docker compose build readmeabooksucceeds with no errors
Non-Goals
- No "move" option (copy only, matching existing pipeline)
- No file-level selection (folder only)
- No drag-and-drop upload
- No non-admin access
Technical Notes
- Audio extensions:
.m4b,.m4a,.mp3,.mp4,.aa,.aax,.flac,.ogg(fromsrc/lib/constants/audio-formats.ts) - Config keys:
download_dir(database),media_dir(database) - Existing file organizer:
src/lib/utils/file-organizer.ts - Organize processor:
src/lib/processors/organize-files.processor.ts - Job queue service:
src/lib/services/job-queue.service.ts - Auth middleware:
requireAuth(),requireAdmin()fromsrc/lib/middleware/auth.ts - Frontend API pattern:
fetchWithAuth()fromsrc/lib/utils/api.ts - Modal base:
src/components/ui/Modal.tsx - Audiobook details modal:
src/components/audiobooks/AudiobookDetailsModal.tsx - Toast:
useToast()from toast context