👔(frontend) integrate attachment-upload endpoint

Integrate the `documents/${docId}/attachment-upload/`
endpoint. This endpoint is used to upload attachments
to a document.
To have automatically the good content-type form-data,
the `fetchApi` function has been updated to remove the
prefill `Content-Type` header.
This commit is contained in:
Anthony LC
2024-08-29 16:32:16 +02:00
committed by Anthony LC
parent 3a3483b776
commit 3eb8f88b5c
4 changed files with 66 additions and 17 deletions

View File

@@ -1,34 +1,33 @@
import { baseApiUrl, useAuthStore } from '@/core';
/**
* Retrieves the CSRF token from the document's cookies.
*
* @returns {string|null} The CSRF token if found in the cookies, or null if not present.
*/
function getCSRFToken() {
return document.cookie
.split(';')
.filter((cookie) => cookie.trim().startsWith('csrftoken='))
.map((cookie) => cookie.split('=')[1])
.pop();
import { getCSRFToken } from './utils';
interface FetchAPIInit extends RequestInit {
withoutContentType?: boolean;
}
export const fetchAPI = async (
input: string,
init?: RequestInit,
init?: FetchAPIInit,
apiVersion = '1.0',
) => {
const apiUrl = `${baseApiUrl(apiVersion)}${input}`;
const csrfToken = getCSRFToken();
const headers = {
'Content-Type': 'application/json',
...init?.headers,
...(csrfToken && { 'X-CSRFToken': csrfToken }),
};
if (init?.withoutContentType) {
delete headers?.['Content-Type' as keyof typeof headers];
}
const response = await fetch(apiUrl, {
...init,
credentials: 'include',
headers: {
...init?.headers,
'Content-Type': 'application/json',
...(csrfToken && { 'X-CSRFToken': csrfToken }),
},
headers,
});
if (response.status === 401) {

View File

@@ -16,3 +16,14 @@ export const errorCauses = async (response: Response, data?: unknown) => {
data,
};
};
/**
* Retrieves the CSRF token from the document's cookies.
*/
export function getCSRFToken() {
return document.cookie
.split(';')
.filter((cookie) => cookie.trim().startsWith('csrftoken='))
.map((cookie) => cookie.split('=')[1])
.pop();
}

View File

@@ -0,0 +1,36 @@
import { useMutation } from '@tanstack/react-query';
import { APIError, errorCauses, fetchAPI } from '@/api';
import { DocAttachment } from '../types';
interface CreateDocAttachment {
docId: string;
body: FormData;
}
export const createDocAttachment = async ({
docId,
body,
}: CreateDocAttachment): Promise<DocAttachment> => {
const response = await fetchAPI(`documents/${docId}/attachment-upload/`, {
method: 'POST',
body,
withoutContentType: true,
});
if (!response.ok) {
throw new APIError(
'Failed to upload on the doc',
await errorCauses(response),
);
}
return response.json() as Promise<DocAttachment>;
};
export function useCreateDocAttachment() {
return useMutation<DocAttachment, APIError, CreateDocAttachment>({
mutationFn: createDocAttachment,
});
}

View File

@@ -0,0 +1,3 @@
export interface DocAttachment {
file: string;
}