Skip to content

Commit 9903686

Browse files
authored
Merge pull request #140 from buggregator/feature/smtp-attachments-api
Refactors SMTP attachments fetching from HTTP endpoint
2 parents efc9caf + 9274020 commit 9903686

File tree

9 files changed

+105
-24
lines changed

9 files changed

+105
-24
lines changed

pages/smtp/[id].vue

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useSmtp } from "~/src/entities/smtp";
77
import type { SMTP } from "~/src/entities/smtp/types";
88
import { REST_API_URL } from "~/src/shared/lib/io";
99
import { useEvents } from "~/src/shared/lib/use-events";
10-
import type { EventId, ServerEvent } from "~/src/shared/types";
10+
import type { Attachment, EventId, ServerEvent } from "~/src/shared/types";
1111
1212
const { normalizeSmtpEvent } = useSmtp();
1313
@@ -21,16 +21,19 @@ useHead({
2121
});
2222
2323
const { events } = useEvents();
24-
24+
const { smtp } = useSmtp();
2525
const isLoading = ref(false);
2626
const serverEvent = ref<Event | null>(null);
27+
const serverAttachments = ref<Attachment[]>([]);
2728
2829
const event = computed(() =>
2930
serverEvent.value
3031
? normalizeSmtpEvent(serverEvent.value as unknown as ServerEvent<SMTP>)
3132
: null
3233
);
3334
35+
const attachments = computed(() => serverAttachments.value);
36+
3437
const html = computed(
3538
() => `<iframe src="${REST_API_URL}/api/smtp/${eventId}/html"/>`
3639
);
@@ -57,6 +60,11 @@ const getEvent = async () => {
5760
router.push("/404");
5861
},
5962
});
63+
64+
await smtp.getAttachments(eventId)
65+
.then((attachments: Attachment[]) => {
66+
serverAttachments.value = attachments;
67+
});
6068
};
6169
6270
onMounted(getEvent);
@@ -81,7 +89,11 @@ onMounted(getEvent);
8189
</div>
8290

8391
<div class="smtp-event__body">
84-
<SmtpPage v-if="event" :event="event" :html-source="html" />
92+
<SmtpPage v-if="event"
93+
:event="event"
94+
:attachments="attachments"
95+
:html-source="html"
96+
/>
8597
</div>
8698
</main>
8799
</template>

src/entities/smtp/lib/use-smtp.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import type { ServerEvent, NormalizedEvent } from '~/src/shared/types';
22
import type { SMTP } from "../types";
33
import { normalizeSmtpEvent } from "./normalize-smtp-event";
4+
import { type TUseSmtpApi, useSmtpApi } from "~/src/shared/lib/use-smtp";
45

56
type TUseSmtp = () => {
67
normalizeSmtpEvent: (event: ServerEvent<SMTP>) => NormalizedEvent<SMTP>
8+
smtp: TUseSmtpApi
79
}
810

9-
export const useSmtp: TUseSmtp = () => ({
10-
normalizeSmtpEvent
11-
})
11+
export const useSmtp: TUseSmtp = () => {
12+
return {
13+
normalizeSmtpEvent,
14+
smtp: useSmtpApi()
15+
}
16+
}

src/screens/smtp/ui/smtp-page/smtp-page.vue

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ import { SmtpPagePreview } from "../smtp-page-preview";
1515
1616
type Props = {
1717
event: NormalizedEvent<SMTP>;
18+
attachments: Attachment[];
1819
htmlSource: string;
1920
};
2021
21-
const props = defineProps<Props>();
22+
const props = withDefaults(defineProps<Props>(), {
23+
attachments: [],
24+
});
2225
2326
const htmlSource = ref(props.htmlSource || props.event.payload.html);
2427
@@ -60,12 +63,6 @@ const mail = computed(() => props.event.payload);
6063
const date = computed(() =>
6164
moment(props.event.date).format("DD.MM.YYYY HH:mm:ss")
6265
);
63-
64-
const attachments = computed(() =>
65-
Array.isArray(props.event.payload.attachments)
66-
? props.event.payload.attachments
67-
: (Object.values(props.event.payload.attachments || {}) as Attachment[])
68-
);
6966
</script>
7067

