Commit Graph
700 Commits
Author SHA1 Message Date
john-okeefe a1a14c2af8 feat(dashboard): implement Phase 9 dashboard template and TypeScript for Carousel-style dashboard
Replace library browser with Carousel-style collections carousel:

Template Changes (templates/dashboard.templ):
Complete rewrite from library browser to collections carousel:

1. Dashboard Main Template:
   - Sticky library selector dropdown
   - Customize dashboard button (settings modal)
   - Refresh button
   - Loading spinner for async operations
   - Collections container with carousels

2. CollectionCarousel Component:
   - Collection header with icon, title, description
   - View All link for system collections
   - Horizontal scrollable carousel track
   - Left/right navigation buttons
   - Book cards with cover images
   - Empty state handling

3. BookCard Component:
   - Aspect ratio [2/3] book cover
   - Cover image with fallback to placeholder
   - Title and author display
   - Click handler for viewing book details
   - Hover scale animation

4. DashboardSettingsModal Component:
   - Draggable collection list for reordering
   - Toggle switches for collection visibility
   - "System" badges for system collections
   - "Restore" buttons for system collections
   - Items per section slider (10-50, step 5)
   - Save/Cancel buttons

Template Features:
- Uses IsSystem boolean instead of Type string
- data-is-system attribute for JavaScript
- data-collection-id for DOM manipulation
- Supports drag-and-drop reordering
- Settings modal with live preview

TypeScript Implementation (web/src/dashboard.ts):

Core Functions:
- scrollCarousel: Smooth horizontal scrolling
- openDashboardSettings/closeDashboardSettings: Modal control
- toggleCollectionVisibility: Toggle visibility switches
- saveDashboardSettings: Save preferences to API
  * Collects hidden_collections and collection_order
  * Calls PUT /api/dashboard/preferences
  * Reloads page on success
- restoreSystemCollection: Reset system collection to defaults
  * Confirmation dialog
  * Calls POST /api/dashboard/restore-system-collection
  * Shows toast notifications
- switchLibrary: Switch between libraries
  * Async fetch from API
  * Re-renders collections
- renderCollections: Client-side rendering of collections
- renderBookCard: Generate book card HTML
- viewBook: Placeholder for book detail view
- reloadPage: Refresh page
- updateItemsCount: Update slider display
- initDragAndDrop: Drag-and-drop event handlers

Event Handling:
- Event delegation for performance
- data-action attributes for handler routing
- Proper type checking and null safety
- Error handling with toast notifications

Type Safety:
- Uses SectionData and BookInfo from api.d.ts
- Proper TypeScript types throughout
- Null checks for DOM elements
- Type assertions where needed

This implements Phase 9: Dashboard Template with unified collections terminology and full TypeScript interactivity.
2026-02-19 21:11:53 -05:00
john-okeefe 77c7ef965f feat(dashboard): implement Phase 8 SSR template routes for Carousel-style dashboard
Update /dashboard route in frontend.go to use unified collections architecture:

Route Changes:
- Use DashboardService to fetch user dashboard preferences
- Get all dashboard sections (system + user collections)
- Pass sections and library data to template
- Support library_id query parameter for library switching
- Default to first visible library if no library_id specified

Service Integration:
- cfg.DashboardService.GetDashboardPreferences: Fetch user preferences
  * hidden_collections: Collections to hide from dashboard
  * collection_order: Custom collection ordering
  * items_per_section: Number of items per collection
- cfg.DashboardService.GetDashboardSections: Fetch all sections
  * System collections (user_id = NULL): continue-reading, recently-added, recently-read, not-started
  * User collections: User-created collections marked for dashboard
  * Applies user preferences: filters hidden, reorders, sorts by priority
- handlers.BuildSections: Convert service types to handler types

Data Flow:
1. Get user template data with theme
2. Get library_id from query param or default to first library
3. Fetch user dashboard preferences
4. Fetch dashboard sections with preferences applied
5. Convert to handler types for template rendering
6. Render template with sections and library data

Template Signature Change:
- OLD: templates.Dashboard(user)
- NEW: templates.Dashboard(user, sections, libData, currentLibraryID)

This implements Phase 8: SSR Template Routes with unified collections architecture.
2026-02-19 21:11:40 -05:00
john-okeefe 380af685dc feat(dashboard): implement Phase 7 router registration and config setup
Add DashboardService and DashboardHandler to application configuration:

Router Config Updates (internal/router/router.go):
- Add services import for DashboardService type
- Add DashboardService field to Config struct
- DashboardService: Used by SSR routes in frontend.go for data fetching
- DashboardHandler: Used by API routes in dashboard.go for JSON endpoints

Server Initialization (cmd/server/main.go):
- Create dashboardService instance using services.NewDashboardService(queries)
- Keep dashboardHandler creation (already exists from Phase 4)
- Add DashboardService to routerConfig
- Both services now available for dependency injection

Test Helpers (cmd/server/tests/test_helpers.go):
- Create dashboardService instance for testing
- Create dashboardHandler instance for testing
- Add both DashboardService and DashboardHandler to routerConfig
- Ensures test environment matches production setup

Architecture Rationale:
- DashboardService: Service layer with business logic (reusable by SSR, mobile)
- DashboardHandler: HTTP handler layer (JSON API endpoints)
- Separation allows SSR templates to call service directly
- API routes use handler for proper HTTP response handling
- Mobile apps can use API endpoints via DashboardHandler

All three files updated consistently for complete integration.
2026-02-19 21:06:23 -05:00
john-okeefe 9ef94efeb5 feat(dashboard): implement Phase 6 TypeScript type definitions
Add TypeScript interfaces for Carousel-style dashboard to api.d.ts:

New Interfaces:
1. SectionData
   - Matches handlers.SectionData in collections.go (lines 73-81)
   - id: Collection name (string)
   - is_system: Boolean flag (true for system collections, false for user)
   - title: Display title
   - description: Collection description
   - icon: Emoji icon
   - items: Array of BookInfo objects
   - view_all_url: URL to view all items (system collections only)
   - priority: Display order (lower numbers first)

