feat: add collections, read lists, and want-to-read#36
Merged
Conversation
Add the database foundation for three Komga-style grouping concepts: - collections + collection_series: shared, ordered groupings of series - read_lists + read_list_books: shared, ordered groupings of books across series (with a nullable summary) - want_to_read: per-user on-deck queue where each row flags exactly one series or one book, enforced by an inline CHECK constraint and two partial-unique indexes per user Junction tables carry a position column and cascade-delete with their parents; reverse relations are wired into the series, books, and users entities. The CHECK is rendered inline at table creation so it holds on SQLite as well as PostgreSQL. Covered by schema tests for ordered membership, uniqueness, cascade deletes, and the want-to-read CHECK, run on SQLite with ignored PostgreSQL variants.
…tories Introduce six RBAC permissions — collections:read/write/delete and readlists:read/write/delete. Read is granted to the Reader role (so all roles can browse), while write/delete go to Maintainer (inherited by Admin), matching how maintainers already manage series and books. Add repositories backing the new tables: - CollectionRepository: CRUD, idempotent membership add, reorder, and visibility-filtered ordered member fetch plus counts and a collections-for-series lookup - ReadListRepository: the same shape for books, with a nullable summary and series-based book visibility filtering - WantToReadRepository: per-user idempotent add/remove for series and books, queue listing by added-at, and batch in-queue lookups for DTO enrichment Member fetches return stored position order; the unordered computed sort is left to the API layer. Covered by unit tests and updated permission role-count assertions.
Expose the per-user want-to-read queue over /api/v1/want-to-read: - GET lists the queue, newest-first by default, with a sort=added_at:asc|desc toggle - POST flags a series or a book (exactly one; idempotent), 400 on a malformed target and 404 when it doesn't exist - DELETE removes a series or book from the queue Every endpoint scopes to the authenticated user; being signed in is sufficient since a user only manages their own queue. Surface queue membership on the existing series and book DTOs via a new wantToRead flag, populated on detail and list endpoints with a single batched lookup per page so cards can render the toggle state without an extra request. Register the new paths and schemas in the OpenAPI doc and regenerate the committed spec. Covered by integration tests.
Add the frontend for the per-user want-to-read queue: - A Want to Read page with a Newest/Oldest sort toggle and a responsive grid that reuses the standard media card, with per-entry removal and empty/loading states - A bookmark toggle on the series and book detail pages, driven by the DTO's wantToRead flag, that adds/removes the item and refreshes state - A sidebar nav link and route, plus the API client and query hooks Also surface wantToRead on the full series and book responses (the flattened DTOs the detail pages fetch), populated with one batched query per page, and regenerate the OpenAPI spec and TypeScript types. Covered by a component test for the toggle.
Expose shared, ordered collections of series over /api/v1/collections: - List, create, get, rename / toggle ordering, and delete collections - Manage members: add one or many series, remove, and set manual order - Browse members as full series DTOs, filtered by the requesting user's sharing-tag visibility, with the visible count on each collection - A thumbnail endpoint that redirects to the first visible member's cover, and a reverse lookup of the collections containing a series Reads are available to every role; create/modify require collections write and delete requires collections delete. Register the paths and schemas in the OpenAPI doc and regenerate the committed spec and types. Covered by integration tests including the permission matrix.
Add the frontend for shared collections of series: - A collections list page with cover thumbnails and a gated "New collection" modal - A collection detail page showing member series, with per-member removal and up/down reordering for ordered collections, plus gated edit and delete - An "Add to collection" menu on the series page that toggles membership across collections and can create new ones inline - A sidebar link and routes, the API client, and query hooks Mirror the new collection and read-list permissions in the frontend permission map so create/modify/delete controls only render for users who can manage collections. Covered by a component test.
Expose shared, ordered read lists of books over /api/v1/readlists: - List, create (with an optional summary), get, rename / edit summary / toggle ordering, and delete read lists - Manage members: add one or many books, remove, and set manual reading order - Browse members as full book DTOs, filtered by the requesting user's sharing-tag visibility, with the visible count on each read list - A thumbnail endpoint that redirects to the first visible member's cover, and a reverse lookup of the read lists containing a book Reads are available to every role; create/modify require read-list write and delete requires read-list delete. The update request distinguishes an omitted summary from an explicit null (which clears it). Register the paths and schemas in the OpenAPI doc and regenerate the committed spec and types. Covered by integration tests including the permission matrix.
Add the frontend for shared read lists of books: - A read lists list page with cover thumbnails and a gated "New read list" modal that captures a name, summary, and reading-order flag - A read list detail page showing the summary and member books, with per-member removal and up/down reordering for ordered lists, plus gated edit and delete - An "Add to read list" menu on the book page that toggles membership across read lists and can create new ones inline - A sidebar link and routes, the API client, and query hooks Controls that create, modify, or delete only render for users who can manage read lists. Covered by a component test.
Replace the empty collection and read-list stubs in the Komga-compatible API with real data, so third-party Komga apps can browse them: - List and detail endpoints return collections (with member series IDs) and read lists (with summary and member book IDs) - Member endpoints render the series and books in Komga's own DTO shape, reusing the existing series/book builders with batched metadata and read progress - Thumbnail endpoints redirect to the first visible member's cover, and reverse lookups expose the collections/read lists containing a given series or book All endpoints are exposed under both the v1 and v2 Komga routers, filter members by the requesting user's sharing-tag visibility, and keep the Spring-Data page wrapper Komga clients expect. Covered by integration tests; the existing Komga suite still passes after dropping the stubs.
Deploying codex with
|
| Latest commit: |
85587c4
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://7dccd26b.codex-asm.pages.dev |
| Branch Preview URL: | https://collections-read-lists-want.codex-asm.pages.dev |
Expose collections and read lists through both OPDS catalogs so e-reader apps can browse them: - OPDS 1.2 gains navigation feeds listing collections and read lists, a collection feed of its member series, and an acquisition feed of a read list's books (with download, page-streaming, and cover links) - OPDS 2.0 gains the equivalent JSON navigation and publication feeds, including per-book reading progress - Both root catalogs now link to the new Collections and Read Lists sections Member series and books are filtered by the requesting user's sharing-tag visibility. Covered by integration tests for both catalog versions.
Add a user guide covering the three grouping features — the per-user Want to Read queue, shared Collections of series, and shared Read Lists of books — including how they differ, how to use them, the management permissions, and visibility behavior. Update the Komga and OPDS pages to reflect that collections and read lists are now served read-only (with their endpoint and feed listings), and add a collection/read-list permission table to the permissions reference.
The collection, read-list, and want-to-read features added new admin permissions, raising ADMIN_PERMISSIONS from 23 to 29. The source unit test in codex-models was updated, but two duplicate hardcoded assertions in the integration tests still expected 23, causing test_permission_sets and test_user_with_multiple_api_keys to fail. Bump both stale assertions to 29 to match the current permission set.
Surface collection and read-list membership directly from the library grid instead of only the series/book detail pages. - Add nested "Add to collection" / "Add to read list" submenus to the media card dropdown, gated by collections:write / readlists:write. Series cards manage collections; book cards manage read lists. The membership query is deferred until a card's menu opens, so a grid does not fan out one request per card. - Add bulk "Add to collection" / "Add to read list" submenus to the selection toolbar's More menu. Picking a target adds every selected item, with an inline option to create a new collection/read list that immediately receives the selection. - Group the card dropdowns into divided sections (reading, management, membership) with guards so empty groups never leave orphan dividers. - Label the card menu trigger for accessibility. Fix a navigation regression: the inline-create modal was a child of the card, so its portaled clicks bubbled through React's tree to the card's navigation handler and opened the detail page. The modals now render as siblings of the card. Add tests for the new card menu entries and permission gating.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds three Komga-style organization features to Codex: Collections (shared, ordered groupings of series), Read Lists (shared, ordered groupings of books across series), and Want to Read (a per-user on-deck queue of series and books). Each is fully managed through the native API with browsing surfaced in the web UI, the read-only Komga compatibility layer, and OPDS catalogs.
Motivation
Codex had no way to group related series (franchises, publisher lines, themes) or to curate cross-series reading orders such as crossover events, and Komga apps connecting to the compatibility layer saw empty collection and read-list stubs. Separately, users had been faking a "read later" queue by opening page 1 of a title so it surfaced in "Keep Reading," abusing read-progress state. These features provide first-class grouping and a proper personal queue.
Changes
/api/v1/collectionsand/api/v1/readlists, including member add/remove/reorder, per-container thumbnails, and reverse lookups (collections containing a series, read lists containing a book). Member lists are filtered to what the requesting user is allowed to see, and counts reflect only visible members./api/v1/want-to-readto add/remove series and books and list the queue (sortable by when items were added). Series and book responses gain awantToReadflag reflecting the current user's queue state.collections:read|write|deleteandreadlists:read|write|deletepermissions. Read access is granted to all roles; write/delete go to Maintainer and Admin. Want to Read requires only authentication. These also act as API-key scopes.Notes
komga_api.enabledflag; no new configuration is required for the native API or OPDS.