7168
<template>
@@ -108,7 +105,7 @@ const attachments = computed(() =>
108105
suffix="<span class='smtp-page__body-tab-badge'>HTML</span>"
109106
>
110107
<SmtpPagePreview device="tablet">
111-
<div v-html="htmlSource" />
108+
<div v-html="htmlSource"/>
112109
</SmtpPagePreview>
113110
</Tab>
114111
<Tab v-if="isHtml" name="HTML">
@@ -127,14 +124,13 @@ const attachments = computed(() =>
127124
</Tab>
128125
<Tab
129126
v-if="attachments.length"
130-
name="Attachments"
131-
:suffix="`<span class='smtp-page__body-tab-badge'>${attachments.length}</span>`"
127+
:name="`Attachments (${attachments.length})`"
132128
>
133129
<section class="mb-5">
134130
<div class="flex gap-x-3">
135131
<FileAttachment
136132
v-for="a in attachments"
137-
:key="a.id"
133+
:key="a.uuid"
138134
:event-id="event.id"
139135
:event="event"
140136
:attachment="a"
@@ -143,7 +139,7 @@ const attachments = computed(() =>
143139
</section>
144140
</Tab>
145141
<Tab name="Raw">
146-
<CodeSnippet language="html" :code="event.payload.raw" />
142+
<CodeSnippet language="html" :code="event.payload.raw"/>
147143
</Tab>
148144
<Tab name="Tech Info">
149145
<section>
@@ -156,22 +152,22 @@ const attachments = computed(() =>
156152
{{ event.payload.subject }}
157153
</TableBaseRow>
158154
<TableBaseRow title="From">
159-
<SmtpPageAddresses :addresses="event.payload.from" />
155+
<SmtpPageAddresses :addresses="event.payload.from"/>
160156
</TableBaseRow>
161157
<TableBaseRow title="To">
162-
<SmtpPageAddresses :addresses="event.payload.to" />
158+
<SmtpPageAddresses :addresses="event.payload.to"/>
163159
</TableBaseRow>
164160
<TableBaseRow v-if="event.payload.cc.length" title="Cc">
165-
<SmtpPageAddresses :addresses="event.payload.cc" />
161+
<SmtpPageAddresses :addresses="event.payload.cc"/>
166162
</TableBaseRow>
167163
<TableBaseRow v-if="event.payload.bcc.length" title="Bcc">
168-
<SmtpPageAddresses :addresses="event.payload.bcc" />
164+
<SmtpPageAddresses :addresses="event.payload.bcc"/>
169165
</TableBaseRow>
170166
<TableBaseRow
171167
v-if="event.payload.reply_to.length"
172168
title="Reply to"
173169
>
174-
<SmtpPageAddresses :addresses="event.payload.reply_to" />
170+
<SmtpPageAddresses :addresses="event.payload.reply_to"/>
175171
</TableBaseRow>
176172
</TableBase>
177173
</section>

src/shared/lib/io/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './constants';
22
export * from './types';
33
export * from './use-events-requests';
4+
export * from './use-smtp-requests';
45
export * from './logger';
56
export * from './centrifuge';
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Attachment, EventId } from "../../types";
2+
import { type NuxtApp, useNuxtApp } from "#app"; // eslint-disable-line @conarti/feature-sliced/layers-slices
3+
import { REST_API_URL } from "./constants";
4+
5+
type TUseSmtpRequests = () => {
6+
getAttachments: (id: EventId) => Promise<Attachment[]>
7+
}
8+
9+
// TODO: add 403 response handling
10+
11+
export const useSmtpRequests: TUseSmtpRequests = () => {
12+
13+
const app: NuxtApp = useNuxtApp()
14+
const { token } = app.$authToken ?? { token: null }
15+
const headers = { "X-Auth-Token": token || '' }
16+
17+
const getAttachmentsRestUrl = (id: EventId): string => `${REST_API_URL}/api/smtp/${id}/attachments`
18+
19+
const getAttachments = (id: EventId) => fetch(getAttachmentsRestUrl(id), { headers })
20+
.then((response) => response.json())
21+
.then((response) => {
22+
if (response?.data) {
23+
return response.data as Attachment[]
24+
}
25+
26+
if (response?.code === 403) {
27+
console.error('Forbidden')
28+
return [];
29+
}
30+
31+
console.error('Fetch Error')
32+
33+
return [];
34+
})
35+
.then((attachments: Attachment[]) => attachments)
36+
37+
return {
38+
getAttachmentsRestUrl,
39+
getAttachments
40+
}
41+
}

src/shared/lib/use-smtp/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./use-smtp-api";
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { Attachment, EventId } from '../../types';
2+
import { useSmtpRequests } from "../io";
3+
4+
export type TUseSmtpApi = {
5+
getAttachments: (id: EventId) => Promise<Attachment[]>
6+
}
7+
8+
export const useSmtpApi: TUseSmtpApi = () => {
9+
const {
10+
getAttachments
11+
} = useSmtpRequests()
12+
13+
return {
14+
getAttachments
15+
}
16+
}

src/shared/types/events.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export enum EVENT_TYPES {
1414
}
1515

1616
export type EventId = string;
17+
export type Uuid = string;
1718

1819
export type EventType = OneOfValues<typeof EVENT_TYPES>;
1920

@@ -35,3 +36,11 @@ export interface NormalizedEvent<T> {
3536
date: Date | null,
3637
payload: T
3738
}
39+
40+
export interface Attachment {
41+
uuid: Uuid,
42+
name: string,
43+
path: string,
44+
size: number,
45+
mime: string,
46+
}

src/shared/ui/file-attachment/file-attachment.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const props = defineProps<Props>();
1515
const size = computed(() => formatFileSize(props.attachment.size || 0));
1616
const downloadUrl = computed(
1717
() =>
18-
`${REST_API_URL}/api/smtp/${props.eventId}/attachment/${props.attachment.id}`
18+
`${REST_API_URL}/api/smtp/${props.eventId}/attachments/${props.attachment.uuid}`
1919
);
2020
</script>
2121

0 commit comments

Comments
 (0)