181 lines
5.0 KiB
JavaScript

import { Card, Flex, Typography, Button, Tag, Divider } from 'antd'
import PropTypes from 'prop-types'
import FileIcon from '../../Icons/FileIcon'
import BinIcon from '../../Icons/BinIcon'
import EyeIcon from '../../Icons/EyeIcon'
import DownloadIcon from '../../Icons/DownloadIcon'
import { useContext, useState } from 'react'
import { ApiServerContext } from '../context/ApiServerContext'
import FilePreview from './FilePreview'
import EyeSlashIcon from '../../Icons/EyeSlashIcon'
import { getModelByName } from '../../../database/ObjectModels'
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
import { useNavigate } from 'react-router-dom'
const { Text } = Typography
const FileList = ({
files,
onChange,
multiple = true,
editing = false,
showPreview = true,
showInfo = true,
showDownload = true,
defaultPreviewOpen = false,
card = true
}) => {
const { fetchFileContent, flushFile } = useContext(ApiServerContext)
const navigate = useNavigate()
const [previewOpen, setPreviewOpen] = useState(defaultPreviewOpen)
const infoAction = getModelByName('file').actions.filter(
(action) => action.name == 'info'
)[0]
// Check if there are no items in the list
const hasNoItems = multiple
? !files || !Array.isArray(files) || files.length === 0
: !files
if (hasNoItems) {
return null
}
const handleRemove = (fileToRemove) => {
flushFile(fileToRemove._id)
if (multiple) {
const currentFiles = Array.isArray(files) ? files : []
const updatedFiles = currentFiles.filter((file) => {
const fileUid = file._id || file.id
const removeUid = fileToRemove._id || fileToRemove.id
return fileUid !== removeUid
})
onChange(updatedFiles)
} else {
onChange(null)
}
}
const handleDownload = async (file) => {
await fetchFileContent(file, true)
}
const filesToRender = multiple ? files : [files]
const renderFileContent = (file) => (
<Flex vertical gap='10px' style={{ maxWidth: '100%', minWidth: 0 }}>
<Flex
justify={card ? 'space-between' : 'start'}
style={{ maxWidth: '100%', minWidth: 0 }}
>
<Flex gap={'small'} align='center' style={{ minWidth: 0 }}>
<FileIcon
style={{ margin: 0, fontSize: card == true ? '24px' : '16px' }}
/>
<Text style={{ marginTop: '1px', minWidth: 0 }} ellipsis>
{file.name || file.filename || 'Unknown file'}
</Text>
<Tag>{file.extension}</Tag>
</Flex>
<Flex gap={'small'} align='center'>
{showDownload && (
<Button
icon={<DownloadIcon />}
size='small'
type='text'
onClick={() => handleDownload(file)}
/>
)}
{showPreview && (
<Button
icon={previewOpen ? <EyeSlashIcon /> : <EyeIcon />}
size='small'
type='text'
onClick={() => {
if (previewOpen == true) {
setPreviewOpen(false)
} else {
setPreviewOpen(true)
}
}}
/>
)}
{showInfo && (
<Button
icon={<InfoCircleIcon />}
size='small'
type='text'
onClick={() => {
navigate(infoAction.url(file._id))
}}
/>
)}
{editing && (
<Button
icon={<BinIcon />}
size='small'
type='text'
onClick={() => handleRemove(file)}
/>
)}
</Flex>
</Flex>
{previewOpen ? (
<>
<Divider style={{ marginTop: 0, marginBottom: card ? 0 : '4px' }} />
<FilePreview file={file} style={{ width: '100%' }} />
</>
) : null}
</Flex>
)
return (
<div style={{ width: '100%' }}>
{filesToRender.map((file, index) => {
const key = file._id || file.id || index
const style = {
marginTop: index > 0 && multiple ? '4px' : undefined
}
if (card) {
return (
<Card
styles={{ body: { padding: '10px' } }}
key={key}
style={style}
>
{renderFileContent(file)}
</Card>
)
} else {
return (
<div
key={key}
style={{
...style
}}
>
{index > 0 && <Divider />}
{renderFileContent(file)}
</div>
)
}
})}
</div>
)
}
FileList.propTypes = {
files: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
onChange: PropTypes.func,
multiple: PropTypes.bool,
editing: PropTypes.bool,
showPreview: PropTypes.string,
showInfo: PropTypes.bool,
showDownload: PropTypes.bool,
defaultPreviewOpen: PropTypes.bool,
card: PropTypes.bool
}
export default FileList