Mobile Responsive Layout: - Add useMediaQuery, useIsMobile, useIsTablet, useIsDesktop hooks for device detection - Create MobileHeader component with hamburger menu and action drawer - Create BottomToolbar for mobile navigation (Files, Members) - Create SlidePanel component for full-screen mobile sidebars - Update RoomDetail.tsx with mobile/desktop conditional rendering - Update RoomList.tsx with single-column grid and touch-friendly buttons - Add CSS custom properties for safe areas and touch targets (min 44px) - Add mobile viewport meta tags for notched devices Open Room Access: - All authenticated users can view all rooms (not just their own) - Users can join active rooms they're not members of - Add is_member field to room responses - Update room list API to return all rooms by default Admin Room Management: - Add permanent delete functionality for system admins - Add delete confirmation dialog with room title verification - Broadcast room deletion via WebSocket to connected users - Add users search API for adding members 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
168 lines
4.8 KiB
Python
168 lines
4.8 KiB
Python
"""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")
|
|
my_rooms: Optional[bool] = Field(False, description="Filter to show only rooms where user is a member")
|
|
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_member: bool = False
|
|
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 |