Skip to content

Commit d99f3a9

Browse files
authored
Merge pull request #150 from scientist-softserv/134-show-attachments
134 show attachments
2 parents 8b531e3 + 3500f28 commit d99f3a9

File tree

7 files changed

+225
-8
lines changed

7 files changed

+225
-8
lines changed

src/assets/fontawesome.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {
33
faArrowDown,
44
faArrowUp,
55
faEnvelope,
6+
faFileLines,
67
faListCheck,
78
faPaperclip,
89
faSquareCheck,
10+
faUpload,
911
faVial,
1012
faVialCircleCheck,
1113
} from '@fortawesome/free-solid-svg-icons'
@@ -18,11 +20,13 @@ library.add(
1820
faArrowDown,
1921
faArrowUp,
2022
faEnvelope,
23+
faFileLines,
2124
faListCheck,
2225
faMinusSquare,
26+
faPaperclip,
2327
faPlusSquare,
2428
faSquareCheck,
25-
faPaperclip,
29+
faUpload,
2630
faVial,
2731
faVialCircleCheck,
2832
)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import React from 'react'
2+
import PropTypes from 'prop-types'
3+
import {
4+
// Button,
5+
Table,
6+
} from 'react-bootstrap'
7+
import { allowNull } from '../../resources/utilityFunctions'
8+
9+
const FilesTable = ({ addClass, files }) => {
10+
if (files.length === 0) {
11+
return (
12+
<h6 className='mt-3'>You do not have this type of document yet.</h6>
13+
)
14+
}
15+
16+
return (
17+
<Table striped bordered hover size='sm' className={`${addClass}`}>
18+
<thead>
19+
<tr>
20+
<th>File Name</th>
21+
<th>Uploaded By</th>
22+
<th>Size</th>
23+
<th>Created At</th>
24+
</tr>
25+
</thead>
26+
<tbody>
27+
{files.map((file) => {
28+
const { uuid, fileName, uploadedBy, contentLength, createdAt } = file
29+
return (
30+
<tr key={uuid} className='small'>
31+
<td>{fileName}</td>
32+
<td>{uploadedBy}</td>
33+
<td>{contentLength}</td>
34+
<td>{createdAt}</td>
35+
</tr>
36+
)
37+
})}
38+
</tbody>
39+
</Table>
40+
)
41+
}
42+
43+
FilesTable.propTypes = {
44+
addClass: PropTypes.string,
45+
files: PropTypes.arrayOf(
46+
PropTypes.shape({
47+
contentLength: PropTypes.string.isRequired,
48+
contentType: PropTypes.string.isRequired,
49+
createdAt: PropTypes.string.isRequired,
50+
download: PropTypes.string.isRequired,
51+
fileName: PropTypes.string.isRequired,
52+
href: PropTypes.string.isRequired,
53+
status: allowNull(PropTypes.string.isRequired),
54+
uploadedBy: PropTypes.string.isRequired,
55+
uuid: PropTypes.string.isRequired,
56+
}),
57+
).isRequired,
58+
}
59+
60+
FilesTable.defaultProps = {
61+
addClass: '',
62+
}
63+
64+
export default FilesTable
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react'
2+
import FilesTable from './FilesTable'
3+
4+
export default {
5+
title: 'Components/FilesTable',
6+
component: FilesTable,
7+
}
8+
9+
const Template = (args) => <FilesTable {...args} />
10+
11+
export const Default = Template.bind({})
12+
Default.args = {
13+
files: [{
14+
contentLength: '938.57 KB',
15+
contentType: 'image/png',
16+
createdAt: ' Dec 22 2022 at 12:56:48 PM',
17+
download: '/quote_groups/10bd825f-c7e0-4c07-bd9e-f7982b21f435/attachments/nepal5.png',
18+
fileName: 'nepal5.png',
19+
href: 'https://acme.scientist.com/secure_attachments/4611434c-ba99-481e-84ee-37e1fdbd203e',
20+
status: null,
21+
uploadedBy: 'Summer Cook',
22+
uuid: '4611434c-ba99-481e-84ee-37e1fdbd203e',
23+
}],
24+
}

src/compounds/ActionsGroup/ActionsGroup.jsx

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ import React, { useState } from 'react'
22
import PropTypes from 'prop-types'
33
import { ListGroup } from 'react-bootstrap'
44
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
5-
import SendMessage from './actions/SendMessage'
5+
// import SendMessage from './actions/SendMessage'
6+
import ViewFiles from './actions/ViewFiles'
7+
import { allowNull } from '../../resources/utilityFunctions'
68
import './actions-group.scss'
79

