Files
znakovni.hr/videos.md

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 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

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

  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