-
Alexandru Munteanu authored0fafd5ab
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
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 = ({
author,
editMode,
listIndex,
isFetching,
saveChanges,
deleteAuthor,
isSubmitting,
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
icon="x-circle"
iconSize={2}
onClick={toggleEditMode}
right={48}
top={15}
/>
{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 = ({
countries,
author,
editMode,
listIndex,
isFetching,
isSubmitting,
handleSubmit,
toggleEditMode,
isAuthorsFetching,
...props
}) => (
<AuthorContainer>
<AuthorTitle
editMode={editMode}
formSubmitting={isSubmitting}
isAuthorsFetching={isAuthorsFetching}
isCorresponding={author.isCorresponding}
isFetching={isFetching}
isSubmitting={author.isSubmitting}
listIndex={listIndex}
saveChanges={handleSubmit}
toggleEditMode={toggleEditMode}
/>
<Row>
<Field component={Empty} name="id" />
<Field component={Empty} name="isSubmitting" />
<Item mr={1} vertical>
<Label required>Email</Label>
<ValidatedField
component={TextField}
name="email"
validate={[required, validators.emailValidator]}
/>
</Item>
<Item mr={1} vertical>
<Label required>First name</Label>
<ValidatedField
component={TextField}
name="firstName"
validate={[required]}
/>
</Item>
<Item mr={1} vertical>
<Label required>Last name</Label>
<ValidatedField
component={TextField}
name="lastName"
validate={[required]}
/>
</Item>
<Item mr={1} vertical>
<Label required>Affiliation</Label>
<ValidatedField
component={TextField}
name="affiliation"
validate={[required]}
/>
</Item>
<Item vertical>
<Label required>Country</Label>
<ValidatedField
component={input => (
<Menu {...input} options={countries} placeholder="Please select" />
)}
name="country"
/>
</Item>
</Row>
</AuthorContainer>
)
// #endregion
const EnhancedAuthorEdit = compose(
withCountries,
withProps(({ author }) => ({
initialValues: author,
})),
reduxForm({
form: 'author-edit',
}),
)(AuthorEdit)
const Author = ({
author,
listIndex,
isFetching,
isAuthorEdit,
deleteAuthor,
toggleEditMode,
isAuthorsFetching,
}) => (
<AuthorContainer>
<AuthorTitle
author={author}
deleteAuthor={deleteAuthor}
isAuthorEdit={isAuthorEdit}
isAuthorsFetching={isAuthorsFetching}
isCorresponding={author.isCorresponding}
isFetching={isFetching}
isSubmitting={author.isSubmitting}
listIndex={listIndex}
toggleEditMode={toggleEditMode}
/>
<PersonInfo person={author} />
</AuthorContainer>
)
const AuthorCard = ({
item,
isOver,
editMode,
dragHandle,
toggleEdit,
isDragging,
isFetching,
index = null,
deleteAuthor,
isAuthorEdit,
saveNewAuthor,
isAuthorsFetching,
editExistingAuthor,
authorEditorSubmit,
}) => (
<Root isDragging={isDragging} isOver={isOver}>
{!editMode &&
(typeof dragHandle === 'function' ? dragHandle() : dragHandle)}
{editMode ? (
<EnhancedAuthorEdit
author={item}
editExistingAuthor={editExistingAuthor}
editMode={editMode}
isFetching={isFetching}
listIndex={index}
onSubmit={authorEditorSubmit}
saveNewAuthor={saveNewAuthor}
toggleEditMode={toggleEdit(index)}
/>
) : (
<Author
author={item}
deleteAuthor={deleteAuthor(item)}
editMode={editMode}
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)
setEditMode(e => !e)
},
}),
setDisplayName('AuthorCard'),
)(AuthorCard)
// #region styles
const AuthorTags = styled.div`
align-items: center;
display: flex;
`
const AuthorContainer = styled.div`
display: flex;
flex: 1;
flex-direction: column;
padding: calc(${th('gridUnit')} * 2);
`
const Root = styled.div`
align-items: center;
background-color: ${props =>
props.isOver ? th('colorFurniture') : th('colorBackgroundHue')};
border-radius: ${th('borderRadius')};
box-shadow: ${th('boxShadow')};
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);
`
// #endregion