Files
LinkDesk/backend/schemas/task.py
T
indigo eb5587eb40 Consistent status colors, prevent native context menu leaks, fix settings 404
- Task status badges (bulk change-status popover, right-click menu) now
  use the real per-project TaskStatusesStore colors/labels instead of the
  hardcoded TaskStatus enum, matching EditableTaskStatus everywhere.
- Suppress the native browser context menu from leaking through gaps in
  the task table (header/empty space), open popovers/dropdowns and their
  submenus, the status Select, and a second right-click at the same
  coordinates (the popover's positioning anchor now has
  pointer-events: none so it doesn't intercept the repeat click).
- Fix 404s on /api/settings/* caused by a double-declared route prefix.
- Fix 422 on bulk-applying a custom task status by relaxing
  BulkStatusUpdate.status from the TaskStatus enum to str, matching the
  existing single-task update schema.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 16:07:39 +08:00

233 lines
5.7 KiB
Python

from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import date, datetime
from enum import Enum
from models.task import TaskType, TaskStatus, ReviewDecision, AttachmentType
from models.user import DepartmentRole
class TaskBase(BaseModel):
name: str = Field(..., min_length=1, max_length=255)
description: Optional[str] = None
task_type: str # Changed from TaskType enum to str to support custom task types
deadline: Optional[date] = None
status: str = "not_started" # Changed from TaskStatus enum to str to support custom statuses
class TaskCreate(TaskBase):
project_id: int
episode_id: Optional[int] = None
shot_id: Optional[int] = None
asset_id: Optional[int] = None
assigned_user_id: Optional[int] = None
class TaskUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=255)
description: Optional[str] = None
task_type: Optional[str] = None # Changed from TaskType enum to str to support custom task types
deadline: Optional[date] = None
status: Optional[str] = None # Changed from TaskStatus enum to str to support custom statuses
assigned_user_id: Optional[int] = None
class TaskStatusUpdate(BaseModel):
status: str # Changed from TaskStatus enum to str to support custom statuses
class TaskAssignment(BaseModel):
assigned_user_id: int
class TaskResponse(TaskBase):
id: int
project_id: int
episode_id: Optional[int] = None
shot_id: Optional[int] = None
asset_id: Optional[int] = None
assigned_user_id: Optional[int] = None
created_at: datetime
updated_at: datetime
# Related entity names for display
project_name: Optional[str] = None
episode_name: Optional[str] = None
shot_name: Optional[str] = None
asset_name: Optional[str] = None
assigned_user_name: Optional[str] = None
assigned_user_email: Optional[str] = None
assigned_user_avatar_url: Optional[str] = None
class Config:
from_attributes = True
class TaskListResponse(BaseModel):
id: int
name: str
task_type: str # Changed from TaskType enum to str to support custom task types
status: str # Changed from TaskStatus enum to str to support custom statuses
deadline: Optional[date] = None
project_id: int
project_name: str
episode_id: Optional[int] = None
episode_name: Optional[str] = None
shot_id: Optional[int] = None
shot_name: Optional[str] = None
asset_id: Optional[int] = None
asset_name: Optional[str] = None
assigned_user_id: Optional[int] = None
assigned_user_name: Optional[str] = None
assigned_user_avatar_url: Optional[str] = None
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
# Production Notes schemas
class ProductionNoteBase(BaseModel):
content: str = Field(..., min_length=1)
parent_note_id: Optional[int] = None
class ProductionNoteCreate(ProductionNoteBase):
pass
class ProductionNoteUpdate(BaseModel):
content: str = Field(..., min_length=1)
class ProductionNoteResponse(ProductionNoteBase):
id: int
task_id: int
user_id: int
created_at: datetime
updated_at: datetime
# User information
user_first_name: str
user_last_name: str
user_email: str
user_avatar_url: Optional[str] = None
# Child notes for threading
child_notes: Optional[List['ProductionNoteResponse']] = None
class Config:
from_attributes = True
# Task Attachment schemas
class TaskAttachmentBase(BaseModel):
file_name: str
attachment_type: AttachmentType = AttachmentType.REFERENCE
description: Optional[str] = None
class TaskAttachmentCreate(TaskAttachmentBase):
pass
class TaskAttachmentResponse(TaskAttachmentBase):
id: int
task_id: int
user_id: int
file_path: str
file_type: str
file_size: int
uploaded_at: datetime
# User information
user_first_name: str
user_last_name: str
# File serving URLs (computed properties)
download_url: Optional[str] = None
thumbnail_url: Optional[str] = None
class Config:
from_attributes = True
# Submission schemas
class SubmissionBase(BaseModel):
notes: Optional[str] = None
class SubmissionCreate(SubmissionBase):
pass
class SubmissionResponse(SubmissionBase):
id: int
task_id: int
user_id: int
file_path: str
file_name: str
version_number: int
submitted_at: datetime
# User information
user_first_name: str
user_last_name: str
# Latest review if any
latest_review: Optional['ReviewResponse'] = None
# File serving URLs (computed properties)
download_url: Optional[str] = None
thumbnail_url: Optional[str] = None
stream_url: Optional[str] = None
class Config:
from_attributes = True
# Review schemas
class ReviewBase(BaseModel):
decision: ReviewDecision
feedback: Optional[str] = None
class ReviewCreate(ReviewBase):
pass
class ReviewResponse(ReviewBase):
id: int
submission_id: int
reviewer_id: int
reviewed_at: datetime
# Reviewer information
reviewer_first_name: str
reviewer_last_name: str
class Config:
from_attributes = True
# Bulk action schemas
class BulkStatusUpdate(BaseModel):
task_ids: List[int] = Field(..., min_length=1)
status: str # Changed from TaskStatus enum to str to support custom statuses
class BulkAssignment(BaseModel):
task_ids: List[int] = Field(..., min_length=1)
assigned_user_id: int
class BulkActionResult(BaseModel):
success_count: int
failed_count: int
errors: Optional[List[dict]] = None
# Update forward references
ProductionNoteResponse.model_rebuild()
SubmissionResponse.model_rebuild()