Add admin interface for term management with video upload support
This commit is contained in:
216
videos.md
Normal file
216
videos.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# 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 `Term` and `TermMedia` models
|
||||
- ✅ Static file serving configured for `/uploads` directory
|
||||
- ✅ 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
|
||||
```prisma
|
||||
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
|
||||
```prisma
|
||||
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
|
||||
|
||||
1. **File Storage**: Videos stored in `packages/backend/uploads/videos/`
|
||||
2. **URL Format**: Store relative URLs like `/uploads/videos/dobar-dan-1234567890.mp4`
|
||||
3. **Normalized Text**: Auto-generate from wordText (lowercase, remove diacritics)
|
||||
4. **Video Metadata**: Extract duration/dimensions server-side if possible (use ffprobe or similar)
|
||||
5. **Error Handling**: Validate file types, sizes, and handle upload failures gracefully
|
||||
6. **Security**: Ensure only admins can upload/delete, validate file types to prevent malicious uploads
|
||||
7. **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
|
||||
|
||||
Reference in New Issue
Block a user