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

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)