collabrix/backend/app/schemas.py

608 lines
13 KiB
Python

from pydantic import BaseModel, EmailStr
from typing import Optional, List
from datetime import datetime
from enum import Enum
class UserRole(str, Enum):
USER = "user"
ADMIN = "admin"
SUPERADMIN = "superadmin"
# 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
role: UserRole = UserRole.USER
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
attachments: List["DirectMessageAttachmentResponse"] = []
class Config:
from_attributes = True
# Direct Message Attachment Schemas
class DirectMessageAttachmentCreate(BaseModel):
permission: str = "read" # "read" or "write"
class DirectMessageAttachmentResponse(BaseModel):
id: int
filename: str
original_filename: str
mime_type: str
file_size: int
uploaded_at: datetime
direct_message_id: int
upload_permission: Optional[str] = "read"
uploader_id: Optional[int] = None
is_editable: bool = False
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
message_id: int
upload_permission: Optional[str] = "read"
uploader_id: Optional[int] = None
is_editable: 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
# Kanban Schemas
class KanbanBoardBase(BaseModel):
name: str = "Kanban Board"
class KanbanBoardCreate(KanbanBoardBase):
channel_id: int
class KanbanBoardUpdate(BaseModel):
name: Optional[str] = None
class KanbanBoardResponse(KanbanBoardBase):
id: int
channel_id: int
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class KanbanColumnBase(BaseModel):
name: str
position: int = 0
color: Optional[str] = None
class KanbanColumnCreate(KanbanColumnBase):
board_id: int
class KanbanColumnUpdate(BaseModel):
name: Optional[str] = None
position: Optional[int] = None
color: Optional[str] = None
class KanbanColumnResponse(KanbanColumnBase):
id: int
board_id: int
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class KanbanCardBase(BaseModel):
title: str
description: Optional[str] = None
assignee_id: Optional[int] = None
position: int = 0
due_date: Optional[datetime] = None
priority: Optional[str] = "medium"
labels: Optional[str] = None
estimated_time: Optional[int] = None
actual_time: Optional[int] = None
class KanbanCardCreate(KanbanCardBase):
column_id: int
class KanbanCardUpdate(BaseModel):
title: Optional[str] = None
description: Optional[str] = None
assignee_id: Optional[int] = None
position: Optional[int] = None
due_date: Optional[datetime] = None
priority: Optional[str] = None
labels: Optional[str] = None
estimated_time: Optional[int] = None
actual_time: Optional[int] = None
is_archived: Optional[bool] = None
class KanbanCardResponse(KanbanCardBase):
id: int
column_id: int
created_at: datetime
updated_at: datetime
attachments_count: int = 0
checklists_count: int = 0
comments_count: int = 0
is_archived: bool = False
assignee: Optional["UserResponse"] = None
class Config:
from_attributes = True
class KanbanBoardWithColumns(KanbanBoardResponse):
columns: List["KanbanColumnWithCards"] = []
class KanbanColumnWithCards(KanbanColumnResponse):
cards: List[KanbanCardResponse] = []
# Checklist Schemas
class KanbanChecklistBase(BaseModel):
title: str
position: int = 0
class KanbanChecklistCreate(KanbanChecklistBase):
card_id: int
class KanbanChecklistUpdate(BaseModel):
title: Optional[str] = None
position: Optional[int] = None
class KanbanChecklistResponse(KanbanChecklistBase):
id: int
card_id: int
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class KanbanChecklistItemBase(BaseModel):
title: str
is_completed: bool = False
position: int = 0
class KanbanChecklistItemCreate(KanbanChecklistItemBase):
checklist_id: int
class KanbanChecklistItemUpdate(BaseModel):
title: Optional[str] = None
is_completed: Optional[bool] = None
position: Optional[int] = None
class KanbanChecklistItemResponse(KanbanChecklistItemBase):
id: int
checklist_id: int
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class KanbanChecklistWithItems(KanbanChecklistResponse):
items: List[KanbanChecklistItemResponse] = []
class KanbanCardWithChecklists(KanbanCardResponse):
checklists: List[KanbanChecklistWithItems] = []
# Comment Schemas
class KanbanCardCommentBase(BaseModel):
content: str
class KanbanCardCommentCreate(BaseModel):
content: str
class KanbanCardCommentUpdate(BaseModel):
content: Optional[str] = None
class KanbanCardCommentResponse(KanbanCardCommentBase):
id: int
card_id: int
user_id: int
created_at: datetime
updated_at: datetime
user: Optional[UserResponse] = None
class Config:
from_attributes = True
# Attachment Schemas
class KanbanCardAttachmentBase(BaseModel):
filename: str
original_filename: str
mime_type: str
file_size: int
file_path: str
class KanbanCardAttachmentCreate(BaseModel):
card_id: int
file: bytes # This will be handled by FastAPI's UploadFile
class KanbanCardAttachmentResponse(KanbanCardAttachmentBase):
id: int
card_id: int
uploader_id: int
uploaded_at: datetime
uploader: Optional[UserResponse] = None
class Config:
from_attributes = True
# Time Tracking Schemas
class KanbanTimeEntryBase(BaseModel):
description: Optional[str] = None
start_time: datetime
end_time: Optional[datetime] = None
duration_minutes: Optional[int] = None
class KanbanTimeEntryCreate(BaseModel):
card_id: int
description: Optional[str] = None
class KanbanTimeEntryUpdate(BaseModel):
description: Optional[str] = None
end_time: Optional[datetime] = None
class KanbanTimeEntryResponse(KanbanTimeEntryBase):
id: int
card_id: int
user_id: int
is_running: bool
created_at: datetime
user: Optional[UserResponse] = None
class Config:
from_attributes = True
# Custom Field Schemas
class KanbanCustomFieldBase(BaseModel):
name: str
field_type: str
options: Optional[str] = None
is_required: bool = False
position: int = 0
class KanbanCustomFieldCreate(KanbanCustomFieldBase):
board_id: int
class KanbanCustomFieldUpdate(BaseModel):
name: Optional[str] = None
field_type: Optional[str] = None
options: Optional[str] = None
is_required: Optional[bool] = None
position: Optional[int] = None
class KanbanCustomFieldResponse(KanbanCustomFieldBase):
id: int
board_id: int
created_at: datetime
class Config:
from_attributes = True
class KanbanCustomFieldValueBase(BaseModel):
value: str
class KanbanCustomFieldValueCreate(KanbanCustomFieldValueBase):
field_id: int
card_id: int
class KanbanCustomFieldValueUpdate(BaseModel):
value: Optional[str] = None
class KanbanCustomFieldValueResponse(KanbanCustomFieldValueBase):
id: int
field_id: int
card_id: int
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
# Template Schemas
class KanbanCardTemplateBase(BaseModel):
name: str
description: Optional[str] = None
template_data: str
is_default: bool = False
class KanbanCardTemplateCreate(KanbanCardTemplateBase):
board_id: int
class KanbanCardTemplateUpdate(BaseModel):
name: Optional[str] = None
description: Optional[str] = None
template_data: Optional[str] = None
is_default: Optional[bool] = None
class KanbanCardTemplateResponse(KanbanCardTemplateBase):
id: int
board_id: int
created_at: datetime
class Config:
from_attributes = True
# Extended Card Response with all features
class KanbanCardExtendedResponse(KanbanCardResponse):
estimated_time: Optional[int] = None
actual_time: Optional[int] = None
comments: List[KanbanCardCommentResponse] = []
attachments: List[KanbanCardAttachmentResponse] = []
time_entries: List[KanbanTimeEntryResponse] = []
custom_field_values: List[KanbanCustomFieldValueResponse] = []
checklists: List[KanbanChecklistWithItems] = []
class KanbanBoardExtendedResponse(KanbanBoardResponse):
custom_fields: List[KanbanCustomFieldResponse] = []
templates: List[KanbanCardTemplateResponse] = []