import { useSignal } from '@preact/signals'; import { Directory, DirectoryFile } from '/lib/types.ts'; import { ResponseBody as UploadResponseBody } from '/routes/api/files/upload.tsx'; import { RequestBody as RenameRequestBody, ResponseBody as RenameResponseBody } from '/routes/api/files/rename.tsx'; import { RequestBody as MoveRequestBody, ResponseBody as MoveResponseBody } from '/routes/api/files/move.tsx'; import { RequestBody as DeleteRequestBody, ResponseBody as DeleteResponseBody } from '/routes/api/files/delete.tsx'; import { RequestBody as CreateDirectoryRequestBody, ResponseBody as CreateDirectoryResponseBody, } from '/routes/api/files/create-directory.tsx'; import { RequestBody as RenameDirectoryRequestBody, ResponseBody as RenameDirectoryResponseBody, } from '/routes/api/files/rename-directory.tsx'; import { RequestBody as MoveDirectoryRequestBody, ResponseBody as MoveDirectoryResponseBody, } from '/routes/api/files/move-directory.tsx'; import { RequestBody as DeleteDirectoryRequestBody, ResponseBody as DeleteDirectoryResponseBody, } from '/routes/api/files/delete-directory.tsx'; import SearchFiles from './SearchFiles.tsx'; import ListFiles from './ListFiles.tsx'; import FilesBreadcrumb from './FilesBreadcrumb.tsx'; import CreateDirectoryModal from './CreateDirectoryModal.tsx'; import RenameDirectoryOrFileModal from './RenameDirectoryOrFileModal.tsx'; import MoveDirectoryOrFileModal from './MoveDirectoryOrFileModal.tsx'; interface MainFilesProps { initialDirectories: Directory[]; initialFiles: DirectoryFile[]; initialPath: string; } export default function MainFiles({ initialDirectories, initialFiles, initialPath }: MainFilesProps) { const isAdding = useSignal(false); const isUploading = useSignal(false); const isDeleting = useSignal(false); const isUpdating = useSignal(false); const directories = useSignal(initialDirectories); const files = useSignal(initialFiles); const path = useSignal(initialPath); const areNewOptionsOption = useSignal(false); const isNewDirectoryModalOpen = useSignal(false); const renameDirectoryOrFileModal = useSignal< { isOpen: boolean; isDirectory: boolean; parentPath: string; name: string } | null >(null); const moveDirectoryOrFileModal = useSignal< { isOpen: boolean; isDirectory: boolean; path: string; name: string } | null >(null); function onClickUploadFile() { const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.multiple = true; fileInput.click(); fileInput.onchange = async (event) => { const chosenFilesList = (event.target as HTMLInputElement)?.files!; const chosenFiles = Array.from(chosenFilesList); isUploading.value = true; for (const chosenFile of chosenFiles) { if (!chosenFile) { continue; } areNewOptionsOption.value = false; const requestBody = new FormData(); requestBody.set('parent_path', path.value); requestBody.set('name', chosenFile.name); requestBody.set('contents', chosenFile); try { const response = await fetch(`/api/files/upload`, { method: 'POST', body: requestBody, }); const result = await response.json() as UploadResponseBody; if (!result.success) { throw new Error('Failed to upload file!'); } files.value = [...result.newFiles]; } catch (error) { console.error(error); } } isUploading.value = false; }; } function onClickCreateDirectory() { if (isNewDirectoryModalOpen.value) { isNewDirectoryModalOpen.value = false; return; } isNewDirectoryModalOpen.value = true; } async function onClickSaveDirectory(newDirectoryName: string) { if (isAdding.value) { return; } if (!newDirectoryName) { return; } areNewOptionsOption.value = false; isAdding.value = true; try { const requestBody: CreateDirectoryRequestBody = { parentPath: path.value, name: newDirectoryName, }; const response = await fetch(`/api/files/create-directory`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as CreateDirectoryResponseBody; if (!result.success) { throw new Error('Failed to create directory!'); } directories.value = [...result.newDirectories]; isNewDirectoryModalOpen.value = false; } catch (error) { console.error(error); } isAdding.value = false; } function onCloseCreateDirectory() { isNewDirectoryModalOpen.value = false; } function toggleNewOptionsDropdown() { areNewOptionsOption.value = !areNewOptionsOption.value; } function onClickOpenRenameDirectory(parentPath: string, name: string) { renameDirectoryOrFileModal.value = { isOpen: true, isDirectory: true, parentPath, name, }; } function onClickOpenRenameFile(parentPath: string, name: string) { renameDirectoryOrFileModal.value = { isOpen: true, isDirectory: false, parentPath, name, }; } function onClickCloseRename() { renameDirectoryOrFileModal.value = null; } async function onClickSaveRenameDirectory(newName: string) { if ( isUpdating.value || !renameDirectoryOrFileModal.value?.isOpen || !renameDirectoryOrFileModal.value?.isDirectory ) { return; } isUpdating.value = true; try { const requestBody: RenameDirectoryRequestBody = { parentPath: renameDirectoryOrFileModal.value.parentPath, oldName: renameDirectoryOrFileModal.value.name, newName, }; const response = await fetch(`/api/files/rename-directory`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as RenameDirectoryResponseBody; if (!result.success) { throw new Error('Failed to rename directory!'); } directories.value = [...result.newDirectories]; } catch (error) { console.error(error); } isUpdating.value = false; renameDirectoryOrFileModal.value = null; } async function onClickSaveRenameFile(newName: string) { if ( isUpdating.value || !renameDirectoryOrFileModal.value?.isOpen || renameDirectoryOrFileModal.value?.isDirectory ) { return; } isUpdating.value = true; try { const requestBody: RenameRequestBody = { parentPath: renameDirectoryOrFileModal.value.parentPath, oldName: renameDirectoryOrFileModal.value.name, newName, }; const response = await fetch(`/api/files/rename`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as RenameResponseBody; if (!result.success) { throw new Error('Failed to rename file!'); } files.value = [...result.newFiles]; } catch (error) { console.error(error); } isUpdating.value = false; renameDirectoryOrFileModal.value = null; } function onClickOpenMoveDirectory(parentPath: string, name: string) { moveDirectoryOrFileModal.value = { isOpen: true, isDirectory: true, path: parentPath, name, }; } function onClickOpenMoveFile(parentPath: string, name: string) { moveDirectoryOrFileModal.value = { isOpen: true, isDirectory: false, path: parentPath, name, }; } function onClickCloseMove() { moveDirectoryOrFileModal.value = null; } async function onClickSaveMoveDirectory(newPath: string) { if (isUpdating.value || !moveDirectoryOrFileModal.value?.isOpen || !moveDirectoryOrFileModal.value?.isDirectory) { return; } isUpdating.value = true; try { const requestBody: MoveDirectoryRequestBody = { oldParentPath: moveDirectoryOrFileModal.value.path, newParentPath: newPath, name: moveDirectoryOrFileModal.value.name, }; const response = await fetch(`/api/files/move-directory`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as MoveDirectoryResponseBody; if (!result.success) { throw new Error('Failed to move directory!'); } directories.value = [...result.newDirectories]; } catch (error) { console.error(error); } isUpdating.value = false; moveDirectoryOrFileModal.value = null; } async function onClickSaveMoveFile(newPath: string) { if (isUpdating.value || !moveDirectoryOrFileModal.value?.isOpen || moveDirectoryOrFileModal.value?.isDirectory) { return; } isUpdating.value = true; try { const requestBody: MoveRequestBody = { oldParentPath: moveDirectoryOrFileModal.value.path, newParentPath: newPath, name: moveDirectoryOrFileModal.value.name, }; const response = await fetch(`/api/files/move`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as MoveResponseBody; if (!result.success) { throw new Error('Failed to move file!'); } files.value = [...result.newFiles]; } catch (error) { console.error(error); } isUpdating.value = false; moveDirectoryOrFileModal.value = null; } async function onClickDeleteDirectory(parentPath: string, name: string) { if (confirm('Are you sure you want to delete this directory?')) { if (isDeleting.value) { return; } isDeleting.value = true; try { const requestBody: DeleteDirectoryRequestBody = { parentPath, name, }; const response = await fetch(`/api/files/delete-directory`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as DeleteDirectoryResponseBody; if (!result.success) { throw new Error('Failed to delete directory!'); } directories.value = [...result.newDirectories]; } catch (error) { console.error(error); } isDeleting.value = false; } } async function onClickDeleteFile(parentPath: string, name: string) { if (confirm('Are you sure you want to delete this file?')) { if (isDeleting.value) { return; } isDeleting.value = true; try { const requestBody: DeleteRequestBody = { parentPath, name, }; const response = await fetch(`/api/files/delete`, { method: 'POST', body: JSON.stringify(requestBody), }); const result = await response.json() as DeleteResponseBody; if (!result.success) { throw new Error('Failed to delete file!'); } files.value = [...result.newFiles]; } catch (error) { console.error(error); } isDeleting.value = false; } } return ( <>
{isDeleting.value ? ( <> Deleting... ) : null} {isAdding.value ? ( <> Creating... ) : null} {isUploading.value ? ( <> Uploading... ) : null} {isUpdating.value ? ( <> Updating... ) : null} {!isDeleting.value && !isAdding.value && !isUploading.value && !isUpdating.value ? <>  : null}
); }