feat: message and attachment download
Signed-off-by: Sebastian <krupinski01@gmail.com>
This commit is contained in:
@@ -1,16 +1,25 @@
|
||||
<script setup lang="ts">
|
||||
import { MessageObject } from '@MailManager/models/message'
|
||||
import { computed } from 'vue'
|
||||
import RecipientDetails from '@/components/common/RecipientDetails.vue'
|
||||
import type { EntityObject } from '@MailManager/models';
|
||||
|
||||
interface Props {
|
||||
message: MessageObject
|
||||
entity: EntityObject | null
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const addressKey = (address: { address?: string | null; label?: string | null } | null | undefined, index: number): string => {
|
||||
return `${address?.address || address?.label || 'address'}-${index}`
|
||||
}
|
||||
const emit = defineEmits<{
|
||||
downloadAttachment: [index: number]
|
||||
}>()
|
||||
|
||||
const message = computed(() => {
|
||||
return props.entity?.properties ?? null
|
||||
})
|
||||
|
||||
const randomKey = computed(() => {
|
||||
return Math.random().toString(36).substring(2, 15)
|
||||
})
|
||||
|
||||
// Format date for display
|
||||
const formatDate = (date: Date | string | null | undefined): string => {
|
||||
@@ -36,6 +45,10 @@ const formatFileSize = (bytes: number | undefined): string => {
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
|
||||
return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
|
||||
}
|
||||
|
||||
const download = async (index: number): Promise<void> => {
|
||||
emit('downloadAttachment', index)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -66,7 +79,7 @@ const formatFileSize = (bytes: number | undefined): string => {
|
||||
<!-- Recipients -->
|
||||
<div v-if="message?.to && message?.to.length > 0" class="text-body-2 mb-1">
|
||||
<span class="text-medium-emphasis">To:</span>
|
||||
<template v-for="(recipient, index) in message.to" :key="addressKey(recipient, index)">
|
||||
<template v-for="(recipient, index) in message.to" :key="randomKey">
|
||||
<RecipientDetails :address="recipient">
|
||||
<template #default="{ label }">
|
||||
<span class="contact-link">{{ label }}</span>
|
||||
@@ -78,7 +91,7 @@ const formatFileSize = (bytes: number | undefined): string => {
|
||||
|
||||
<div v-if="message?.cc && message?.cc.length > 0" class="text-body-2 mb-1">
|
||||
<span class="text-medium-emphasis">Cc:</span>
|
||||
<template v-for="(recipient, index) in message.cc" :key="addressKey(recipient, index)">
|
||||
<template v-for="(recipient, index) in message.cc" :key="randomKey">
|
||||
<RecipientDetails :address="recipient">
|
||||
<template #default="{ label }">
|
||||
<span class="contact-link">{{ label }}</span>
|
||||
@@ -94,19 +107,24 @@ const formatFileSize = (bytes: number | undefined): string => {
|
||||
Attachments ({{ message?.attachments.length }})
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<v-chip
|
||||
<div
|
||||
v-for="(attachment, index) in message?.attachments"
|
||||
:key="index"
|
||||
prepend-icon="mdi-paperclip"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
class="attachment-chip"
|
||||
:key="randomKey"
|
||||
class="attachment-item"
|
||||
>
|
||||
<span class="attachment-name">{{ attachment.name || 'Untitled' }}</span>
|
||||
<span v-if="attachment.size" class="text-caption text-medium-emphasis ml-1">
|
||||
({{ formatFileSize(attachment.size) }})
|
||||
</span>
|
||||
</v-chip>
|
||||
<v-chip
|
||||
prepend-icon="mdi-paperclip"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
class="attachment-chip"
|
||||
@click="download(index)"
|
||||
>
|
||||
<span class="attachment-name">{{ attachment.name || 'Untitled' }}</span>
|
||||
<span v-if="attachment.size" class="text-caption text-medium-emphasis ml-1">
|
||||
({{ formatFileSize(attachment.size ?? undefined) }})
|
||||
</span>
|
||||
</v-chip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -121,8 +139,15 @@ const formatFileSize = (bytes: number | undefined): string => {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.attachment-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.attachment-chip {
|
||||
max-width: 300px;
|
||||
cursor: pointer;
|
||||
|
||||
.attachment-name {
|
||||
overflow: hidden;
|
||||
@@ -131,6 +156,11 @@ const formatFileSize = (bytes: number | undefined): string => {
|
||||
}
|
||||
}
|
||||
|
||||
.attachment-error {
|
||||
color: rgb(var(--v-theme-error));
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.contact-link {
|
||||
display: inline-block;
|
||||
border-radius: 4px;
|
||||
|
||||
Reference in New Issue
Block a user