UMBRA/backend/app/schemas/project_task.py
Kyle Pope ccfbf6df96 Add subtasks feature to project tasks
Backend:
- Add self-referencing parent_task_id FK on project_tasks with CASCADE delete
- Add Alembic migration 002 for parent_task_id column + index
- Update schemas with parent_task_id in create, nested subtasks in response
- Chain selectinload for subtasks on all project queries
- Validate parent must be top-level task (single nesting level only)

Frontend:
- Add parent_task_id and subtasks[] to ProjectTask type
- ProjectDetail: expand/collapse chevrons, subtask progress bars, inline
  subtask rendering with accent left border, add/edit/delete subtask buttons
- TaskForm: accept parentTaskId prop, include in create payload, context-aware
  dialog title (New Task vs New Subtask)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 01:31:46 +08:00

46 lines
1.1 KiB
Python

from pydantic import BaseModel, ConfigDict
from datetime import datetime, date
from typing import Optional, List
class ProjectTaskCreate(BaseModel):
title: str
description: Optional[str] = None
status: str = "pending"
priority: str = "medium"
due_date: Optional[date] = None
person_id: Optional[int] = None
sort_order: int = 0
parent_task_id: Optional[int] = None
class ProjectTaskUpdate(BaseModel):
title: Optional[str] = None
description: Optional[str] = None
status: Optional[str] = None
priority: Optional[str] = None
due_date: Optional[date] = None
person_id: Optional[int] = None
sort_order: Optional[int] = None
class ProjectTaskResponse(BaseModel):
id: int
project_id: int
parent_task_id: Optional[int] = None
title: str
description: Optional[str]
status: str
priority: str
due_date: Optional[date]
person_id: Optional[int]
sort_order: int
created_at: datetime
updated_at: datetime
subtasks: List["ProjectTaskResponse"] = []
model_config = ConfigDict(from_attributes=True)
ProjectTaskResponse.model_rebuild()