chore: remove obsolete collection planning documents

Remove completed implementation plans that have been superseded:
- COLLECTION_LIBRARY_FILTERING_PLAN.md (library filtering feature completed)
- IMPLEMENTATION_COLLECTION_FIX.md (collection detail fix implemented)

These plans were for features that have already been implemented
in recent commits. Keeping only current/future planning docs.
This commit is contained in:
2026-03-05 00:42:41 -05:00
parent 9b3d8cc949
commit 75260d1b10
2 changed files with 0 additions and 1737 deletions
-291
View File
@@ -1,291 +0,0 @@
# Collection Library Filtering Implementation Plan
## Overview
Implement library-aware filtering for collection detail pages to preserve context when navigating from the dashboard.
**Current Behavior:**
- Dashboard shows collections filtered by selected library
- Clicking "View All" navigates to `/collections/:id` showing ALL books across all libraries
- This causes UX confusion: user sees 2 books on dashboard, 5 on collection page
**Target Behavior:**
- Navigate to `/collections/:id` → Show ALL books in collection (maintains backward compatibility)
- Navigate to `/collections/:id?library_id=xxx` → Show books from that specific library only
- Dashboard "View All" links preserve library context
---
## Files to Modify
### 1. `internal/handlers/dashboard.go`
**Location:** Lines 188-193
**Current Code:**
```go
func getViewAllURL(collectionID string) string {
if collectionID != "" {
return "/collections/" + collectionID
}
return ""
}
```
**Change To:**
```go
func getViewAllURL(collectionID string) libraryID string) string {
if collectionID != "" {
if libraryID != "" {
return "/collections/" + collectionID + "?library_id=" + libraryID
}
return "/collections/" + collectionID
}
return ""
}
```
**Also Update Line 180:**
```go
// Current:
ViewAllURL: getViewAllURL(ds.CollectionID.String()),
// Change To:
ViewAllURL: getViewAllURL(ds.CollectionID.String(), currentLibraryID),
```
**Also Update Function Signature (Line 157):**
```go
// Current:
func BuildSections(sections []services.DashboardSection) []SectionData {
// Change To:
func BuildSections(sections []services.DashboardSection, currentLibraryID string) []SectionData {
```
**Also Update Call Site (frontend.go Lines 194, 195):**
```go
// Current:
sectionData := handlers.BuildSections(visibleSections)
allSectionsData := handlers.BuildSections(allSections)
// Change To:
sectionData := handlers.BuildSections(visibleSections, libraryID)
allSectionsData := handlers.BuildSections(allSections, libraryID)
```
---
### 2. `internal/router/frontend.go`
**Location:** Lines 360-378 (collection detail page handler)
**Current Code:**
```go
} else {
// User collection - fetch collection items
collItems, err := cfg.Queries.GetCollectionItems(c.Request().Context(), pgtype.UUID{Bytes: collUUID, Valid: true})
if err != nil {
books = []handlers.BookInfo{}
}
// Convert to BookInfo format
bookCards := make([]handlers.BookInfo, len(collItems))
for i, item := range collItems {
itemUUID, _ := uuid.FromBytes(item.MediaItemID.Bytes[0:16])
bookCards[i] = handlers.BookInfo{
MediaItemID: itemUUID.String(),
Title: item.Title,
Author: getText(item.Author),
CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
}
}
books = bookCards
}
```
**Change To:**
```go
} else {
// User collection - check if library_id filter is present
libraryID := c.QueryParam("library_id")
if libraryID != "" {
// Filter by library - reuse dashboard query
libUUID, err := uuid.Parse(libraryID)
if err != nil {
return renderErrorPage(c, "Invalid library ID", "invalid_library_id")
}
// Use GetCollectionItemsForDashboard for library-filtered results
collItems, err := cfg.Queries.GetCollectionItemsForDashboard(c.Request().Context(),
database.GetCollectionItemsForDashboardParams{
CollectionID: pgtype.UUID{Bytes: collUUID, Valid: true},
LibraryID: pgtype.UUID{Bytes: libUUID, Valid: true},
Limit: 1000,
})
if err != nil {
books = []handlers.BookInfo{}
} else {
// Convert to BookInfo format (non-excluded only)
var validItems []database.GetCollectionItemsForDashboardRow
for _, item := range collItems {
if !item.Excluded.Valid || !item.Excluded.Bool {
validItems = append(validItems, item)
}
}
bookCards := make([]handlers.BookInfo, len(validItems))
for i, item := range validItems {
itemUUID, _ := uuid.FromBytes(item.ID.Bytes[0:16])
bookCards[i] = handlers.BookInfo{
MediaItemID: itemUUID.String(),
Title: item.Title,
Author: getText(item.Author),
CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
}
}
books = bookCards
}
} else {
// No library filter - show all books in collection
collItems, err := cfg.Queries.GetCollectionItems(c.Request().Context(), pgtype.UUID{Bytes: collUUID, Valid: true})
if err != nil {
books = []handlers.BookInfo{}
}
// Convert to BookInfo format
bookCards := make([]handlers.BookInfo, len(collItems))
for i, item := range collItems {
itemUUID, _ := uuid.FromBytes(item.MediaItemID.Bytes[0:16])
bookCards[i] = handlers.BookInfo{
MediaItemID: itemUUID.String(),
Title: item.Title,
Author: getText(item.Author),
CoverImagePath: utils.ResolveMediaURL(item.LibraryID, item.CoverImagePath),
}
}
books = bookCards
}
}
```
---
### 3. `internal/handlers/dashboard_test.go`
**Location:** Lines 60-66
**Current Code:**
```go
assert.Equal(t, "/section/continue-reading", section1.ViewAllURL, "ViewAllURL should match system collection")
assert.Equal(t, "", section2.ViewAllURL, "ViewAllURL should be empty for user collections")
```
**Add New Test Function:**
```go
func TestGetViewAllURLWithLibrary(t *testing.T) {
tests := []struct {
name string
collectionID string
libraryID string
expected string
}{
{
name: "with library ID",
collectionID: "collection-123",
libraryID: "library-abc",
expected: "/collections/collection-123?library_id=library-abc",
},
{
name: "without library ID",
collectionID: "collection-123",
libraryID: "",
expected: "/collections/collection-123",
},
{
name: "empty collection ID",
collectionID: "",
libraryID: "library-abc",
expected: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := getViewAllURL(tt.collectionID, tt.libraryID)
assert.Equal(t, tt.expected, result, "getViewAllURL mismatch")
})
}
}
```
---
### 4. `docs/user/collections.md` (Create if doesn't exist)
**Create documentation file:**
```markdown
# Collections
Collections allow you to organize books across multiple libraries.
## Viewing Collections
### From Collections Page
Navigate to `/collections` to see all your collections. Clicking on a collection shows ALL books in that collection across all libraries.
### From Dashboard
When viewing a specific library's dashboard, collections only show books from that library. Clicking "View All" preserves this context and shows only books from that library in the collection.
### Library Filtering
- **No filter** (`/collections/favorites`): Shows all books across all libraries
- **With filter** (`/collections/favorites?library_id=xxx`): Shows only books from the specified library
## Creating Collections
[Instructions for creating collections]
## Managing Collections
[Instructions for editing/deleting collections]
```
---
## Implementation Order
1. **Step 1:** Modify `dashboard.go` `getViewAllURL()` function signature and implementation
2. **Step 2:** Update `BuildSections()` to accept and pass `currentLibraryID`
3. **Step 3:** Update call sites in `frontend.go` dashboard handler
4. **Step 4:** Modify `frontend.go` collection detail handler to support library_id query parameter
5. **Step 5:** Add tests to `dashboard_test.go`
6. **Step 6:** Create/update documentation in `docs/user/collections.md`
7. **Step 7:** Rebuild TypeScript if needed (no changes expected)
8. **Step 8:** Rebuild container: `podman compose build`
9. **Step 9:** Restart container: `podman compose up -d`
10. **Step 10:** Test navigation from dashboard to collection detail page
---
## Testing Checklist
- [ ] Navigate to dashboard with Library A selected
- [ ] Click "View All" on a collection
- [ ] Verify URL includes `?library_id=library-a-id`
- [ ] Verify only books from Library A appear
- [ ] Navigate to collections page directly
- [ ] Click on same collection
- [ ] Verify URL has no library_id parameter
- [ ] Verify ALL books from all libraries appear
- [ ] Run tests: `go test ./internal/handlers/... -v`
- [ ] Verify no regressions in existing functionality
---
## Notes
- **Backward Compatibility:** URLs without `library_id` parameter work exactly as before
- **Reuses Existing Query:** `GetCollectionItemsForDashboard` already filters by library - no new SQL needed
- **Progressive Enhancement:** Works without JavaScript (server-side rendering)
- **Follows Guidelines:** No custom CSS, TypeScript only, service layer pattern maintained
File diff suppressed because it is too large Load Diff