diff --git a/frontend/components/Item/AttachmentsList.vue b/frontend/components/Item/AttachmentsList.vue
index f215256..1dd8855 100644
--- a/frontend/components/Item/AttachmentsList.vue
+++ b/frontend/components/Item/AttachmentsList.vue
@@ -10,7 +10,12 @@
{{ attachment.document.title }}
@@ -31,26 +36,12 @@
});
const api = useUserApi();
- const toast = useNotifier();
- async function getAttachmentUrl(attachment: ItemAttachment) {
- const url = await api.items.getAttachmentUrl(props.itemId, attachment.id);
- if (!url) {
- toast.error("Failed to get attachment url");
- return;
- }
-
- if (!document) {
- window.open(url, "_blank");
- return;
- }
-
- const link = document.createElement("a");
- link.href = url;
- link.target = "_blank";
- link.setAttribute("download", attachment.document.title);
- link.click();
+ function attachmentURL(attachmentId : string) {
+ return api.authURL(`/items/${props.itemId}/attachments/${attachmentId}`);
}
+
+
diff --git a/frontend/composables/use-api.ts b/frontend/composables/use-api.ts
index 69da2ed..cd06588 100644
--- a/frontend/composables/use-api.ts
+++ b/frontend/composables/use-api.ts
@@ -43,5 +43,5 @@ export function useUserApi(): UserClient {
requests.addResponseInterceptor(observer.handler);
}
- return new UserClient(requests);
+ return new UserClient(requests, authStore.attachmentToken);
}
diff --git a/frontend/lib/api/base/base-api.ts b/frontend/lib/api/base/base-api.ts
index b48d10b..bef9326 100644
--- a/frontend/lib/api/base/base-api.ts
+++ b/frontend/lib/api/base/base-api.ts
@@ -27,9 +27,21 @@ export function parseDate(obj: T, keys: Array = []): T {
export class BaseAPI {
http: Requests;
+ attachmentToken: string
- constructor(requests: Requests) {
+ constructor(requests: Requests, attachmentToken: string = "") {
this.http = requests;
+ this.attachmentToken = attachmentToken;
+ }
+
+ // if a attachmentToken is present it will be added to URL as a query param
+ // this is done with a simple appending of the query param to the URL. If your
+ // URL already has a query param, this will not work.
+ authURL(url: string): string {
+ if (this.attachmentToken) {
+ return `/api/v1${url}?access_token=${this.attachmentToken}`;
+ }
+ return url;
}
/**
diff --git a/frontend/lib/api/classes/items.ts b/frontend/lib/api/classes/items.ts
index a97152d..2d6cce7 100644
--- a/frontend/lib/api/classes/items.ts
+++ b/frontend/lib/api/classes/items.ts
@@ -1,7 +1,6 @@
import { BaseAPI, route } from "../base";
import { parseDate } from "../base/base-api";
import {
- ItemAttachmentToken,
ItemAttachmentUpdate,
ItemCreate,
ItemOut,
@@ -79,18 +78,6 @@ export class ItemsApi extends BaseAPI {
});
}
- async getAttachmentUrl(id: string, attachmentId: string): Promise {
- const payload = await this.http.get({
- url: route(`/items/${id}/attachments/${attachmentId}`),
- });
-
- if (!payload.data) {
- return "";
- }
-
- return route(`/items/${id}/attachments/download`, { token: payload.data.token });
- }
-
async deleteAttachment(id: string, attachmentId: string) {
return await this.http.delete({ url: route(`/items/${id}/attachments/${attachmentId}`) });
}
diff --git a/frontend/lib/api/types/data-contracts.ts b/frontend/lib/api/types/data-contracts.ts
index 9829f14..464b8e7 100644
--- a/frontend/lib/api/types/data-contracts.ts
+++ b/frontend/lib/api/types/data-contracts.ts
@@ -324,6 +324,7 @@ export interface ItemAttachmentToken {
}
export interface TokenResponse {
+ attachmentToken: string;
expiresAt: Date;
token: string;
}
diff --git a/frontend/lib/api/user.ts b/frontend/lib/api/user.ts
index 5c4940f..31538a8 100644
--- a/frontend/lib/api/user.ts
+++ b/frontend/lib/api/user.ts
@@ -15,8 +15,8 @@ export class UserClient extends BaseAPI {
user: UserApi;
actions: ActionsAPI;
- constructor(requests: Requests) {
- super(requests);
+ constructor(requests: Requests, attachmentToken: string) {
+ super(requests, attachmentToken);
this.locations = new LocationsApi(requests);
this.labels = new LabelsApi(requests);
diff --git a/frontend/pages/index.vue b/frontend/pages/index.vue
index 44183c6..070fa05 100644
--- a/frontend/pages/index.vue
+++ b/frontend/pages/index.vue
@@ -105,6 +105,7 @@
authStore.$patch({
token: data.token,
expires: data.expiresAt,
+ attachmentToken: data.attachmentToken,
});
navigateTo("/home");
diff --git a/frontend/pages/item/[id]/index.vue b/frontend/pages/item/[id]/index.vue
index e3d6afb..b003023 100644
--- a/frontend/pages/item/[id]/index.vue
+++ b/frontend/pages/item/[id]/index.vue
@@ -27,17 +27,30 @@
});
type FilteredAttachments = {
- photos: ItemAttachment[];
attachments: ItemAttachment[];
warranty: ItemAttachment[];
manuals: ItemAttachment[];
receipts: ItemAttachment[];
};
+ type Photo = {
+ src: string;
+ }
+
+ const photos = computed(() => {
+ return item.value?.attachments.reduce((acc, cur) => {
+ if (cur.type === "photo") {
+ acc.push({
+ src: api.authURL(`/items/${item.value.id}/attachments/${cur.id}`),
+ })
+ }
+ return acc;
+ }, [] as Photo[]) || [];
+ });
+
const attachments = computed(() => {
if (!item.value) {
return {
- photos: [],
attachments: [],
manuals: [],
warranty: [],
@@ -48,8 +61,9 @@
return item.value.attachments.reduce(
(acc, attachment) => {
if (attachment.type === "photo") {
- acc.photos.push(attachment);
- } else if (attachment.type === "warranty") {
+ return acc;
+ }
+ if (attachment.type === "warranty") {
acc.warranty.push(attachment);
} else if (attachment.type === "manual") {
acc.manuals.push(attachment);
@@ -61,7 +75,6 @@
return acc;
},
{
- photos: [] as ItemAttachment[],
attachments: [] as ItemAttachment[],
warranty: [] as ItemAttachment[],
manuals: [] as ItemAttachment[],
@@ -144,7 +157,6 @@
}
return (
- attachments.value.photos.length > 0 ||
attachments.value.attachments.length > 0 ||
attachments.value.warranty.length > 0 ||
attachments.value.manuals.length > 0 ||
@@ -163,10 +175,6 @@
});
};
- if (attachments.value.photos.length > 0) {
- push("Photos");
- }
-
if (attachments.value.attachments.length > 0) {
push("Attachments");
}
@@ -292,10 +300,51 @@
toast.success("Item deleted");
navigateTo("/home");
}
+
+ const refDialog = ref();
+ const dialoged = reactive({
+ src: "",
+ })
+
+ function openDialog(img: Photo) {
+ refDialog.value.showModal();
+ dialoged.src = img.src;
+ }
+
+ function closeDialog() {
+ refDialog.value.close();
+ }
+
+ const refDialogBody = ref();
+ onClickOutside(refDialogBody, () => {
+ closeDialog();
+ });
+
+
+
+
@@ -353,6 +402,15 @@
+
+ Photos
+
+
+
Attachments
@@ -377,13 +435,6 @@
:item-id="item.id"
/>
-
-
-
({
token: useLocalStorage("pinia/auth/token", ""),
+ attachmentToken: useLocalStorage("pinia/auth/attachmentToken", ""),
expires: useLocalStorage("pinia/auth/expires", ""),
self: null as UserOut | null,
}),
@@ -27,6 +28,7 @@ export const useAuthStore = defineStore("auth", {
const result = await api.user.logout();
this.token = "";
+ this.attachmentToken = "";
this.expires = "";
this.self = null;