from pydantic import BaseModel, EmailStr from typing import Optional, List from datetime import datetime # User Schemas class UserBase(BaseModel): username: str email: EmailStr full_name: Optional[str] = None profile_picture: Optional[str] = None theme: str = "light" class UserCreate(UserBase): password: str class UserUpdate(BaseModel): email: Optional[EmailStr] = None full_name: Optional[str] = None password: Optional[str] = None theme: Optional[str] = None class UserLogin(BaseModel): username: str password: str class UserResponse(UserBase): id: int is_active: bool is_admin: bool = False created_at: datetime class Config: from_attributes = True class UserWithDepartments(UserResponse): departments: List["DepartmentResponse"] = [] # Token Schemas class Token(BaseModel): access_token: str token_type: str class TokenData(BaseModel): username: Optional[str] = None # Department Schemas class DepartmentBase(BaseModel): name: str description: Optional[str] = None class DepartmentCreate(DepartmentBase): pass class DepartmentResponse(DepartmentBase): id: int snippets_enabled: bool created_at: datetime class Config: from_attributes = True # Channel Schemas class ChannelBase(BaseModel): name: str description: Optional[str] = None department_id: int class ChannelCreate(ChannelBase): pass class ChannelResponse(ChannelBase): id: int created_at: datetime class Config: from_attributes = True # Message Schemas class MessageBase(BaseModel): content: str channel_id: int snippet_id: Optional[int] = None reply_to_id: Optional[int] = None class MessageCreate(MessageBase): pass class MessageResponse(MessageBase): id: int sender_id: int created_at: datetime is_deleted: bool = False sender_username: Optional[str] = None sender_full_name: Optional[str] = None sender_profile_picture: Optional[str] = None attachments: List["FileAttachmentResponse"] = [] snippet: Optional["SnippetResponse"] = None reply_to: Optional[dict] = None # Contains replied message info class Config: from_attributes = True # Direct Message Schemas class DirectMessageBase(BaseModel): content: str receiver_id: int snippet_id: Optional[int] = None reply_to_id: Optional[int] = None class DirectMessageCreate(DirectMessageBase): pass class DirectMessageResponse(DirectMessageBase): id: int sender_id: int created_at: datetime is_read: bool sender_username: Optional[str] = None receiver_username: Optional[str] = None sender_full_name: Optional[str] = None sender_profile_picture: Optional[str] = None snippet: Optional["SnippetResponse"] = None reply_to: Optional[dict] = None # Contains replied message info class Config: from_attributes = True # File Attachment Schemas class FileAttachmentCreate(BaseModel): permission: str = "read" # "read" or "write" class FileAttachmentResponse(BaseModel): id: int filename: str original_filename: str mime_type: str file_size: int uploaded_at: datetime permission: Optional[str] = "read" uploader_id: Optional[int] = None can_edit: bool = False # Computed: whether current user can edit class Config: from_attributes = True # Snippet Schemas class SnippetBase(BaseModel): title: str language: str content: str tags: Optional[str] = None visibility: str = "private" # private, department, organization department_id: Optional[int] = None class SnippetCreate(SnippetBase): pass class SnippetUpdate(BaseModel): title: Optional[str] = None language: Optional[str] = None content: Optional[str] = None tags: Optional[str] = None visibility: Optional[str] = None department_id: Optional[int] = None class SnippetResponse(SnippetBase): id: int owner_id: int owner_username: Optional[str] = None created_at: datetime updated_at: datetime class Config: from_attributes = True class LanguageBase(BaseModel): code: str name: str class LanguageCreate(LanguageBase): pass class LanguageResponse(LanguageBase): id: int is_default: bool created_at: datetime class Config: from_attributes = True class TranslationEntryResponse(BaseModel): translation_id: int language_id: int language_code: str language_name: str value: str class TranslationGroupResponse(BaseModel): key: str label: str description: Optional[str] = None entries: List[TranslationEntryResponse] class TranslationUpdateRequest(BaseModel): translation_id: int value: str