7.2 KiB
Video Upload Feature for Admin Panel
Overview
This document provides AI instructions for implementing video upload functionality for Croatian Sign Language words in the admin panel. Admins should be able to upload videos for existing words and create new words with videos.
Context from main-plan.md
According to the main plan (lines 60-70, 366-382):
- Each Term has associated TermMedia records
- TermMedia stores video URLs, duration, dimensions, and checksums
- Videos are stored in
/uploads/videos/directory - Video format: MP4 (H.264) for maximum compatibility
- File uploads use Multer middleware (already in dependencies)
- Static file serving is already configured at
/uploads
Current State
Backend
- ✅ Prisma schema has
TermandTermMediamodels - ✅ Static file serving configured for
/uploadsdirectory - ✅ Multer is in package.json dependencies
- ✅ Terms routes exist at
packages/backend/src/routes/terms.ts(currently read-only) - ✅ Admin authentication middleware exists (
isAuthenticated,isAdmin) - ❌ No upload routes or middleware configured yet
- ❌ No admin endpoints for creating/editing terms with media
Frontend
- ✅ Admin panel exists at
packages/frontend/src/pages/Admin.tsx(user management) - ✅ Dictionary page displays terms with videos
- ✅ WordDetailModal shows videos with autoplay
- ❌ No admin UI for managing terms/videos
Implementation Tasks
Backend Tasks
1. Create Upload Middleware
File: packages/backend/src/middleware/upload.ts
Create Multer configuration for video uploads:
- Accept video files (mp4, webm, mov)
- Store in
uploads/videos/directory - Generate unique filenames with timestamp
- Validate file size (max 100MB from env)
- Validate MIME types
- Handle errors gracefully
2. Add Admin Term Routes
File: packages/backend/src/routes/terms.ts
Add the following admin-only endpoints:
POST /api/terms (Admin only)
- Create new term with metadata
- Fields: wordText, wordType, cefrLevel, shortDescription, tags, iconAssetId
- Return created term with ID
PUT /api/terms/:id (Admin only)
- Update existing term metadata
- Validate term exists
- Return updated term
DELETE /api/terms/:id (Admin only)
- Delete term and cascade to TermMedia
- Optionally delete associated video files from disk
- Return success message
POST /api/terms/:id/media (Admin only)
- Upload video file using Multer middleware
- Create TermMedia record linked to term
- Extract video metadata (duration, dimensions) if possible
- Store relative URL path (e.g.,
/uploads/videos/filename.mp4) - Return created TermMedia record
DELETE /api/terms/:id/media/:mediaId (Admin only)
- Delete TermMedia record
- Optionally delete video file from disk
- Return success message
3. Update Server Routes
File: packages/backend/src/server.ts
Ensure upload routes are registered (if creating separate upload routes file).
Frontend Tasks
1. Create Admin Terms Management Page
File: packages/frontend/src/pages/AdminTerms.tsx
Create a new admin page for managing terms:
- List all terms in a table with search/filter
- Show term details: word, type, CEFR level, video status
- Actions: Edit, Delete, Upload Video
- "Create New Term" button
- Pagination for large datasets
2. Create Term Form Component
File: packages/frontend/src/components/admin/TermForm.tsx
Form for creating/editing terms:
- Input: Word Text (required)
- Select: Word Type (NOUN, VERB, ADJECTIVE, etc.)
- Select: CEFR Level (A1, A2, B1, B2, C1, C2)
- Textarea: Short Description
- Input: Tags (comma-separated or tag input)
- Input: Icon Asset ID (optional)
- Submit button
- Cancel button
- Validation with error messages
3. Create Video Upload Component
File: packages/frontend/src/components/admin/VideoUpload.tsx
Video upload interface:
- File input accepting video files (.mp4, .webm, .mov)
- Drag-and-drop zone
- Upload progress indicator
- Preview uploaded video
- Display existing video if present
- Delete video button
- File size validation (client-side)
- Success/error notifications
4. Update Admin Navigation
File: packages/frontend/src/components/layout/Sidebar.tsx
Add navigation link to Admin Terms page:
- Show only for admin users
- Label: "Upravljanje riječima" (Word Management)
- Icon: Book or Video icon
- Place near existing "User Management" link
5. Update Routing
File: packages/frontend/src/App.tsx
Add route for admin terms page:
- Path:
/admin/terms - Protected route (admin only)
- Component: AdminTerms
API Endpoints Summary
New Backend Endpoints
POST /api/terms - Create term (admin)
PUT /api/terms/:id - Update term (admin)
DELETE /api/terms/:id - Delete term (admin)
POST /api/terms/:id/media - Upload video (admin)
DELETE /api/terms/:id/media/:mediaId - Delete video (admin)
Existing Endpoints (Read-only)
GET /api/terms - List terms (public)
GET /api/terms/:id - Get term details (public)
Database Schema Reference
Term Model
model Term {
id String @id @default(uuid())
wordText String @map("word_text")
normalizedText String @map("normalized_text")
language String @default("hr")
wordType WordType @map("word_type")
cefrLevel CefrLevel @map("cefr_level")
shortDescription String? @map("short_description")
tags String? // JSON array
iconAssetId String? @map("icon_asset_id")
media TermMedia[]
// ... relations
}
TermMedia Model
model TermMedia {
id String @id @default(uuid())
termId String @map("term_id")
kind MediaKind // VIDEO, IMAGE, ILLUSTRATION
url String
durationMs Int? @map("duration_ms")
width Int?
height Int?
checksum String?
term Term @relation(...)
}
Implementation Notes
- File Storage: Videos stored in
packages/backend/uploads/videos/ - URL Format: Store relative URLs like
/uploads/videos/dobar-dan-1234567890.mp4 - Normalized Text: Auto-generate from wordText (lowercase, remove diacritics)
- Video Metadata: Extract duration/dimensions server-side if possible (use ffprobe or similar)
- Error Handling: Validate file types, sizes, and handle upload failures gracefully
- Security: Ensure only admins can upload/delete, validate file types to prevent malicious uploads
- Croatian Labels: Use Croatian text in UI (Riječ, Dodaj video, Obriši, etc.)
Testing Checklist
- Admin can create new term without video
- Admin can create new term with video upload
- Admin can edit existing term metadata
- Admin can upload video to existing term
- Admin can replace existing video
- Admin can delete video from term
- Admin can delete entire term
- Video appears in Dictionary (Riječi) page
- Video plays in WordDetailModal
- Non-admin users cannot access admin endpoints
- File size limits are enforced
- Invalid file types are rejected
- Upload progress is shown
- Success/error messages display correctly