8-
const ActionsGroup = ({ handleSendingMessages }) => {
10+
// TODO: add back handleSendingMessagesOrFiles into the props, removing for now to avoid console error. see below TODO.
11+
const ActionsGroup = ({ initialFiles }) => {
912
const [show, setShow] = useState(false)
1013
const [action, setAction] = useState(null)
1114

@@ -18,28 +21,59 @@ const ActionsGroup = ({ handleSendingMessages }) => {
1821
setAction(null)
1922
setShow(false)
2023
}
21-
2224
return (
2325
<>
2426
<ListGroup className='actions-group'>
25-
<ListGroup.Item action variant='primary' onClick={() => handleShow('SendMessage')}>
27+
{/* TODO(@summercook): return this and the below commented code
28+
once we are able to refactor posting messages & attachments */}
29+
{/* <ListGroup.Item action variant='primary' onClick={() => handleShow('SendMessage')}>
2630
<FontAwesomeIcon icon='fa-envelope' />
2731
Send Message
32+
</ListGroup.Item> */}
33+
<ListGroup.Item
34+
action
35+
variant='primary'
36+
onClick={() => handleShow('ViewFiles')}
37+
role='presentation'
38+
>
39+
<FontAwesomeIcon icon='fa-file-lines' />
40+
View Files
2841
</ListGroup.Item>
2942
</ListGroup>
30-
{(action === 'SendMessage' && show)
43+
{/* {(action === 'SendMessage' && show)
3144
&& (
3245
<SendMessage
3346
handleClose={handleClose}
34-
onSubmit={handleSendingMessages}
47+
onSubmit={handleSendingMessagesOrFiles}
48+
/>
49+
)} */}
50+
{(action === 'ViewFiles' && show)
51+
&& (
52+
<ViewFiles
53+
handleClose={handleClose}
54+
initialFiles={initialFiles}
55+
// onSubmit={handleSendingMessagesOrFiles}
3556
/>
3657
)}
3758
</>
3859
)
3960
}
4061

4162
ActionsGroup.propTypes = {
42-
handleSendingMessages: PropTypes.func.isRequired,
63+
handleSendingMessagesOrFiles: PropTypes.func.isRequired,
64+
initialFiles: PropTypes.arrayOf(
65+
PropTypes.shape({
66+
contentLength: PropTypes.string.isRequired,
67+
contentType: PropTypes.string.isRequired,
68+
createdAt: PropTypes.string.isRequired,
69+
download: PropTypes.string.isRequired,
70+
fileName: PropTypes.string.isRequired,
71+
href: PropTypes.string.isRequired,
72+
status: allowNull(PropTypes.string.isRequired),
73+
uploadedBy: PropTypes.string.isRequired,
74+
uuid: PropTypes.string.isRequired,
75+
}),
76+
).isRequired,
4377
}
4478

4579
export default ActionsGroup

src/compounds/ActionsGroup/ActionsGroup.stories.jsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,15 @@ Default.args = {
1515
console.log('the message is:', message)
1616
console.log(`attached file(s): ${files.map((file) => file.split('name=')[1])}`)
1717
},
18+
initialFiles: [{
19+
contentLength: '938.57 KB',
20+
contentType: 'image/png',
21+
createdAt: ' Dec 22 2022 at 12:56:48 PM',
22+
download: '/quote_groups/10bd825f-c7e0-4c07-bd9e-f7982b21f435/attachments/nepal5.png',
23+
fileName: 'nepal5.png',
24+
href: 'https://acme.scientist.com/secure_attachments/4611434c-ba99-481e-84ee-37e1fdbd203e',
25+
status: null,
26+
uploadedBy: 'Summer Cook',
27+
uuid: '4611434c-ba99-481e-84ee-37e1fdbd203e',
28+
}],
1829
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React
2+
from 'react'
3+
import PropTypes from 'prop-types'
4+
import {
5+
Offcanvas,
6+
Tab,
7+
Tabs,
8+
} from 'react-bootstrap'
9+
import FilesTable from '../../../components/FilesTable/FilesTable'
10+
import { allowNull } from '../../../resources/utilityFunctions'
11+
12+
const ViewFiles = ({ initialFiles, handleClose }) => {
13+
const documentTabs = [
14+
{
15+
eventKey: 'files',
16+
title: 'Attachments',
17+
status: 'Other File',
18+
},
19+
{
20+
eventKey: 'status-updates',
21+
title: 'Status Updates',
22+
status: 'Status Update',
23+
},
24+
]
25+
26+
return (
27+
<Offcanvas show onHide={handleClose} placement='end' scroll='true'>
28+
<Offcanvas.Header className='d-flex border-bottom px-3 py-2 bg-light' closeButton>
29+
<Offcanvas.Title>Documents</Offcanvas.Title>
30+
</Offcanvas.Header>
31+
<Offcanvas.Body className='border rounded p-2 m-3'>
32+
<Tabs defaultActiveKey='files' id='document-tabs' justify fill>
33+
{documentTabs && documentTabs.map((tab) => {
34+
const { eventKey, title, status } = tab
35+
const filteredFiles = initialFiles.filter((f) => (status === f.status) || (status === 'Other File' && f.status === null))
36+
return (
37+
<Tab
38+
eventKey={eventKey}
39+
title={title}
40+
className='p-2'
41+
key={eventKey}
42+
>
43+
<FilesTable
44+
files={filteredFiles}
45+
status={status}
46+
/>
47+
</Tab>
48+
)
49+
})}
50+
</Tabs>
51+
</Offcanvas.Body>
52+
</Offcanvas>
53+
)
54+
}
55+
56+
ViewFiles.propTypes = {
57+
initialFiles: PropTypes.arrayOf(
58+
PropTypes.shape({
59+
contentLength: PropTypes.string.isRequired,
60+
contentType: PropTypes.string.isRequired,
61+
createdAt: PropTypes.string.isRequired,
62+
download: PropTypes.string.isRequired,
63+
fileName: PropTypes.string.isRequired,
64+
href: PropTypes.string.isRequired,
65+
status: allowNull(PropTypes.string.isRequired),
66+
uploadedBy: PropTypes.string.isRequired,
67+
uuid: PropTypes.string.isRequired,
68+
}),
69+
).isRequired,
70+
handleClose: PropTypes.func.isRequired,
71+
}
72+
73+
export default ViewFiles

src/resources/utilityFunctions.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,10 @@ export const addDays = (date, days) => {
1515
date.setDate(date.getDate() + days)
1616
return date
1717
}
18+
19+
export const allowNull = (wrappedPropTypes) => {
20+
return (props, propName, ...rest) => {
21+
if (props[propName] === null) return null
22+
return wrappedPropTypes(props, propName, ...rest)
23+
}
24+
}

0 commit comments

Comments
 (0)