From 5bb28e5dfa0ed938575668d952cf6f1de83013df Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Thu, 19 Feb 2026 11:42:19 -0500 Subject: [PATCH] docs(dashboard): update verification checklist for unified collections architecture UPDATES: - Remove smart_section_types table references - Update for collections table with user_id, query_type, priority, is_system_collection - Update TypeScript type examples (8 fields instead of 11) - Update type field values ('system'/'user' instead of 'smart'/'collection') - Update method names: getContinueReading, getNotStarted, RestoreSystemCollection - Update field names: hidden_collections, collection_order - Update template verification for collection terminology - Add per-collection restore button verification - Remove getInProgress and getUnread method references - Update all example code to match unified architecture VERIFICATION: - All checklist items now verify unified collections approach - Type examples show correct 8-field structure - System collections properly distinguished from user collections - Per-collection restore functionality included --- CAROUSEL_DASHBOARD_VERIFICATION_CHECKLIST.md | 229 +++++++++---------- 1 file changed, 108 insertions(+), 121 deletions(-) diff --git a/CAROUSEL_DASHBOARD_VERIFICATION_CHECKLIST.md b/CAROUSEL_DASHBOARD_VERIFICATION_CHECKLIST.md index f31cefb..7c21fbb 100644 --- a/CAROUSEL_DASHBOARD_VERIFICATION_CHECKLIST.md +++ b/CAROUSEL_DASHBOARD_VERIFICATION_CHECKLIST.md @@ -24,18 +24,15 @@ type SectionData struct { ... } // DON'T DO THIS - duplicates handlers.SectionD interface SectionData { id: string; // matches Go's json:"id" - type: string; // matches Go's json:"type" + type: string; // matches Go's json:"type" ("system" or "user") title: string; // matches Go's json:"title" description: string; // matches Go's json:"description" icon: string; // matches Go's json:"icon" items: BookInfo[]; // matches Go's json:"items" view_all_url: string; // matches Go's json:"view_all_url" priority: number; // matches Go's json:"priority" - is_hidden: boolean; // matches Go's json:"is_hidden" - created_at: string; // matches Go's json:"created_at" - updated_at: string; // matches Go's json:"updated_at" } -// All 11 fields from Go struct included - COMPLETE TYPE MATCHING +// All 8 fields from Go struct included - COMPLETE TYPE MATCHING ``` ### ❌ UNACCEPTABLE: Partial TypeScript Types @@ -46,7 +43,7 @@ interface SectionData { type: string; title: string; items: BookInfo[]; - // Missing: description, icon, view_all_url, priority, is_hidden, created_at, updated_at + // Missing: description, icon, view_all_url, priority // This is a PARTIAL type and violates type safety guidelines } ``` @@ -167,20 +164,33 @@ dropdb test_bookhoard - [ ] `id UUID PRIMARY KEY DEFAULT gen_random_uuid()` - [ ] `user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE` - [ ] `library_id UUID REFERENCES libraries(id) ON DELETE CASCADE` - - [ ] `hidden_sections TEXT[] DEFAULT '{}'` - - [ ] `section_order TEXT[] DEFAULT '{}'` + - [ ] `hidden_collections TEXT[] DEFAULT '{}'` + - [ ] `collection_order TEXT[] DEFAULT '{}'` - [ ] `items_per_section INT DEFAULT 20` - [ ] `created_at TIMESTAMP DEFAULT NOW()` - [ ] `updated_at TIMESTAMP DEFAULT NOW()` -- [ ] Unique constraint on `(user_id, library_id)` -- [ ] Index on `(user_id, library_id)` for fast lookups + - [ ] Unique constraint on `(user_id, library_id)` + - [ ] Index on `(user_id, library_id)` for fast lookups + +**For `collections` table modifications:** +- [ ] `user_id UUID NULL REFERENCES users(id)` added (NULL for system collections) +- [ ] `show_on_dashboard BOOLEAN DEFAULT false` added +- [ ] `query_type TEXT DEFAULT 'filter'` added +- [ ] `priority INT DEFAULT 100` added +- [ ] `is_system_collection BOOLEAN DEFAULT false` added +- [ ] Index created on `(user_id, show_on_dashboard, priority)` WHERE show_on_dashboard = true +- [ ] 4 system collections pre-seeded with user_id = NULL: + - [ ] `continue-reading` (priority 1, query_type='continue-reading') + - [ ] `recently-added` (priority 2, query_type='recently-added') + - [ ] `recently-read` (priority 3, query_type='recently-read') + - [ ] `not-started` (priority 4, query_type='not-started') **For `collections.show_on_dashboard` column:** - [ ] Column added with `ALTER TABLE collections ADD COLUMN` - [ ] `IF NOT EXISTS` clause included - [ ] Default value is `false` -- [ ] Index created on `(user_id, show_on_dashboard) WHERE show_on_dashboard = true` +- [ ] Index created on `(user_id, show_on_dashboard, priority) WHERE show_on_dashboard = true **For `collection_items.excluded` column:** @@ -190,31 +200,14 @@ dropdb test_bookhoard - [ ] Index created on `(collection_id, excluded) WHERE excluded = true` - [ ] Allows users to exclude auto-assigned items from filter-based collections -**For `smart_section_types`:** - -- [ ] All required columns exist: - - [ ] `id SERIAL PRIMARY KEY` - - [ ] `section_key TEXT UNIQUE NOT NULL` - - [ ] `title TEXT NOT NULL` - - [ ] `description TEXT` - - [ ] `icon TEXT` - - [ ] `default_priority INT` - - [ ] `is_global BOOLEAN DEFAULT false` -- [ ] Default sections inserted: - - [ ] `continue-reading` (priority 1, is_global=false) - - [ ] `recently-added` (priority 2, is_global=true) - - [ ] `recently-read` (priority 3, is_global=false) - - [ ] `unread` (priority 4, is_global=false) - **Verification:** ```bash # Check table definitions psql bookhoard -c "\d user_dashboard_preferences" -psql bookhoard -c "\d smart_section_types" -psql bookhoard -c "\d collections" | grep show_on_dashboard +psql bookhoard -c "\d collections" | grep -E "show_on_dashboard|query_type|priority|is_system_collection" -# Check default data -psql bookhoard -c "SELECT * FROM smart_section_types ORDER BY default_priority" +# Check system collections exist +psql bookhoard -c "SELECT name, query_type, priority, is_system_collection FROM collections WHERE user_id IS NULL" ``` ### 2.3 Verify No Migration Files @@ -281,12 +274,12 @@ rg "import.*net/http" internal/services/dashboard_service.go - [ ] `filterHiddenSections(items []SectionItems, hidden []string) []SectionItems` - [ ] `reorderSections(items []SectionItems, order []string) []SectionItems` - [ ] `getContinueReading(ctx, userID, libraryID, limit) ([]MediaItems, error)` -- [ ] `getInProgress(ctx, userID, libraryID, limit) ([]MediaItems, error)` - [ ] `getRecentlyAdded(ctx, libraryID, limit) ([]MediaItems, error)` - [ ] `getRecentlyRead(ctx, userID, libraryID, limit) ([]MediaItems, error)` -- [ ] `getUnread(ctx, userID, libraryID, limit) ([]MediaItems, error)` +- [ ] `getNotStarted(ctx, userID, libraryID, limit) ([]MediaItems, error)` - [ ] `getCollectionSections(ctx, userID, libraryID, limit) ([]SectionItems, error)` - [ ] `GetDashboardPreferences(ctx, userID, libraryID) (UserDashboardPreferences, error)` +- [ ] `RestoreSystemCollection(ctx, userID, collectionName) error` **Verification:** ```bash @@ -305,7 +298,7 @@ rg "GetSectionItems.*\[\]SectionItems" internal/services/dashboard_service.go - [ ] **Recently Added**: ORDER BY created_at DESC - [ ] **Recently Read**: Progress >= 1 (completed) - [ ] **Not Started**: Progress = 0 OR no reading_progress record -- [ ] **Collections**: WHERE show_on_dashboard = true +- [ ] **User Collections**: WHERE show_on_dashboard = true AND is_system_collection = false **Check:** ```bash @@ -319,20 +312,20 @@ rg "ORDER BY" internal/services/dashboard_service.go ### 3.4 Verify User Preference Logic -**Filter hidden sections:** +**Filter hidden collections:** -- [ ] Empty hidden list returns all sections -- [ ] Non-empty hidden list filters matching sections +- [ ] Empty hidden list returns all collections +- [ ] Non-empty hidden list filters matching collections - [ ] Comparison is case-sensitive -- [ ] No errors on empty section list +- [ ] No errors on empty collection list -**Reorder sections:** +**Reorder collections:** -- [ ] Empty order returns sections as-is -- [ ] Ordered sections come first -- [ ] Unordered sections appended at end -- [ ] No sections are lost -- [ ] No duplicate sections in result +- [ ] Empty order returns collections as-is +- [ ] Ordered collections come first +- [ ] Unordered collections appended at end +- [ ] No collections are lost +- [ ] No duplicate collections in result **Verification:** ```bash @@ -459,15 +452,16 @@ rg "GetDashboardPreferences|UpsertDashboardPreferences|UpdateDashboardPreference - [ ] Returns inserted/updated row **For `GetCollectionsForDashboard`:** -- [ ] Filters on `user_id` -- [ ] Filters on `show_on_dashboard = true` -- [ ] Orders by `created_at DESC` +- [ ] Two separate queries for system and user collections +- [ ] System collections: WHERE user_id IS NULL AND show_on_dashboard = true +- [ ] User collections: WHERE user_id = $1 AND show_on_dashboard = true AND is_system_collection = false +- [ ] Both ordered by priority ASC - [ ] Returns multiple rows -**For `SetCollectionDashboardVisibility`:** -- [ ] INSERTs on conflict with `id` -- [ ] Updates `show_on_dashboard` column -- [ ] Returns modified row +**For `RestoreSystemCollection`:** +- [ ] Deletes user-owned copy of system collection +- [ ] WHERE user_id = $1 AND name = $2 AND is_system_collection = true +- [ ] System collection (user_id = NULL) automatically appears after deletion **Verification:** ```bash @@ -552,13 +546,13 @@ rg "c\.Get\(\"user\"\)" internal/handlers/dashboard.go - [ ] Returns JSON object with `sections` array - [ ] Each section has: - - [ ] `id` (section key) - - [ ] `type` ("smart" or "collection") + - [ ] `id` (collection key or name) + - [ ] `type` ("system" or "user") - [ ] `title` - [ ] `icon` - [ ] `items` (array of books) - - [ ] `view_all_url` -- [ ] Each book has: + - [ ] `view_all_url` (empty for user collections) + - [ ] `priority` - [ ] `id` (UUID string) - [ ] `title` - [ ] `author` @@ -594,18 +588,18 @@ cd bruno/dashboard/ - [ ] `getSectionIcon(key string) string` - [ ] `getSectionViewAllURL(key string) string` -**Smart sections mapping:** +**System collections mapping:** -- [ ] `continue-reading` → type: "smart", title: "Continue Reading", icon: "📖" -- [ ] `recently-added` → type: "smart", title: "Recently Added", icon: "🆕" -- [ ] `recently-read` → type: "smart", title: "Recently Read", icon: "✅" -- [ ] `unread` → type: "smart", title: "Not Started", icon: "📕" +- [ ] `continue-reading` → type: "system", title: "Continue Reading", icon: "📖" +- [ ] `recently-added` → type: "system", title: "Recently Added", icon: "🆕" +- [ ] `recently-read` → type: "system", title: "Recently Read", icon: "✅" +- [ ] `not-started` → type: "system", title: "Not Started", icon: "📕" -**Collections:** +**User collections:** -- [ ] Non-smart sections → type: "collection" +- [ ] Non-system collections → type: "user" - [ ] Title uses collection name -- [ ] Icon defaults to "📚" +- [ ] Icon uses collection icon - [ ] view_all_url is empty string **Verification:** @@ -947,24 +941,25 @@ rg '