R-8 — Linguist language competence: - Add User.languages[] BCP-47 field to backend model + UserResponse schema - Frontend: show amber warning in assign modal when selected linguist has no competence listed for the target language PM VTT editing (FinalDetail): - PM and ADMIN can now edit captions/AD in the final review stage - VttEditor becomes read-write with onCueSave wired to updateVttMutation - Other roles remain read-only Timeline right-click + add pause: - Right-click anywhere on the timeline opens a context menu showing the timestamp - If near a pause point marker: "Edit timing" + "Regenerate TTS" options - If on empty space: "Add AD cue at Xs" → inserts a new AD cue in the editor - Pause point markers widened from 1px → 2px (3px on hover) for easier clicking - Right-click on a pause point marker directly opens the editor VttEditor insertAtTimeMs prop: - New prop triggers programmatic insert at a specific video timestamp - Used by the timeline right-click "Add AD cue here" action Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
70 lines
1.8 KiB
Python
70 lines
1.8 KiB
Python
from datetime import datetime
|
|
from enum import Enum
|
|
from typing import Optional, Annotated
|
|
|
|
from bson import ObjectId
|
|
from pydantic import BaseModel, EmailStr, Field, BeforeValidator
|
|
|
|
|
|
def validate_object_id(v) -> str:
|
|
"""Convert ObjectId to string"""
|
|
if isinstance(v, ObjectId):
|
|
return str(v)
|
|
if isinstance(v, str):
|
|
return v
|
|
raise ValueError('Invalid ObjectId')
|
|
|
|
|
|
PyObjectId = Annotated[str, BeforeValidator(validate_object_id)]
|
|
|
|
|
|
class UserRole(str, Enum):
|
|
CLIENT = "client"
|
|
REVIEWER = "reviewer"
|
|
LINGUIST = "linguist"
|
|
PRODUCTION = "production"
|
|
PROJECT_MANAGER = "project_manager"
|
|
ADMIN = "admin"
|
|
|
|
|
|
class AuthProvider(str, Enum):
|
|
LOCAL = "local"
|
|
MICROSOFT = "microsoft"
|
|
|
|
|
|
class User(BaseModel):
|
|
id: Optional[PyObjectId] = Field(None, alias="_id")
|
|
email: EmailStr
|
|
hashed_password: Optional[str] = None # Optional for Microsoft users
|
|
full_name: str
|
|
role: UserRole = UserRole.CLIENT
|
|
auth_provider: AuthProvider = AuthProvider.LOCAL
|
|
is_active: bool = True
|
|
pm_client_ids: list[str] = [] # Client IDs where this user is Project Manager (admin-assigned)
|
|
languages: list[str] = [] # BCP-47 language codes the user is competent in (R-8)
|
|
created_at: Optional[datetime] = None
|
|
updated_at: Optional[datetime] = None
|
|
|
|
class Config:
|
|
populate_by_name = True
|
|
use_enum_values = True
|
|
|
|
|
|
class UserInDB(User):
|
|
pass
|
|
|
|
|
|
class UserCreate(BaseModel):
|
|
email: EmailStr
|
|
password: str
|
|
full_name: str
|
|
role: UserRole = UserRole.CLIENT
|
|
|
|
|
|
class UserUpdate(BaseModel):
|
|
email: Optional[EmailStr] = None
|
|
full_name: Optional[str] = None
|
|
role: Optional[UserRole] = None
|
|
is_active: Optional[bool] = None
|
|
pm_client_ids: Optional[list[str]] = None
|
|
languages: Optional[list[str]] = None
|