Newer
Older
import React, { Fragment } from 'react'
import { isNumber, get } from 'lodash'
import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit'
import { required } from 'xpub-validators'
import { reduxForm, Field } from 'redux-form'
import {
Menu,
H3,
ValidatedField,
TextField,
Checkbox,
Spinner,
} from '@pubsweet/ui'
import {
compose,
withState,
withProps,
withHandlers,
setDisplayName,
} from 'recompose'
import { withCountries } from 'pubsweet-component-faraday-ui'
import { Tag, Label, Row, Item, PersonInfo, IconButton, OpenModal } from './'
import { validators } from './helpers'
const Empty = () => <div />
// #region AuthorTitle
const AuthorTitle = ({
deleteAuthor,
isAuthorEdit,
formSubmitting,
toggleEditMode,
isCorresponding,
}) => (
<Fragment>
{!editMode ? (
<Fragment>
{!isSubmitting && (
<OpenModal
isFetching={isFetching}
modalKey="deleteAuthor"
onConfirm={deleteAuthor}
subtitle={`${get(author, 'firstName', '')} ${get(
author,
'lastName',
'',
)}`}
title="Delete author?"
>
{showModal => (
<IconButton
icon="trash-2"
iconSize={2}
onClick={showModal}
right={48}
top={15}
/>
)}
</OpenModal>
)}
<IconButton
disabled={isAuthorEdit}
icon="edit-2"
iconSize={2}
onClick={toggleEditMode}
right={8}
top={15}
/>
</Fragment>
) : (
<Fragment>
<IconButton
onClick={toggleEditMode}
right={48}
{isFetching ? (
<StyledSpinner>
<Spinner />
</StyledSpinner>
) : (
<IconButton
disabled={formSubmitting}
icon="check-circle"
iconSize={2}
onClick={saveChanges}
right={8}
top={15}
/>
)}
</Fragment>
)}
<Row alignItems="center" justify="flex-start">
<H3>{isNumber(listIndex) ? `#${listIndex + 1} Author` : 'Author'}</H3>
{!editMode ? (
<AuthorTags>
{isSubmitting && <Tag mr={1}>SUBMITTING</Tag>}
{isCorresponding && <Tag mr={1}>CORRESPONDING</Tag>}
</AuthorTags>
) : (
<ValidatedField
component={({ value, onChange }) => (
<Checkbox
checked={value}
label="Corresponding"
onChange={onChange}
value={value}
/>
)}
name="isCorresponding"
/>
)}
</Row>
</Fragment>
)
// #endregion
// #region AuthorEdit
const AuthorEdit = ({
author,
editMode,
listIndex,

Alexandru Munteanu
committed
isFetching,
isSubmitting,
handleSubmit,
toggleEditMode,
isAuthorsFetching,
...props

Alexandru Munteanu
committed
<AuthorContainer>
<AuthorTitle
editMode={editMode}
formSubmitting={isSubmitting}
isAuthorsFetching={isAuthorsFetching}
isCorresponding={author.isCorresponding}

Alexandru Munteanu
committed
isFetching={isFetching}
isSubmitting={author.isSubmitting}
listIndex={listIndex}
saveChanges={handleSubmit}
toggleEditMode={toggleEditMode}
/>
<Field component={Empty} name="id" />
<Field component={Empty} name="isSubmitting" />
<Item mr={1} vertical>
<Label required>Email</Label>
<ValidatedField
component={TextField}
data-test-id="author-card-email"
validate={[required, validators.emailValidator]}
<Item mr={1} vertical>
<Label required>First name</Label>
<ValidatedField
component={TextField}
data-test-id="author-card-firstname"
name="firstName"
validate={[required]}
/>
</Item>
<Item mr={1} vertical>
<Label required>Last name</Label>
<ValidatedField
component={TextField}
data-test-id="author-card-lastname"
name="lastName"
validate={[required]}
/>
</Item>
<Label required>Affiliation</Label>
<ValidatedField
component={TextField}
data-test-id="author-card-affiliation"
name="affiliation"
validate={[required]}
/>
</Item>
<Item vertical>
<Label required>Country</Label>
<ValidatedField
component={input => (
<Menu {...input} options={countries} placeholder="Please select" />
)}
data-test-id="author-card-country"

Alexandru Munteanu
committed
</AuthorContainer>
)
// #endregion
const EnhancedAuthorEdit = compose(
withProps(({ author }) => ({
initialValues: author,
reduxForm({
form: 'author-edit',
}),
)(AuthorEdit)
const Author = ({
author,
listIndex,
isAuthorEdit,
deleteAuthor,
toggleEditMode,
isAuthorsFetching,
}) => (

Alexandru Munteanu
committed
<AuthorContainer>
author={author}
deleteAuthor={deleteAuthor}
isAuthorEdit={isAuthorEdit}
isAuthorsFetching={isAuthorsFetching}
isCorresponding={author.isCorresponding}
isFetching={isFetching}
isSubmitting={author.isSubmitting}
listIndex={listIndex}
toggleEditMode={toggleEditMode}
/>
<PersonInfo person={author} />

Alexandru Munteanu
committed
</AuthorContainer>

Alexandru Munteanu
committed
const AuthorCard = ({

Alexandru Munteanu
committed
isOver,

Alexandru Munteanu
committed
editMode,
dragHandle,

Alexandru Munteanu
committed
isDragging,
isFetching,
deleteAuthor,
isAuthorEdit,
isAuthorsFetching,
editExistingAuthor,
authorEditorSubmit,

Alexandru Munteanu
committed
}) => (
<Root isDragging={isDragging} isOver={isOver}>

Alexandru Munteanu
committed
{!editMode &&
(typeof dragHandle === 'function' ? dragHandle() : dragHandle)}
{editMode ? (
<EnhancedAuthorEdit
author={item}
editExistingAuthor={editExistingAuthor}

Alexandru Munteanu
committed
isFetching={isFetching}
listIndex={index}
onSubmit={authorEditorSubmit}
saveNewAuthor={saveNewAuthor}
toggleEditMode={toggleEdit(index)}
deleteAuthor={deleteAuthor(item)}
isAuthorEdit={isAuthorEdit}
isAuthorsFetching={isAuthorsFetching}
isFetching={isFetching}
listIndex={index}
toggleEditMode={toggleEdit(index)}
/>
)}
</Root>
)
export default compose(
withState('editMode', 'setEditMode', ({ item }) => item.id === 'newAuthor'),
withHandlers({
toggleEdit: ({ editMode, setEditMode, onEdit }) => index => () => {
onEdit(editMode ? null : index)
setDisplayName('AuthorCard'),
)(AuthorCard)
// #region styles
const AuthorTags = styled.div`
align-items: center;
display: flex;
`

Alexandru Munteanu
committed
const AuthorContainer = styled.div`
display: flex;
flex: 1;
flex-direction: column;
padding: calc(${th('gridUnit')} * 2);

Alexandru Munteanu
committed
`

Alexandru Munteanu
committed
align-items: center;
background-color: ${props =>
props.isOver ? th('colorFurniture') : th('colorBackgroundHue')};
border-radius: ${th('borderRadius')};
box-shadow: ${th('boxShadow')};

Alexandru Munteanu
committed
display: flex;
justify-content: flex-start;
margin-bottom: ${th('gridUnit')};
position: relative;
${Row} {
margin-bottom: ${th('gridUnit')};
}
${H3} {
margin: 0;
margin-right: ${th('gridUnit')};
& + div div[role='alert'] {
margin-top: 0;
}
const StyledSpinner = styled.div`
position: absolute;
right: ${th('gridUnit')};
top: calc(${th('gridUnit')} * 2);
`