Disable dev pages; FolderViewer table view; CustomTable type safety;

This commit is contained in:
cracklesparkle
2024-12-19 17:37:01 +09:00
parent 65b7e275fe
commit b54c2f0e20
3 changed files with 165 additions and 180 deletions

View File

@ -32,7 +32,7 @@ const CustomTable = () => {
{ id: 2, name: 'Jane Smith', age: 30 }, { id: 2, name: 'Jane Smith', age: 30 },
{ id: 3, name: 'Sam Green', age: 22 }, { id: 3, name: 'Sam Green', age: 22 },
]); ]);
const [editingCell, setEditingCell] = useState({ rowIndex: null, columnId: null }); const [editingCell, setEditingCell] = useState<{ rowIndex: string | number | null, columnId: string | number | null }>({ rowIndex: null, columnId: null });
const tableColumns = useMemo<ColumnDef<typeof data[0]>[]>(() => columns, []); const tableColumns = useMemo<ColumnDef<typeof data[0]>[]>(() => columns, []);
@ -50,7 +50,7 @@ const CustomTable = () => {
value: DataType[keyof DataType] value: DataType[keyof DataType]
) => { ) => {
const updatedData = [...data]; const updatedData = [...data];
updatedData[rowIndex][columnId] = value; (updatedData[rowIndex][columnId] as DataType[keyof DataType]) = value;
setData(updatedData); setData(updatedData);
//setEditingCell({ rowIndex: null, columnId: null }); //setEditingCell({ rowIndex: null, columnId: null });
}; };
@ -90,8 +90,8 @@ const CustomTable = () => {
{isEditing ? ( {isEditing ? (
<Input <Input
type='text' type='text'
value={data[rowIndex][cell.column.id]} value={data[rowIndex][cell.column.id as keyof DataType]}
onChange={(e) => handleEditCell(rowIndex, cell.column.id, e.target.value)} onChange={(e) => handleEditCell(rowIndex, (cell.column.id as keyof DataType), e.target.value)}
onBlur={() => setEditingCell({ rowIndex: null, columnId: null })} onBlur={() => setEditingCell({ rowIndex: null, columnId: null })}
autoFocus autoFocus
/> />

View File

@ -4,19 +4,11 @@ import React, { useEffect, useState } from 'react'
import DocumentService from '../services/DocumentService' import DocumentService from '../services/DocumentService'
import { mutate } from 'swr' import { mutate } from 'swr'
import FileViewer from './modals/FileViewer' import FileViewer from './modals/FileViewer'
import { ActionIcon, Anchor, Breadcrumbs, Button, Divider, FileButton, Flex, Loader, MantineStyleProp, RingProgress, ScrollAreaAutosize, Table, Text } from '@mantine/core' import { ActionIcon, Anchor, Breadcrumbs, Button, Divider, FileButton, Flex, Loader, MantineStyleProp, RingProgress, ScrollAreaAutosize, Stack, Table, Text } from '@mantine/core'
import { IconCancel, IconDownload, IconFile, IconFileFilled, IconFilePlus, IconFileUpload, IconFolderFilled, IconX } from '@tabler/icons-react' import { IconCancel, IconDownload, IconFile, IconFileFilled, IconFilePlus, IconFileUpload, IconFolderFilled, IconX } from '@tabler/icons-react'
interface FolderProps {
folder: IDocumentFolder;
index: number;
handleFolderClick: (folder: IDocumentFolder) => void;
}
interface DocumentProps { interface DocumentProps {
doc: IDocument; doc: IDocument;
index: number;
handleDocumentClick: (index: number) => void;
} }
const FileItemStyle: MantineStyleProp = { const FileItemStyle: MantineStyleProp = {
@ -29,22 +21,6 @@ const FileItemStyle: MantineStyleProp = {
padding: '8px' padding: '8px'
} }
function ItemFolder({ folder, handleFolderClick, ...props }: FolderProps) {
return (
<Flex
onClick={() => handleFolderClick(folder)}
>
<Flex
style={FileItemStyle}
{...props}
>
<IconFolderFilled />
{folder.name}
</Flex>
</Flex>
)
}
const handleSave = async (file: Blob, filename: string) => { const handleSave = async (file: Blob, filename: string) => {
const link = document.createElement('a') const link = document.createElement('a')
link.href = window.URL.createObjectURL(file) link.href = window.URL.createObjectURL(file)
@ -54,7 +30,7 @@ const handleSave = async (file: Blob, filename: string) => {
window.URL.revokeObjectURL(link.href) window.URL.revokeObjectURL(link.href)
} }
function ItemDocument({ doc, index, handleDocumentClick, ...props }: DocumentProps) { function ItemDocument({ doc }: DocumentProps) {
const [shouldFetch, setShouldFetch] = useState(false) const [shouldFetch, setShouldFetch] = useState(false)
const { file, isLoading } = useDownload(shouldFetch ? doc?.document_folder_id : null, shouldFetch ? doc?.id : null) const { file, isLoading } = useDownload(shouldFetch ? doc?.document_folder_id : null, shouldFetch ? doc?.id : null)
@ -66,33 +42,24 @@ function ItemDocument({ doc, index, handleDocumentClick, ...props }: DocumentPro
setShouldFetch(false) setShouldFetch(false)
} }
} }
}, [shouldFetch, file]) }, [shouldFetch, file, doc.name])
return ( return (
<Flex align='center'> <Flex>
<Flex <ActionIcon
style={FileItemStyle} onClick={(e) => {
onClick={() => handleDocumentClick(index)} e.stopPropagation()
{...props} if (!isLoading) {
> setShouldFetch(true)
<IconFileFilled />
{doc.name}
</Flex>
<Flex>
<ActionIcon
onClick={() => {
if (!isLoading) {
setShouldFetch(true)
}
}}
variant='subtle'>
{isLoading ?
<Loader size='sm' />
:
<IconDownload />
} }
</ActionIcon> }}
</Flex> variant='subtle'>
{isLoading ?
<Loader size='sm' />
:
<IconDownload />
}
</ActionIcon>
</Flex> </Flex>
) )
} }
@ -175,133 +142,151 @@ export default function FolderViewer() {
return ( return (
<ScrollAreaAutosize w={'100%'} h={'100%'} p={'sm'}> <ScrollAreaAutosize w={'100%'} h={'100%'} p={'sm'}>
<FileViewer {fileViewerModal &&
open={fileViewerModal} <FileViewer
setOpen={setFileViewerModal} open={fileViewerModal}
currentFileNo={currentFileNo} setOpen={setFileViewerModal}
setCurrentFileNo={setCurrentFileNo} currentFileNo={currentFileNo}
docs={documents} setCurrentFileNo={setCurrentFileNo}
/> docs={documents}
/>
<Breadcrumbs>
<Anchor
onClick={() => {
setCurrentFolder(null)
setBreadcrumbs([])
}}
>
Главная
</Anchor>
{breadcrumbs.map((breadcrumb, index) => (
<Anchor
key={breadcrumb.id}
onClick={() => handleBreadcrumbClick(index)}
>
{breadcrumb.name}
</Anchor>
))}
</Breadcrumbs>
{currentFolder &&
<Flex direction='column' gap='sm'>
<Flex direction='column' gap='sm' p='sm' style={{
border: filesToUpload.length > 0 ? '1px dashed gray' : 'none',
borderRadius: '8px',
}}>
<Flex gap='sm'>
<FileButton multiple onChange={handleFileInput}>
{(props) => <Button variant='filled' leftSection={isUploading ? <Loader /> : <IconFilePlus />} {...props}>Добавить</Button>}
</FileButton>
{filesToUpload.length > 0 &&
<>
<Button
variant='filled'
leftSection={isUploading ? <RingProgress sections={[{ value: uploadProgress, color: 'blue' }]} /> : <IconFileUpload />}
onClick={uploadFiles}
>
Загрузить все
</Button>
<Button
variant='outline'
leftSection={<IconCancel />}
onClick={() => {
setFilesToUpload([])
}}
>
Отмена
</Button>
</>
}
</Flex>
<Divider />
{filesToUpload.length > 0 &&
<Flex direction='column'>
{filesToUpload.map((file, index) => (
<Flex key={index} p='8px'>
<Flex gap='sm' direction='row' align='center'>
<IconFile />
<Text>{file.name}</Text>
</Flex>
<ActionIcon onClick={() => {
setFilesToUpload(prev => {
return prev.filter((_, i) => i != index)
})
}} ml='auto' variant='subtle'>
<IconX />
</ActionIcon>
</Flex>
))}
</Flex>
}
</Flex>
</Flex>
} }
<Table
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
bg={dragOver ? 'rgba(0, 0, 0, 0.1)' : 'inherit'}
highlightOnHover>
<Table.Thead>
<Table.Tr>
</Table.Tr> <Stack>
</Table.Thead> <Breadcrumbs>
<Anchor
onClick={() => {
setCurrentFolder(null)
setBreadcrumbs([])
}}
>
Главная
</Anchor>
{breadcrumbs.map((breadcrumb, index) => (
<Anchor
key={breadcrumb.id}
onClick={() => handleBreadcrumbClick(index)}
>
{breadcrumb.name}
</Anchor>
))}
</Breadcrumbs>
<Table.Tbody> {currentFolder &&
{currentFolder ? ( <Flex direction='column' gap='sm'>
documents?.map((doc: IDocument, index: number) => ( <Flex direction='column' gap='sm' p='sm' style={{
<Table.Tr key={doc.id}> border: filesToUpload.length > 0 ? '1px dashed gray' : 'none',
<Table.Td> borderRadius: '8px',
<ItemDocument }}>
doc={doc} <Flex gap='sm'>
index={index} <FileButton multiple onChange={handleFileInput}>
handleDocumentClick={handleDocumentClick} {(props) => <Button variant='filled' leftSection={isUploading ? <Loader /> : <IconFilePlus />} {...props}>Добавить</Button>}
/> </FileButton>
</Table.Td>
</Table.Tr> {filesToUpload.length > 0 &&
)) <>
) : ( <Button
folders?.map((folder: IDocumentFolder, index: number) => ( variant='filled'
<Table.Tr key={folder.id}> leftSection={isUploading ? <RingProgress sections={[{ value: uploadProgress, color: 'blue' }]} /> : <IconFileUpload />}
<Table.Td> onClick={uploadFiles}
<ItemFolder >
folder={folder} Загрузить все
index={index} </Button>
handleFolderClick={handleFolderClick}
/> <Button
</Table.Td> variant='outline'
</Table.Tr> leftSection={<IconCancel />}
)) onClick={() => {
)} setFilesToUpload([])
</Table.Tbody> }}
</Table> >
Отмена
</Button>
</>
}
</Flex>
<Divider />
{filesToUpload.length > 0 &&
<Flex direction='column'>
{filesToUpload.map((file, index) => (
<Flex key={index} p='8px'>
<Flex gap='sm' direction='row' align='center'>
<IconFile />
<Text>{file.name}</Text>
</Flex>
<ActionIcon onClick={() => {
setFilesToUpload(prev => {
return prev.filter((_, i) => i != index)
})
}} ml='auto' variant='subtle'>
<IconX />
</ActionIcon>
</Flex>
))}
</Flex>
}
</Flex>
</Flex>
}
<Table
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
bg={dragOver ? 'rgba(0, 0, 0, 0.1)' : 'inherit'}
highlightOnHover>
<Table.Thead>
<Table.Tr>
<Table.Th>Название</Table.Th>
<Table.Th p={0}>Дата создания</Table.Th>
<Table.Th p={0}></Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>
{currentFolder ? (
documents?.map((doc: IDocument, index: number) => (
<Table.Tr key={doc.id} onClick={() => handleDocumentClick(index)} style={{ cursor: 'pointer' }}>
<Table.Td p={0}>
<Flex style={FileItemStyle}>
<IconFileFilled />
{doc.name}
</Flex>
</Table.Td>
<Table.Td p={0}>
{new Date(doc.create_date).toLocaleDateString()}
</Table.Td>
<Table.Td p={0}>
<ItemDocument
doc={doc}
/>
</Table.Td>
</Table.Tr>
))
) : (
folders?.map((folder: IDocumentFolder) => (
<Table.Tr key={folder.id} onClick={() => handleFolderClick(folder)} style={{ cursor: 'pointer' }}>
<Table.Td p={0}>
<Flex style={FileItemStyle}>
<IconFolderFilled />
{folder.name}
</Flex>
</Table.Td>
<Table.Td p={0} align='left'>
{new Date(folder.create_date).toLocaleDateString()}
</Table.Td>
<Table.Td p={0}>
</Table.Td>
</Table.Tr>
))
)}
</Table.Tbody>
</Table>
</Stack>
</ScrollAreaAutosize> </ScrollAreaAutosize>
) )
} }

View File

@ -133,7 +133,7 @@ const pages = [
component: <MonitorPage />, component: <MonitorPage />,
drawer: true, drawer: true,
dashboard: true, dashboard: true,
enabled: true, enabled: false,
}, },
{ {
label: "Table test", label: "Table test",
@ -142,7 +142,7 @@ const pages = [
component: <TableTest />, component: <TableTest />,
drawer: true, drawer: true,
dashboard: true, dashboard: true,
enabled: true, enabled: false,
}, },
{ {
label: "Component test", label: "Component test",
@ -151,7 +151,7 @@ const pages = [
component: <ComponentTest />, component: <ComponentTest />,
drawer: true, drawer: true,
dashboard: true, dashboard: true,
enabled: true, enabled: false,
}, },
] ]