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>
2.6 KiB
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
Decision 1: Link files to messages via foreign key
- Add
message_idcolumn totr_room_filestable - When file is uploaded, create an
image_reforfile_refmessage - 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
- Add
message_idcolumn totr_room_files(nullable) - Create migration script to generate messages for existing files
- Update upload API to create message + file atomically
- Deploy backend changes
- Deploy frontend with inline file display
- Verify existing files display correctly
Open Questions
- Should file deletion also delete the associated message? (Proposed: Yes, soft delete both)