Commit graph

398 commits

Author SHA1 Message Date
23a844dd12 fix(actions): prevent clickOutside race condition in update method
Fix a race condition where the clickOutside action's update() method
would remove and re-add the event listener every time it was called,
even when the enabled state hadn't changed. This caused clicks to be
missed during the setTimeout delay.

Changes:
- Track previous enabled state before updating
- Only use setTimeout when transitioning from disabled to enabled
- Immediately re-add listener when enabled state stays true
- No listener changes when enabled state stays false

This ensures click-outside events are consistently detected without
gaps in event listener registration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 22:13:30 -07:00
dcca9eb6e5 refactor(ui): update BasePane to use clickOutside action
Replace manual click event listener with clickOutside action for the
pane backdrop click handling. This simplifies the code and ensures
consistent click-outside behavior.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 22:00:54 -07:00
7300bd672b refactor(admin): update EssayForm to use clickOutside action
Replace manual click event listener with clickOutside action for the
publish menu dropdown. This simplifies the code and ensures consistent
click-outside behavior across all admin dropdowns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 22:00:06 -07:00
9cc7baddc6 refactor(admin): migrate dropdowns to clickOutside action
Updated components to use the new clickOutside action instead of manual
event listener management:
- ProjectListItem: Add clickOutside action and dropdown coordination
- AdminSegmentedController: Replace $effect with clickOutside action
- BubbleTextStyleMenu: Simplify click-outside handling
- BubbleColorPicker: Simplify click-outside handling
- Posts/Projects pages: Remove redundant page-level click handlers

The clickOutside action provides a cleaner, more maintainable way to
handle click-outside behavior with proper lifecycle management.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 21:58:34 -07:00
97a80d9c3e feat(admin): add clickOutside action and update dropdowns
Created a reusable clickOutside Svelte action that dispatches a custom
event when users click outside an element. This replaces manual
document.addEventListener patterns.

Features:
- TypeScript support with generic event types
- Configurable enabled/disabled state
- Optional callback parameter
- Proper cleanup on destroy
- setTimeout to avoid immediate triggering

Updated components to use the new action:
- BaseDropdown.svelte: Removed $effect with manual listeners
- PostDropdown.svelte: Replaced manual click handling

Part of Task 5 - Click-Outside Primitives

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 21:33:33 -07:00
128a24ccde fix(admin): remove infinite loop in navigation guards
Fixed infinite loop caused by calling goto() inside beforeNavigate,
which would trigger the same navigation guard again.

The correct approach is to NOT cancel navigation, but simply await
the autosave flush. SvelteKit's beforeNavigate accepts async callbacks,
so navigation will naturally wait for the flush to complete before
proceeding.

Changes:
- Removed navigation.cancel() calls
- Removed goto() calls that created the loop
- Simply await autoSave.flush() and let navigation proceed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 18:43:28 -07:00
8fa26fb39e fix(admin): replace navigation.retry() with goto() after flush
Fixed navigation guards in all forms that were calling the non-existent
navigation.retry() method. After canceling navigation and flushing autosave,
now properly uses goto() to navigate to the intended destination.

Files fixed:
- ProjectForm.svelte
- EssayForm.svelte
- PhotoPostForm.svelte
- SimplePostForm.svelte
- posts/[id]/edit/+page.svelte

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 18:34:56 -07:00
eebaf86b64 refactor(admin): migrate media list to use URL params and server loads
Refactored media list to follow SvelteKit data loading patterns:
- Removed client-side fetch() calls and manual state management
- Filter/sort/search state now driven by URL search params
- Page navigation triggers server-side reloads via goto()
- Mutations use invalidate('admin:media') to reload data
- Replaced error state with toast notifications for better UX
- Removed redundant loading state (handled by SvelteKit)

This completes Task 2 - all admin lists now use server-side data loading with proper session authentication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 18:30:06 -07:00
39e82146d9 docs: update autosave completion guide with new API
Added implementation summary showing:
- All 5 forms now use runes-based autosave
- New reactive API without subscriptions
- Key improvements (prime, auto-idle, smart guards)
- Marked as completed January 2025

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 16:16:32 -07:00
305000f4dc refactor(tests): rename autoSaveController test file
Renamed test file to match new createAutoSaveStore naming convention. All tests pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 16:16:08 -07:00
fe923c3dbf refactor(admin): add autosave to SimplePostForm
Added runes-based autosave functionality to SimplePostForm:
- Added autosave store with updatedAt conflict detection
- Smart navigation guards and beforeunload warnings
- Draft recovery banner instead of inline prompt
- Only saves to localStorage on autosave failure
- Added AutoSaveStatus component
- Fixed $derived syntax to use $derived.by()

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 14:19:38 -07:00
6ed1b0f1a8 refactor(admin): add autosave to PhotoPostForm
Added runes-based autosave functionality to PhotoPostForm following the same pattern as EssayForm:
- Added autosave store with updatedAt conflict detection
- Smart navigation guards and beforeunload warnings
- Draft recovery banner instead of inline prompt
- Only saves to localStorage on autosave failure
- Added AutoSaveStatus component

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 14:04:20 -07:00
c49ce5cbb5 feat(admin): add runes-based autosave to EssayForm
- Add createAutoSaveStore for edit mode
- Add updatedAt tracking for conflict detection
- Add hasLoaded flag to prevent autosave on initial load
- Prime autosave after initial data loads
- Add AutoSaveStatus indicator in header
- Move draft recovery from inline to prominent banner
- Only save draft on autosave failure (not every change)
- Smart navigation guard (only blocks if unsaved)
- Add beforeunload warning (only if unsaved changes)
- Add keyboard shortcut (Cmd/Ctrl+S)
- Add proper cleanup on unmount
- Update clearDraft calls in restore/dismiss functions
- Fix $derived syntax (use $derived.by for draftTimeText)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 14:00:28 -07:00
32b4d16f9a refactor(admin): migrate Posts editor to runes-based autosave
- Update to use createAutoSaveStore with Svelte 5 runes
- Fix $derived syntax (use $derived.by for draftTimeText)
- Add hasLoaded flag to prevent autosave on initial load
- Add prime() call after loading post data
- Move draft recovery from inline header to prominent banner
- Implement missing restoreDraft() and dismissDraft() functions
- Only save draft on autosave failure (not every change)
- Smart navigation guard (only blocks if unsaved)
- Add beforeunload warning (only if unsaved changes)
- Update AutoSaveStatus to use reactive props
- Add keyboard shortcut and proper cleanup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 13:31:27 -07:00
672eb47143 fix(admin): only block navigation/close when changes are unsaved
- Update beforeNavigate guard to check autosave status before blocking
- Allow instant navigation when status is 'saved' (no interruption)
- Add beforeunload warning for browser close/reload
- Only show warnings when status is NOT 'saved' (saving/error/idle)
- Improves UX by not interrupting users when everything is already saved

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 13:21:57 -07:00
f35fa60207 refactor(admin): only save local draft on autosave failure
- Remove redundant localStorage saves on every form change
- Only save draft when autosave status is 'error' or 'offline'
- Reduces draft recovery banner noise for successful autosaves
- Navigation guard still prevents data loss when navigating away

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 13:09:39 -07:00
dfbf45f8a4 refactor(admin): migrate ProjectForm to runes-based autosave
- Update ProjectForm to use new createAutoSaveStore with Svelte 5 runes
- Fix $derived syntax in AutoSaveStatus (use $derived.by for multi-statement)
- Add hasLoaded flag to prevent infinite loop on autosave completion
- Move draft recovery from inline header to prominent banner below header
- Style draft banner with blue info colors and slide-down animation
- Fix draft persistence by clearing localStorage on restore/dismiss
- Call beforeNavigate at top level for proper Svelte 5 lifecycle
- Add keyboard shortcut (Cmd/Ctrl+S) and navigation guard effects
- Update AutoSaveStatus to support both old stores and new reactive props

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 11:55:51 -07:00
0334d3a831 feat(admin): create Svelte 5 runes-based autosave store
Introduces createAutoSaveStore() using $state() for automatic reactivity.
New store provides cleaner API while maintaining backward compatibility.

Changes:
- New: src/lib/admin/autoSave.svelte.ts with createAutoSaveStore()
- Uses $state() for status and lastError (reactive getters)
- Export AutoSaveStore and AutoSaveStoreOptions types
- Add JSDoc with usage examples
- Update autoSaveLifecycle.ts to accept both old and new types
- Export AutoSaveController type from old file for compatibility

Old createAutoSaveController() remains unchanged for gradual migration.
Type checking passes with no new errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 07:58:20 -07:00
c209417381 feat(admin): add prime() and auto-idle to autosave controller
Enhances autosave controller with missing features:
- prime(payload): Sets initial hash baseline to prevent autosaves on page load
- idleResetMs option: Auto-transitions from 'saved' → 'idle' status (default 2s)
- onSaved callback: Now receives { prime } helper for re-priming after server response
- Cleanup: destroy() now properly clears idle reset timer

All existing tests pass. Backward compatible - forms not using new features yet.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 07:54:49 -07:00
66d5240240 refactor(admin): extract shared list filtering utilities
Introduces createListFilters() with type-safe, reactive filtering and sorting
for admin list pages. Eliminates ~120 lines of duplicate code across projects
and posts pages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 07:41:13 -07:00
c67dbeaf38 fix(admin): make filters reactive in Svelte 5
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-07 07:30:01 -07:00
42be8ebcfc chore(admin): remove basic auth fallback 2025-10-07 06:31:52 -07:00
3554d0af2c fix(admin): keep universe route authenticated 2025-10-07 06:09:26 -07:00
6a0e9c2fdb refactor(admin): let session auth drive albums/media routes 2025-10-07 05:58:49 -07:00
e2949bff20 refactor(admin): update form flows for session auth 2025-10-07 05:57:45 -07:00
94fb5f6daf refactor(admin): use session fetch in media components 2025-10-07 05:54:18 -07:00
376df12c20 refactor(admin): remove legacy client auth helper 2025-10-07 05:53:55 -07:00
878c0ae248 refactor(admin): drive media page from server data 2025-10-07 05:31:02 -07:00
3a588fdf89 refactor(admin): load posts list on server 2025-10-07 05:30:50 -07:00
dbcd7a9e1b refactor(admin): load projects list on server 2025-10-07 05:30:34 -07:00
22e53a7d30 feat(admin): add authenticated fetch helper 2025-10-07 05:25:44 -07:00
4d7ddf81ee feat(admin): add session-backed auth flow 2025-10-07 05:22:39 -07:00
f3c8315c59 fix: resolve scss global import path 2025-10-07 04:55:30 -07:00
006e1db96e Add modernization plan 2025-10-07 04:49:11 -07:00
ed906b6c75
Merge pull request #15 from jedmund/jedmund/autosave
complete autosave implementation
2025-10-07 03:25:12 -07:00
c96def2789 feat: add minimal not-found error page 2025-10-07 03:18:17 -07:00
6b21c4f7b3 test: cover autosave controller and lifecycle helper 2025-10-07 03:18:10 -07:00
7b5af20dee docs: capture autosave roll-out plan 2025-10-07 03:18:02 -07:00
c63608938a
Merge pull request #14 from jedmund/jedmund/autosave
Add autosave to admin interface
2025-10-02 19:27:39 -07:00
280bdfc06d feat(drafts): add local draft backup with restore prompt to EssayForm, SimplePostForm, and PhotoPostForm 2025-08-31 11:03:27 -07:00
c98ba3dcf0 feat(admin): integrate autosave and local draft prompt into ProjectForm and Post Edit; add Cmd/Ctrl+S and beforeNavigate flush 2025-08-31 11:03:27 -07:00
1a5ecf9ecf feat(autosave): add autosave controller and status component 2025-08-31 11:03:27 -07:00
9bc942211a refactor(admin): use shared api client across projects list, posts list, new post, project edit load, and media modal 2025-08-31 11:03:27 -07:00
f5a440a2ca feat(api/server): add posts PATCH and optimistic concurrency (updatedAt) for posts and projects 2025-08-31 11:03:27 -07:00
3aec443534 feat(api): add admin API client with auth, error handling, FormData, and abortable requests 2025-08-31 11:03:27 -07:00
c89b2b0db5
Merge pull request #13 from jedmund/feature/video-upload-support
Add video upload support
2025-08-23 00:19:48 -07:00
82581f9496 fix: update chevron icon to use Svelte 5 snippet syntax
- Replace slot="icon" with snippet syntax for dropdown chevron button
- Fixes missing chevron icon in Media tab actions dropdown

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-23 03:18:53 -04:00
aa3622d606 feat: add video playback UI and thumbnail display
- Add video player with controls in MediaDetailsModal
- Display video metadata (duration, codecs, bitrate) in metadata panel
- Show video thumbnails with play icon overlay in MediaGrid
- Support video preview in upload components
- Replace emoji icons with SVG play icon
- Maintain natural video aspect ratio in all views
- Add proper styling for video thumbnails and placeholders

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-23 03:14:06 -04:00
4f46b0e666 feat: add video upload support with ffmpeg processing
- Add video MIME types support (WebM, MP4, OGG, MOV, AVI)
- Increase upload size limit to 100MB for videos
- Add ffmpeg integration for local video processing
- Generate video thumbnails at 50% duration
- Extract video metadata (duration, codecs, bitrate)
- Add database fields for video metadata
- Support video uploads in both local and Cloudinary storage
- Maintain aspect ratio for video thumbnails (1920px max width)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-23 03:13:36 -04:00
bc2d1b4092
Merge pull request #12 from jedmund/hotfix/universe-actions
Fix universe actions
2025-08-22 22:10:15 -07:00