2. DashboardPreferences
   - Matches database.UserDashboardPreferences (models.go:381-390)
   - library_id: Library UUID
   - hidden_collections: Array of collection names to hide
   - collection_order: Array of collection names for custom ordering
   - items_per_section: Number of items per section

Existing Interface:
- BookInfo: Already defined (media_item_id, title, author, cover_image_path)
  - Reused by SectionData for items array
  - No duplicate definitions needed

Key Compliance:
- is_system: boolean matches database is_system_collection field
- media_item_id matches Go BookInfo.MediaItemID field
- Uses existing BookInfo struct (no duplicates)
- Added to existing api.d.ts file (follows established pattern)
2026-02-19 21:05:59 -05:00
john-okeefe 190914c004 test(dashboard): implement Phase 5 Bruno API tests for Carousel-style dashboard
Update and create Bruno API tests to reflect new unified collections architecture:

Updated Tests:
1. get-dashboard-sections.yml
   - Updated response structure documentation
   - Changed from type field to is_system boolean
   - Changed from id to media_item_id in items
   - Added priority field documentation
   - Updated example response to show unified collections structure
   - Added test for sections array in response

2. update-preferences.yml
   - Changed HTTP method from POST to PUT (matching handler implementation)
   - Updated request body field names:
     * hidden_sections → hidden_collections
     * section_order → collection_order
   - Updated documentation with new field names
   - Updated example request with valid system collection names

New Tests:
3. restore-system-collection.yml
   - Tests POST /api/dashboard/restore-system-collection endpoint
   - Validates collection_name against allowed system collections
   - Tests success response with message
   - Documents valid collection names:
     * continue-reading
     * recently-added
     * recently-read
     * not-started

Test Coverage:
- GET /api/dashboard/sections: Returns all dashboard sections
- PUT /api/dashboard/preferences: Updates user preferences
- POST /api/dashboard/restore-system-collection: Resets system collection

