Files
LinkDesk/backend/schemas/shot.py
T
indigo 0acf9ddff2 Optimize shot table loading performance
- Pass episode_id filter to backend API instead of client-side filtering,
  reducing payload size when an episode is selected
- Skip getShot refetch in ShotDetailPanel when initialShot prop is provided
- Fix redundant DB query in list_shots: read project.custom_task_statuses
  directly from the already-fetched project object
- Add missing indexes on Task.shot_id, Task.assigned_user_id,
  Task.deleted_at and Episode.project_id; add add_perf_indexes.py
  migration script to apply them to existing databases
- Center login page layout
- Update CLAUDE.md and AGENTS.md with correct venv path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 00:30:18 +08:00

104 lines
3.6 KiB
Python

from pydantic import BaseModel, Field
from typing import Optional, List, Dict
from datetime import datetime
from models.shot import ShotStatus
from models.task import TaskType, TaskStatus
class ShotBase(BaseModel):
name: str = Field(..., min_length=1, max_length=255)
description: Optional[str] = None
frame_start: int = Field(default=1001, ge=1)
frame_end: int = Field(default=1001, ge=1)
status: ShotStatus = ShotStatus.NOT_STARTED
project_id: Optional[int] = Field(None, description="Project ID - auto-populated from episode if not provided")
class ShotCreate(ShotBase):
pass
class ShotUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=255)
description: Optional[str] = None
frame_start: Optional[int] = Field(None, ge=1)
frame_end: Optional[int] = Field(None, ge=1)
status: Optional[ShotStatus] = None
project_id: Optional[int] = Field(None, description="Project ID - must match episode's project")
class TaskStatusInfo(BaseModel):
"""Task status information for table display"""
task_type: str # String to support custom task types
status: str # Changed from TaskStatus enum to str to support custom statuses
task_id: Optional[int] = None
assigned_user_id: Optional[int] = None
class ShotResponse(ShotBase):
id: int
project_id: int # Make required in response
episode_id: int
created_at: datetime
updated_at: datetime
# Summary information
task_count: int = 0
# Optional computed field for display
project_name: Optional[str] = Field(None, description="Project name for display purposes")
# Task status information for detail display
task_status: Dict[str, Optional[str]] = Field(default_factory=dict, description="Task status by task type")
task_ids: Dict[str, int] = Field(default_factory=dict, description="Task IDs by task type")
task_details: List[TaskStatusInfo] = Field(default_factory=list, description="Detailed task information")
class Config:
from_attributes = True
class ShotListResponse(BaseModel):
id: int
name: str
description: Optional[str] = None
frame_start: int
frame_end: int
status: ShotStatus
project_id: int
episode_id: int
created_at: datetime
updated_at: datetime
# Summary information
task_count: int = 0
# Optional computed field for display
project_name: Optional[str] = Field(None, description="Project name for display purposes")
# Task status information for table display
task_status: Dict[str, Optional[str]] = Field(default_factory=dict, description="Task status by task type")
task_details: List[TaskStatusInfo] = Field(default_factory=list, description="Detailed task information")
class Config:
from_attributes = True
class BulkShotCreate(BaseModel):
"""Schema for bulk shot creation with naming patterns"""
name_prefix: str = Field(..., min_length=1, max_length=100)
shot_count: int = Field(..., ge=1, le=1000)
start_number: int = Field(default=10, ge=1)
number_padding: int = Field(default=3, ge=1, le=6)
frame_start: int = Field(default=1001, ge=1)
frame_end: int = Field(default=1001, ge=1)
description_template: Optional[str] = None
create_default_tasks: bool = Field(default=True)
task_types: Optional[List[str]] = None # If None, use default shot task types (changed from TaskType to str)
class BulkShotResponse(BaseModel):
"""Response for bulk shot creation"""
created_shots: List[ShotResponse]
created_tasks_count: int = 0
message: str