181 lines
5.0 KiB
JavaScript
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
|