Commit e698e286 authored by Giannis Kopanas's avatar Giannis Kopanas
Browse files

update fields from form builder

parent 1acaa850
Pipeline #10351 passed with stages
in 9 minutes and 29 seconds
import React from 'react'
import { branch, renderComponent } from 'recompose'
import styled, { css } from 'styled-components'
import { FormSection } from 'redux-form'
import ReactHtmlParser from 'react-html-parser'
import { ValidatedField, RadioGroup } from '@pubsweet/ui'
import { th } from '@pubsweet/ui-toolkit'
import { withJournal } from 'xpub-journal'
import { required } from 'xpub-validators'
import { Section, Legend, SubNote } from './styles'
const hoverStyles = css`
background-image: linear-gradient(to right, #666 50%, white 0%);
background-position: 0 90%;
background-repeat: repeat-x;
background-size: 6px 1px;
position: relative;
`
const DeclarationSection = Section.extend`
margin: calc(${th('gridUnit')} * 6) 0;
`
const Question = styled.div`
display: flex;
justify-content: space-between;
margin-bottom: ${th('gridUnit')};
&:hover {
${props => !props.readonly && hoverStyles};
}
`
const DeclarationsEditable = ({ journal, readonly }) => (
<FormSection name="declarations">
{journal.declarations.questions.map(question => (
<DeclarationSection id={`declarations.${question.id}`} key={question.id}>
<Question>
<Legend>{ReactHtmlParser(question.legend)}</Legend>
<ValidatedField
component={props => (
<RadioGroup inline options={question.options} {...props} />
)}
name={question.id}
readonly={readonly}
required
validate={[required]}
/>
</Question>
<SubNote>{ReactHtmlParser(question.description)}</SubNote>
</DeclarationSection>
))}
</FormSection>
)
const DeclarationsNonEditable = ({ journal, readonly, version }) => (
<div>
{version.metadata.articleType && (
<DeclarationSection>
<Legend>Type of article</Legend>
{version.metadata.articleType}
</DeclarationSection>
)}
{journal.declarations.questions.map(question => (
<DeclarationSection>
<Legend>{ReactHtmlParser(question.legend)}</Legend>
{version.declarations[question.id]}
</DeclarationSection>
))}
</div>
)
export default withJournal(
branch(
({ readonly }) => readonly === true,
renderComponent(DeclarationsNonEditable),
)(DeclarationsEditable),
)
import React from 'react'
import styled from 'styled-components'
import { branch, renderComponent } from 'recompose'
import { FormSection } from 'redux-form'
import { AbstractEditor, TitleEditor } from 'xpub-edit'
import { CheckboxGroup, Menu, TextField, ValidatedField } from '@pubsweet/ui'
import { withJournal } from 'xpub-journal'
import {
join,
required,
minChars,
maxChars,
minSize,
split,
} from 'xpub-validators'
import AuthorsInput from './AuthorsInput'
import { Section, Legend } from './styles'
const minSize1 = minSize(1)
const minChars10 = minChars(10)
const minChars100 = minChars(100)
const maxChars500 = maxChars(500)
const maxChars5000 = maxChars(5000)
const TitleInput = ({ validationStatus, ...input }) => (
<TitleEditor placeholder="Enter the title…" title="Title" {...input} />
)
const AbstractInput = ({ validationStatus, ...input }) => (
<AbstractEditor
placeholder="Enter the abstract…"
title="Abstract"
{...input}
/>
)
const Abstract = styled.div`
word-wrap: break-word;
`
const KeywordsInput = input => (
<TextField placeholder="Enter keywords…" {...input} />
)
const ArticleTypeInput = journal => input => (
<Menu options={journal.articleTypes} {...input} />
)
const ArticleSectionInput = journal => input => (
<CheckboxGroup options={journal.articleSections} {...input} />
)
const MetadataFieldsEditable = ({ journal, readonly }) => (
<FormSection name="metadata">
<Section id="metadata.title">
<ValidatedField
component={TitleInput}
name="title"
readonly={readonly}
required
validate={[minChars10, maxChars500]}
/>
</Section>
<Section id="metadata.abstract">
<ValidatedField
component={AbstractInput}
name="abstract"
readonly={readonly}
required
validate={[minChars100, maxChars5000]}
/>
</Section>
<Section id="metadata.authors">
<Legend space>Authors</Legend>
<ValidatedField
component={AuthorsInput}
name="authors"
readonly={readonly}
required
validate={[minSize1]}
/>
</Section>
<Section id="metadata.keywords">
<Legend space>Keywords</Legend>
<ValidatedField
component={KeywordsInput}
format={join()}
name="keywords"
parse={split()}
readonly={readonly}
required
validate={[minSize1]}
/>
</Section>
<Section id="metadata.articleType">
<Legend space>Type of article</Legend>
<ValidatedField
component={ArticleTypeInput(journal)}
name="articleType"
readonly={readonly}
required
validate={[required]}
/>
</Section>
<Section id="metadata.articleSection">
<Legend space>Section</Legend>
<ValidatedField
component={ArticleSectionInput(journal)}
name="articleSection"
readonly={readonly}
required
validate={[required]}
/>
</Section>
</FormSection>
)
const MetadataFieldsNonEditable = ({ version, journal, readonly }) => [
<Section id="metadata.title">
<Legend>Title</Legend>
<div>{version.metadata.title}</div>
</Section>,
<Section id="metadata.abstract">
<Legend>Abstract</Legend>
<Abstract>{version.metadata.abstract}</Abstract>
</Section>,
<Section id="metadata.keywords">
{version.metadata.keywords && [
<Legend>Keywords</Legend>,
<div>{version.metadata.keywords.join(', ')}</div>,
]}
</Section>,
]
export default withJournal(
branch(
({ readonly }) => readonly === true,
renderComponent(MetadataFieldsNonEditable),
)(MetadataFieldsEditable),
)
import React from 'react'
import styled from 'styled-components'
import { withJournal } from 'xpub-journal'
import { Attachment } from '@pubsweet/ui'
const Root = styled.div``
const Title = styled.div``
const Table = styled.table`
border-spacing: 0;
`
const Heading = styled.span`
font-weight: inherit;
padding: 0 1em 0 0;
white-space: nowrap;
text-align: right;
flex-grow: 0;
flex-shrink: 0;
flex-basis: 50%;
`
const Metadata = styled.div`
div {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
`
const Cell = styled.span`
padding: 0;
flex-grow: 0;
flex-shrink: 0;
flex-basis: 50%;
`
const arrayToText = text => (text.length === 0 ? ['none'] : text).join(', ')
const ReviewMetadata = ({ version, handlingEditors, journal }) => (
<Root>
<Title>Metadata</Title>
<Metadata>
<div>
{version.declarations.openPeerReview && [
<Heading>Open Peer Review :</Heading>,
<Cell>
{version.declarations.openPeerReview === 'yes' ? 'Yes' : 'No'}
</Cell>,
]}
</div>
<div>
{version.declarations.streamlinedReview && [
<Heading>Streamlined Review :</Heading>,
<Cell>
{version.declarations.streamlinedReview === 'yes'
? 'Please view supplementary uploaded files'
: 'No'}
</Cell>,
]}
</div>
<div>
{version.declarations.researchNexus && [
<Heading>Part of Research Nexus :</Heading>,
<Cell>
{version.declarations.researchNexus === 'yes' ? 'Yes' : 'No'}
</Cell>,
]}
</div>
<div>
{version.declarations.preregistered && [
<Heading>Pre-registered :</Heading>,
<Cell>
{version.declarations.preregistered === 'yes' ? 'Yes' : 'No'}
</Cell>,
]}
</div>
<div>
{((version.suggestions || {}).reviewers || {}).suggested && [
<Heading>Suggested Reviewers :</Heading>,
<Cell>
{arrayToText(
((version.suggestions || {}).reviewers || {}).suggested || [],
)}
</Cell>,
]}
</div>
<div>
{((version.suggestions || {}).reviewers || {}).opposed && [
<Heading>Opposed Reviewers :</Heading>,
<Cell>
{arrayToText(
((version.suggestions || {}).reviewers || {}).opposed || [],
)}
</Cell>,
]}
</div>
<div>
{((version.suggestions || {}).editors || {}).suggested && [
<Heading>Suggested Editors :</Heading>,
<Cell>
{arrayToText(
((version.suggestions || {}).editors || {}).suggested || [],
)}
</Cell>,
]}
</div>
<div>
{((version.suggestions || {}).editors || {}).opposed && [
<Heading>Opposed Editors :</Heading>,
<Cell>
{arrayToText(
((version.suggestions || {}).editors || {}).opposed || [],
)}
</Cell>,
]}
</div>
<div>
{(version.notes || {}).specialInstructions && [
<Heading>Special Instructions :</Heading>,
<Cell>
{((version.notes || {}).specialInstructions || '') === '' && 'none'}
{(version.notes || {}).specialInstructions || ''}
</Cell>,
]}
</div>
{version.files.supplementary.length > 0 && (
<div>
<Heading>
{version.files.supplementary.length} supplementary{' '}
{version.files.supplementary.length === 1 ? 'file' : 'files'} :
</Heading>
{!!version.files.supplementary.length && (
<Cell>
{version.files.supplementary.map(file => (
<Attachment file={file} key={file.url} uploaded />
))}
</Cell>
)}
</div>
)}
</Metadata>
<Table>
<tbody>
{!!handlingEditors && (
<tr>
<Heading>handling editor:</Heading>
<Cell>
{handlingEditors.map(user => (
<span key={user.username}>{user.username}</span>
))}
</Cell>
</tr>
)}
</tbody>
</Table>
</Root>
)
export default withJournal(ReviewMetadata)
import React from 'react'
import { branch, renderComponent } from 'recompose'
import { FormSection } from 'redux-form'
import { TextField, ValidatedField } from '@pubsweet/ui'
import { th } from '@pubsweet/ui-toolkit'
import { join, split } from 'xpub-validators'
import { Section, Legend } from './styles'
const joinComma = join(',')
const splitComma = split(',')
const SuggestedReviewerInput = input => (
<TextField placeholder="Add reviewer names" {...input} />
)
const OpposedReviewerInput = input => (
<TextField placeholder="Add reviewer names" {...input} />
)
const SuggestedEditorInput = input => (
<TextField placeholder="Add editor names" {...input} />
)
const OpposedEditorInput = input => (
<TextField placeholder="Add editor names" {...input} />
)
const SubLegend = Legend.extend`
font-weight: normal;
margin-top: calc(${th('gridUnit')} * 3);
`
const SuggestionsEditable = ({ readonly }) => (
<FormSection name="suggestions">
<Section id="suggestions.reviewers">
<FormSection name="reviewers">
<Legend>Suggested or opposed reviewers</Legend>
<div>
<SubLegend space>Suggested reviewers</SubLegend>
<ValidatedField
component={SuggestedReviewerInput}
format={joinComma}
name="suggested"
parse={splitComma}
readonly={readonly}
/>
</div>
<div>
<SubLegend space>Opposed reviewers</SubLegend>
<ValidatedField
component={OpposedReviewerInput}
format={joinComma}
name="opposed"
parse={splitComma}
readonly={readonly}
/>
</div>
</FormSection>
</Section>
<Section id="suggestions.editors">
<FormSection name="editors">
<Legend>Suggested or opposed editors</Legend>
<div>
<SubLegend space>Suggested editors</SubLegend>
<ValidatedField
component={SuggestedEditorInput}
format={joinComma}
name="suggested"
parse={splitComma}
readonly={readonly}
/>
</div>
<div>
<SubLegend space>Opposed editors</SubLegend>
<ValidatedField
component={OpposedEditorInput}
format={joinComma}
name="opposed"
parse={splitComma}
readonly={readonly}
/>
</div>
</FormSection>
</Section>
</FormSection>
)
const SuggestionsNonEditable = ({ readonly, version }) => {
const suggestions = version.suggestions || {}
return [
<Section id="suggestions.reviewers">
{suggestions.reviewers && [
<Legend>Suggested or opposed reviewers</Legend>,
<SubLegend>Suggested reviewers</SubLegend>,
<div>{suggestionsText(suggestions.reviewers, 'suggested')}</div>,
<SubLegend>Opposed reviewers</SubLegend>,
<div>{suggestionsText(suggestions.reviewers, 'opposed')}</div>,
]}
</Section>,
<Section id="suggestions.editors">
{suggestions.editors && [
<Legend>Suggested or opposed editors</Legend>,
<SubLegend>Suggested editors</SubLegend>,
<div>{suggestionsText(suggestions.editors, 'suggested')}</div>,
<SubLegend>Opposed editors</SubLegend>,
<div>{suggestionsText(suggestions.editors, 'opposed')}</div>,
]}
</Section>,
]
}
const suggestionsText = (source, property) => {
if (source && Array.isArray(source[property]) && !!source[property].length) {
return source[property].join(', ')
}
return 'none'
}
export default branch(
({ readonly }) => readonly === true,
renderComponent(SuggestionsNonEditable),
)(SuggestionsEditable)
import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit'
export const Heading1 = styled.h1`
margin: 0 0 calc(${th('gridUnit')} * 3);
font-size: ${th('fontSizeHeading1')};
line-height: ${th('lineHeightHeading1')};
`
export const Section = styled.div`
margin: calc(${th('gridUnit')} * 6) 0;
display: flex;
flex-direction: ${({ cssOverrides }) =>
cssOverrides && cssOverrides['flex-direction']
? cssOverrides['flex-direction']
: 'column'};
flex-wrap: ${({ cssOverrides }) =>
cssOverrides && cssOverrides.wrap ? cssOverrides.wrap : 'nowrap'};
justify-content: space-between;
`
export const Legend = styled.div`
font-size: ${th('fontSizeBase')};
font-weight: 600;
margin-bottom: ${({ space, theme }) => space && theme.gridUnit};
`
export const SubNote = styled.span`
font-size: ${th('fontSizeBaseSmall')};
line-height: ${th('lineHeightBaseSmall')};
color: ${th('colorTextPlaceholder')};
width: 100%;
`
export default {
questions: [
{
id: 'openData',
legend: 'Data is open ?',
options: [
{
label: 'Yes',
value: 'yes',
},
{
label: 'No/Not Applicable',
value: 'no',
},
],
description:
'The journal requires data be openly available, and our full policy is <a href="https://www.collabra.org/about/editorialpolicies/#open-data-open-analytic-methods-code-and-research-materials-transparency" target="_blank">here</a>. If you have exceptions that need to be considered, please click "No" and explain in your cover letter below. Please click N/A if your submission does not feature data.',
},
{
id: 'previouslySubmitted',
legend: 'Previously submitted ?',
options: [
{
label: 'Yes',
value: 'yes',
},
{
label: 'No',
value: 'no',
},
],
description:
'Provide further details in your cover letter below, if necessary.',
},
{
id: 'openPeerReview',
legend: 'Open peer review ?',
options: [
{
label: 'Yes',
value: 'yes',
},
{
label: 'No',
value: 'no',