import React from 'react' import { get } from 'lodash' import PropTypes from 'prop-types' import { connect } from 'react-redux' import styled from 'styled-components' import { withRouter } from 'react-router-dom' import { change as changeForm } from 'redux-form' import { compose, lifecycle, withState, getContext, withContext, withHandlers, } from 'recompose' import { SortableList } from 'pubsweet-components-faraday/src/components' import FileSection from './FileSection' import { uploadFile, deleteFile, getRequestStatus, getSignedUrl, getFileError, } from '../../redux/files' const Files = ({ files, addFile, moveItem, removeFile, changeList, dropSortableFile, previewFile, error, ...rest }) => ( <div> <Error show={error}>Error uploading file, please try again.</Error> <FileSection addFile={addFile('manuscripts')} allowedFileExtensions={['pdf', 'doc', 'docx']} changeList={changeList} dropSortableFile={dropSortableFile} files={get(files, 'manuscripts') || []} isFirst listId="manuscripts" maxFiles={Number.POSITIVE_INFINITY} moveItem={moveItem('manuscripts')} previewFile={previewFile} removeFile={removeFile('manuscripts')} title="Main manuscript" /> <FileSection addFile={addFile('supplementary')} changeList={changeList} dropSortableFile={dropSortableFile} files={get(files, 'supplementary') || []} listId="supplementary" maxFiles={Number.POSITIVE_INFINITY} moveItem={moveItem('supplementary')} previewFile={previewFile} removeFile={removeFile('supplementary')} title="Supplementarry files" /> <FileSection addFile={addFile('coverLetter')} allowedFileExtensions={['pdf', 'doc', 'docx']} changeList={changeList} dropSortableFile={dropSortableFile} files={get(files, 'coverLetter') || []} isLast listId="coverLetter" maxFiles={1} moveItem={moveItem('coverLetter')} previewFile={previewFile} removeFile={removeFile('coverLetter')} title="Cover letter" /> </div> ) export default compose( withRouter, getContext({ version: PropTypes.object, project: PropTypes.object }), connect( state => ({ isFetching: getRequestStatus(state), error: getFileError(state), }), { changeForm, uploadFile, deleteFile, getSignedUrl, }, ), withState('files', 'setFiles', { manuscripts: [], coverLetter: [], supplementary: [], }), lifecycle({ componentDidMount() { const { version: { files }, setFiles } = this.props setFiles(prev => ({ manuscripts: get(files, 'manuscripts') || [], coverLetter: get(files, 'coverLetter') || [], supplementary: get(files, 'supplementary') || [], })) }, }), withHandlers({ previewFile: ({ getSignedUrl, files, getFileName }) => fileId => e => { e.preventDefault() const windowReference = window.open() getSignedUrl(fileId).then(({ signedUrl, ...rest }) => { windowReference.location = signedUrl }) }, dropSortableFile: ({ files, setFiles, changeForm }) => ( otherProps, dragProps, ) => { // do something if the file is not changing list const { listId: fromListId } = otherProps const { listId: toListId } = dragProps if (fromListId === toListId) { setFiles(files) changeForm('wizard', 'files', files) } }, changeList: ({ files, setFiles, changeForm }) => ( fromListId, toListId, id, ) => { const swappedFile = files[fromListId].find(f => f.id === id) const fromFiles = files[fromListId].filter(f => f.id !== id) const toFiles = [...files[toListId], swappedFile] const newFiles = { ...files, [toListId]: toFiles, [fromListId]: fromFiles, } setFiles(newFiles) changeForm('wizard', 'files', newFiles) }, addFile: ({ files, uploadFile, setFiles, changeForm, version, }) => type => file => { uploadFile(file, type, version.id) .then(file => { const newFiles = { ...files, [type]: [...files[type], file], } setFiles(newFiles) setTimeout(() => { changeForm('wizard', 'files', newFiles) }, 1000) }) .catch(e => console.error(`Couldn't upload file.`, e)) }, moveItem: ({ moveFiles, files, setFiles }) => type => ( dragIndex, hoverIndex, ) => { const newFiles = { ...files, [type]: SortableList.moveItem(files[type], dragIndex, hoverIndex), } setFiles(newFiles) }, removeFile: ({ setFiles, changeForm, files, deleteFile, version, }) => type => id => e => { e.preventDefault() deleteFile(id) const newFiles = { ...files, [type]: files[type].filter(f => f.id !== id), } setFiles(newFiles) changeForm('wizard', 'files', files) }, }), withContext( { isFetching: PropTypes.object, }, ({ isFetching }) => ({ isFetching, }), ), )(Files) // #region styles const Error = styled.div` color: firebrick; display: flex; justify-content: flex-end; margin: 5px 0; opacity: ${({ show }) => (show ? 1 : 0)}; ` // #endregion