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>
74 lines
2.6 KiB
Markdown
74 lines
2.6 KiB
Markdown
# 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_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
|
|
```json
|
|
{
|
|
"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)
|