Skip to content
Snippets Groups Projects
Commit 631e1f5b authored by Sebastian Mihalache's avatar Sebastian Mihalache
Browse files

:Merge branch 'develop' of gitlab.coko.foundation:xpub/xpub-faraday into develop

parents 82c486b3 f92f5fad
No related branches found
No related tags found
1 merge request!8Sprint #10
Showing
with 524 additions and 5 deletions
...@@ -11,7 +11,7 @@ stages: ...@@ -11,7 +11,7 @@ stages:
- demo - demo
build: build:
image: docker:latest image: docker:stable
stage: build stage: build
script: script:
- docker version - docker version
......
...@@ -30,7 +30,7 @@ const Container = styled.div` ...@@ -30,7 +30,7 @@ const Container = styled.div`
const SideBar = styled.div` const SideBar = styled.div`
flex: ${({ flex }) => flex || 1}; flex: ${({ flex }) => flex || 1};
background-color: ${th('colorBackground')}; background-color: ${th('colorBackground')};
padding: 0 ${th('subGridUnit')}; padding: ${th('subGridUnit')};
` `
const Header = styled.div` const Header = styled.div`
......
import React from 'react'
import { th } from '@pubsweet/ui'
import styled from 'styled-components'
const TR = ({ name, email, affiliation }) => (
<Row>
<td>{name}</td>
<td>{email}</td>
<td>{affiliation}</td>
</Row>
)
const Authors = ({ authors }) => (
<Table>
<thead>
<tr>
<td>Full Name</td>
<td>Email</td>
<td>Affiliation</td>
</tr>
</thead>
<tbody>
{authors.map(
({ firstName = '', lastName = '', email = '', affiliation = '' }) => (
<TR
affiliation={affiliation}
email={email}
key={email}
name={`${firstName} ${lastName}`}
/>
),
)}
</tbody>
</Table>
)
export default Authors
// #region styled-components
const Row = styled.tr`
border-bottom: ${th('borderDefault')};
color: ${th('colorPrimary')};
font-family: ${th('fontReading')};
font-size: ${th('fontSizeBaseSmall')};
height: 40px;
text-align: left;
&:hover {
background-color: ${th('backgroundColorReverse')};
}
`
const Table = styled.table`
border-spacing: 0;
border-collapse: collapse;
width: 100%;
& thead tr {
border-bottom: ${th('borderDefault')};
color: ${th('colorPrimary')};
font-family: ${th('fontReading')};
font-size: ${th('fontSizeBaseSmall')};
font-weight: bold;
height: 40px;
text-align: left;
}
`
// #endregion
import React from 'react'
import styled from 'styled-components'
import { th, Icon } from '@pubsweet/ui'
import { compose, withState, withHandlers } from 'recompose'
const Expandable = ({ expanded, label, children, toggle }) => (
<Root expanded={expanded}>
<Header onClick={toggle}>
<Chevron expanded={expanded}>
<Icon primary size={3}>
chevron_up
</Icon>
</Chevron>
<SectionLabel>{label}</SectionLabel>
</Header>
{expanded && <ChildrenContainer>{children}</ChildrenContainer>}
</Root>
)
export default compose(
withState('expanded', 'setExpanded', ({ startExpanded }) => startExpanded),
withHandlers({
toggle: ({ setExpanded }) => () => {
setExpanded(e => !e)
},
}),
)(Expandable)
// #region styled-components
const Chevron = styled.div`
align-items: center;
height: calc(${th('subGridUnit')} * 5);
display: flex;
justify-content: center;
transform: ${({ expanded }) => `rotateZ(${expanded ? 0 : 180}deg)`};
transition: transform 0.2s;
width: calc(${th('subGridUnit')} * 5);
`
const SectionLabel = styled.span`
color: ${th('colorPrimary')};
font-family: ${th('fontHeading')};
font-size: ${th('fontSizeBase')};
text-transform: uppercase;
`
const ChildrenContainer = styled.div`
cursor: default;
padding: calc(${th('subGridUnit')} * 3);
padding-top: 0;
`
const Header = styled.div`
align-items: center;
border-bottom: ${th('borderDefault')};
margin-bottom: calc(${th('subGridUnit')} * 3);
cursor: pointer;
display: flex;
justify-content: flex-start;
`
const Root = styled.div`
cursor: pointer;
display: flex;
flex-direction: column;
transition: all 0.3s;
`
// #endregion
import React, { Fragment } from 'react'
import { last } from 'lodash'
import styled, { css } from 'styled-components'
import { th, Icon } 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>
)
const Files = ({
previewFile,
downloadFile,
files: { manuscripts = [], coverLetter = [], supplementary = [] },
}) => (
<Root>
{!!manuscripts.length && (
<Fragment>
<Header>
<span>Main manuscript</span>
<div />
</Header>
{manuscripts.map(file => (
<File
key={file.id}
{...file}
downloadFile={downloadFile}
previewFile={previewFile}
/>
))}
</Fragment>
)}
{!!supplementary.length && (
<Fragment>
<Header>
<span>Supplemetary files</span>
<div />
</Header>
{supplementary.map(file => (
<File
key={file.id}
{...file}
downloadFile={downloadFile}
previewFile={previewFile}
/>
))}
</Fragment>
)}
{!!coverLetter.length && (
<Fragment>
<Header>
<span>Cover letter</span>
<div />
</Header>
{coverLetter.map(file => (
<File
key={file.id}
{...file}
downloadFile={downloadFile}
previewFile={previewFile}
/>
))}
</Fragment>
)}
</Root>
)
export default Files
// #region styled-component
const defaultText = css`
color: ${th('colorPrimary')};
font-family: ${th('fontHeading')};
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;
display: flex;
flex-direction: row;
& span {
${defaultText};
margin-right: ${th('subGridUnit')};
margin-top: ${th('subGridUnit')};
text-transform: uppercase;
}
& div {
background: ${th('colorPrimary')};
flex: 1;
height: 1px;
}
`
const Root = styled.div`
align-items: flex-start;
display: flex;
flex-direction: column;
justify-content: flex-start;
`
// #endregion
import React from 'react'
import { isEmpty } from 'lodash'
import { th } from '@pubsweet/ui'
import styled from 'styled-components'
import { Authors, Expandable, Files } from './'
const ManuscriptDetails = ({
previewFile,
downloadFile,
collection: { authors = [] },
fragment: { conflicts = {}, files = {}, metadata: { abstract = '' } },
}) => (
<Root>
<Expandable label="Details" startExpanded>
{!!abstract && (
<Expandable label="abstract" startExpanded>
<Text dangerouslySetInnerHTML={{ __html: abstract }} />
</Expandable>
)}
{conflicts.hasConflicts === 'yes' && (
<Expandable label="Conflict of interest">
<Text>{conflicts.message}</Text>
</Expandable>
)}
{!!authors.length && (
<Expandable label="authors">
<Authors authors={authors} />
</Expandable>
)}
{!isEmpty(files) && (
<Expandable label="files">
<Files
downloadFile={downloadFile}
files={files}
previewFile={previewFile}
/>
</Expandable>
)}
</Expandable>
</Root>
)
export default ManuscriptDetails
// #region styled-components
const Text = styled.span`
color: ${th('colorPrimary')};
font-family: ${th('fontReading')};
font-size: ${th('fontSizeBaseSmall')};
`
const Root = styled.div`
background-color: ${th('colorBackground')};
border: ${th('borderDefault')};
margin-top: calc(${th('subGridUnit')} * 2);
transition: height 0.3s;
`
// #endregion
...@@ -12,6 +12,7 @@ import { ...@@ -12,6 +12,7 @@ import {
LeftDetails, LeftDetails,
RightDetails, RightDetails,
} from '../atoms' } from '../atoms'
import { ManuscriptDetails, SideBarActions, SideBarRoles } from './'
const ManuscriptLayout = ({ const ManuscriptLayout = ({
currentUser, currentUser,
...@@ -19,6 +20,8 @@ const ManuscriptLayout = ({ ...@@ -19,6 +20,8 @@ const ManuscriptLayout = ({
project, project,
version, version,
journal, journal,
previewFile,
downloadFile,
}) => ( }) => (
<Root> <Root>
<Container flex={3}> <Container flex={3}>
...@@ -35,8 +38,17 @@ const ManuscriptLayout = ({ ...@@ -35,8 +38,17 @@ const ManuscriptLayout = ({
</RightDetails> </RightDetails>
</Header> </Header>
<ManuscriptHeader journal={journal} project={project} version={version} /> <ManuscriptHeader journal={journal} project={project} version={version} />
<ManuscriptDetails
collection={project}
downloadFile={downloadFile}
fragment={version}
previewFile={previewFile}
/>
</Container> </Container>
<SideBar flex={1}>Sidebar</SideBar> <SideBar flex={1}>
<SideBarActions project={project} version={version} />
<SideBarRoles project={project} version={version} />
</SideBar>
</Root> </Root>
) )
......
...@@ -9,10 +9,11 @@ import { ...@@ -9,10 +9,11 @@ import {
} from 'xpub-selectors' } from 'xpub-selectors'
import { replace } from 'react-router-redux' import { replace } from 'react-router-redux'
import { compose, lifecycle, withHandlers } from 'recompose' import { compose, lifecycle, withHandlers } from 'recompose'
import { reviewerDecision } from 'pubsweet-components-faraday/src/redux/reviewers'
import { getSignedUrl } from 'pubsweet-components-faraday/src/redux/files'
import ManuscriptLayout from './ManuscriptLayout' import ManuscriptLayout from './ManuscriptLayout'
import { parseSearchParams, redirectToError } from './utils' import { parseSearchParams, redirectToError } from './utils'
import { reviewerDecision } from '../../../components-faraday/src/redux/reviewers'
export default compose( export default compose(
withJournal, withJournal,
...@@ -29,7 +30,12 @@ export default compose( ...@@ -29,7 +30,12 @@ export default compose(
project: selectCollection(state, match.params.project), project: selectCollection(state, match.params.project),
version: selectFragment(state, match.params.version), version: selectFragment(state, match.params.version),
}), }),
{ reviewerDecision, replace, updateVersion: actions.updateFragment }, {
reviewerDecision,
replace,
updateVersion: actions.updateFragment,
getSignedUrl,
},
), ),
lifecycle({ lifecycle({
componentDidMount() { componentDidMount() {
...@@ -50,5 +56,24 @@ export default compose( ...@@ -50,5 +56,24 @@ export default compose(
id: version.id, id: version.id,
...data, ...data,
}), }),
previewFile: ({ getSignedUrl }) => fileId => e => {
e.preventDefault()
getSignedUrl(fileId).then(({ signedUrl }) => {
const windowReference = window.open()
windowReference.location = signedUrl
})
},
downloadFile: ({ getSignedUrl }) => (fileId, fileName) => e => {
e.preventDefault()
getSignedUrl(fileId).then(({ signedUrl }) => {
const a = document.createElement('a')
a.href = `${signedUrl}`
a.download = fileName
a.target = '_blank'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
})
},
}), }),
)(ManuscriptLayout) )(ManuscriptLayout)
import React from 'react'
import { th, Button, Icon } from '@pubsweet/ui'
import styled, { css } from 'styled-components'
import ZipFiles from 'pubsweet-components-faraday/src/components/Dashboard/ZipFiles'
const SideBarActions = ({ project, version }) => (
<Root>
<ActionButton> Make Decision </ActionButton>
<ZipFiles archiveName={`ID-${project.customId}`} fragmentId={version.id}>
<ClickableIcon>
<Icon>download</Icon>
</ClickableIcon>
</ZipFiles>
</Root>
)
export default SideBarActions
// #region styled-components
const defaultText = css`
color: ${th('colorText')};
font-family: ${th('fontReading')};
font-size: ${th('fontSizeBaseSmall')};
`
const Root = styled.div`
border-bottom: ${th('borderDefault')};
display: flex;
justify-content: space-between;
padding: ${th('subGridUnit')};
`
const ActionButton = styled(Button)`
${defaultText};
align-items: center;
background-color: ${th('colorPrimary')};
color: ${th('colorTextReverse')};
display: flex;
padding: 4px 8px;
text-align: center;
height: calc(${th('subGridUnit')}*5);
text-transform: uppercase;
`
const ClickableIcon = styled.div`
margin: 0 ${th('subGridUnit')};
&:hover {
opacity: 0.7;
}
`
// #endregion
import React from 'react'
import { th, Button } from '@pubsweet/ui'
import { get } from 'lodash'
import styled, { css } from 'styled-components'
const getHE = project => {
const heName = get(project, 'handlingEditor.name')
if (heName) {
return <Name> {heName} </Name>
}
return <ActionButton>Assign</ActionButton>
}
const SideBarRoles = ({ project }) => (
<Root>
<Row>
<Text>Editor in Chief</Text>
<Name>John Snow</Name>
</Row>
<Row>
<Text>Handling Editor</Text>
{getHE(project)}
</Row>
</Root>
)
export default SideBarRoles
// #region styled-components
const defaultText = css`
color: ${th('colorText')};
font-family: ${th('fontReading')};
font-size: ${th('fontSizeBaseSmall')};
`
const Root = styled.div`
display: flex;
flex-direction: column;
padding: calc(${th('subGridUnit')}*3) ${th('subGridUnit')};
`
const Text = styled.div`
${defaultText};
text-transform: uppercase;
`
const Name = styled.div`
${defaultText};
text-decoration: underline;
`
const Row = styled.div`
display: flex;
justify-content: space-between;
`
const ActionButton = styled(Button)`
${defaultText};
align-items: center;
background-color: ${th('colorBackground')};
padding: 4px 8px;
text-align: center;
height: calc(${th('subGridUnit')}*5);
text-transform: uppercase;
margin: 0;
`
// #endregion
export { default as Files } from './Files'
export { default as Authors } from './Authors'
export { default as Expandable } from './Expandable'
export { default as ManuscriptPage } from './ManuscriptPage' export { default as ManuscriptPage } from './ManuscriptPage'
export { default as ManuscriptDetails } from './ManuscriptDetails'
export { default as SideBarActions } from './SideBarActions'
export { default as SideBarRoles } from './SideBarRoles'
export { default as authors } from './authors' export { default as authors } from './authors'
export { default as editors } from './editors' export { default as editors } from './editors'
export { default as files } from './files'
export { default as reviewers } from './reviewers'
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