Files
tests/frontend_reactjs/src/components/FolderViewer.tsx
cracklesparkle 2c71e4f6af File uploading
2024-07-02 10:51:02 +09:00

227 lines
7.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useDocuments, useFolders } from '../hooks/swrHooks'
import { IDocument, IDocumentFolder } from '../interfaces/documents'
import { Box, Breadcrumbs, Button, Card, CardActionArea, CircularProgress, Input, InputLabel, LinearProgress, Link } from '@mui/material'
import { Folder, InsertDriveFile, Upload, UploadFile } from '@mui/icons-material'
import { useRef, useState } from 'react'
import DocumentService from '../services/DocumentService'
import { mutate } from 'swr'
interface FolderProps {
folder: IDocumentFolder;
handleFolderClick: (folder: IDocumentFolder) => void;
}
function ItemFolder({ folder, handleFolderClick, ...props }: FolderProps) {
return (
<Card
key={folder.id}
>
<CardActionArea>
<Box
sx={{
cursor: 'pointer',
display: 'flex',
flexDirection: 'row',
gap: '8px',
alignItems: 'center',
padding: '8px'
}}
onClick={() => handleFolderClick(folder)}
{...props}
>
<Folder />
{folder.name}
</Box>
</CardActionArea>
</Card>
)
}
interface DocumentProps {
doc: IDocument;
handleDocumentClick: (doc: IDocument) => void;
}
function ItemDocument({ doc, handleDocumentClick, ...props }: DocumentProps) {
return (
<Card
key={doc.id}
>
<CardActionArea>
<Box
sx={{
cursor: 'pointer',
display: 'flex',
flexDirection: 'row',
gap: '8px',
alignItems: 'center',
padding: '8px',
}}
onClick={() => {
handleDocumentClick(doc)
}}
{...props}
>
<InsertDriveFile />
{doc.name}
</Box>
</CardActionArea>
</Card>
)
}
export default function FolderViewer() {
const [currentFolder, setCurrentFolder] = useState<IDocumentFolder | null>(null)
const [breadcrumbs, setBreadcrumbs] = useState<IDocumentFolder[]>([])
const { folders, isLoading: foldersLoading } = useFolders()
const { documents, isLoading: documentsLoading } = useDocuments(currentFolder?.id)
const [uploadProgress, setUploadProgress] = useState(0)
const [isUploading, setIsUploading] = useState(false)
const fileInputRef = useRef<HTMLInputElement>(null)
const handleFolderClick = (folder: IDocumentFolder) => {
setCurrentFolder(folder)
setBreadcrumbs((prev) => [...prev, folder])
}
const handleDocumentClick = async (doc: IDocument) => {
try {
const response = await DocumentService.downloadDoc(doc.document_folder_id, doc.id);
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', doc.name);
document.body.appendChild(link);
link.click();
link.remove();
} catch (error) {
console.error(error);
}
}
const handleBreadcrumbClick = (index: number) => {
const newBreadcrumbs = breadcrumbs.slice(0, index + 1);
setBreadcrumbs(newBreadcrumbs)
setCurrentFolder(newBreadcrumbs[newBreadcrumbs.length - 1])
}
const handleFileUpload = async (event: any) => {
setIsUploading(true)
const file = event.target.files?.[0]
if (file && currentFolder && currentFolder.id) {
const formData = new FormData()
formData.append('files', file)
try {
const response = await DocumentService.uploadFiles(currentFolder.id, formData, setUploadProgress);
setIsUploading(false);
mutate(`/info/documents/${currentFolder.id}`);
} catch (error) {
console.error(error);
setIsUploading(false);
}
}
}
const handleUploadClick = () => {
if (fileInputRef.current) {
fileInputRef.current.click();
}
}
if (foldersLoading || documentsLoading) {
return (
<CircularProgress />
)
}
return (
<Box sx={{
display: 'flex',
flexDirection: 'column',
gap: '24px'
}}>
<Breadcrumbs>
<Link
underline='hover'
color='inherit'
onClick={() => {
setCurrentFolder(null)
setBreadcrumbs([])
}}
sx={{ cursor: 'pointer' }}
>
Главная
</Link>
{breadcrumbs.map((breadcrumb, index) => (
<Link
key={breadcrumb.id}
underline="hover"
color="inherit"
onClick={() => handleBreadcrumbClick(index)}
sx={{ cursor: 'pointer' }}
>
{breadcrumb.name}
</Link>
))}
</Breadcrumbs>
<Box>
{currentFolder &&
<Button
LinkComponent="label"
role={undefined}
variant="outlined"
tabIndex={-1}
startIcon={
isUploading ? <CircularProgress sx={{ maxHeight: "20px", maxWidth: "20px" }} variant="determinate" value={uploadProgress} /> : <UploadFile />
}
onClick={handleUploadClick}
>
<input
type='file'
ref={fileInputRef}
style={{ display: 'none' }}
onChange={handleFileUpload}
/>
Загрузить
</Button>
}
</Box>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
flexWrap: 'wrap',
gap: '16px'
}}>
{currentFolder ? (
documents?.map((doc: IDocument) => (
<ItemDocument
key={`doc-${doc.id}`}
doc={doc}
handleDocumentClick={handleDocumentClick}
/>
))
) : (
folders?.map((folder: IDocumentFolder) => (
<ItemFolder
key={`folder-${folder.id}`}
folder={folder}
handleFolderClick={handleFolderClick}
/>
))
)}
</Box>
</Box>
)
}