Spaces:
Sleeping
Sleeping
File size: 3,498 Bytes
e5f65c7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | # Ticket Comment Attachments - Frontend Guide
## What We Built
Comments now support image and document attachments. The API returns enriched attachment data so you don't need extra calls.
## Upload Flow
### 1. Upload File First
```http
POST /api/v1/documents/upload
Content-Type: multipart/form-data
file: <binary>
entity_type: "ticket"
entity_id: "ticket-uuid"
document_type: "comment_attachment"
document_category: "operational"
```
**Response:**
```json
{
"id": "doc-uuid",
"file_name": "photo.jpg",
"file_url": "https://storage.../photo.jpg"
}
```
### 2. Create Comment with Attachment
```http
POST /api/v1/tickets/{ticket_id}/comments
{
"comment_text": "Found this issue",
"is_internal": true,
"comment_type": "issue",
"attachment_document_ids": ["doc-uuid"]
}
```
## Response Structure
```json
{
"id": "comment-uuid",
"comment_text": "Found this issue",
"attachment_document_ids": ["doc-uuid"],
"attachments": [
{
"id": "doc-uuid",
"file_name": "photo.jpg",
"file_type": "image/jpeg",
"file_url": "https://storage.../photo.jpg",
"file_size": 245678,
"is_image": true
}
]
}
```
## Key Fields
- `attachment_document_ids`: Array of document UUIDs
- `attachments`: Full attachment details (auto-populated)
- `attachments[].is_image`: Boolean flag - use this to filter images vs other files
- `attachments[].file_url`: Direct URL - ready to use in `<img>` or download links
## Multiple Attachments
```json
{
"comment_text": "Before and after photos",
"attachment_document_ids": ["doc-1", "doc-2", "doc-3"]
}
```
All attachments returned in `attachments` array.
## Mobile Example (React Native)
```typescript
// Upload image
const formData = new FormData();
formData.append('file', {
uri: photo.uri,
type: 'image/jpeg',
name: 'photo.jpg'
});
formData.append('entity_type', 'ticket');
formData.append('entity_id', ticketId);
formData.append('document_type', 'comment_attachment');
const uploadRes = await api.post('/documents/upload', formData);
// Create comment
await api.post(`/tickets/${ticketId}/comments`, {
comment_text: "Found damaged cable",
is_internal: true,
comment_type: "issue",
attachment_document_ids: [uploadRes.data.id]
});
```
## Web Example (React)
```typescript
// Upload file
const formData = new FormData();
formData.append('file', file);
formData.append('entity_type', 'ticket');
formData.append('entity_id', ticketId);
formData.append('document_type', 'comment_attachment');
const uploadRes = await api.post('/documents/upload', formData);
// Create comment
await api.post(`/tickets/${ticketId}/comments`, {
comment_text: "See attached diagram",
is_internal: true,
comment_type: "resolution",
attachment_document_ids: [uploadRes.data.id]
});
```
## Display Logic
```typescript
// Separate images from other files
const images = comment.attachments.filter(a => a.is_image);
const files = comment.attachments.filter(a => !a.is_image);
// Render images
images.forEach(img => {
// <img src={img.file_url} alt={img.file_name} />
});
// Render file links
files.forEach(file => {
// <a href={file.file_url} download={file.file_name}>{file.file_name}</a>
});
```
## Notes
- Upload files BEFORE creating comment
- Max file size and allowed types handled by `/documents/upload` endpoint
- Images auto-detected via MIME type (`image/*`)
- File URLs are permanent and CDN-backed
- No need to fetch attachment details separately - included in comment response
|