-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAttachmentsList.tsx
105 lines (95 loc) · 3.51 KB
/
AttachmentsList.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import {Delete} from '@mui/icons-material'
import ArticleIcon from '@mui/icons-material/Article'
import ErrorIcon from '@mui/icons-material/Error'
import UploadFileIcon from '@mui/icons-material/UploadFile'
import {IconButton} from '@mui/material'
import Avatar from '@mui/material/Avatar'
import LinearProgress from '@mui/material/LinearProgress'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
import ListItemAvatar from '@mui/material/ListItemAvatar'
import ListItemText from '@mui/material/ListItemText'
import TextField from '@mui/material/TextField'
import React, {useCallback} from 'react'
import {useTranslation} from 'react-i18next'
import {AttachmentState, AttachmentStatus, ID} from '../../state'
const statusToProgress = (t: (s: string) => string, status: AttachmentStatus) => {
switch(status) {
case AttachmentStatus.NEW:
return <LinearProgress variant="determinate" value={0}/>
case AttachmentStatus.UPLOADING:
return <LinearProgress variant="determinate" value={50}/>
case AttachmentStatus.DONE:
return <LinearProgress variant="determinate" value={100}/>
case AttachmentStatus.ERROR:
return t('error.transfer')
}
}
const statusToIcon = (status: AttachmentStatus) => {
switch(status) {
case AttachmentStatus.NEW:
return <ArticleIcon/>
case AttachmentStatus.UPLOADING:
return <UploadFileIcon/>
case AttachmentStatus.DONE:
return <ArticleIcon/>
case AttachmentStatus.ERROR:
return <ErrorIcon/>
}
}
type AttachmentEntryProps = {
description: string
onChangeDescription: (description: string) => void
onDeleteItem: (id: ID) => void
}
const AttachmentEntry = ({ id, description, onChangeDescription, blob, status, onDeleteItem }: AttachmentEntryProps & AttachmentState) => {
const {t} = useTranslation()
const handleChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
onChangeDescription(event.target.value)
}, [onChangeDescription])
return <ListItem secondaryAction={
<IconButton edge="end" aria-label={t('delete')} onClick={() => onDeleteItem(id)}>
<Delete />
</IconButton>
}>
<ListItemAvatar>
<Avatar>
{statusToIcon(status)}
</Avatar>
</ListItemAvatar>
<ListItemText
primary={<TextField
id={`attachment-description-${blob.name}`}
variant='outlined'
sx={{ width: '100%' }}
label={t('attachment.description', { name: blob.name })}
onChange={handleChange}
value={description}
// indicate warning if attachment description is left blank
focused={!description}
color={!description ? 'warning' : 'secondary'}
/>}
secondary={statusToProgress(t, status)}
/>
</ListItem>
}
type AttachementListProps = {
attachmentStates: AttachmentState[]
descriptions: { id: ID, description: string }[]
onChangeDescription: (id: ID, description: string) => void
onDeleteItem: (id: ID) => void
}
const AttachmentsList = ({attachmentStates, descriptions, onChangeDescription, onDeleteItem}: AttachementListProps) => {
const getDescription = (id: ID) =>
descriptions.filter(description => description.id === id)[0]?.description
return <List>
{attachmentStates.map(({id, blob, status}) =>
<AttachmentEntry key={id} id={id} blob={blob} status={status}
description={getDescription(id)}
onChangeDescription={description => onChangeDescription(id, description)}
onDeleteItem={onDeleteItem}
/>
)}
</List>
}
export default AttachmentsList