Files
egg 44822a561a feat: Improve file display, timezone handling, and LOT management
Changes:
- Fix datetime serialization with UTC 'Z' suffix for correct timezone display
- Add PDF upload support with extension fallback for MIME detection
- Fix LOT add/remove by creating new list for SQLAlchemy JSON change detection
- Add file message components (FileMessage, ImageLightbox, UploadPreview)
- Add multi-file upload support with progress tracking
- Link uploaded files to chat messages via message_id
- Include file attachments in AI report generation
- Update specs for file-storage, realtime-messaging, and ai-report-generation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 12:39:15 +08:00

2.6 KiB

Design: File Display and Timezone Improvements

Context

Users upload files during incident discussions, but these files only appear in a separate drawer. This breaks the conversation flow and makes it hard to understand what was being discussed when a file was uploaded. The AI report generator also lacks this context.

Goals

  • Files appear inline in chat at the time they were uploaded
  • Images show thumbnails with click-to-expand preview
  • AI reports include file context with surrounding messages
  • All timestamps display in GMT+8

Non-Goals

  • Drag-and-drop upload (future enhancement)
  • Video file preview (out of scope)
  • File editing/annotation

Decisions

  • Add message_id column to tr_room_files table
  • When file is uploaded, create an image_ref or file_ref message
  • Store the message_id in the file record
  • Allows bidirectional lookup

Decision 2: Image thumbnail generation

  • Option A: Generate thumbnails server-side on upload (MinIO)
  • Option B: Use MinIO presigned URL with CSS resize on frontend
  • Chosen: Option B - simpler, no additional storage needed, modern browsers handle resizing well

Decision 3: File message format

{
  "message_type": "image_ref",
  "content": "optional caption from user",
  "message_metadata": {
    "file_id": "uuid",
    "filename": "defect.jpg",
    "file_type": "image",
    "mime_type": "image/jpeg",
    "file_size": 2621440,
    "thumbnail_url": "presigned-url",
    "download_url": "presigned-url"
  }
}

Decision 4: Lightbox implementation

  • Use a simple modal-based image viewer
  • Support keyboard navigation (ESC to close)
  • Show loading state while image loads

Decision 5: AI Report file context

  • When collecting data, include the message content and surrounding 2 messages for each file
  • Format: [附件: filename.ext] - 上傳者: display_name, 說明: "{message_content}"

Risks / Trade-offs

Risk Mitigation
Large images slow down chat Use lazy loading, thumbnails
Existing files have no message Migration script to create messages for orphan files
Presigned URLs expire Frontend refreshes URLs on load

Migration Plan

  1. Add message_id column to tr_room_files (nullable)
  2. Create migration script to generate messages for existing files
  3. Update upload API to create message + file atomically
  4. Deploy backend changes
  5. Deploy frontend with inline file display
  6. Verify existing files display correctly

Open Questions

  • Should file deletion also delete the associated message? (Proposed: Yes, soft delete both)