From 0f2729da8d8a250462c4a34cdab33b4b460d20b5 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Mon, 19 Aug 2024 10:06:40 -0300 Subject: [PATCH] refactor: add use-download-files hook for downloading files on chat (#3399) * feat: add useGetDownloadFileMutation hook for downloading files This commit adds a new hook called useGetDownloadFileMutation to handle the downloading of files in the frontend. The hook takes in the path and filename as parameters and uses the fetch API to download the file. It then creates a URL object for the downloaded file and sets it as the href of a dynamically created anchor element. Finally, it triggers a click event on the anchor element to initiate the file download. The URL object is revoked after the download is complete. * feat: add use-download-files hook for downloading files on chat This commit adds a new hook called use-download-files to handle the downloading of files in the frontend. The hook takes in the path and filename as parameters and uses the fetch API to download the file. It then creates a URL object for the downloaded file and sets it as the href of a dynamically created anchor element. Finally, it triggers a click event on the anchor element to initiate the file download. The URL object is revoked after the download is complete. * [autofix.ci] apply automated fixes * feat: refactor file download handling in chat view Refactor the file download handling in the chat view by introducing a new hook called `use-download-files`. This hook takes in the path and filename as parameters and uses the fetch API to download the file. It creates a URL object for the downloaded file and sets it as the href of a dynamically created anchor element. Finally, it triggers a click event on the anchor element to initiate the file download. The URL object is revoked after the download is complete. * remove console.log --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Cristhian Zanforlin Lousa <72977554+Cristhianzl@users.noreply.github.com> --- .../controllers/API/queries/files/index.ts | 1 + .../API/queries/files/use-download-files.ts | 45 +++++++++++++++++++ .../components/fileCardWrapper/index.tsx | 7 +-- .../chatView/fileComponent/index.tsx | 17 ++++--- .../fileComponent/utils/handle-download.tsx | 41 ----------------- .../IOModal/components/chatView/index.tsx | 1 - src/frontend/src/types/components/index.ts | 2 +- 7 files changed, 58 insertions(+), 56 deletions(-) create mode 100644 src/frontend/src/controllers/API/queries/files/use-download-files.ts delete mode 100644 src/frontend/src/modals/IOModal/components/chatView/fileComponent/utils/handle-download.tsx diff --git a/src/frontend/src/controllers/API/queries/files/index.ts b/src/frontend/src/controllers/API/queries/files/index.ts index 54d5f7070..62533f72f 100644 --- a/src/frontend/src/controllers/API/queries/files/index.ts +++ b/src/frontend/src/controllers/API/queries/files/index.ts @@ -1,3 +1,4 @@ +export * from "./use-download-files"; export * from "./use-get-download-images"; export * from "./use-get-profile-pictures"; export * from "./use-post-upload-file"; diff --git a/src/frontend/src/controllers/API/queries/files/use-download-files.ts b/src/frontend/src/controllers/API/queries/files/use-download-files.ts new file mode 100644 index 000000000..051f76532 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/files/use-download-files.ts @@ -0,0 +1,45 @@ +import { keepPreviousData } from "@tanstack/react-query"; +import { + useMutationFunctionType, + useQueryFunctionType, +} from "../../../../types/api"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +interface DownloadImagesQueryParams { + path: string; + filename: string; +} + +export const useGetDownloadFileMutation: useMutationFunctionType< + DownloadImagesQueryParams +> = (params, options) => { + const { mutate } = UseRequestProcessor(); + + const getDownloadImagesFn = async () => { + if (!params) return; + // need to use fetch because axios convert blob data to string, and this convertion can corrupt the file + const response = await fetch(`${getURL("FILES")}/download/${params.path}`); + const blob = await response.blob(); + const url = URL.createObjectURL(blob); + + const link = document.createElement("a"); + link.href = url; + link.setAttribute("download", params.filename); // Set the filename + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + URL.revokeObjectURL(url); + return {}; + }; + + const queryResult = mutate( + ["useGetDownloadFileMutation", params.path], + getDownloadImagesFn, + options, + ); + + return queryResult; +}; diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatMessage/components/fileCardWrapper/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatMessage/components/fileCardWrapper/index.tsx index e6b4509d0..3a3467b62 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatMessage/components/fileCardWrapper/index.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/chatMessage/components/fileCardWrapper/index.tsx @@ -24,12 +24,7 @@ export default function FileCardWrapper({ {formatFileName(name, 50)} - + ); } diff --git a/src/frontend/src/modals/IOModal/components/chatView/fileComponent/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/fileComponent/index.tsx index 17708aa3f..704d9934c 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/fileComponent/index.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/fileComponent/index.tsx @@ -1,3 +1,4 @@ +import { useGetDownloadFileMutation } from "@/controllers/API/queries/files"; import { useState } from "react"; import { ForwardedIconComponent } from "../../../../../components/genericIconComponent"; import { BACKEND_URL, BASE_URL_API } from "../../../../../constants/constants"; @@ -6,18 +7,20 @@ import { fileCardPropsType } from "../../../../../types/components"; import formatFileName from "../filePreviewChat/utils/format-file-name"; import DownloadButton from "./components/downloadButton/downloadButton"; import getClasses from "./utils/get-classes"; -import handleDownload from "./utils/handle-download"; const imgTypes = new Set(["png", "jpg", "jpeg", "gif", "webp", "image"]); export default function FileCard({ fileName, - content, + path, fileType, showFile = true, }: fileCardPropsType): JSX.Element | undefined { const [isHovered, setIsHovered] = useState(false); - const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId); + const { mutate } = useGetDownloadFileMutation({ + filename: fileName, + path: path, + }); function handleMouseEnter(): void { setIsHovered(true); } @@ -27,7 +30,7 @@ export default function FileCard({ const fileWrapperClasses = getClasses(isHovered); - const imgSrc = `${BASE_URL_API}files/images/${content}`; + const imgSrc = `${BASE_URL_API}files/images/${path}`; if (showFile) { if (imgTypes.has(fileType)) { @@ -46,7 +49,7 @@ export default function FileCard({ /> handleDownload({ fileName, content })} + handleDownload={() => mutate(undefined)} /> @@ -56,7 +59,7 @@ export default function FileCard({ return (
handleDownload({ fileName, content })} + onClick={() => mutate(undefined)} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} > @@ -69,7 +72,7 @@ export default function FileCard({
handleDownload({ fileName, content })} + handleDownload={() => mutate(undefined)} /> ); diff --git a/src/frontend/src/modals/IOModal/components/chatView/fileComponent/utils/handle-download.tsx b/src/frontend/src/modals/IOModal/components/chatView/fileComponent/utils/handle-download.tsx deleted file mode 100644 index 53a9cf770..000000000 --- a/src/frontend/src/modals/IOModal/components/chatView/fileComponent/utils/handle-download.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { - BACKEND_URL, - BASE_URL_API, -} from "../../../../../../constants/constants"; - -let isDownloading = false; - -export default async function handleDownload({ - fileName, - content, -}: { - fileName: string; - content: string; -}): Promise { - if (isDownloading) return; - - try { - isDownloading = true; - - const response = await fetch(`${BASE_URL_API}files/download/${content}`); - if (!response.ok) { - throw new Error("Network response was not ok"); - } - - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - - const link = document.createElement("a"); - link.href = url; - link.setAttribute("download", fileName); // Set the filename - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - - URL.revokeObjectURL(url); // Clean up the URL object - } catch (error) { - console.error("Failed to download file:", error); - } finally { - isDownloading = false; - } -} diff --git a/src/frontend/src/modals/IOModal/components/chatView/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/index.tsx index 5e0b2d4fd..fd6bb270a 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/index.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/index.tsx @@ -80,7 +80,6 @@ export default function ChatView({ const is_ai = sender === "Machine" || sender === null || sender === undefined; - return { isSend: !is_ai, message, diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 632b24d1b..ddd5a2a48 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -617,7 +617,7 @@ export interface Props { export type fileCardPropsType = { fileName: string; - content: string; + path: string; fileType: string; showFile?: boolean; };