Commit aa651ace authored by Giannis Kopanas's avatar Giannis Kopanas Committed by Yannis Barlas

File attachments submissions

parent 85146b0b
......@@ -13,6 +13,7 @@ const EditorItemWithVersion = withVersion(EditorItem)
const ReviewerItemWithVersion = withVersion(ReviewerItem)
const Dashboard = ({
acceptFiles,
currentUser,
conversion,
dashboard,
......@@ -23,6 +24,7 @@ const Dashboard = ({
<Page>
<UploadContainer>
<UploadManuscript
acceptFiles={acceptFiles}
conversion={conversion}
uploadManuscript={uploadManuscript}
/>
......
......@@ -23,6 +23,17 @@ jest.mock('config', () => ({
authsome: {
mode: 'authsome',
},
'pubsweet-component-xpub-dashboard': {
acceptUploadFiles: [
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/x-latex',
'text/vnd.latex-z',
'text/x-tex',
'application/pdf',
'application/epub+zip',
'application/zip',
],
},
}))
// Mock out the API
......
......@@ -4,9 +4,20 @@ import { withRouter } from 'react-router-dom'
import { actions } from 'pubsweet-client'
import { newestFirst, selectCurrentUser } from 'xpub-selectors'
import { ConnectPage } from 'xpub-connect'
import { uploadManuscript } from '../redux/conversion'
import config from 'config'
import {
uploadManuscript,
uploadManuscriptNoConversion,
} from '../redux/conversion'
import Dashboard from './Dashboard'
const { acceptUploadFiles } = config['pubsweet-component-xpub-dashboard'] || {}
const acceptFiles =
acceptUploadFiles.length > 0
? acceptUploadFiles.join()
: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
const reviewerResponse = (project, version, reviewer, status) => dispatch => {
reviewer.status = status
......@@ -34,7 +45,13 @@ export default compose(
const dashboard = newestFirst(collections)
return { collections, conversion, currentUser, dashboard }
return {
acceptFiles,
collections,
conversion,
currentUser,
dashboard,
}
},
(dispatch, { history }) => ({
deleteProject: collection => {
......@@ -45,8 +62,16 @@ export default compose(
},
reviewerResponse: (project, version, reviewer, status) =>
dispatch(reviewerResponse(project, version, reviewer, status)),
uploadManuscript: acceptedFiles =>
dispatch(uploadManuscript(acceptedFiles, history)),
uploadManuscript: acceptedFiles => {
if (
acceptedFiles[0].type ===
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
) {
dispatch(uploadManuscript(acceptedFiles, history))
} else {
dispatch(uploadManuscriptNoConversion(acceptedFiles, history))
}
},
}),
),
withRouter,
......
......@@ -202,11 +202,11 @@ class UploadManuscript extends Component {
}
render() {
const { uploadManuscript, conversion } = this.props
const { acceptFiles, uploadManuscript, conversion } = this.props
return (
<StyledDropzone
accept="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
accept={acceptFiles}
disableUpload={this.status === 'converting' ? 'disableUpload' : null}
onDrop={uploadManuscript}
>
......@@ -229,6 +229,8 @@ class UploadManuscript extends Component {
<SubInfo>
{this.status === 'converting' &&
'Your manuscript is being converted into a directly editable version. This might take a while.'}
{this.status !== 'converting' &&
'Accepted file types: pdf, epub, zip, docx, latex'}
</SubInfo>
</Root>
</StyledDropzone>
......
......@@ -26,7 +26,10 @@ export const uploadManuscriptFailure = error => ({
type: UPLOAD_MANUSCRIPT_FAILURE,
})
export const uploadManuscript = (acceptedFiles, history) => dispatch => {
export const uploadManuscriptNoConversion = (
acceptedFiles,
history,
) => dispatch => {
if (acceptedFiles.length > 1) {
throw new Error('Only one manuscript file can be uploaded')
}
......@@ -34,8 +37,20 @@ export const uploadManuscript = (acceptedFiles, history) => dispatch => {
const inputFile = acceptedFiles[0]
dispatch(uploadManuscriptRequest())
startUploadFile(inputFile, dispatch, request => {
const fileURL = request.responseText
return createFragmentVersion(
dispatch,
inputFile,
fileURL,
{ converted: '' },
history,
)
})
}
const request = dispatch(uploadFile(inputFile))
const startUploadFile = (file, dispatch, load) => {
const request = dispatch(uploadFile(file))
request.addEventListener('load', event => {
if (request.status >= 400) {
......@@ -46,57 +61,79 @@ export const uploadManuscript = (acceptedFiles, history) => dispatch => {
)
throw new Error('There was an error uploading the file')
}
load(request)
})
}
const createFragmentVersion = (
dispatch,
inputFile,
fileURL,
response,
history,
) => {
const source = response.converted
const title = extractTitle(source) || generateTitle(inputFile.name)
dispatch(actions.createCollection({ title })).then(({ collection }) => {
if (!collection.id) {
throw new Error('Failed to create a project')
}
const fileURL = request.responseText
// TODO: rethrow errors so they can be caught here
return dispatch(
actions.createFragment(collection, {
created: new Date(), // TODO: set on server
collections: [collection.id],
files: {
manuscript: {
name: inputFile.name,
url: fileURL,
type: inputFile.type,
},
supplementary: [],
},
fragmentType: 'version',
metadata: {
title,
},
source,
version: 1,
}),
).then(({ fragment }) => {
dispatch(uploadManuscriptSuccess(collection, fragment))
const route = `/projects/${collection.id}/versions/${fragment.id}/submit`
// redirect after a short delay
window.setTimeout(() => {
history.push(route)
}, 2000)
})
})
}
export const uploadManuscript = (acceptedFiles, history) => dispatch => {
if (acceptedFiles.length > 1) {
throw new Error('Only one manuscript file can be uploaded')
}
const inputFile = acceptedFiles[0]
dispatch(uploadManuscriptRequest())
startUploadFile(inputFile, dispatch, request => {
const fileURL = request.responseText
dispatch(ink(inputFile, { recipe: 'editoria-typescript' }))
.then(response => {
if (!response.converted) {
throw new Error('The file was not converted')
}
const source = response.converted
const title = extractTitle(source) || generateTitle(inputFile.name)
return dispatch(actions.createCollection({ title })).then(
({ collection }) => {
if (!collection.id) {
throw new Error('Failed to create a project')
}
// TODO: create teams?
// TODO: rethrow errors so they can be caught here
return dispatch(
actions.createFragment(collection, {
created: new Date(), // TODO: set on server
collections: [collection.id],
files: {
manuscript: {
name: inputFile.name,
url: fileURL,
},
supplementary: [],
},
fragmentType: 'version',
metadata: {
title,
},
source,
version: 1,
}),
).then(({ fragment }) => {
dispatch(uploadManuscriptSuccess(collection, fragment))
const route = `/projects/${collection.id}/versions/${
fragment.id
}/submit`
// redirect after a short delay
window.setTimeout(() => {
history.push(route)
}, 2000)
})
},
return createFragmentVersion(
dispatch,
inputFile,
fileURL,
response,
history,
)
})
.catch(error => {
......
......@@ -26,6 +26,17 @@ const MainEditorStyled = styled(MainEditor)`
cursor: col-resize;
}
`
const Info = styled.span`
padding: 0;
margin: 0;
list-style: none;
display: flex;
align-items: center;
justify-content: center;
height: 500px;
`
const Manuscript = ({
content,
currentUser,
......@@ -33,12 +44,16 @@ const Manuscript = ({
history,
updateManuscript,
version,
}) => (
<MainEditorStyled
fileUpload={fileUpload}
onChange={source => updateManuscript({ source })}
value={content}
/>
)
}) =>
version.files.manuscript.type ===
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ? (
<MainEditorStyled
fileUpload={fileUpload}
onChange={source => updateManuscript({ source })}
value={content}
/>
) : (
<Info>No supported view of the file</Info>
)
export default withRouter(Manuscript)
......@@ -9,6 +9,7 @@ import AssignEditorsReviewers from '../assignEditors/AssignEditorsReviewers'
import ReviewMetadata from '../metadata/ReviewMetadata'
import Decision from './Decision'
import { Columns, Manuscript, Admin } from '../atoms/Columns'
import { Info } from '../molecules/Info'
import AdminSection from '../atoms/AdminSection'
// TODO -- is passing arrays of react components as props an ok practice?
......@@ -49,15 +50,19 @@ const DecisionLayout = ({
})
editorSections.push({
content: (
<SimpleEditor
content={version.source}
editing="selection"
key={version.id}
layout="bare"
readOnly
/>
),
content:
version.files.manuscript.type ===
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ? (
<SimpleEditor
content={version.source}
editing="selection"
key={version.id}
layout="bare"
readOnly
/>
) : (
<Info>No supported view of the file</Info>
),
key: version.id,
label,
})
......@@ -99,15 +104,19 @@ const DecisionLayout = ({
})
editorSections.push({
content: (
<SimpleEditor
content={currentVersion.source}
editing="selection"
key={currentVersion.id}
layout="bare"
readOnly
/>
),
content:
currentVersion.files.manuscript.type ===
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ? (
<SimpleEditor
content={currentVersion.source}
editing="selection"
key={currentVersion.id}
layout="bare"
readOnly
/>
) : (
<Info>No supported view of the file</Info>
),
key: currentVersion.id,
label,
})
......
import styled from 'styled-components'
const Info = styled.span`
padding: 0;
margin: 0;
list-style: none;
display: flex;
align-items: center;
justify-content: center;
height: 500px;
`
export { Info }
import React from 'react'
import moment from 'moment'
// import classnames from 'classnames'
import { Tabs } from '@pubsweet/ui'
import SimpleEditor from 'wax-editor-react'
......@@ -9,6 +8,7 @@ import ReviewForm from './ReviewForm'
import ReviewMetadata from '../metadata/ReviewMetadata'
import Review from './Review'
import { Columns, Manuscript, Admin } from '../atoms/Columns'
import { Info } from '../molecules/Info'
const ReviewLayout = ({
project,
......@@ -52,15 +52,19 @@ const ReviewLayout = ({
// TODO: need to include unreviewed versions?
editorSections.push({
content: (
<SimpleEditor
content={version.source}
editing="selection"
key={key}
layout="bare"
readOnly
/>
),
content:
lastSubmitted.files.manuscript.type ===
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ? (
<SimpleEditor
content={lastSubmitted.source}
editing="selection"
key={key}
layout="bare"
readOnly
/>
) : (
<Info>No supported view of the file</Info>
),
key,
label,
})
......@@ -96,15 +100,19 @@ const ReviewLayout = ({
})
editorSections.push({
content: (
<SimpleEditor
content={lastSubmitted.source}
editing="selection"
key={key}
layout="bare"
readOnly
/>
),
content:
lastSubmitted.files.manuscript.type ===
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ? (
<SimpleEditor
content={lastSubmitted.source}
editing="selection"
key={key}
layout="bare"
readOnly
/>
) : (
<Info>No supported view of the file</Info>
),
key,
label,
})
......
import React from 'react'
import styled from 'styled-components'
import { Link } from 'react-router-dom'
import { Button } from '@pubsweet/ui'
import { Button, Attachment } from '@pubsweet/ui'
import { th } from '@pubsweet/ui-toolkit'
import Metadata from './MetadataFields'
import Declarations from './Declarations'
......@@ -10,7 +10,7 @@ import Notes from './Notes'
import SupplementaryFiles from './SupplementaryFiles'
import Confirm from './Confirm'
import { Heading1 } from '../styles'
import { Heading1, Section, Legend } from '../styles'
// import Validots from './Validots'
const Wrapper = styled.div`
......@@ -77,6 +77,17 @@ const CurrentVersion = ({
uploadFile={uploadFile}
version={version}
/>
{version.files.manuscript.type !==
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' && (
<Section id="files.manuscript">
<Legend space>Submitted Manuscript</Legend>
<Attachment
file={version.files.manuscript}
key={version.files.manuscript.url}
uploaded
/>
</Section>
)}
{!version.submitted && (
<div>
......@@ -85,7 +96,6 @@ const CurrentVersion = ({
</Button>
</div>
)}
{confirming && (
<ModalWrapper>
<Confirm toggleConfirming={toggleConfirming} />
......
Markdown is supported
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