Skip to content
Snippets Groups Projects
Commit b1781499 authored by Bogdan Cochior's avatar Bogdan Cochior
Browse files

feat(report): add/delete file

parent 8a2706e0
No related branches found
No related tags found
1 merge request!8Sprint #10
import React, { Fragment } from 'react'
import { last } from 'lodash'
import styled, { css } from 'styled-components'
import { th, Icon } from '@pubsweet/ui'
import { th } from '@pubsweet/ui'
const parseFileSize = (size = 0) => {
const kbSize = Math.floor(size / 1000)
const mbSize = Math.floor(kbSize / 1000)
const gbSize = Math.floor(mbSize / 1000)
if (gbSize) {
return `${gbSize} GB`
} else if (mbSize) {
return `${mbSize} MB`
} else if (kbSize) {
return `${kbSize} kB`
}
return `${size} bytes`
}
const hasPreview = (name = '') => {
const extension = last(name.split('.'))
return ['pdf', 'png', 'jpg'].includes(extension)
}
const File = ({ name = 'filename', size, id, previewFile, downloadFile }) => (
<FileRoot>
{hasPreview(name) && (
<IconButton onClick={previewFile(id)}>
<Icon primary size={3}>
eye
</Icon>
</IconButton>
)}
<IconButton onClick={downloadFile(id, name)}>
<Icon primary size={3}>
download
</Icon>
</IconButton>
<FileName>{name}</FileName>
<FileSize>{parseFileSize(size)}</FileSize>
</FileRoot>
)
import { FileItem } from 'pubsweet-components-faraday/src/components/Files'
const Files = ({
previewFile,
......@@ -55,7 +17,9 @@ const Files = ({
<div />
</Header>
{manuscripts.map(file => (
<File
<FileItem
compact
id={file.id}
key={file.id}
{...file}
downloadFile={downloadFile}
......@@ -71,7 +35,9 @@ const Files = ({
<div />
</Header>
{supplementary.map(file => (
<File
<FileItem
compact
id={file.id}
key={file.id}
{...file}
downloadFile={downloadFile}
......@@ -87,7 +53,9 @@ const Files = ({
<div />
</Header>
{coverLetter.map(file => (
<File
<FileItem
compact
id={file.id}
key={file.id}
{...file}
downloadFile={downloadFile}
......@@ -108,34 +76,6 @@ const defaultText = css`
font-size: ${th('fontSizeBaseSmall')};
`
const FileName = styled.span`
${defaultText};
margin: 0 ${th('subGridUnit')};
`
const FileSize = FileName.extend`
margin-left: ${th('subGridUnit')};
`
const IconButton = styled.div`
align-items: center;
cursor: pointer;
display: flex;
justify-content: center;
margin: 0 ${th('subGridUnit')};
&:hover {
opacity: 0.7;
}
`
const FileRoot = styled.div`
align-items: center;
border: ${th('borderDefault')};
display: flex;
flex-direction: row;
margin-bottom: ${th('subGridUnit')};
padding: ${th('subGridUnit')};
`
const Header = styled.div`
align-self: stretch;
align-items: center;
......
......@@ -12,6 +12,16 @@ import {
} from 'redux-form'
import AutosaveIndicator from 'pubsweet-component-wizard/src/components/AutosaveIndicator'
import {
uploadFile,
deleteFile,
getSignedUrl,
} from 'pubsweet-components-faraday/src/redux/files'
import {
FileItem,
FilePicker,
} from 'pubsweet-components-faraday/src/components/Files'
import {
ConfirmationModal,
withModal2,
......@@ -57,6 +67,9 @@ const ReviewerReportForm = ({
handleSubmit,
formValues = {},
review = {},
addFile,
removeFile,
previewFile,
}) => (
<Root>
<Row>
......@@ -81,10 +94,14 @@ const ReviewerReportForm = ({
/>
</Row>
<Spacing />
<Row>
<Label>
Report <ActionText left={12}>Upload file</ActionText>
</Label>
<Row left>
<Label>Report</Label>
<FilePicker
allowedFileExtensions={['pdf', 'doc', 'docx']}
onUpload={addFile}
>
<ActionText left={12}>Upload file</ActionText>
</FilePicker>
</Row>
<Row>
<FullWidth>
......@@ -102,6 +119,21 @@ const ReviewerReportForm = ({
/>
</FullWidth>
</Row>
{formValues.files && (
<Row>
{formValues.files.map(file => (
<FileItem
compact
id={file.id}
key={file.id}
{...file}
downloadFile={previewFile}
previewFile={previewFile}
removeFile={removeFile}
/>
))}
</Row>
)}
{formValues.hasConfidential ? (
<Fragment>
<Row>
......@@ -176,6 +208,9 @@ export default compose(
getFormValues,
createRecommendation,
updateRecommendation,
uploadFile,
deleteFile,
getSignedUrl,
},
),
withProps(({ review = {} }) => ({
......@@ -188,6 +223,44 @@ export default compose(
changeField: ({ changeForm }) => (field, value) => {
changeForm('reviewerReport', field, value)
},
addFile: ({
formValues: { files = [] },
uploadFile,
changeForm,
version,
}) => file => {
uploadFile(file, 'review', version.id)
.then(file => {
const newFiles = [...files, file]
setTimeout(() => {
changeForm('reviewerReport', 'files', newFiles)
}, 1000)
})
.catch(e => console.error(`Couldn't upload file.`, e))
},
removeFile: ({
formValues: { files = [] },
changeForm,
deleteFile,
}) => id => e => {
deleteFile(id)
.then(r => {
const newFiles = files.filter(f => f.id !== id)
changeForm('reviewerReport', 'files', newFiles)
})
.catch(e => console.error(`Couldn't delete the file.`, e))
const newFiles = files.filter(f => f.id !== id)
changeForm('reviewerReport', 'files', newFiles)
},
previewFile: ({ getSignedUrl }) => fileId => e => {
e.preventDefault()
const windowReference = window.open()
getSignedUrl(fileId).then(({ signedUrl }) => {
windowReference.location = signedUrl
})
},
}),
reduxForm({
form: 'reviewerReport',
......@@ -266,7 +339,7 @@ const Row = styled.div`
flex: 1;
box-sizing: border-box;
flex-wrap: wrap;
justify-content: space-between;
justify-content: ${({ left }) => (left ? 'left' : 'space-between')};
${defaultText};
`
......
import React from 'react'
import { Icon } from '@pubsweet/ui'
import styled, { withTheme } from 'styled-components'
import React, { Fragment } from 'react'
import { last } from 'lodash'
import { Icon, th } from '@pubsweet/ui'
import styled, { withTheme, css } from 'styled-components'
const parseFileSize = size => {
const kbSize = size / 1000
......@@ -17,6 +18,11 @@ const parseFileSize = size => {
return `${size} bytes`
}
const hasPreview = (name = '') => {
const extension = last(name.split('.'))
return ['pdf', 'png', 'jpg'].includes(extension)
}
const FileItem = ({
dragHandle,
name,
......@@ -24,42 +30,82 @@ const FileItem = ({
id,
removeFile,
previewFile,
downloadFile,
compact = false,
theme,
...rest
}) => (
<Root data-test={`file-${id}`}>
{dragHandle}
<Info>
<span>{name}</span>
<span>{parseFileSize(size)}</span>
</Info>
<Buttons>
<button onClick={previewFile(id)}>
<Icon color={theme.colorPrimary} size={3}>
eye
</Icon>
</button>
<button onClick={removeFile(id)} title="Delete">
<Icon color={theme.colorPrimary} size={3}>
trash-2
</Icon>
</button>
</Buttons>
</Root>
<Fragment>
{compact ? (
<FileRoot data-test={`file-${id}`}>
{hasPreview(name) && (
<IconButton onClick={previewFile(id)}>
<Icon primary size={3}>
eye
</Icon>
</IconButton>
)}
{downloadFile && (
<IconButton onClick={downloadFile(id, name)}>
<Icon primary size={3}>
download
</Icon>
</IconButton>
)}
<FileName>{name}</FileName>
<FileSize>{parseFileSize(size)}</FileSize>
{removeFile && (
<IconButton onClick={removeFile(id)}>
<Icon primary size={3}>
trash-2
</Icon>
</IconButton>
)}
</FileRoot>
) : (
<Root data-test={`file-${id}`}>
{dragHandle}
<Info>
<span>{name}</span>
<span>{parseFileSize(size)}</span>
</Info>
<Buttons>
<button onClick={previewFile(id)}>
<Icon color={theme.colorPrimary} size={3}>
eye
</Icon>
</button>
{removeFile && (
<button onClick={removeFile(id)} title="Delete">
<Icon color={theme.colorPrimary} size={3}>
trash-2
</Icon>
</button>
)}
</Buttons>
</Root>
)}
</Fragment>
)
export default withTheme(FileItem)
// #region styles
const defaultText = css`
color: ${th('colorPrimary')};
font-family: ${th('fontHeading')};
font-size: ${th('fontSizeBaseSmall')};
`
const Root = styled.div`
align-items: center;
border: ${({ theme }) => theme.borderDefault};
border: ${th('borderDefault')};
display: flex;
margin: 5px;
`
const Info = styled.div`
border-right: ${({ theme }) => theme.borderDefault};
border-right: ${th('borderDefault')};
display: flex;
flex: 1;
justify-content: space-between;
......@@ -88,4 +134,31 @@ const Buttons = styled.div`
}
}
`
const FileName = styled.span`
${defaultText};
margin: 0 ${th('subGridUnit')};
`
const FileSize = FileName.extend`
margin-left: ${th('subGridUnit')};
`
const IconButton = styled.div`
align-items: center;
cursor: pointer;
display: flex;
justify-content: center;
margin: 0 ${th('subGridUnit')};
&:hover {
opacity: 0.7;
}
`
const FileRoot = styled.div`
align-items: center;
border: ${th('borderDefault')};
display: flex;
flex-direction: row;
margin-bottom: ${th('subGridUnit')};
padding: ${th('subGridUnit')};
`
// #endregion
export { default as Files } from './Files'
export { default as FileItem } from './FileItem'
export { default as FilePicker } from './FilePicker'
......@@ -16,4 +16,5 @@ module.exports = {
'application/msword',
])
.error(new Error('Only Word documents and PDFs are allowed')),
review: Joi.any(),
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment