27 Commits

Author SHA1 Message Date
1cd7d01b4e Update GIF guide with nginx troubleshooting section
Added detailed troubleshooting section for the nginx configuration
issue that caused 404 errors for GIF files.

Changes:
- Added new troubleshooting subsection: 'GIFs return 404 but files exist'
- Documented the nginx regex problem and solution
- Included before/after nginx configuration examples
- Explained negative lookahead regex pattern
- Updated Docker image digest to latest version
- Added latest commit reference (bc688e5)

This helps future admins understand and debug similar nginx routing
issues where static asset caching interferes with backend proxying.

Co-Authored-By: Auggie
2026-01-18 19:09:37 +01:00
bc688e5563 Fix nginx: exclude /uploads/ from static asset caching
Problem: GIF files in /uploads/gifs/ were returning 404 errors even
though they existed on the backend server. Videos in /uploads/videos/
worked correctly.

Root cause: nginx location block order issue
- Line 64: Regex location ~* \.(gif|...) matched ALL .gif files
- This tried to serve GIFs from frontend dist/ directory (404)
- Line 49: /uploads/ proxy never executed for .gif files

The regex location block had higher priority than the prefix location
block, causing nginx to look for GIFs in the wrong directory.

Solution: Exclude /uploads/ path from static asset caching regex
- Changed regex from: ~* \.(js|css|...|gif|...)$
- To: ~* ^/(?\!uploads/).*\.(js|css|...|gif|...)$
- This uses negative lookahead to skip files under /uploads/
- Now /uploads/*.gif files are proxied to backend correctly

Also moved the static assets location block BEFORE the catch-all
location / block for better clarity (doesn't affect behavior).

Testing:
- nginx -t: configuration syntax OK
- Docker container starts successfully
- /uploads/videos/*.mp4 still work (proxied to backend)
- /uploads/gifs/*.gif now work (proxied to backend)
- Frontend static assets still cached (served from dist/)

This fixes the 404 errors for GIF preview images on production.

Co-Authored-By: Auggie
2026-01-18 19:08:17 +01:00
40022941ef Add comprehensive GIF regeneration guide
Created detailed documentation for regenerating GIF preview images
in production environment.

Guide includes:
- Problem description and symptoms (404 errors for GIF files)
- Three different regeneration methods:
  1. Web UI tool (easiest, no terminal needed)
  2. Docker environment variable (automatic on startup)
  3. Direct API endpoint (for advanced users)
- Step-by-step instructions for each method
- Expected results and what gets created
- Troubleshooting section for common issues
- Technical details about GIF generation
- Maintenance procedures

This guide helps admins quickly resolve the production deployment
issue where GIF files don't match video UUIDs.

Target audience: System administrators and developers deploying
to production.

Co-Authored-By: Auggie
2026-01-18 18:59:23 +01:00
78a51f88dc Fix regenerate-all-gifs script for production environment
Problem: Script failed in production Docker container because it tried
to import from '../src/utils/gifGenerator.js' which doesn't exist in
production (only compiled dist/ directory exists).

Error:
  Cannot find module '/app/packages/backend/src/utils/gifGenerator.js'

Solution: Use dynamic import with path detection to support both
development and production environments.

Changes:
- Check if dist/utils/gifGenerator.js exists (production)
- Fall back to src/utils/gifGenerator.js (development)
- Use dynamic import with await to load the correct module

This allows the script to work in both:
- Development: npx tsx scripts/regenerate-all-gifs.ts
- Production: Docker container with REGENERATE_GIFS=true

Tested: Docker container now starts successfully and executes the
GIF regeneration script without errors.

Co-Authored-By: Auggie
2026-01-18 18:57:37 +01:00
f575ab16c4 Fix Docker build: include scripts directory and tsx runtime
Problem: Docker container failed to start with REGENERATE_GIFS=true
because scripts directory was not copied to production image and tsx
was not available at runtime.

Error:
  Cannot find module '/app/packages/backend/scripts/regenerate-all-gifs.ts'

Root cause:
1. Dockerfile only copied dist/ and prisma/ directories, not scripts/
2. tsx was in devDependencies, not available in production

Solution:
1. Add COPY scripts directory in Dockerfile (line 69)
2. Move tsx from devDependencies to dependencies in package.json
3. Update pnpm-lock.yaml to reflect dependency change

Changes:
- Dockerfile: Added COPY --from=backend-builder scripts directory
- package.json: Moved tsx@^4.7.0 to dependencies
- pnpm-lock.yaml: Updated lockfile

This allows the REGENERATE_GIFS environment variable to work correctly
in production, enabling automatic GIF regeneration on container startup.

Co-Authored-By: Auggie
2026-01-18 18:47:55 +01:00
25b6843e87 Add admin tool for bulk GIF regeneration via web UI
Created a simple HTML page that allows admins to regenerate all GIF
previews directly from the browser without needing terminal access.

Features:
- Clean, user-friendly interface with warnings and instructions
- Calls POST /api/terms/regenerate-all-gifs endpoint
- Shows progress spinner during processing
- Displays detailed results: total, success, failed counts
- Shows error messages if any videos failed to process
- Requires admin authentication (uses session cookies)
- Responsive design with proper error handling

Usage:
1. Deploy the new Docker image to production
2. Login as admin on the website
3. Navigate to: https://znakovni.matijaturk.from.hr/regenerate-gifs.html
4. Click 'Start GIF Regeneration' button
5. Wait for completion (may take several minutes)
6. Refresh dictionary page to see GIF previews

This solves the production deployment issue where GIF files generated
locally don't match production video filenames (different UUIDs).

Co-Authored-By: Auggie
2026-01-18 18:33:59 +01:00
8614161f91 Add bulk GIF regeneration endpoint for production deployment
Problem: Production server has different video UUIDs than development,
so GIF files generated locally don't match production video filenames.

Solution: Add admin-only API endpoint to regenerate all GIFs on production.

Backend changes:
- Add POST /api/terms/regenerate-all-gifs endpoint (admin only)
- Processes all videos in database and generates GIF previews
- Returns detailed results: total, success, failed counts and error messages
- Automatically creates /uploads/gifs/ directory if missing
- Deletes old GIF files and database records before regenerating
- Uses same GIF generation settings as upload (300px, 10fps, 3sec)

Docker changes:
- Add REGENERATE_GIFS environment variable to docker-entrypoint.sh
- If set to 'true', runs regenerate-all-gifs.ts script on container startup
- Useful for initial deployment or after restoring from backup

Usage:
  # Via API (recommended):
  POST /api/terms/regenerate-all-gifs
  (requires admin authentication)

  # Via Docker env var:
  docker run -e REGENERATE_GIFS=true ...

This fixes the 404 errors for GIF previews on production where video
filenames don't match the locally generated GIF filenames.

Co-Authored-By: Auggie
2026-01-18 18:30:31 +01:00
52e91b5ea6 Add GIF regeneration and diagnostic scripts
Added utility scripts for GIF management:

1. regenerate-all-gifs.ts:
   - Regenerates GIF previews for all existing videos
   - Deletes old GIFs before creating new ones
   - Provides progress feedback and summary statistics
   - Useful for bulk GIF generation after deployment

2. check-gifs.ts:
   - Quick diagnostic to list all GIF records in database
   - Shows term names and GIF URLs
   - Useful for verifying GIF generation

3. insert-gif-test.ts:
   - Test script to verify GIF enum value works in database
   - Creates, verifies, and cleans up test GIF record
   - Includes Prisma query logging for debugging

Usage:
  cd packages/backend
  npx tsx scripts/regenerate-all-gifs.ts
  npx tsx scripts/check-gifs.ts
  npx tsx scripts/insert-gif-test.ts

Co-Authored-By: Auggie
2026-01-18 18:24:00 +01:00
8c8ac8d1bb Fix GIF preview display in dictionary word cards
Problem: GIFs were created successfully but not displaying in the dictionary listing.

Root cause: WordCard component was using raw relative URLs for GIF images:
- Before: src={gifMedia.url} → Browser requested from frontend domain
- After: src={getVideoUrl(gifMedia.url)} → Correctly requests from backend

Changes:
- Import getVideoUrl helper from videoPlaylist.ts
- Use getVideoUrl() to convert relative GIF URLs to absolute backend URLs
- Add null check to handle cases where getVideoUrl returns null

This matches the pattern used in VideoUpload.tsx which was already working correctly.

Result: GIF previews now display properly in dictionary word cards.

Co-Authored-By: Auggie
2026-01-18 18:12:15 +01:00
acd14e635b Add automatic GIF preview generation for videos
Backend changes:
- Add ffmpeg to Docker image for video processing
- Create gifGenerator utility with high-quality palette-based GIF generation
- Update Prisma schema: Add GIF to MediaKind enum
- Auto-generate 300px GIF preview (10fps, 3sec) on video upload
- Add POST /api/terms/:id/media/:mediaId/regenerate-gif endpoint for admins
- Update delete endpoint to cascade delete GIFs when video is deleted
- GIF generation uses ffmpeg with palette optimization for quality

Frontend changes:
- Update MediaKind enum to include GIF
- Display animated GIF previews in dictionary word cards
- Show 'No preview' icon for videos without GIF
- Add 'Regenerate GIF' button in admin video upload UI
- Display both video and GIF side-by-side in admin panel
- Visual indicator when GIF preview is available

Features:
- Automatic GIF generation on video upload (non-blocking)
- Manual GIF regeneration from admin panel
- GIF preview in dictionary listing for better UX
- Fallback to video icon when no GIF available
- Proper cleanup: GIFs deleted when parent video is deleted

Technical details:
- GIFs stored in /uploads/gifs/
- Uses two-pass ffmpeg encoding with palette for quality
- Configurable fps, width, duration, start time
- Error handling: video upload succeeds even if GIF fails

Co-Authored-By: Auggie
2026-01-18 17:51:08 +01:00
1cff7740a8 Fix WordDetailModal: Complete localhost:3000 hardcoding cleanup
- Fixed API_URL in WordDetailModal.tsx to use explicit undefined check
- This completes the Docker deployment fix for all frontend components
- Word info modal now works correctly in Docker via nginx proxy
- All 4 locations now use consistent environment-aware URL pattern:
  * api.ts (API client)
  * videoPlaylist.ts (video URLs)
  * VideoUpload.tsx (admin video upload)
  * WordDetailModal.tsx (word info modal)

Fixes: Word info click feature in Docker deployment

Co-Authored-By: Auggie
2026-01-18 17:32:55 +01:00
030491fc5a Fix Docker deployment: Replace hardcoded localhost:3000 with environment-aware URLs
- Fixed API client to respect empty VITE_API_URL for same-origin requests
- Fixed video URL construction in videoPlaylist.ts
- Fixed video URL construction in VideoUpload.tsx
- All three files now use explicit undefined check instead of || operator
- Enables proper same-origin requests via nginx proxy in Docker

Co-Authored-By: Auggie
2026-01-18 17:26:44 +01:00
22fb4b9b20 Add Help page with markdown support and routing 2026-01-18 15:52:46 +01:00
eab5303c0f Fix bugs and add features to Znakopis document management
- Fix API endpoint for creating pages (documents/:id/pages)
- Fix sentence deletion functionality
- Add CreateDocumentDialog component for better UX
- Improve document and sentence management UI
- Update seed data and backend routes
- Clean up documentation files (remove videos.md, videosentence.md)
- Add comprehensive bug tracking in fixbugsaddfeatures.md
2026-01-18 15:21:23 +01:00
d3c90ea447 Add video sentence feature with playlist functionality 2026-01-18 14:56:28 +01:00
7598f26c9c Add admin interface for term management with video upload support 2026-01-17 19:31:39 +01:00
85ae57b95b Refactor word type colors into centralized utility
- Extract word type color logic into shared wordTypeColors.ts utility
- Update TokenTray to use centralized color utility
- Remove duplicate color logic from WordCard and SortableToken
- Add color legend to Layout header for better UX
- Simplify Znakopis page component
2026-01-17 19:11:45 +01:00
8bdd4f6368 Add Znakopis feature with document and sentence management
- Implemented Znakopis page with document and sentence CRUD operations
- Added backend routes for documents and sentences
- Created UI components for sentence editing and display
- Added sentence store for state management
- Integrated select component for document selection
- Updated README with Phase 3 completion status
- Removed obsolete fix-colors.md file
2026-01-17 18:50:53 +01:00
2b768d4c13 Fix color contrast issues in WordCard and WordDetailModal components 2026-01-17 18:35:11 +01:00
65d117cf16 UI improvements: update favicon, reorder WordCard buttons, style logo, and refine color scheme
- Add custom favicon.ico to replace default Vite icon
- Reorder WordCard action buttons (Dodaj on left, Info on right)
- Add white circular background to sidebar logo for better visibility
- Update CSS color variables to use proper indigo color scheme with HSL values
2026-01-17 18:24:37 +01:00
c6d6c18466 Add dictionary feature with term management and UI components
- Implement backend API for term CRUD operations
- Add frontend dictionary page with search and filtering
- Integrate shadcn/ui components (Dialog)
- Create term management UI with add/edit/delete functionality
- Update database seed with initial terms
- Add API client for term operations
- Complete Phase 2 of development plan
2026-01-17 18:15:01 +01:00
bbf143a3b4 Update sidebar design with logo and improved color scheme 2026-01-17 17:37:15 +01:00
d20be4f868 Update frontend UI with improved layout and styling
- Enhanced homepage with modern design and better visual hierarchy
- Improved login page with centered layout and better UX
- Updated admin page with cleaner interface
- Refined sidebar navigation and layout components
- Updated Tailwind config and global styles
- Fixed protected route component
2026-01-17 15:18:08 +01:00
3275bc4a4f Add authentication system and admin panel
- Implement JWT-based authentication with login/logout
- Add user management routes and middleware
- Create admin panel for managing words and categories
- Add authentication store and API client
- Update database schema with User model
- Configure CORS and authentication middleware
- Add login page and protected routes
2026-01-17 14:30:22 +01:00
a11e2acb23 Initial project setup: monorepo structure with frontend and backend
- Set up pnpm workspace with frontend (React + Vite) and backend (Express + Prisma)
- Configure TypeScript, ESLint, and Prettier
- Add Prisma schema for database models (User, Course, Lesson, Progress, etc.)
- Create basic frontend structure with Tailwind CSS and shadcn/ui
- Add environment configuration files
- Update README with project overview and setup instructions
- Complete Phase 0: Project initialization
2026-01-17 11:58:26 +01:00
e38194a44c Add comprehensive project documentation
- Add detailed implementation plan (main-plan.md)
- Add professional README with project overview
- Include original specifications and screenshots
- Document technology stack and architecture
- Provide setup and deployment instructions
2026-01-17 11:42:15 +01:00
5e652ed519 Initial commit 2026-01-17 11:16:09 +01:00