feat(ingestion): implement hybrid metadata verification form #34 #41

Merged
mjasin merged 2 commits from feature/issue-34 into develop 2026-05-12 18:19:07 +00:00
Collaborator

Description

This PR implements Issue #34: [UI/UX] Implement Hybrid Metadata Verification Form in Ingestion Modal.

Key Changes

  • Metadata Verification State: Introduced a new state in BookIngestionModal.razor allowing users to edit Title and Author before final ingestion.
  • Cover Image Preview: Added a high-fidelity cover preview with a CSS-based glowing placeholder fallback for books without embedded covers.
  • Ingestion Pipeline:
    • Implemented IngestEbookCommand and IngestEbookCommandHandler.
    • Added IBookStorageService and its implementation for managing EPUB and cover file storage.
    • Exposed POST /api/library/ingest Minimal API endpoint with .DisableAntiforgery() to handle client-side JSON uploads.
  • Stability Fixes:
    • Resolved DI validation errors in the WASM client by providing a dummy IBookStorageService registration.
    • Adjusted Kestrel request limits to handle large EPUB payloads (up to 100MB).
    • Corrected middleware ordering to ensure Antiforgery works correctly with Authentication.

Verification

  • Solution builds successfully.
  • Manual verification of modal state transitions and API ingestion logic.

Closes #34.

### Description This PR implements **Issue #34: [UI/UX] Implement Hybrid Metadata Verification Form in Ingestion Modal**. ### Key Changes - **Metadata Verification State**: Introduced a new state in `BookIngestionModal.razor` allowing users to edit `Title` and `Author` before final ingestion. - **Cover Image Preview**: Added a high-fidelity cover preview with a CSS-based glowing placeholder fallback for books without embedded covers. - **Ingestion Pipeline**: - Implemented `IngestEbookCommand` and `IngestEbookCommandHandler`. - Added `IBookStorageService` and its implementation for managing EPUB and cover file storage. - Exposed `POST /api/library/ingest` Minimal API endpoint with `.DisableAntiforgery()` to handle client-side JSON uploads. - **Stability Fixes**: - Resolved DI validation errors in the WASM client by providing a dummy `IBookStorageService` registration. - Adjusted Kestrel request limits to handle large EPUB payloads (up to 100MB). - Corrected middleware ordering to ensure Antiforgery works correctly with Authentication. ### Verification - Solution builds successfully. - Manual verification of modal state transitions and API ingestion logic. Closes #34.
Antigravity added 1 commit 2026-05-12 12:55:50 +00:00
mjasin approved these changes 2026-05-12 12:58:44 +00:00
Antigravity reviewed 2026-05-12 17:59:45 +00:00
Antigravity left a comment
Author
Collaborator

Automated review – please address the inline comments.

Automated review – please address the inline comments.
Author
Collaborator

Consider adding XML documentation for SaveCoverAsync to clarify that a null return indicates no cover image.

Consider adding XML documentation for `SaveCoverAsync` to clarify that a `null` return indicates no cover image.
Author
Collaborator

Adding an overload that accepts a Stream could improve memory usage for large files.

Adding an overload that accepts a Stream could improve memory usage for large files.
Author
Collaborator

Document why the default TenantId is "global" and how multi‑tenant usage should override it.

Document why the default `TenantId` is "global" and how multi‑tenant usage should override it.
Author
Collaborator

Returned epubPath is a relative URL – confirm that Ebook.FilePath expects this format.

Returned `epubPath` is a relative URL – confirm that `Ebook.FilePath` expects this format.
Author
Collaborator

Replace ToLower() comparison with String.Equals(..., StringComparison.OrdinalIgnoreCase) for case‑insensitive author lookup.

Replace `ToLower()` comparison with `String.Equals(..., StringComparison.OrdinalIgnoreCase)` for case‑insensitive author lookup.
Author
Collaborator

EF Core will assign the Author Id after SaveChangesAsync; the comment about needing to save can be removed.

EF Core will assign the Author Id after `SaveChangesAsync`; the comment about needing to save can be removed.
Author
Collaborator

Consider wrapping only expected failure points in the catch block to avoid swallowing programming errors.

Consider wrapping only expected failure points in the catch block to avoid swallowing programming errors.
Author
Collaborator

Include the original exception message in the error result for easier debugging.

Include the original exception message in the error result for easier debugging.
Author
Collaborator

Mutable record is fine for binding; add XML docs for each property to improve IDE help.

Mutable record is fine for binding; add XML docs for each property to improve IDE help.
Author
Collaborator

IBookStorageService is registered as Scoped. Since it only depends on IWebHostEnvironment, consider registering it as Singleton.

`IBookStorageService` is registered as Scoped. Since it only depends on `IWebHostEnvironment`, consider registering it as Singleton.
Author
Collaborator

Directory creation is lazy – ensure these folders are intended to be publicly served via wwwroot.

Directory creation is lazy – ensure these folders are intended to be publicly served via wwwroot.
Author
Collaborator

Method returns a relative path. Document that callers should treat this as a URL path.

Method returns a relative path. Document that callers should treat this as a URL path.
Author
Collaborator

Consider streaming the write operation for large files instead of loading the entire byte array.

Consider streaming the write operation for large files instead of loading the entire byte array.
Author
Collaborator

Added additional services – confirm they are registered in DI.

Added additional services – confirm they are registered in DI.
Author
Collaborator

verification-state visibility logic looks correct.

`verification-state` visibility logic looks correct.
Author
Collaborator

Placeholder SVG uses hard‑coded colors; consider using CSS variables for theme consistency.

Placeholder SVG uses hard‑coded colors; consider using CSS variables for theme consistency.
Author
Collaborator

IsIngesting flag correctly disables the Save button and shows loading state.

`IsIngesting` flag correctly disables the Save button and shows loading state.
Author
Collaborator

SaveToLibrary creates IngestEbookRequest – ensure the server side endpoint matches this contract.

`SaveToLibrary` creates `IngestEbookRequest` – ensure the server side endpoint matches this contract.
Author
Collaborator

After successful ingestion, consider navigating to the new book (uncomment navigation call).

After successful ingestion, consider navigating to the new book (uncomment navigation call).
Author
Collaborator

ThrowingBookStorageService ensures DI validation; include a clear exception message.

`ThrowingBookStorageService` ensures DI validation; include a clear exception message.
Author
Collaborator

HttpClient configuration now falls back to NavigationManager.BaseUri – good for local dev.

HttpClient configuration now falls back to NavigationManager.BaseUri – good for local dev.
Author
Collaborator

UseAntiforgery() appears twice; remove the duplicate call.

`UseAntiforgery()` appears twice; remove the duplicate call.
Author
Collaborator

Missing using System.Security.Claims; – add it to compile.

Missing `using System.Security.Claims;` – add it to compile.
Author
Collaborator

Endpoint api/library/ingest correctly disables antiforgery and requires auth.

Endpoint `api/library/ingest` correctly disables antiforgery and requires auth.
mjasin added 1 commit 2026-05-12 18:12:15 +00:00
mjasin merged commit d5c2952bec into develop 2026-05-12 18:19:07 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mjasin/Nexus.Reader#41