refactor(cards): collections JSON detail + preview-adjacent ladder through the builder

GET /api/collections/:id books — all four branches now build cards via
the cards.go adapters. LibraryTypeMap hoisted to once per handler (it
was 1 query per item in the smart and no-library branches). The system
branch — which before stamped cards BARE (no format_group, no badge —
the ladder's only JSON gap) — now emits the same card shape as its
siblings by feeding section.Items through BookCardsFromMediaItems,
matching what BuildSections produces for the identical data. The
collection-error seed dies via the adapters' non-nil empty slices;
the no-matching-section nil result is preserved as-is (that branch
never seeded — today's 'items': null stays today's 'items': null).

Pins: CollectionsJSON, DashboardSections, MediaListBothBranches green.
This commit is contained in:
John O'Keefe committed 2026-10-17 14:02:16 -04:00
1 parent 1ce1b79489
commit 23765934ef
1 file changed
+6 -51
+6 -51
View File
@@ -254,6 +254,7 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error {
} }
isSmart := h.collectionService.IsSmartCollection(collection.AutoAssignRules) isSmart := h.collectionService.IsSmartCollection(collection.AutoAssignRules)
libTypes := LibraryTypeMap(c.Request().Context(), h.db)
if isSmart { if isSmart {
rules := h.collectionService.ParseRules(collection.AutoAssignRules) rules := h.collectionService.ParseRules(collection.AutoAssignRules)
visibleIDs, err := h.userVisibleLibraryIDs(c) visibleIDs, err := h.userVisibleLibraryIDs(c)
@@ -267,19 +268,7 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error {
if evalErr != nil { if evalErr != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": evalErr.Error()}) return c.JSON(http.StatusInternalServerError, map[string]string{"error": evalErr.Error()})
} }
bookList = make([]BookInfo, 0, len(matches)) bookList = BookCardsFromMediaItems(matches, libTypes)
for _, item := range matches {
itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16])
libTypes := LibraryTypeMap(c.Request().Context(), h.db)
bookList = append(bookList, BookInfo{
MediaItemID: itemUUID.String(),
Title: item.Title,
Author: textToString(item.Author),
CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
FormatGroup: item.FormatGroup,
Badge: MediaBadgeKind(item.FormatGroup, libTypes[uuid.UUID(item.LibraryID.Bytes).String()]),
})
}
} else if collection.IsSystemCollection.Bool && collection.QueryType.Valid && collection.QueryType.String != "" && collection.QueryType.String != "filter" { } else if collection.IsSystemCollection.Bool && collection.QueryType.Valid && collection.QueryType.String != "" && collection.QueryType.String != "filter" {
user := c.Get("user").(database.Users) user := c.Get("user").(database.Users)
userUUID := uuid.UUID(user.ID.Bytes) userUUID := uuid.UUID(user.ID.Bytes)
@@ -290,17 +279,7 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error {
} }
for _, section := range sections { for _, section := range sections {
if section.CollectionID == collectionID { if section.CollectionID == collectionID {
bookCards := make([]BookInfo, len(section.Items)) bookList = BookCardsFromMediaItems(section.Items, libTypes)
for i, item := range section.Items {
itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16])
bookCards[i] = BookInfo{
MediaItemID: itemUUID.String(),
Title: item.Title,
Author: textToString(item.Author),
CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
}
}
bookList = bookCards
break break
} }
} }
@@ -312,7 +291,7 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error {
Limit: pgtype.Int4{Int32: 10000, Valid: true}, Limit: pgtype.Int4{Int32: 10000, Valid: true},
}) })
if collErr != nil { if collErr != nil {
bookList = []BookInfo{} bookList = BookCardsFromCollectionDashRows(nil, libTypes)
} else { } else {
var validItems []database.GetCollectionItemsForDashboardRow var validItems []database.GetCollectionItemsForDashboardRow
for _, item := range collItems { for _, item := range collItems {
@@ -320,38 +299,14 @@ func (h *CollectionHandler) GetCollection(c *echo.Context) error {
validItems = append(validItems, item) validItems = append(validItems, item)
} }
} }
libTypes := LibraryTypeMap(c.Request().Context(), h.db) bookList = BookCardsFromCollectionDashRows(validItems, libTypes)
bookCards := make([]BookInfo, len(validItems))
for i, item := range validItems {
itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16])
bookCards[i] = BookInfo{
MediaItemID: itemUUID.String(),
Title: item.Title,
Author: textToString(item.Author),
CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
FormatGroup: item.FormatGroup,
Badge: MediaBadgeKind(item.FormatGroup, libTypes[uuid.UUID(item.LibraryID.Bytes).String()]),
}
}
bookList = bookCards
} }
} else { } else {
books, booksErr := h.GetCollectionBooksData(c, collectionID) books, booksErr := h.GetCollectionBooksData(c, collectionID)
if booksErr != nil { if booksErr != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{"error": booksErr.Error()}) return c.JSON(http.StatusInternalServerError, map[string]string{"error": booksErr.Error()})
} }
bookList = make([]BookInfo, 0, len(books)) bookList = BookCardsFromCollectionItemRows(books, libTypes)
for _, book := range books {
libTypes := LibraryTypeMap(c.Request().Context(), h.db)
bookList = append(bookList, BookInfo{
MediaItemID: uuid.UUID(book.MediaItemID.Bytes).String(),
Title: book.Title,
Author: textToString(book.Author),
CoverImagePath: utils.ResolveMediaURL(book.LibraryID, book.CoverImagePath),
FormatGroup: book.FormatGroup,
Badge: MediaBadgeKind(book.FormatGroup, libTypes[uuid.UUID(book.LibraryID.Bytes).String()]),
})
}
} }
var viewSettings map[string]interface{} var viewSettings map[string]interface{}