All tests follow Bruno YAML format with proper authentication via auth: inherit.
2026-02-19 21:02:47 -05:00
john-okeefe 804dc6d069 chore(dashboard): wire up DashboardHandler in server main
Create dashboardHandler instance and add to router config:
- Initialize dashboardHandler using handlers.NewDashboardHandler(queries)
- Add dashboardHandler to router.Config for route registration
- All dashboard routes are now available at /api/dashboard/*
2026-02-19 20:59:27 -05:00
john-okeefe 91288a0695 feat(dashboard): register dashboard API routes
Add dashboard route registration and wire up handler:

Router Changes:
- Add DashboardHandler to router.Config struct
- Create internal/router/dashboard.go with dashboard route registration
- Register dashboard routes in main RegisterRoutes function

Dashboard Routes (all protected by JWT):
- GET /api/dashboard/sections: Get dashboard sections for user
  * Query params: library_id (required), limit (optional, default 20, max 100)
  * Returns: JSON with sections array
- PUT /api/dashboard/preferences: Update dashboard preferences
  * Body: library_id, hidden_collections, collection_order, items_per_section
  * Returns: Updated preferences
- POST /api/dashboard/restore-system-collection: Restore system collection to defaults
  * Body: collection_name (must be valid system collection)
  * Returns: Success message

Server Integration:
- Create dashboardHandler in cmd/server/main.go
- Add dashboardHandler to routerConfig
- Routes are automatically registered on server startup
2026-02-19 20:59:24 -05:00
john-okeefe 810316694a feat(dashboard): implement Phase 4 API handlers for Carousel-style dashboard
Add dashboard API endpoints with handler layer:

Step 1: Add SectionData to collections.go
- SectionData struct represents dashboard section (carousel of books)
- Used by: Dashboard handler, Templates (SSR), API JSON responses
- Shared type from collections.go (no duplicate definitions)
- Fields: ID, IsSystem, Title, Description, Icon, Items, ViewAllURL, Priority

Step 2: Create dashboard.go handler
- DashboardHandler struct with injected database and dashboard service
- GetSections: Returns dashboard sections as JSON (mobile apps, web UI TypeScript, plugins)
  * Validates library_id parameter
  * Fetches user dashboard preferences
  * Configurable limit (default 20, max 100)
  * Calls service layer for business logic
  * Converts service types to handler types for JSON serialization
- UpdatePreferences: Saves dashboard preferences
  * Validates library_id
  * Upserts user dashboard preferences
- RestoreSystemCollection: Resets system collection to defaults
  * Validates collection_name against allowed system collections
  * Deletes user's copy (system collection reappears automatically)
- BuildSections: Converts service DashboardSection to handler SectionData
  * Converts database.MediaItems to handlers.BookInfo
  * Uses shared types from collections.go
- getViewAllURL: Maps system collections to their view-all URLs
- Reuses existing textToString helper from collections.go

Architecture Compliance:
- Generic API handler for reuse by SSR, mobile, plugins
- Uses shared types from collections.go (SectionData, BookInfo)
- IsSystem bool matches database field (no string conversion)
- Single service method returns structured data (simpler, less bugs)
- Handler just converts types (no matching logic needed)
- Reusable by mobile apps, web UI, plugins
2026-02-19 20:59:19 -05:00
john-okeefe 336f5fc6d4 feat(dashboard): implement Phase 2 dashboard service layer
Create DashboardService with business logic for Carousel-style dashboard:

Service Methods:
- NewDashboardService: Create service instance with injected dependencies
- GetDashboardSections: Fetch all collections (system + user) with their items
  * Gets system collections (user_id = NULL) by query type
  * Gets user collections with manual + auto-assigned items
  * Filters hidden collections based on user preferences
  * Reorders collections based on user custom order
  * Sorts by priority if no custom order exists
- GetDashboardPreferences: Fetch user dashboard preferences for library
- UpsertDashboardPreferences: Save or update user dashboard preferences
- RestoreSystemCollection: Reset user's copy of system collection to defaults

Helper Methods:
- filterHiddenCollections: Remove hidden collections from results
- reorderCollections: Reorder sections based on user preference
- sortByPriority: Sort sections by priority (lower numbers first)
- getCollectionItemsByQueryType: Return items for system collections by query type
- getUserCollectionItems: Return items for user collections (manual + auto-assign)

Type Conversion Helpers:
- mediaItemsToListMediaItemsRow: Convert MediaItems to ListMediaItemsRow for rule evaluation
- getCollectionItemsRowToMediaItems: Convert GetCollectionItemsForDashboardRow to MediaItems

Architecture Compliance:
- Service layer holds all business logic (reusable by SSR, API, mobile)
- Returns database types (type safety at DB layer)
- Handler converts to API types (clean JSON contracts)
- Uses existing database queries and collection service
- Procedural/imperative style (no OOP)
- Follows existing pattern from collections.go
2026-02-19 20:56:13 -05:00
john-okeefe dd1e56d2f7 chore(dashboard): regenerate database code from Phase 3 queries
Run sqlc generate to create Go code for dashboard queries:
- GetDashboardPreferences / UpsertDashboardPreferences / UpdateDashboardPreferences
- GetSystemCollectionsForDashboard / GetUserCollectionsForDashboard
- DeleteUserSystemCollection
- GetContinueReadingItems / GetRecentlyAddedItems / GetRecentlyReadItems / GetNotStartedItems
- GetCollectionItemsForDashboard / GetLibraryItems

Auto-generated from queries.sql changes.
2026-02-19 20:55:59 -05:00
john-okeefe 1f80f6acfd feat(dashboard): add Phase 3 database queries for Carousel-style dashboard
Add SQL queries for dashboard functionality and system collections:

Dashboard Preferences Queries:
- GetDashboardPreferences: Fetch user preferences for a library
- UpsertDashboardPreferences: Create or update user dashboard preferences
- UpdateDashboardPreferences: Update existing preferences

Dashboard Collections Queries:
- GetSystemCollectionsForDashboard: Fetch system collections (user_id IS NULL)
- GetUserCollectionsForDashboard: Fetch user collections marked for dashboard
- DeleteUserSystemCollection: Delete user's copy of a system collection

System Collection Smart Queries:
- GetContinueReadingItems: Books with 0 < progress < 1
- GetRecentlyAddedItems: Newly added items to library
- GetRecentlyReadItems: Books with progress >= 1
- GetNotStartedItems: Books with progress = 0 or no record

Collection Management Queries:
- GetCollectionItemsForDashboard: Fetch collection items with excluded flag
- GetLibraryItems: Fetch all items in a library

These queries support the unified collections architecture where system
defaults and user-created sections are both collections with user_id
NULL for system-owned and NOT NULL for user-created.
2026-02-19 20:55:54 -05:00
john-okeefe 3af2fb0ba4 schema(dashboard): implement Phase 1 unified collections architecture
Add support for Carousel-style dashboard with unified collections architecture:

Database Schema Changes:
- Add user_dashboard_preferences table:
  - hidden_collections: TEXT[] for managing section visibility
  - collection_order: TEXT[] for custom ordering
  - items_per_section: INT for limiting items per section
- Update collections table:
  - user_id: Make nullable to support system-owned collections (NULL = system)
  - show_on_dashboard: BOOLEAN for controlling visibility
  - query_type: TEXT for different query types (continue-reading, recently-added, etc.)
  - priority: INT for display order (lower = higher priority)
  - is_system_collection: BOOLEAN for flagging system defaults
- Update collection_items table:
  - Add excluded BOOLEAN for user overrides of auto-assigned items

Indexes:
- idx_collections_dashboard: (user_id, show_on_dashboard, priority) WHERE show_on_dashboard = true
- idx_dashboard_prefs_user_library: (user_id, library_id)
- idx_collection_items_excluded: (collection_id, excluded) WHERE excluded = true

System Collections (pre-seeded defaults):
- continue-reading: Books with 0 < progress < 1
- recently-added: Newly added items to library
- recently-read: Books with progress >= 1
- not-started: Books with progress = 0 or no record

This implements Phase 1 of the Carousel-style dashboard redesign plan.
2026-02-19 20:52:21 -05:00
john-okeefe ceca81f098 docs: Add CreateCollection manual books update summary
Add comprehensive summary document for the CreateCollection manual books
support feature (Phase 4.6).

Document contents:
- Summary of changes made to plan and checklist
- Key design decisions and rationale
  - 50 book validation limit (DoS prevention)
  - Graceful degradation strategy
  - Backward compatibility approach
  - Infrastructure reuse decisions

- Implementation effort breakdown (2 hours total)
- Pre-implementation checklist (all complete)
- Post-implementation checklist
- Testing requirements
  - Unit tests (to be added)
  - Integration tests (to be added)
  - Bruno tests (documented)
  - Manual testing checklist

This document serves as:
1. Change log for Phase 4.6
2. Quick reference for implementation
3. Testing checklist
4. Design rationale documentation

Status: Documentation complete, ready for implementation
2026-02-19 20:48:46 -05:00
john-okeefe 9c34a45ba6 docs: Add verification checklist for Phase 4.6
Update the verification checklist to cover all aspects of Phase 4.6
(CreateCollection manual books support).

New verification sections:
- Section 6.4: Verify CreateCollection Endpoint Manual Books Support
  - Struct field verification (ManualBookIDs)
  - Validation tag verification (validate:"max=50")
  - Handler implementation verification
  - Error handling and logging verification
  - Graceful degradation verification

- Section 19.1b: Verify Collections Bruno Tests Created
  - New bruno/collections/ directory structure
  - All 5 required test files
  - Test coverage verification

- Section 19.1b: Verify Collections API Documentation
  - manual_book_ids field documentation
  - Validation limits (max 50)
  - Example requests
  - Error handling explanation
  - Backward compatibility notes

Bug fix:
- Fixed BuildSections function signature to match actual service
  (services.DashboardSection instead of services.SectionItems)

All verification includes:
- Step-by-step verification commands
- Common pitfalls to avoid
- Success criteria for each section
2026-02-19 20:48:40 -05:00
john-okeefe f34914166d docs: Add Phase 4.6 - CreateCollection manual books support
Add comprehensive documentation for Phase 4.6 which enables the
CreateCollection endpoint to support manual book selection alongside
auto-assign rules. This is required for the Custom Section Builder.

Key additions:
- Phase 4.6: Update CreateCollection Endpoint (30-45 min)
  - Add ManualBookIDs field to CreateCollectionRequest struct
  - Implement graceful handling of invalid book IDs
  - Add validation (max 50 book IDs) to prevent DoS
  - Reuse existing AddBookToCollection service method
  - Maintain backward compatibility (field is optional)

- Updated Phase 12.5: Collections Bruno tests
  - create-collection-with-manual-books.bru
  - create-collection-too-many-books.bru (validation test)
  - create-collection-invalid-book-id.bru
  - create-collection-rules-only.bru
  - create-collection-unauthorized.bru

- Added section 13.3: Collections API documentation
  - manual_book_ids field documentation
  - Validation limits (max 50 items)
  - Example combining auto-assign + manual books
  - Error handling explanation

Design decisions:
- Graceful degradation: Collection created even if some books fail
- Reuse existing infrastructure: No new service methods needed
- Backward compatible: Optional field doesn't break existing clients
- UI constraint: 50 book limit prevents abuse while allowing flexibility
2026-02-19 20:48:32 -05:00
john-okeefe da33e2c126 docs: update Carousel Dashboard plan and resolve verification checklist discrepancies
Updated Carousel Dashboard documentation to reflect finalized architecture decisions
and resolve discrepancies between plan and verification checklist.

## CAROUSEL_DASHBOARD_PLAN.md Changes

### Added Phase 4.5: Collections Preview Endpoint
- Documented why preview endpoint is required (web UI + mobile apps)
- Explained why client-side preview is a bad idea (download entire library,
  code duplication, maintenance nightmare)
- Added full PreviewCollection handler implementation
- Added Bruno test specification

### Enhanced Phase 7: Router Registration & Config Setup
- Renamed from "Router Registration" to "Router Registration & Config Setup"
- Added Step 1: Update router.go Config struct with line numbers
- Added Step 2: Update main.go initialization with line numbers
- Added Step 3: Update test_helpers.go with line numbers
- Added explanation: Why both DashboardService AND DashboardHandler?

### Updated Phase 10.5.4: Collections Preview Endpoint
- Referenced Phase 4.5 (endpoint already implemented earlier)
- Clarified needed for web UI AND mobile apps
- Noted no additional work needed

### Added Phase 10.6: Implementation Checklist
- 30+ checklist items with file paths and verification commands
- Organized by layer (Database, Service, Handler, Router, Templates, TypeScript, Tests, Docs)
- Added Build & Verification section
- Added Timeline Estimate (20-26 hours)
- Added Post-Implementation Tasks

## CAROUSEL_DASHBOARD_VERIFICATION_CHECKLIST.md Changes

### Added Clarification Section (at top)
- Explained all discrepancies between plan and checklist
- Preview endpoint IS in plan (Phase 4.5)
- Custom Section Builder IS in plan (Phase 10.5.2 and 10.5.3)
- Service method names - Plan is correct
- Config struct - Documented with exact line numbers
- DashboardService vs DashboardHandler - Explained why both needed

### Updated Service Method Names (Section 3.2)
Changed to match plan's actual implementation:
- GetDashboardSections (not GetSectionItems)
- filterHiddenCollections (not filterHiddenSections)
- reorderCollections (not reorderSections)
- sortByPriority (new method)
- getUserCollectionItems (not getCollectionSections)
- getCollectionItemsByQueryType (renamed)

### Enhanced Config Verification (Section 6.4)
Added exact line numbers for all 3 files:
- internal/router/router.go lines 58-59
- cmd/server/main.go lines 123-124, 172-173
- cmd/server/tests/test_helpers.go lines 419-420, 458-459

### Updated Preview Endpoint Section (Section 6.3)
Added clear explanation of why endpoint is REQUIRED and why NOT client-side.

### Clarified Custom Section Builder (Sections 8.5, 9.4)
Both now explicitly state "IS in the plan (Phase 10.5)"

## docs/developer/api/dashboard.md Changes

Updated API documentation to match new unified collections architecture:
- Terminology: "smart sections" → "system collections"
- Field: `type: string` → `is_system: boolean`
- Field: `id` → `media_item_id` for books
- Request: `hidden_sections` → `hidden_collections`
- Request: `section_order` → `collection_order`
- Removed: "in-progress" and "unread" smart sections
- Added: Update Dashboard Preferences endpoint
- Added: Restore System Collection endpoint
- Updated: Example responses with new field names and types
- Updated: Error responses table

## Impact

These changes clarify:
1. Preview endpoint is required for both web UI custom section builder and mobile apps
2. Custom Section Builder IS a major feature in the plan (not missing)
3. Service method names use "collections" terminology consistently
4. Config struct updates are clearly documented with exact line numbers (3 files only)
5. Why both DashboardService AND DashboardHandler are needed in Config

All documentation now accurately reflects the finalized Carousel Dashboard architecture.
2026-02-19 18:48:09 -05:00
john-okeefe 5bb28e5dfa 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
2026-02-19 11:42:19 -05:00
john-okeefe 1069c82e81 docs(dashboard): refactor to unified collections architecture
BREAKING CHANGES:
- Remove smart_section_types table entirely
- Use collections table for both system defaults and user sections
- Add user_id (nullable), query_type, priority, is_system_collection to collections
- Pre-seed 4 system collections (user_id = NULL): continue-reading, recently-added, recently-read, not-started

FEATURES:
- System collections are now editable by users
- Per-collection restore functionality (restore-system-collection endpoint)
- Single query type for all dashboard items (unified approach)

UPDATES:
- Database schema changes for collections table
- Service layer methods updated (RestoreSystemCollection instead of RestoreSystemCollections)
- API handler with per-collection restore endpoint
- Templates updated with collection terminology
- TypeScript types updated (8 fields instead of 11, type values: 'system'/'user')
- Field names updated: hidden_collections, collection_order
- All tests updated for new architecture

BENEFITS:
- Simpler data model (single table, single concept)
- System defaults use same code path as user collections
- Users can customize system collections
- Easy reset with per-collection restore buttons
2026-02-19 11:42:13 -05:00
john-okeefe 6d9b1e065e docs: add custom section builder and backend testing to Carousel dashboard
- Add custom section builder functionality (Phase 9.3)
  - Template for creating filter-based sections with auto-assign rules
  - Dynamic rule builder UI (field, operator, value, priority)
  - Preview functionality to see matching books before creating
  - Integration with existing collections API

- Add TypeScript implementation (Phase 10.3)
  - web/src/custom-section-builder.ts
  - Procedural style with event delegation
  - Rule collection, preview, and form submission
  - No duplicate event listeners (delegation only)

- Add backend testing suite (Phase 12)
  - Unit tests for dashboard service (filter, reorder)
  - Unit tests for dashboard handler (buildSections, helpers)
  - Integration tests with test_helpers for API endpoints
  - Integration tests for custom collections with auto-assign
  - Coverage requirements (>80%)

- Add collections preview endpoint
  - POST /api/collections/preview
  - Evaluates auto-assign rules against library items
  - Returns matching books for preview

- Add /custom-section route
  - GET route for custom section builder page
  - SSR rendering with libraries selector
  - Linked from dashboard settings modal

- Update database schema
  - Keep smart_section_types table for 4 default smart sections
  - Add collection_items.excluded column for user overrides
  - Index on excluded items for performance

- Update verification checklist
  - Section 2.2: Add collection_items.excluded verification
  - Section 3.4: Add auto-assign rule evaluation verification
  - Section 6.3: Add collections preview endpoint verification
  - Section 8.5: Add custom section builder template verification
  - Section 9.4: Add custom section builder TypeScript verification
  - Section 14.4: Add backend tests verification

- Fix duplicate event listener issue
  - Removed duplicate change listener for library selector
  - Rely on event delegation only for consistency

- Fix buildJSONSections type safety
  - Now reuses buildSections() instead of map[string]interface{}
  - Better type safety and code reuse

Timeline: 3-4 days dashboard implementation + comprehensive testing
2026-02-18 21:39:37 -05:00
john-okeefe 8d37df249d docs(dashboard): update Carousel plan for post-TypeScript conversion
Major updates:
- Reduce smart sections from 5 to 4 (removed 'In Progress')
  - Continue Reading: 0% < progress < 100%
  - Recently Added: newest items
  - Recently Read: progress >= 100%
  - Not Started: progress = 0% or no record

- Update paths from web/ts/ to web/src/ structure
- Add handler types instead of duplicate template types
- Types defined in internal/handlers/dashboard.go
- Templates import handlers.SectionData, handlers.BookInfo directly

New features:
- Drag-and-drop section reordering
- Section visibility toggles
- Items per section slider
- Manual progress marking (mark as read/unread)

TypeScript updates:
- Use (window as any).api from web/src/api.ts
- Use (window as any).showToast from web/src/toast.ts
- Import types from web/src/types/dashboard.d.ts
- Event delegation via data-action attributes

Add verification checklist for comprehensive plan review:
- Type definition verification against actual API responses
- API contract and endpoint verification
- Cross-reference verification for template-handler types
- Progressive enhancement testing
- Build and deployment verification
2026-02-18 16:42:54 -05:00
john-okeefe ba3d9e4f37 refactor(login): remove duplicate theme code from template
- Remove inline theme functions (lines 62-88)
  - applyTheme, loadTheme, changeTheme functions
- Add script tag for /static/theme.js
- Theme logic now uses shared theme.ts module
- Eliminates code duplication with web/src/theme.ts
- Part of TypeScript conversion plan Phase 6.1.1
2026-02-18 16:42:13 -05:00
john-okeefe 9d2bed92f2 build(typescript): update compiled search.js from TypeScript source
- Compiled from web/src/search.ts
- Added proper type annotations
- Fixed null checks for DOM elements
- Added escapeHtml for library name display
- Updated onclick to use window.selectLibraryAndBook
2026-02-18 16:42:05 -05:00
john-okeefe dfd9cbcde7 feat(typescript): add feature modules for template conversion
- Add search.ts - header search with keyboard navigation
  - Debounced search with 300ms delay
  - Arrow key navigation through results
  - Escape to close, Enter to select
  - Library type icons and highlighting

- Add collections.ts - collection and rule management
  - Rule CRUD operations (create, update, delete)
  - Rule testing functionality
  - Bulk collection operations

- Add bookshelf.ts - book display and navigation
  - Library selection state management
  - Book viewing interactions
  - Pagination logic

- Add linking.ts - book matching and manual linking
  - Search and match functionality
  - Manual link modal
  - Bulk auto-link and suggestions

- Add api-explorer.ts - API testing interface
  - Request/response display
  - cURL command generation
  - History tracking

- Add admin.ts - admin dashboard actions
  - Library scan triggers
  - System statistics display
  - Profile management

- Add analytics.ts - analytics data loading
  - Chart.js integration
  - Daily reading minutes chart
  - Device usage and popular books display

- Add queue.ts - sync queue management
  - Process pending items
  - Clear failed/all items
  - Filter by status, type, device

- Add conflicts.ts - conflict resolution
  - Individual and bulk resolve operations
  - Winner device selection
  - Manual override inputs

- Add docs.ts - documentation search
  - Lunr.js search integration
  - Sidebar toggle for mobile
2026-02-18 16:40:51 -05:00
john-okeefe 60c5a093b5 feat(typescript): add core infrastructure modules
- Add centralized API type definitions (types/api.d.ts)
  - Interfaces for all API responses matching Go handler JSON
  - Snake_case field names matching actual API responses
  - Source file references in comments for verification

- Add API client module (api.ts)
  - Procedural get/post/put/delete functions
  - Automatic auth header injection
  - Exported to window for cross-module access

- Add DOM utilities (dom.ts)
  - escapeHtml for safe HTML rendering
  - querySelector wrappers with null checks
  - Element creation helpers

- Add event delegation helpers (events.ts)
  - Reusable event delegation pattern
  - Data attribute selectors for dynamic content

- Add localStorage wrapper (storage.ts)
  - Type-safe token management
  - Theme persistence helpers
2026-02-18 16:40:29 -05:00
john-okeefe 364de1ee93 docs(typescript): add comprehensive verification checklist for conversion plan 2026-02-18 16:38:13 -05:00
john-okeefe d709510a28 docs(typescript): update conversion plan with accurate line counts and template analysis 2026-02-18 16:38:12 -05:00
john-okeefe 0e386ca87f docs(dashboard): use existing test helpers and document automatic cleanup
Fixed integration tests to use existing helpers from test_helpers.go:

Changes:
- Replace getUserUUIDFromToken() with getTestUserID(t, db) helper 
- Replace parseUUID() with uuid.MustParse() 
- Add explicit comments about automatic cleanup via t.Cleanup() 

Test Helpers Used (all from test_helpers.go):
- setupTestServer(t) - creates test server with automatic cleanup
- loginTestUser(t, ts, db) - logs in admin user
- loginRegularUser(t, ts, db) - logs in regular user
- setupDeviceTest(t) - creates server + user + device + library
- getTestUserID(t, db) - gets/creates admin test user UUID
- uuid.MustParse() - parses UUID strings

Cleanup Pattern:
- Automatic via t.Cleanup() inside setupTestServer()
- Registered automatically when setupTestServer() is called
- No manual defer setup.Close() needed
- Runs even if test fails or panics
- Cleanup order: queue → connections → server → database

Dashboard-Specific Helper:
- updateDashboardPreferences() - only for dashboard testing
- Saves dashboard preferences for test scenarios

Benefits:
- Uses proven, existing helpers (no reinventing the wheel)
- Automatic cleanup prevents resource leaks
- Follows project testing patterns exactly
- Less custom code = fewer bugs
2026-02-17 22:31:38 -05:00
john-okeefe ac88031855 docs(dashboard): document test helpers and cleanup patterns
Added comprehensive documentation of available test helpers:

Available Helpers (from test_helpers.go):
- setupTestServer(t) - Creates test server with auto cleanup via t.Cleanup()
- loginTestUser(t, ts, db) - Logs in admin user, returns JWT token
- loginRegularUser(t, ts, db) - Logs in regular user, returns JWT token
- setupDeviceTest(t) - Creates server + user + device + library
- getTestUserID(t, db) - Gets/creates admin test user UUID
- getRegularUserID(t, db) - Gets/creates regular test user UUID

TestServerSetup Structure:
- Server *httptest.Server
- DB *database.Queries
- DBPool *pgxpool.Pool
- Config *config.Config
- ConnManager, QueueProcessor
- Auto cleanup via t.Cleanup()

Cleanup Pattern:
- Automatic cleanup registered in setupTestServer()
- Runs even if test fails or panics
- Order: queue processor → connection manager → HTTP server → database pool
- No manual defer setup.Close() needed

Updated Integration Tests:
- Added proper imports (database, uuid, pgtype)
- Documented available helpers
- Removed custom helpers that don't exist
- Uses existing project patterns

This ensures developers know what helpers are available and how to use them correctly.
2026-02-17 22:27:51 -05:00
john-okeefe c775ed0a8e docs(dashboard): add comprehensive unit and integration test phases
Phase 14: Unit Tests (2-3 hours)
- Service layer tests (dashboard_service_test.go)
  - filterHiddenSections() - tests no filters, one hidden, multiple hidden
  - reorderSections() - tests default order, custom order, partial order
- Handler helper tests (dashboard_test.go)
  - getSectionType() - smart vs collection sections
  - getSectionTitle() - all smart sections and collections
  - getSectionIcon() - icons for all sections
  - getSectionViewAllURL() - URLs for all sections
- Table-driven tests for multiple scenarios
- Uses testify/assert
- Skips database-dependent tests (use integration tests instead)

Phase 15: Integration Tests (2-3 hours)
- File: cmd/server/tests/dashboard_test.go
- Uses setupTestServer(t) helper from test_helpers.go
- Tests /api/dashboard/sections JSON endpoint:
  - Three-context testing (no auth, user, admin)
  - Missing library_id → 400
  - Invalid library_id → 400
  - With limit parameter
- Tests user preferences:
  - Hidden sections filtered correctly
  - Custom order applied correctly
- Tests SSR /dashboard page:
  - Returns HTML with dashboard elements
  - Requires auth
- Helper functions:
  - updateDashboardPreferences()
  - getUserUUIDFromToken()
  - parseUUID()

Testing Strategy:
- Unit tests alongside source files (project convention)
- Integration tests in cmd/server/tests/ (project convention)
- setupTestServer() helper creates full test environment
- Uses loginTestUser(), loginRegularUser(), setupDeviceTest()
- Follows existing patterns from auth_test.go, collections_bulk_test.go

Updated Timeline: 23-31 days total (added 4-6 hours for testing)

Benefits:
- Comprehensive test coverage before production
- Catches regressions in user preferences logic
- Validates API endpoint behavior across contexts
- Ensures SSR and JSON return consistent data
- Follows project testing conventions
2026-02-17 22:25:48 -05:00
john-okeefe d981fdf517 docs(dashboard): update Carousel plan with API endpoint and user preferences
Major architectural improvements:

1. Add generic /api/dashboard/sections JSON endpoint
   - Created internal/handlers/dashboard.go (new file)
   - Created internal/router/dashboard.go (new file)
   - Single source of truth for web UI, mobile apps, plugins
   - Follows existing handler/router pattern

2. Update DashboardService to apply user preferences
   - GetSectionItems() now accepts sectionOrder and hiddenSections
   - filterHiddenSections() removes user's hidden sections
   - reorderSections() applies user's custom order
   - Ensures consistent behavior across all clients

3. Separate concerns properly
   - API handlers in internal/handlers/dashboard.go
   - SSR routes remain in internal/router/frontend.go
   - Both use same DashboardService (single source of truth)

4. Reorganize implementation phases
   - Phase 1-3: Database, service, queries
   - Phase 4-6: Handler, router, frontend routes
   - Phase 7-9: Templates and settings
   - Phase 10-11: TypeScript modules
   - Phase 12-13: Documentation and testing

5. Add documentation
   - docs/developer/api/dashboard.md (API reference)
   - docs/user/dashboard.md (user guide)

6. Bruno tests already exist
   - bruno/dashboard/ has 5 comprehensive test files
   - Three-context testing (no user, user, admin)
   - No additional tests needed

Benefits:
- Uniform dashboard across web, mobile, plugins
- Single source of truth (no duplicate logic)
- User preferences respected by all clients
- Follows established project patterns
- Comprehensive test coverage

Timeline: Updated to reflect 13 phases (19-25 days total with TypeScript)
2026-02-17 22:20:54 -05:00
john-okeefe 3758532d31 docs(dashboard): update plan to support post-TypeScript conversion patterns
- Add prerequisites section (TypeScript conversion must be completed first)
- Update execution order: TypeScript (16-21 days) then dashboard (3-4 days)
- Revise Phase 7 TypeScript implementation:
  - Change file locations from web/src/ to web/ts/features/dashboard/
  - Replace inline onclick with data-action attributes
  - Use shared apiClient instead of raw fetch()
  - Add event delegation with on() utility
  - Import showToast from core instead of global
  - Add type definitions matching Go handlers
- Update templates to load new TypeScript module paths
- Add summary of key changes from original plan
- Ensure consistency with TypeScript Conversion Plan patterns
2026-02-17 21:58:37 -05:00
john-okeefe 4d756acff4 docs(typescript): add TypeScript conversion plan for inline JavaScript
- Create comprehensive plan to convert ~5,500 lines of inline JS to TypeScript
- Hybrid SSR + TypeScript CRUD approach (keeps existing JSON API)
- Event delegation pattern (no inline onclick handlers)
- Shared infrastructure: apiClient, toast, event utilities
- Procedural/imperative style (no OOP, classes, inheritance)
- 6 phases, 16-21 day timeline
- Preserves single API for all clients (web, mobile, plugins)
- No new backend routes needed
2026-02-17 21:58:33 -05:00
john-okeefe 17ce558522 docs(dashboard): refactor Carousel dashboard plan to align with guidelines
Major restructuring of the dashboard implementation plan to better match project guidelines:

- Change from handler types to template types (SectionData, BookCardData)
- Update from TypeScript to inline JavaScript matching existing pattern
- Change from separate handlers to inline routes in frontend.go
- Refactor service to return raw data (handler formats for templates)
- Add Settings template implementation
- Update TypeScript files to use IIFE pattern with window exports
- Change from .bru files to OpenCollection YAML .yml files
- Add Bruno tests note indicating tests already exist in bruno/dashboard/

This aligns the plan with actual project patterns and reduces architectural divergence.
2026-02-17 20:24:29 -05:00
john-okeefe 420ab930ae test(bruno): add token handling scripts to auth endpoints
Add after-response scripts to automatically save access and refresh tokens to Bruno environment variables after successful authentication. This eliminates manual token copying during testing.

Changes:
- Refresh Token.yml: Add script to save tokens from refresh response
- Register User.yml: Add script to save tokens from registration response
2026-02-17 20:24:24 -05:00
john-okeefe 105c427544 docs: update Bruno terminology to OpenCollection YAML format
Update all references from "Bruno DSL .bru files" to "Bruno OpenCollection YAML .yml files" to reflect the current Bruno format. This includes:

- PROJECT_GUIDELINES.md: Update API testing requirements
- README.md: Update command examples
- TEST_DATA.md: Update test data references
- docs/contributing/development.md: Update API testing section
- docs/developer/api-reference.md: Update Bruno testing documentation
- docs/developer/collections-api.md: Update test file references
- scripts/README.md: Update validation script documentation
- scripts/verify-guidelines.sh: Update file extension check (.bru → .yml)
- bruno/opencollection.yml: Rename collection from "Untitled Collection" to "Bookhoard"
2026-02-17 20:24:20 -05:00
john-okeefe f859b2714d refactor(bruno): reorganize file structure from bruno-yaml to flat bruno directory
- Move all files from bruno-yaml/* to bruno/*
- Maintains existing directory structure within categories
- Updates bruno/user/auth files with OAuth2 refresh token flow
- Updates bruno/user/profile files for user profile management
- Adds bruno/dashboard/ directory with dashboard API tests
- Preserves all existing test scenarios and OpenCollection YAML format
- No functional changes - file reorganization only
2026-02-17 20:22:21 -05:00
john-okeefe 96730d9475 docs: add Carousel dashboard implementation plan 2026-02-17 17:00:46 -05:00
john-okeefe fce16b53f7 fix(auth): return JSON for HTMX login failures instead of HTML 2026-02-16 21:08:15 -05:00
john-okeefe e25dc106fa chore: remove obsolete REFACTORING_PLAN.md 2026-02-16 16:51:26 -05:00
john-okeefe 81c72e706a chore(templates): regenerate template files after templ update
Regenerate all _templ.go files with latest templ generator.
Changes are minimal formatting updates (error message file paths).
2026-02-16 16:51:10 -05:00
john-okeefe 8a6ea39ed2 docs(auth): document 7-day session authentication with constants
- Add comprehensive authentication overview.md explaining:
  - 7-day session duration for JWT and refresh tokens
  - Constants-based implementation (no hardcoded values)
  - Complete authentication flow (register/login/refresh/logout)
  - Session expiration handling (HTML redirect vs JSON error)
  - Security features (HTTP-only cookies, token rotation)
  - Token storage recommendations
- Update login.md with 7-day expires_in field and cookie MaxAge
- Update register.md with 7-day session duration details
- Update refresh_token.md with expires_in: 604800

Documentation provides complete reference for authentication
endpoints with examples and security considerations.
2026-02-16 16:50:43 -05:00
john-okeefe 586f293e09 test(auth): add comprehensive 7-day session tests
- Add seven_day_session_test.go with comprehensive test coverage:
  - Test login returns 7-day session (expires_in: 604800)
  - Test cookie MaxAge is 7 days (604800 seconds)
  - Test refresh token returns 7-day access token
  - Test JWT token has 7-day expiration claim
  - Test 401 error handler redirects HTML requests
  - Test 401 error handler returns JSON for API requests
  - Test register/login do not set document.cookie
- Tests use getTestUserID() and setupTestServer() helpers
- Update security_test.go JWT expiration comment to reflect 7 days

Tests verify all aspects of the 7-day session implementation
including constants usage, cookie values, API responses, and
smart 401 error handling.
2026-02-16 16:50:31 -05:00
john-okeefe 53aad2701b feat(frontend): enhance 401 handling to clear tokens and redirect
- Update fetch interceptor to special-case 401 responses
- Clear invalid tokens from localStorage on 401 (token, refreshToken, user)
- Distinguish between page navigation and API calls:
  - Page navigation: throw error to prevent further processing
  - API calls: show toast error with session expired message
- Suppress network error toast for redirect errors
- Compile TypeScript to JavaScript

This ensures frontend properly handles expired sessions by clearing
stale credentials and showing appropriate error messages.
2026-02-16 16:50:19 -05:00
john-okeefe 7b07645ee2 feat(auth): show session expired message on login page
- Update Login template to accept sessionExpired boolean parameter
- Add conditional message box when session=expired query param present
- Update /login route handler to parse session query param
- Pass sessionExpired flag to Login template
- Regenerate login_templ.go with new signature

Displays friendly message: "Your session has expired. Please log in
again to continue." when users are redirected due to expired sessions.
2026-02-16 16:50:10 -05:00
john-okeefe 7952bc7f6a feat(router): add smart 401 error handler for HTML vs API requests
- Add strings import for Accept header parsing
- Add wantsHTML() helper function to detect HTML vs API requests
  - Checks Accept header for text/html
  - Checks HX-Request header for HTMX requests
  - Checks X-Requested-With for AJAX (should return JSON)
  - Defaults to JSON for API routes
- Update JWT middleware ErrorHandler to:
  - Redirect HTML requests to /login?session=expired
  - Return JSON error for API requests with session_expired message
- Enables browser navigation to redirect gracefully while API calls
  return proper error responses

This fixes the issue where protected routes returned JSON 401
for browser navigation instead of redirecting to login.
2026-02-16 16:49:54 -05:00
john-okeefe 2e1af8d20b feat(auth): extend session duration to 7 days using constants
- Add SessionDuration constant (7 days) and SessionDurationSec computed value
- Update JWT token expiration to use SessionDuration instead of 1 hour
- Update register/login cookie MaxAge to use SessionDurationSec (604800)
- Update register/login API response ExpiresIn to use SessionDurationSec
- Update refresh token endpoint ExpiresIn to use SessionDurationSec
- Remove redundant client-side document.cookie lines from login/register
- Add TODO comment for HTTPS cookie Secure flag

This provides Google-like persistent sessions with a single source of truth
for session duration, eliminating hardcoded values throughout the codebase.
2026-02-16 16:49:43 -05:00
john-okeefe c9ebc5b11a feat: add authorization header to device token regeneration
- Add Bearer token from localStorage to regenerate-token API request
- Update code formatting for consistency (double quotes, indentation)

This ensures the device token regeneration endpoint receives proper
authentication via the Authorization header.
2026-02-16 09:18:02 -05:00
john-okeefe a0e9a2b6e6 refactor: remove auth inherit and token handling from login request
- Remove 'auth: inherit' from POST request configuration
- Remove post-response script that set token environment variable
- Clean up documentation formatting

This simplifies the login request configuration as authentication
will now be handled via HTTP-only cookies instead of bearer tokens.
2026-02-16 09:17:56 -05:00
john-okeefe b5156bbe16 feat: add HTTP-only cookie for browser authentication
- Set HTTP-only cookie in login handler for SSR authentication
- Set HTTP-only cookie in registration handler
- Change default redirect from /bookshelf to /dashboard
- Cookie enables browser page navigation without JavaScript
2026-02-15 21:36:42 -05:00
john-okeefe 6b3ccdfc55 feat: add protected frontend SSR routes
- Add frontendProtected group for authenticated pages
- Add /dashboard, /collections, /progress, /devices, /conflicts, /analytics routes
- Add /admin, /admin/, /admin/profile, /admin/library routes
- Keep legacy /api/devices-page and /api/conflicts-page for backward compatibility
- All routes use JWT middleware for authentication
2026-02-15 21:36:36 -05:00