feat: Initial commit - Task Reporter incident response system

Complete implementation of the production line incident response system (生產線異常即時反應系統) including:

Backend (FastAPI):
- User authentication with AD integration and session management
- Chat room management (create, list, update, members, roles)
- Real-time messaging via WebSocket (typing indicators, reactions)
- File storage with MinIO (upload, download, image preview)

Frontend (React + Vite):
- Authentication flow with token management
- Room list with filtering, search, and pagination
- Real-time chat interface with WebSocket
- File upload with drag-and-drop and image preview
- Member management and room settings
- Breadcrumb navigation
- 53 unit tests (Vitest)

Specifications:
- authentication: AD auth, sessions, JWT tokens
- chat-room: rooms, members, templates
- realtime-messaging: WebSocket, messages, reactions
- file-storage: MinIO integration, file management
- frontend-core: React SPA structure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-01 17:42:52 +08:00
commit c8966477b9
135 changed files with 23269 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
"""Pydantic schemas for chat room management
Request and response models for API endpoints
"""
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
from enum import Enum
class IncidentType(str, Enum):
"""Types of production incidents"""
EQUIPMENT_FAILURE = "equipment_failure"
MATERIAL_SHORTAGE = "material_shortage"
QUALITY_ISSUE = "quality_issue"
OTHER = "other"
class SeverityLevel(str, Enum):
"""Incident severity levels"""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
CRITICAL = "critical"
class RoomStatus(str, Enum):
"""Room lifecycle status"""
ACTIVE = "active"
RESOLVED = "resolved"
ARCHIVED = "archived"
class MemberRole(str, Enum):
"""Room member roles"""
OWNER = "owner"
EDITOR = "editor"
VIEWER = "viewer"
# Request Schemas
class CreateRoomRequest(BaseModel):
"""Request to create a new incident room"""
title: str = Field(..., min_length=1, max_length=255, description="Room title")
incident_type: IncidentType = Field(..., description="Type of incident")
severity: SeverityLevel = Field(..., description="Severity level")
location: Optional[str] = Field(None, max_length=255, description="Incident location")
description: Optional[str] = Field(None, description="Detailed description")
template: Optional[str] = Field(None, description="Template name to use")
class UpdateRoomRequest(BaseModel):
"""Request to update room metadata"""
title: Optional[str] = Field(None, min_length=1, max_length=255)
severity: Optional[SeverityLevel] = None
status: Optional[RoomStatus] = None
location: Optional[str] = Field(None, max_length=255)
description: Optional[str] = None
resolution_notes: Optional[str] = None
class AddMemberRequest(BaseModel):
"""Request to add a member to a room"""
user_id: str = Field(..., description="User email or ID to add")
role: MemberRole = Field(..., description="Role to assign")
class UpdateMemberRoleRequest(BaseModel):
"""Request to update a member's role"""
role: MemberRole = Field(..., description="New role")
class TransferOwnershipRequest(BaseModel):
"""Request to transfer room ownership"""
new_owner_id: str = Field(..., description="User ID of new owner")
class RoomFilterParams(BaseModel):
"""Query parameters for filtering rooms"""
status: Optional[RoomStatus] = None
incident_type: Optional[IncidentType] = None
severity: Optional[SeverityLevel] = None
created_after: Optional[datetime] = None
created_before: Optional[datetime] = None
search: Optional[str] = Field(None, description="Search in title and description")
all: Optional[bool] = Field(False, description="Admin: show all rooms")
limit: int = Field(20, ge=1, le=100)
offset: int = Field(0, ge=0)
# Response Schemas
class MemberResponse(BaseModel):
"""Room member information"""
user_id: str
role: MemberRole
added_by: str
added_at: datetime
removed_at: Optional[datetime] = None
class Config:
from_attributes = True
class RoomResponse(BaseModel):
"""Complete room information"""
room_id: str
title: str
incident_type: IncidentType
severity: SeverityLevel
status: RoomStatus
location: Optional[str] = None
description: Optional[str] = None
resolution_notes: Optional[str] = None
created_by: str
created_at: datetime
resolved_at: Optional[datetime] = None
archived_at: Optional[datetime] = None
last_activity_at: datetime
last_updated_at: datetime
ownership_transferred_at: Optional[datetime] = None
ownership_transferred_by: Optional[str] = None
member_count: int
members: Optional[List[MemberResponse]] = None
current_user_role: Optional[MemberRole] = None
is_admin_view: bool = False
class Config:
from_attributes = True
class RoomListResponse(BaseModel):
"""Paginated list of rooms"""
rooms: List[RoomResponse]
total: int
limit: int
offset: int
class TemplateResponse(BaseModel):
"""Room template information"""
template_id: int
name: str
description: Optional[str] = None
incident_type: IncidentType
default_severity: SeverityLevel
default_members: Optional[List[dict]] = None
metadata_fields: Optional[dict] = None
class Config:
from_attributes = True
class PermissionResponse(BaseModel):
"""User permissions in a room"""
role: Optional[MemberRole] = None
is_admin: bool = False
can_read: bool = False
can_write: bool = False
can_manage_members: bool = False
can_transfer_ownership: bool = False
can_update_status: bool = False
can_delete: bool = False
class SuccessResponse(BaseModel):
"""Generic success response"""
message: str