import React, { Fragment } from 'react' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { omit, isBoolean, get } from 'lodash' import { compose, withState, withHandlers } from 'recompose' import { Row, Item, Label, Text, DragHandle, AuthorCard, ActionLink, SortableList, withFetching, handleError, } from './' const castToBool = author => ({ ...author, isCorresponding: isBoolean(author.isCorresponding) && author.isCorresponding, }) const setCorrespondingAuthor = authors => { const corresponding = authors.find(a => a.isCorresponding) return corresponding ? authors : authors.map( a => a.isSubmitting ? { ...a, isCorresponding: true, } : a, ) } const parseEditedAuthors = (editedAuthor, authors) => { const newAuthor = castToBool(editedAuthor) const newAuthors = authors.map( a => a.id === newAuthor.id ? newAuthor : { ...a, isCorresponding: newAuthor.isCorresponding ? false : a.isCorresponding, }, ) return setCorrespondingAuthor(newAuthors) } const WizardAuthors = ({ error, journal, moveAuthor, authors = [], isAuthorEdit, deleteAuthor, addNewAuthor, setAuthorEdit, saveNewAuthor, isAuthorsFetching, editExistingAuthor, authorEditorSubmit, isFetching, }) => ( <Fragment> <Row alignItems="center" justify="flex-start"> <Item> <Label>Authors</Label> <ActionLink icon="plus" onClick={addNewAuthor}> ADD AUTHOR </ActionLink> </Item> <Item justify="flex-end"> <ActionLink icon="link" iconPosition="right" to={get( journal, 'submission.links.authorGuidelines', 'https://www.hindawi.com/journals/', )} > Author Submission Guidelines </ActionLink> </Item> </Row> {authors.length > 0 && ( <SortableContainer> <SortableList authorEditorSubmit={authorEditorSubmit} deleteAuthor={deleteAuthor} dragHandle={DragHandle} editExistingAuthor={editExistingAuthor} isAuthorEdit={isAuthorEdit} isAuthorsFetching={isAuthorsFetching} isFetching={isFetching} itemKey="id" items={authors} listItem={AuthorCard} moveItem={moveAuthor} onEdit={setAuthorEdit} saveNewAuthor={saveNewAuthor} /> </SortableContainer> )} {error && ( <Row justify="flex-start" mb={1} mt={1}> <Text error>{error}</Text> </Row> )} </Fragment> ) export default compose( withFetching, withState('authors', 'setAuthors', ({ authors }) => authors), withHandlers({ setFormAuthors: ({ changeForm, setAuthors, setFetching, onAuthorEdit, formName = 'submission', }) => authors => { setAuthors(authors) setFetching(false) onAuthorEdit(null) changeForm(formName, 'authors', authors) }, }), withHandlers({ addNewAuthor: ({ authors = [], setAuthors, onAuthorEdit }) => () => { if (authors.some(a => a.id === 'newAuthor')) { return } onAuthorEdit(0) setAuthors([ ...authors, { id: 'newAuthor', isCorresponding: false, isSubmitting: false }, ]) }, moveAuthor: ({ authors, setFormAuthors }) => (dragIndex, hoverIndex) => { setFormAuthors(SortableList.moveItem(authors, dragIndex, hoverIndex)) }, setAuthorEdit: ({ authors, setAuthors, onAuthorEdit }) => index => { onAuthorEdit(index) setAuthors(authors.filter(a => a.id !== 'newAuthor')) }, saveNewAuthor: ({ authors, setFormAuthors }) => author => { setFormAuthors( parseEditedAuthors(author, [ ...authors.filter(a => a.id !== 'newAuthor'), author, ]), ) }, editExistingAuthor: ({ authors, setFormAuthors }) => editedAuthor => { const newAuthors = parseEditedAuthors(editedAuthor, authors) setFormAuthors(newAuthors) }, deleteAuthor: ({ authors, project, version, deleteAuthor, setFormAuthors, }) => author => ({ hideModal, setModalError }) => deleteAuthor(project.id, version.id, author.id) .then(() => { const newAuthors = setCorrespondingAuthor( authors.filter(a => a.id !== author.id), ) setFormAuthors(newAuthors) hideModal() }) .catch(handleError(setModalError)), }), withHandlers({ authorEditorSubmit: ({ authors, project, version, addAuthor, setFetching, saveNewAuthor, editExistingAuthor, }) => (values, dispatch, { toggleEditMode }) => { if (values.id === 'newAuthor') { setFetching(true) return addAuthor( { ...omit(values, 'id'), isSubmitting: authors.length === 1, }, project.id, version.id, ).then(saveNewAuthor) } editExistingAuthor(values) setTimeout(toggleEditMode, 10) }, }), )(WizardAuthors) // #region styles const SortableContainer = styled.div` background-color: ${th('colorBackground')}; border-radius: ${th('borderRadius')}; padding: ${th('gridUnit')}; width: 100%; ` // #endregion