email server updates
This commit is contained in:
@@ -5,15 +5,13 @@
|
||||
Email History
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
:icon="mobile ? undefined : 'mdi-refresh'"
|
||||
:size="mobile ? 'default' : 'small'"
|
||||
icon="mdi-refresh"
|
||||
:size="mobile ? 'small' : 'small'"
|
||||
variant="text"
|
||||
@click="loadEmails"
|
||||
:loading="loading"
|
||||
:class="mobile ? 'rounded-circle' : ''"
|
||||
>
|
||||
<v-icon v-if="!loading">mdi-refresh</v-icon>
|
||||
<v-tooltip v-if="mobile" activator="parent" location="bottom">
|
||||
<v-tooltip activator="parent" location="bottom">
|
||||
Refresh emails
|
||||
</v-tooltip>
|
||||
</v-btn>
|
||||
@@ -95,6 +93,34 @@
|
||||
Show less
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Attachments Section -->
|
||||
<div v-if="email.attachments && email.attachments.length > 0" class="mt-3">
|
||||
<v-divider class="mb-2" />
|
||||
<div class="text-caption text-grey mb-2">
|
||||
<v-icon size="small" class="mr-1">mdi-paperclip</v-icon>
|
||||
{{ email.attachments.length }} Attachment{{ email.attachments.length > 1 ? 's' : '' }}
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<v-chip
|
||||
v-for="(attachment, index) in email.attachments"
|
||||
:key="index"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
:prepend-icon="getAttachmentIcon(attachment.contentType)"
|
||||
@click="downloadAttachment(attachment)"
|
||||
:disabled="!!attachment.error"
|
||||
>
|
||||
<span class="text-truncate" style="max-width: 150px">
|
||||
{{ attachment.filename }}
|
||||
</span>
|
||||
<span class="text-caption ml-1">({{ formatFileSize(attachment.size) }})</span>
|
||||
<v-tooltip v-if="attachment.error" activator="parent">
|
||||
{{ attachment.error }}
|
||||
</v-tooltip>
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
@@ -136,6 +162,16 @@ interface EmailMessage {
|
||||
timestamp: string;
|
||||
direction: 'sent' | 'received';
|
||||
threadId?: string;
|
||||
attachments?: Array<{
|
||||
id?: string;
|
||||
filename: string;
|
||||
originalName?: string;
|
||||
contentType: string;
|
||||
size: number;
|
||||
path?: string;
|
||||
bucket?: string;
|
||||
error?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface EmailThread {
|
||||
@@ -269,6 +305,57 @@ const reloadEmails = () => {
|
||||
loadEmails();
|
||||
};
|
||||
|
||||
// Get icon for attachment based on content type
|
||||
const getAttachmentIcon = (contentType: string) => {
|
||||
if (!contentType) return 'mdi-file';
|
||||
|
||||
if (contentType.startsWith('image/')) return 'mdi-file-image';
|
||||
if (contentType.startsWith('video/')) return 'mdi-file-video';
|
||||
if (contentType.startsWith('audio/')) return 'mdi-file-music';
|
||||
if (contentType.includes('pdf')) return 'mdi-file-pdf-box';
|
||||
if (contentType.includes('word') || contentType.includes('document')) return 'mdi-file-word';
|
||||
if (contentType.includes('sheet') || contentType.includes('excel')) return 'mdi-file-excel';
|
||||
if (contentType.includes('powerpoint') || contentType.includes('presentation')) return 'mdi-file-powerpoint';
|
||||
if (contentType.includes('zip') || contentType.includes('compressed')) return 'mdi-folder-zip';
|
||||
|
||||
return 'mdi-file';
|
||||
};
|
||||
|
||||
// Format file size for display
|
||||
const formatFileSize = (bytes: number) => {
|
||||
if (!bytes || bytes === 0) return '0 B';
|
||||
|
||||
const units = ['B', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||
|
||||
return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${units[i]}`;
|
||||
};
|
||||
|
||||
// Download attachment
|
||||
const downloadAttachment = async (attachment: any) => {
|
||||
if (!attachment.path || !attachment.bucket) {
|
||||
toast.error('Attachment information is missing');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Use the proxy download endpoint
|
||||
const downloadUrl = `/api/files/proxy-download?bucket=${attachment.bucket}&fileName=${encodeURIComponent(attachment.path)}`;
|
||||
|
||||
// Create a temporary link and trigger download
|
||||
const link = document.createElement('a');
|
||||
link.href = downloadUrl;
|
||||
link.download = attachment.originalName || attachment.filename;
|
||||
link.target = '_blank';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
} catch (error) {
|
||||
console.error('Failed to download attachment:', error);
|
||||
toast.error('Failed to download attachment');
|
||||
}
|
||||
};
|
||||
|
||||
// Load emails on mount
|
||||
onMounted(() => {
|
||||
loadEmails();
|
||||
|
||||
Reference in New Issue
Block a user