From 20113b3f0eb081523ceaa5a33f9986fdb98ca2a7 Mon Sep 17 00:00:00 2001 From: Samir Kamal <1954121+skamril@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:43:35 +0200 Subject: [PATCH] feat(ui-debug): allow to delete file --- .../Singlestudy/explore/Debug/Data/Folder.tsx | 113 +++++++++++++++--- webapp/src/services/api/studies/raw/index.ts | 15 ++- webapp/src/services/api/studies/raw/types.ts | 5 + 3 files changed, 118 insertions(+), 15 deletions(-) diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx index c565a6a682..4de47da44b 100644 --- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx +++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx @@ -1,12 +1,18 @@ import { Divider, + IconButton, List, + ListItem, ListItemButton, ListItemIcon, ListItemText, ListSubheader, + Menu, + MenuItem, } from "@mui/material"; import FolderIcon from "@mui/icons-material/Folder"; +import MoreVertIcon from "@mui/icons-material/MoreVert"; +import DeleteIcon from "@mui/icons-material/Delete"; import { getFileIcon, getFileType, @@ -14,13 +20,16 @@ import { type DataCompProps, isFolder, } from "../utils"; -import { Fragment } from "react"; +import { Fragment, useState } from "react"; import EmptyView from "../../../../../common/page/SimpleContent"; import { useTranslation } from "react-i18next"; import { Filename, Menubar } from "./styles"; import UploadFileButton from "../../../../../common/buttons/UploadFileButton"; import ConfirmationDialog from "../../../../../common/dialogs/ConfirmationDialog"; import useConfirm from "../../../../../../hooks/useConfirm"; +import { deleteFile } from "../../../../../../services/api/studies/raw"; +import useEnqueueErrorSnackbar from "../../../../../../hooks/useEnqueueErrorSnackbar"; +import { toError } from "../../../../../../utils/fnUtils"; function Folder(props: DataCompProps) { const { @@ -35,6 +44,13 @@ function Folder(props: DataCompProps) { const { t } = useTranslation(); const replaceFile = useConfirm(); + const removeFile = useConfirm(); + const [menuData, setMenuData] = useState(null); + const enqueueErrorSnackbar = useEnqueueErrorSnackbar(); + const treeFolder = treeData as TreeFolder; const list = Object.entries(treeFolder); @@ -53,6 +69,27 @@ function Folder(props: DataCompProps) { } }; + const handleMenuClose = () => { + setMenuData(null); + }; + + const handleDeleteClick = () => { + handleMenuClose(); + + removeFile.showConfirm().then((confirm) => { + const filePath = menuData?.filePath; + if (confirm && filePath) { + deleteFile({ studyId, path: filePath }) + .then((res) => { + reloadTreeData(); + }) + .catch((err) => { + enqueueErrorSnackbar("Delete failed", toError(err)); + }); + } + }); + }; + //////////////////////////////////////////////////////////////// // JSX //////////////////////////////////////////////////////////////// @@ -94,21 +131,45 @@ function Folder(props: DataCompProps) { return ( - - setSelectedFile({ - fileType, - filename, - filePath: `${filePath}/${filename}`, - treeData: data, - }) + { + setMenuData({ + anchorEl: event.currentTarget, + filePath: `${filePath}/${filename}`, + }); + }} + > + + } + disablePadding > - - - - - + + setSelectedFile({ + fileType, + filename, + filePath: `${filePath}/${filename}`, + treeData: data, + }) + } + > + + + + + + {!isLast && } ); @@ -117,6 +178,18 @@ function Folder(props: DataCompProps) { )} + {/* Items menu */} + + + + Delete + + + {/* Confim file replacement */} {t("study.debug.folder.upload.replaceFileConfirm.message")} + {/* Confim file deletion */} + + Delete the file? + ); } diff --git a/webapp/src/services/api/studies/raw/index.ts b/webapp/src/services/api/studies/raw/index.ts index f7350f1015..35240f1e39 100644 --- a/webapp/src/services/api/studies/raw/index.ts +++ b/webapp/src/services/api/studies/raw/index.ts @@ -1,9 +1,14 @@ import client from "../../client"; -import type { DownloadMatrixParams, ImportFileParams } from "./types"; +import type { + DeleteFileParams, + DownloadMatrixParams, + ImportFileParams, +} from "./types"; export async function downloadMatrix(params: DownloadMatrixParams) { const { studyId, ...queryParams } = params; const url = `v1/studies/${studyId}/raw/download`; + const res = await client.get(url, { params: queryParams, responseType: "blob", @@ -16,6 +21,7 @@ export async function importFile(params: ImportFileParams) { const { studyId, file, onUploadProgress, ...queryParams } = params; const url = `v1/studies/${studyId}/raw`; const body = { file }; + await client.putForm(url, body, { params: { ...queryParams, @@ -24,3 +30,10 @@ export async function importFile(params: ImportFileParams) { onUploadProgress, }); } + +export async function deleteFile(params: DeleteFileParams) { + const { studyId, path } = params; + const url = `v1/studies/${studyId}/raw`; + + await client.delete(url, { params: { path } }); +} diff --git a/webapp/src/services/api/studies/raw/types.ts b/webapp/src/services/api/studies/raw/types.ts index 2c62844115..a6a6a251be 100644 --- a/webapp/src/services/api/studies/raw/types.ts +++ b/webapp/src/services/api/studies/raw/types.ts @@ -16,3 +16,8 @@ export interface ImportFileParams { createMissing?: boolean; onUploadProgress?: AxiosRequestConfig["onUploadProgress"]; } + +export interface DeleteFileParams { + studyId: StudyMetadata["id"]; + path: string; +}