diff --git a/packages/component-faraday-ui/src/ActionLink.js b/packages/component-faraday-ui/src/ActionLink.js index 64ec59b5e452ea8e92bc3f8c2bb29be6d77f9b14..7da088b7f4222acd69206dd116a2e9ae64583ae5 100644 --- a/packages/component-faraday-ui/src/ActionLink.js +++ b/packages/component-faraday-ui/src/ActionLink.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import styled from 'styled-components' import { Link } from 'react-router-dom' import { withHandlers } from 'recompose' @@ -57,6 +58,31 @@ const ActionLink = ({ </Root> ) +ActionLink.propTypes = { + /** Link/URL specifying where to navigate, outside or inside the app. + * If present the component will behave like a navigation link. */ + to: PropTypes.string, + /** What icon to be used. */ + icon: PropTypes.string, + /** Size of the icon. */ + iconSize: PropTypes.number, + /** Position of the icon. */ + iconPosition: PropTypes.oneOf(['left', 'right']), + /** Callback function fired when the component is clicked. */ + onClick: PropTypes.func, + /** If true the component will be disabled (can't be interacted with). */ + disabled: PropTypes.bool, +} + +ActionLink.defaultProps = { + iconSize: 2, + to: '', + disabled: true, + icon: '', + onClick: () => {}, + iconPosition: 'left', +} + export default withHandlers({ renderLink: ({ to, internal, disabled, onClick, size, children }) => () => { if (to && !internal) { diff --git a/packages/component-faraday-ui/src/ActionLink.md b/packages/component-faraday-ui/src/ActionLink.md index 0cd8d6bd08b1b05eb671aea9fac370142a1d8866..833522ce676de7d23217b3e9ebc804f843a38745 100644 --- a/packages/component-faraday-ui/src/ActionLink.md +++ b/packages/component-faraday-ui/src/ActionLink.md @@ -1,7 +1,9 @@ A clickable text button. ```js -<ActionLink onClick={() => console.log('I am clicked.')}>Default action</ActionLink> +<ActionLink onClick={() => console.log('I am clicked.')}> + Default action +</ActionLink> ``` A disabled text buton. @@ -24,7 +26,7 @@ A text button with an icon on the right. </ActionLink> ``` -A text link. +A navigation link. ```js <ActionLink icon="eye" iconPosition="right" to="https://www.google.com"> diff --git a/packages/component-faraday-ui/src/AppBar.js b/packages/component-faraday-ui/src/AppBar.js index 80dc030cc5b325b62bc929a143d3500009f3a948..22cf49c553cf64e99dc1c09f7195ddd7491032b5 100644 --- a/packages/component-faraday-ui/src/AppBar.js +++ b/packages/component-faraday-ui/src/AppBar.js @@ -1,5 +1,6 @@ import React, { Fragment } from 'react' import { get, once } from 'lodash' +import PropTypes from 'prop-types' import styled from 'styled-components' import { H2, Button } from '@pubsweet/ui' import { th } from '@pubsweet/ui-toolkit' @@ -7,13 +8,12 @@ import { compose, setDisplayName, withProps } from 'recompose' import { Item, Row, Text } from 'pubsweet-component-faraday-ui' const AppBar = ({ + fixed, logo: Logo, menu: Menu, createDraft, - canCreateDraft = true, - currentUser = {}, - fixed = true, - isSubmit, + canCreateDraft, + currentUser, autosave: Autosave, journal: { metadata: { backgroundImage } }, }) => ( @@ -28,7 +28,6 @@ const AppBar = ({ <Autosave /> </Item> {createDraft && - !isSubmit && currentUser.user && ( <Button data-test-id="new-manuscript" @@ -46,7 +45,7 @@ const AppBar = ({ </RightContainer> </Root> {!canCreateDraft && ( - <RibbonRow bgColor={th('colorInfo')} fixed={fixed}> + <RibbonRow fixed={fixed}> <Text pb={1 / 2} pt={1}> Your account is not confirmed. Please check your email. </Text> @@ -55,10 +54,30 @@ const AppBar = ({ </Fragment> ) +AppBar.propTypes = { + /** If true, it will be fixed at the top of the screen. */ + fixed: PropTypes.bool, + /** Logo that will be added to the fragment. */ + logo: PropTypes.func, + currentUser: PropTypes.shape({ + user: PropTypes.object, + isAuthenticated: PropTypes.bool, + }), + /** If false an error message will appear. */ + canCreateDraft: PropTypes.bool, + /** Pass the menu component. */ + menu: PropTypes.func, + /** Custom component that will be used as an autosave indicator. */ + autosave: PropTypes.func, +} + AppBar.defaultProps = { - autosave: () => <div />, + fixed: true, + currentUser: {}, + canCreateDraft: true, logo: () => <div />, menu: () => <div />, + autosave: () => <div />, } export default compose( @@ -117,7 +136,6 @@ const JournalBackground = styled.div` rgba(0, 0, 0, 0.05) ); ` - const Root = styled.div` align-items: center; background-color: ${th('appBar.colorBackground')}; @@ -140,6 +158,7 @@ const Root = styled.div` ` const RibbonRow = styled(Row)` + background-color: ${th('colorInfo')}; position: ${props => (props.fixed ? 'fixed' : 'relative')}; top: ${props => (props.fixed ? th('appBar.height') : '0')}; ` diff --git a/packages/component-faraday-ui/src/AppBar.md b/packages/component-faraday-ui/src/AppBar.md index 49d8caf19e0c34f49c73d564d41d0bee7c07a981..107dbbe75848be2c09398dcf1608fff58059dbf7 100644 --- a/packages/component-faraday-ui/src/AppBar.md +++ b/packages/component-faraday-ui/src/AppBar.md @@ -18,7 +18,7 @@ const autosave = { const HindawiLogo = () => ( <Logo onClick={() => console.log('Hindawi best publish!')} - title="Hindawi" + title="Anca" src="https://upload.wikimedia.org/wikipedia/en/thumb/c/ca/Hindawi.svg/1200px-Hindawi.svg.png" /> ) diff --git a/packages/component-faraday-ui/src/AuthorCard.js b/packages/component-faraday-ui/src/AuthorCard.js index 910467c3be7f15fa5d30235b3c7cee4414ef5c87..59f4ebe247e23e81dd133c043997c3a0d06ed070 100644 --- a/packages/component-faraday-ui/src/AuthorCard.js +++ b/packages/component-faraday-ui/src/AuthorCard.js @@ -1,10 +1,18 @@ import React, { Fragment } from 'react' +import PropTypes from 'prop-types' 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 { H3, ValidatedField, TextField, Checkbox, Spinner } from '@pubsweet/ui' +import { + H3, + Menu, + Spinner, + Checkbox, + TextField, + ValidatedField, +} from '@pubsweet/ui' import { compose, withState, @@ -12,10 +20,10 @@ import { withHandlers, setDisplayName, } from 'recompose' +import { withCountries } from 'pubsweet-component-faraday-ui' -import { MenuCountry } from 'pubsweet-component-faraday-ui' -import { Tag, Label, Row, Item, PersonInfo, IconButton, OpenModal } from './' import { validators } from './helpers' +import { Tag, Label, Row, Item, PersonInfo, IconButton, OpenModal } from './' const Empty = () => <div /> @@ -122,6 +130,7 @@ const AuthorTitle = ({ // #region AuthorEdit const AuthorEdit = ({ + countries, author, editMode, listIndex, @@ -188,7 +197,7 @@ const AuthorEdit = ({ <Label required>Country</Label> <ValidatedField component={input => ( - <MenuCountry {...input} placeholder="Please select" /> + <Menu {...input} options={countries} placeholder="Please select" /> )} data-test-id="author-card-country" name="country" @@ -200,6 +209,7 @@ const AuthorEdit = ({ // #endregion const EnhancedAuthorEdit = compose( + withCountries, withProps(({ author }) => ({ initialValues: author, })), @@ -278,6 +288,45 @@ const AuthorCard = ({ </Root> ) +AuthorCard.propTypes = { + /** The author details. */ + item: PropTypes.shape({ + email: PropTypes.string, + firstName: PropTypes.string, + lastName: PropTypes.string, + affiliation: PropTypes.string, + country: PropTypes.string, + }).isRequired, + /** Callback function fired when deleting an author after confirmation. + * @param {Author} author + * @returns A function that receives the modal properties as an argument. + * */ + deleteAuthor: PropTypes.func, + /** Whether the author is currently being edited. */ + isAuthorEdit: PropTypes.bool, + /** Callback function fired when editing an author. + * Called with the author's index or null when closing edit mode. + * @param {number} authorIndex + * */ + onEdit: PropTypes.func, // eslint-disable-line + /** Callback function fired when saving a new author. + * The added author is passed as a parameter. */ + saveNewAuthor: PropTypes.func, + /** Callback function fired when editing an author. + * @param {object} values + * @param {function} dispatch + * @param {object} props */ + authorEditorSubmit: PropTypes.func, +} + +AuthorCard.defaultProps = { + onEdit: null, + deleteAuthor: null, + isAuthorEdit: false, + saveNewAuthor: null, + authorEditorSubmit: null, +} + export default compose( withState('editMode', 'setEditMode', ({ item }) => item.id === 'newAuthor'), withHandlers({ diff --git a/packages/component-faraday-ui/src/AuthorCard.md b/packages/component-faraday-ui/src/AuthorCard.md index d71f220ff31a8cbcebb047beb6d1baf8bb7d7324..6496d159d89867168daf9ebeabfc6a0594a83d78 100644 --- a/packages/component-faraday-ui/src/AuthorCard.md +++ b/packages/component-faraday-ui/src/AuthorCard.md @@ -1,3 +1,5 @@ +A component that shows details about an author. It has two modes: a presentation mode and an edit mode. This component can be a part of a submission wizard as well as in a sortable list. + An author card. ```js @@ -11,12 +13,14 @@ const author = { } ;<div> <AuthorCard - onEdit={() => console.log('s-a dat click pe edit')} + onEdit={e => console.log('s-a dat click pe edit', e)} index={0} item={author} deleteAuthor={item => () => { console.log('delete author', item) }} + saveNewAuthor={(...args) => console.log('save new authot', args)} + authorEditorSubmit={(...args) => console.log('edit the author', args)} /> <AuthorCard onEdit={() => console.log('s-a dat click pe edit')} diff --git a/packages/component-faraday-ui/src/AuthorReply.js b/packages/component-faraday-ui/src/AuthorReply.js index 872a4be66501eac3ca9dcf4aadcb4c18d94178ad..e1b6cfff662ac36bcebc29d983b20a17a8fc19fb 100644 --- a/packages/component-faraday-ui/src/AuthorReply.js +++ b/packages/component-faraday-ui/src/AuthorReply.js @@ -1,9 +1,10 @@ -import React, { Fragment } from 'react' import { get } from 'lodash' +import PropTypes from 'prop-types' import { withProps } from 'recompose' import styled from 'styled-components' -import { th } from '@pubsweet/ui-toolkit' +import React, { Fragment } from 'react' import { DateParser } from '@pubsweet/ui' +import { th } from '@pubsweet/ui-toolkit' import { Label, Item, Row, Text, FileItem } from './' @@ -54,6 +55,22 @@ const AuthorReply = ({ )} </Root> ) +AuthorReply.propTypes = { + /** Reply of author. */ + replyContent: PropTypes.string, + /** Name of author that replied. */ + authorName: PropTypes.string, + /** Date of submitted reply. */ + submittedOn: PropTypes.number, + /** Reply File. */ + replyFile: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), +} +AuthorReply.defaultProps = { + replyContent: '', + replyFile: {}, + authorName: '', + submittedOn: Date.now(), +} export default withProps( ({ fragment: { authors, submitted }, authorReply }) => ({ diff --git a/packages/component-faraday-ui/src/AuthorTag.js b/packages/component-faraday-ui/src/AuthorTag.js index 1ac2a56a90bd18468d8235f90746e827801b37fc..9f9394ff8023473f2046f7ab104a6f09afb70b1e 100644 --- a/packages/component-faraday-ui/src/AuthorTag.js +++ b/packages/component-faraday-ui/src/AuthorTag.js @@ -1,7 +1,7 @@ import React from 'react' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' - +import PropTypes from 'prop-types' import Tag from './Tag' import Text from './Text' @@ -23,6 +23,29 @@ const AuthorTag = ({ </Root> ) +AuthorTag.propTypes = { + /** The author you want to be on the card. */ + author: PropTypes.shape({ + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + firstName: PropTypes.string, + lastName: PropTypes.string, + isCorresponding: PropTypes.bool, + isSubmitting: PropTypes.bool, + affiliationNumber: PropTypes.number, + }), +} + +AuthorTag.defaultProps = { + author: { + id: undefined, + firstName: undefined, + lastName: undefined, + isCorresponding: undefined, + isSubmitting: undefined, + affiliationNumber: undefined, + }, +} + export default AuthorTag // #region styles diff --git a/packages/component-faraday-ui/src/AuthorTagList.js b/packages/component-faraday-ui/src/AuthorTagList.js index 5aea50c288cf1b4dde73988203438d07ad0264d5..724643ba05407c3b5a2401bdaad4058cdd7b260b 100644 --- a/packages/component-faraday-ui/src/AuthorTagList.js +++ b/packages/component-faraday-ui/src/AuthorTagList.js @@ -3,6 +3,7 @@ import { get } from 'lodash' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { compose, withProps, withStateHandlers } from 'recompose' +import PropTypes from 'prop-types' import { Row, @@ -42,13 +43,13 @@ const parseAffiliations = (authors = []) => ) const AuthorTagList = ({ - authors = [], + authors, affiliationList, - separator = `, `, - authorKey = 'id', - withTooltip = false, - withAffiliations = false, - showAffiliation = false, + separator, + authorKey, + withTooltip, + withAffiliations, + showAffiliation, toggleAffiliation, }) => ( <Root> @@ -112,6 +113,27 @@ export default compose( })), )(AuthorTagList) +AuthorTagList.propTypes = { + /** The identificator label that will be seen on the card. */ + authorKey: PropTypes.string, + /** All authors we want to be seen on the card. */ + authors: PropTypes.arrayOf(PropTypes.object), + /** Separator between authors. */ + separator: PropTypes.string, + /** Tooltip about author details. */ + withTooltip: PropTypes.bool, + /** Show authors affifiations. */ + withAffiliations: PropTypes.bool, +} + +AuthorTagList.defaultProps = { + authorKey: 'id', + authors: [], + separator: `, `, + withTooltip: false, + withAffiliations: false, +} + // #region styles const Root = styled.div` align-items: center; diff --git a/packages/component-faraday-ui/src/AuthorTagList.md b/packages/component-faraday-ui/src/AuthorTagList.md index 12ff3c606db6c3d514c2b94c31487707967aaf0a..d66972f14e463b8a3a75974fba87ea25d63af785 100644 --- a/packages/component-faraday-ui/src/AuthorTagList.md +++ b/packages/component-faraday-ui/src/AuthorTagList.md @@ -107,12 +107,14 @@ Use a different separator and key for mapping the authors. ```js const authors = [ { + id: 1, email: 'john.doe@gmail.com', firstName: 'John', lastName: 'Doe', isSubmitting: true, }, { + id: 2, email: 'michael.felps@gmail.com', firstName: 'Michael', lastName: 'Felps', @@ -120,6 +122,7 @@ const authors = [ isCorresponding: true, }, { + id: 3, email: 'barrack.obama@gmail.com', firstName: 'Barrack', lastName: 'Obama', diff --git a/packages/component-faraday-ui/src/AutosaveIndicator.js b/packages/component-faraday-ui/src/AutosaveIndicator.js index 10335b7e8305dfd6750c67a2195bfbd36a4b7544..03a3041f2e18a80e6301cb577011c03628df0f71 100644 --- a/packages/component-faraday-ui/src/AutosaveIndicator.js +++ b/packages/component-faraday-ui/src/AutosaveIndicator.js @@ -6,6 +6,7 @@ import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { Icon, Spinner } from '@pubsweet/ui' import { compose, setDisplayName, withStateHandlers } from 'recompose' +import PropTypes from 'prop-types' import Text from './Text' @@ -99,6 +100,14 @@ export default compose( setDisplayName('AutosaveIndicator'), )(AutosaveIndicator) +AutosaveIndicator.propTypes = { + /** Displays the status of the form, in progress, saved or error. */ + autosave: PropTypes.object, // eslint-disable-line +} + +AutosaveIndicator.defaultProps = { + autosave: {}, +} // #region styles const Root = styled.div` align-items: center; diff --git a/packages/component-faraday-ui/src/ContextualBox.js b/packages/component-faraday-ui/src/ContextualBox.js index cbf2761870c26c3740af9e34f12ec5281787566d..188d9a4a38cf3d9c215be5b1da47e778b5d41d68 100644 --- a/packages/component-faraday-ui/src/ContextualBox.js +++ b/packages/component-faraday-ui/src/ContextualBox.js @@ -1,5 +1,6 @@ import React from 'react' -import { has } from 'lodash' +import PropTypes from 'prop-types' +import { isUndefined } from 'lodash' import styled from 'styled-components' import { Icon, H3 } from '@pubsweet/ui' import { override, th } from '@pubsweet/ui-toolkit' @@ -34,7 +35,7 @@ const CustomHeader = ({ ) const ContextualBox = ({ label, children, rightChildren, ...props }) => - has(props, 'expanded') ? ( + !isUndefined(props.expanded) ? ( <ControlledAccordion header={CustomHeader} label={label} @@ -56,6 +57,28 @@ const ContextualBox = ({ label, children, rightChildren, ...props }) => export default ContextualBox +ContextualBox.propTypes = { + /** Label of the contextual box. */ + label: PropTypes.string, + /** Component or html to be rendered on the right side. */ + rightChildren: PropTypes.any, // eslint-disable-line + /** The state of the contextual box. If passed from a parent then the component + * is controlled and can be expanded/collapsed remotely. + */ + expanded: PropTypes.bool, // eslint-disable-line + /** Callback function used to control the state of the component. + * To be used together with the `expanded` prop. + */ + toggle: PropTypes.func, // eslint-disable-line +} + +ContextualBox.defaultProps = { + label: '', + rightChildren: undefined, + expanded: false, + toggle: () => {}, +} + // #region styles const Header = styled.div.attrs(props => ({ 'data-test-id': props['data-test-id'] || 'accordion-header', diff --git a/packages/component-faraday-ui/src/ContextualBox.md b/packages/component-faraday-ui/src/ContextualBox.md index a9c7114bd4eeea1d9cfd51e27ba3fc2a138f4a0c..9e48b6c95951eb92006ba960ff9e21c4f949e652 100644 --- a/packages/component-faraday-ui/src/ContextualBox.md +++ b/packages/component-faraday-ui/src/ContextualBox.md @@ -1,3 +1,7 @@ +*Component to show or hide it's children. Can be controlled from a parent component by passing the expanded state and toggle callback.* + +--- + A collapseable contextual box. ```js @@ -113,7 +117,7 @@ const MyRightComponent = ({ headLabel }) => ( </ContextualBox> ``` -A controlled ContextualBox. +A controlled ContextualBox. This is usually used together with the RemoteOpener component. ```js const MyRightComponent = () => <div>works like a charm!</div> diff --git a/packages/component-faraday-ui/src/DownloadZipFiles.js b/packages/component-faraday-ui/src/DownloadZipFiles.js index 21f24e3e308c5841be21ed3b7542d6bd6ac37818..b642de06304463105af4754056a7c7d65bed4e34 100644 --- a/packages/component-faraday-ui/src/DownloadZipFiles.js +++ b/packages/component-faraday-ui/src/DownloadZipFiles.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { Spinner } from '@pubsweet/ui' import { compose, withState } from 'recompose' import { Item } from 'pubsweet-component-faraday-ui' @@ -17,6 +18,17 @@ const DownloadZipFiles = ({ disabled, fetching, children, downloadFiles }) => ( </Item> ) +DownloadZipFiles.propTypes = { + /** Name for the downloaded archive file. */ + archiveName: PropTypes.string.isRequired, // eslint-disable-line + /** If the user is a reviewer. */ + isReviewer: PropTypes.bool, // eslint-disable-line +} + +DownloadZipFiles.defaultProps = { + isReviewer: false, +} + export default compose( withState('fetching', 'setFetching', false), withZipDownload, diff --git a/packages/component-faraday-ui/src/DragHandle.js b/packages/component-faraday-ui/src/DragHandle.js index f330c98309e6727c2f805168ab5b1e02aa85a0fd..c8db71ce59009e871ba43371c4c76b405046dffa 100644 --- a/packages/component-faraday-ui/src/DragHandle.js +++ b/packages/component-faraday-ui/src/DragHandle.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' @@ -15,6 +16,14 @@ const DragHandle = props => ( DragHandle.displayName = 'DragHandle' +DragHandle.protoTypes = { + /** Designed size for icon */ + size: PropTypes.number, +} +DragHandle.defaultProps = { + size: 2, +} + export default DragHandle // #region styles diff --git a/packages/component-faraday-ui/src/EditorialReportCard.js b/packages/component-faraday-ui/src/EditorialReportCard.js index f43ddb1072b43579b889eaffcbe8b34226258e3d..649beafe62774e2832120318dedae476ce7d43bb 100644 --- a/packages/component-faraday-ui/src/EditorialReportCard.js +++ b/packages/component-faraday-ui/src/EditorialReportCard.js @@ -4,6 +4,7 @@ import { withProps, withHandlers, compose } from 'recompose' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { DateParser } from '@pubsweet/ui' +import PropTypes from 'prop-types' import { Label, Item, Row, Text, Tag } from './' import { getReportComments } from './helpers' @@ -24,11 +25,10 @@ const EditorialReportCard = ({ <Root> <Row justify="space-between" mb={2}> <Item vertical> - {editorRole === 'HE' ? ( - <Label mb={1 / 2}>Recommendation</Label> - ) : ( - <Label mb={1 / 2}>Decision</Label> - )} + <Label mb={1 / 2}> + {editorRole === 'HE' ? 'Recommendation' : 'Decision'} + </Label> + ) <Text>{recommendation}</Text> </Item> @@ -111,6 +111,35 @@ export default compose( ), )(EditorialReportCard) +EditorialReportCard.propTypes = { + /** Label that will be publicly viewed, for example, a message for the author will be seen by other roles also. */ + publicLabel: PropTypes.string, + /** Label that will only be viewed as private message, for example, by the Editorial Team. */ + privateLabel: PropTypes.string, + /** Message by editorial team and other information. */ + report: PropTypes.shape({ + id: PropTypes.string, + userId: PropTypes.string, + comments: PropTypes.arrayOf(PropTypes.object), + createdOn: PropTypes.number, + updatedOn: PropTypes.number, + submittedOn: PropTypes.number, + recommendation: PropTypes.string, + recommendationType: PropTypes.string, + reviewer: PropTypes.object, + }), + /** Object containing the list of recommendations. */ + journal: PropTypes.shape({ + recommendation: PropTypes.arrayOf(PropTypes.object), + }), +} + +EditorialReportCard.defaultProps = { + publicLabel: '', + privateLabel: '', + report: {}, + journal: {}, +} // #region styles const Root = styled.div` box-shadow: ${th('boxShadow')}; diff --git a/packages/component-faraday-ui/src/File.js b/packages/component-faraday-ui/src/File.js index 9c3fbd9e1aa1805d04da04312b09213f856f7de9..c412621398d222e8d065a1983f007f103e0baa1e 100644 --- a/packages/component-faraday-ui/src/File.js +++ b/packages/component-faraday-ui/src/File.js @@ -91,11 +91,17 @@ FileItem.propTypes = { }).isRequired, /** Used when part of a sortable list. */ dragHandle: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), - /** Handler for the preview button. */ + /** Callback function fired when clicking the preview icon. + * @param {File} file + */ onPreview: PropTypes.func, - /** Handler for the download button. */ + /** Callback function fired when clicking the download icon. + * @param {File} file + */ onDownload: PropTypes.func, - /** Handler for the delete button. */ + /** Callback function fired when clicking the delete icon. + * @param {File} file + */ onDelete: PropTypes.func, } diff --git a/packages/component-faraday-ui/src/FileSection.js b/packages/component-faraday-ui/src/FileSection.js index af022f6e5f62708b45a5460b8ce5bc456016553f..f0691d983e217cf913d1b23a0eadc81129ef2890 100644 --- a/packages/component-faraday-ui/src/FileSection.js +++ b/packages/component-faraday-ui/src/FileSection.js @@ -3,6 +3,7 @@ import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { FilePicker, Spinner } from '@pubsweet/ui' import { compose, withState, withHandlers, withProps } from 'recompose' +import PropTypes from 'prop-types' import { radiusHelpers } from './styledHelpers' import { withNativeFileDrop, withFileSectionDrop } from './helpers' @@ -109,6 +110,42 @@ const FileSection = ({ </Root> ) +FileSection.propTypes = { + /** Files that are uploaded. */ + files: PropTypes.arrayOf(PropTypes.object), + /** Error you get on uploading. */ + error: PropTypes.string, + /** Titles of manuscript, cover letter and supplimental files. */ + title: PropTypes.string, + /** Id of manuscript, cover letter and supplimental files. */ + listId: PropTypes.string, + /** Function used for draging and hovering over items. */ + moveItem: PropTypes.func, + /** Extensions allowed to be uploaded. */ + allowedFileExtensions: PropTypes.arrayOf(PropTypes.string), + /** Callback function fired when a file is picked. */ + onFilePick: PropTypes.func, + /** Callback function fired when preview icon is pressed. */ + onPreview: PropTypes.func, + /** Callback function fired when download icon is pressed. */ + onDownload: PropTypes.func, + /** Callback function fired when delete icon is pressed. */ + onDelete: PropTypes.func, +} + +FileSection.defaultProps = { + files: {}, + error: '', + title: '', + listId: '', + moveItem: () => {}, + allowedFileExtensions: [], + onFilePick: () => {}, + onPreview: () => {}, + onDownload: () => {}, + onDelete: () => {}, +} + export default compose( withState('error', 'setStateError', ''), withHandlers({ diff --git a/packages/component-faraday-ui/src/IconTooltip.js b/packages/component-faraday-ui/src/IconTooltip.js index f5399bb1cd8fafb4b823f9c26d2c83b5118bf3d0..391a27877849d6cd8ba5137924b546c5356ee2f2 100644 --- a/packages/component-faraday-ui/src/IconTooltip.js +++ b/packages/component-faraday-ui/src/IconTooltip.js @@ -2,6 +2,7 @@ import React, { Fragment } from 'react' import 'react-tippy/dist/tippy.css' import { Tooltip } from 'react-tippy' import { ThemeProvider, withTheme } from 'styled-components' +import PropTypes from 'prop-types' import { IconButton } from './' @@ -37,5 +38,22 @@ const InfoTooltip = ({ theme, content }) => ( <Fragment>{typeof content === 'function' ? content() : content}</Fragment> </ThemeProvider> ) +IconTooltip.propTypes = { + /** What icon to be used. */ + icon: PropTypes.string, + /** Size of the icon. */ + iconSize: PropTypes.number, + /** What content to be used in tooltip. */ + content: PropTypes.func, + /** If true the content can be clicked (can be interacted with). */ + interactive: PropTypes.bool, +} + +IconTooltip.defaultProps = { + icon: 'help-circle', + iconSize: 2, + content: () => {}, + interactive: false, +} export default withTheme(IconTooltip) diff --git a/packages/component-faraday-ui/src/InviteReviewers.js b/packages/component-faraday-ui/src/InviteReviewers.js index 7f07b70cba1b4e7944aea14142d5bcd1632a1fad..69b113655a3b73e8e551b2190b7a731de9e414e0 100644 --- a/packages/component-faraday-ui/src/InviteReviewers.js +++ b/packages/component-faraday-ui/src/InviteReviewers.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { compose } from 'recompose' import styled from 'styled-components' import { reduxForm } from 'redux-form' @@ -94,6 +95,18 @@ const InviteReviewers = ({ handleSubmit, reset }) => ( </Root> ) +InviteReviewers.propTypes = { + /** Callback function fired after confirming a reviewer invitation. + * @param {Reviewer} reviewer + * @param {object} props + */ + onInvite: PropTypes.func, +} + +InviteReviewers.defaultProps = { + onInvite: () => {}, +} + export default compose( withFetching, withModal(({ isFetching, modalKey }) => ({ diff --git a/packages/component-faraday-ui/src/Label.js b/packages/component-faraday-ui/src/Label.js index 5cbdf06966b47836f257ec677c8189a858e99b83..635efd36c1a793d2d3a5ab4bd1445210d4dc063b 100644 --- a/packages/component-faraday-ui/src/Label.js +++ b/packages/component-faraday-ui/src/Label.js @@ -2,16 +2,25 @@ import React from 'react' import { H4 } from '@pubsweet/ui' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' +import PropTypes from 'prop-types' import { marginHelper } from './' -const Label = ({ children, required = false, ...rest }) => ( +const Label = ({ children, required, ...rest }) => ( <Root {...rest}> <H4>{children}</H4> {required && <Required>*</Required>} </Root> ) +Label.propTypes = { + /** If true the label is required. */ + required: PropTypes.bool, +} + +Label.defaultProps = { + required: false, +} export default Label // #region styles diff --git a/packages/component-faraday-ui/src/Logo.js b/packages/component-faraday-ui/src/Logo.js index 338312793bdfef4b08c3b3cdbe138e5591248392..ddc7b7b7a6ecefb1e4aa2f566d78e44efec512c5 100644 --- a/packages/component-faraday-ui/src/Logo.js +++ b/packages/component-faraday-ui/src/Logo.js @@ -2,8 +2,9 @@ import React from 'react' import { get } from 'lodash' +import PropTypes from 'prop-types' -const Logo = ({ src, onClick, title, height = 36, ...rest }) => ( +const Logo = ({ src, onClick, title, height, ...rest }) => ( <img alt={title} data-test-id={get(rest, 'data-test-id', 'journal-logo')} @@ -14,4 +15,12 @@ const Logo = ({ src, onClick, title, height = 36, ...rest }) => ( /> ) +Logo.propTypes = { + /** Height of the logo. */ + height: PropTypes.number, +} + +Logo.defaultProps = { + height: 36, +} export default Logo diff --git a/packages/component-faraday-ui/src/ManuscriptCard.js b/packages/component-faraday-ui/src/ManuscriptCard.js index 16d8d355dbc10749e3de08c7080cc082f365d703..30a953fff219c1b6eb77198682c493ff63e5b137 100644 --- a/packages/component-faraday-ui/src/ManuscriptCard.js +++ b/packages/component-faraday-ui/src/ManuscriptCard.js @@ -4,8 +4,8 @@ import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { withJournal } from 'xpub-journal' import { H3, H4, DateParser } from '@pubsweet/ui' +import PropTypes from 'prop-types' import { compose, withHandlers, setDisplayName, withProps } from 'recompose' - import { Tag, Text, @@ -19,7 +19,6 @@ import { ReviewerBreakdown, DeleteManuscriptModal, } from './' - import { OpenModal } from './modals' const ManuscriptCard = ({ @@ -27,7 +26,7 @@ const ManuscriptCard = ({ onDelete, isFetching, onCardClick, - fragment = {}, + fragment, canViewReports, deleteManuscript, canDeleteManuscript, @@ -102,9 +101,9 @@ const ManuscriptCard = ({ onClick={showModal} paddingBottom={2} paddingRight={0} - size={1.6} + size={1.65} > - DELETE + Delete </DeleteIcon> )} </OpenModal> @@ -128,7 +127,6 @@ const ManuscriptCard = ({ </Root> ) } - export default compose( withJournal, withHandlers({ @@ -154,8 +152,27 @@ export default compose( })), setDisplayName('ManuscriptCard'), )(ManuscriptCard) - // #region styles + +ManuscriptCard.propTypes = { + fragment: PropTypes.shape({ + authors: PropTypes.arrayOf(PropTypes.object), + created: PropTypes.string, + submitted: PropTypes.number, + metadata: PropTypes.object, + }), // eslint-disable-line + collection: PropTypes.shape({ + customId: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]), + visibleStatus: PropTypes.string, + handlingEditor: PropTypes.object, + }), // eslint-disable-line +} + +ManuscriptCard.defaultProps = { + fragment: {}, + collection: {}, +} + const MainContainer = styled.div` justify-content: flex-start; display: flex; @@ -165,7 +182,6 @@ const MainContainer = styled.div` padding-bottom: ${th('gridUnit')}; width: calc(100% - (${th('gridUnit')} * 5 / 2)); overflow: hidden; - ${Row} { [data-tooltipped] { overflow: hidden; @@ -183,7 +199,10 @@ const MainContainer = styled.div` } } ` -const DeleteIcon = styled(ActionLink)`` +const DeleteIcon = styled(ActionLink)` + cursor: default; + color: ${th('colorWarning')}; +` const SideNavigation = styled.div` align-items: center; @@ -195,7 +214,6 @@ const SideNavigation = styled.div` display: flex; width: calc(${th('gridUnit')} * 5 / 2); ` - const Root = styled.div` background-color: #fff; border-radius: ${th('borderRadius')}; @@ -204,14 +222,11 @@ const Root = styled.div` display: flex; margin: calc(${th('gridUnit')} / 4) calc(${th('gridUnit')} / 4) ${th('gridUnit')} calc(${th('gridUnit')} / 4); - &:hover { box-shadow: ${th('dashboardCard.hoverShadow')}; } - ${H3} { margin: 0; margin-bottom: ${th('gridUnit')}; } ` -// #endregion diff --git a/packages/component-faraday-ui/src/ManuscriptCard.md b/packages/component-faraday-ui/src/ManuscriptCard.md index aea9f0e6cf26bc6bab8d474c0ae54b8ce88828ed..ad9fc06f5ca257832768e68a4ac1d2764613455a 100644 --- a/packages/component-faraday-ui/src/ManuscriptCard.md +++ b/packages/component-faraday-ui/src/ManuscriptCard.md @@ -3,12 +3,14 @@ A manuscript card. ```js const authors = [ { + id:1, email: 'john.doe@gmail.com', firstName: 'John', lastName: 'Doe', isSubmitting: true, }, { + id:2, email: 'michael.felps@gmail.com', firstName: 'Michael', lastName: 'Felps', @@ -16,70 +18,35 @@ const authors = [ isCorresponding: true, }, { + id:3, email: 'barrack.obama@gmail.com', firstName: 'Barrack', lastName: 'Obama', }, { + id:5, email: 'barrack.obama@gmail1.com', firstName: 'Barrack 1', lastName: 'Obama', }, { + id:6, email: 'barrack.obama@gmail2.com', firstName: 'Barrack 2', lastName: 'Obama', }, { + id:7, email: 'barrack.obama@gmail3.com', firstName: 'Barrack 3', lastName: 'Obama', }, { + id:8, email: 'barrack.obama@gmail4.com', firstName: 'Barrack 4', lastName: 'Obama', }, - { - email: 'barrack.obama@gmail5.com', - firstName: 'Barrack 5', - lastName: 'Obama', - }, - { - email: 'barrack.obama@gmail6.com', - firstName: 'Barrack 6', - lastName: 'Obama', - }, - { - email: 'barrack.obama@gmail7.com', - firstName: 'Barrack 7', - lastName: 'Obama', - }, - { - email: 'barrack.obama@gmail8.com', - firstName: 'Barrack 8', - lastName: 'Obama', - }, - { - email: 'barrack.obama@gmail9.com', - firstName: 'Barrack 9', - lastName: 'Obama', - }, - { - email: 'barrack.obama@gmail10.com', - firstName: 'Barrack 10', - lastName: 'Obama', - }, - { - email: 'barrack.obama@gmail11.com', - firstName: 'Barrack 11', - lastName: 'Obama', - }, - { - email: 'barrack.obama@gmail12.com', - firstName: 'Barrack 12', - lastName: 'Obama', - }, ] const collection = { diff --git a/packages/component-faraday-ui/src/Pagination.js b/packages/component-faraday-ui/src/Pagination.js index 0ac4f04721fb5078b3490af365e4911d5338d8f7..d2a7701279a675b0b890f5b87f4b48270546084a 100644 --- a/packages/component-faraday-ui/src/Pagination.js +++ b/packages/component-faraday-ui/src/Pagination.js @@ -1,4 +1,5 @@ import React, { Fragment } from 'react' +import PropTypes from 'prop-types' import styled from 'styled-components' import { TextField } from '@pubsweet/ui' import { th } from '@pubsweet/ui-toolkit' @@ -60,13 +61,33 @@ const PaginationComponent = ({ </Root> ) -export const Pagination = ({ paginatedItems, children, ...props }) => ( +export const Pagination = ({ Items, children, ...props }) => ( <Fragment> <PaginationComponent {...props} /> - {typeof children === 'function' && children(paginatedItems, props)} + {typeof children === 'function' && children(Items, props)} </Fragment> ) +Pagination.propTypes = { + /** Page current number. */ + page: PropTypes.number, + /** Indicates if there are more pages to be displayed. */ + hasMore: PropTypes.bool, + /** Maximum items displayed. */ + maxItems: PropTypes.number, + /** Items displayed per page. */ + itemsPerPage: PropTypes.number, + /** Change how many items should be displayed per page. */ + changeItemsPerPage: PropTypes.func, +} +Pagination.defaultProps = { + page: 1, + hasMore: false, + maxItems: 23, + itemsPerPage: 10, + changeItemsPerPage: () => {}, +} + export default PaginationComponent // #region styles diff --git a/packages/component-faraday-ui/src/PasswordValidation.js b/packages/component-faraday-ui/src/PasswordValidation.js index 70b41dd6a4487fa8e98c449c352b39c0cf5a38f7..bdf79b02204855bff5334a653b9b202b7c622453 100644 --- a/packages/component-faraday-ui/src/PasswordValidation.js +++ b/packages/component-faraday-ui/src/PasswordValidation.js @@ -127,14 +127,14 @@ PasswordValidation.propTypes = { atLeastOnePunctuation: PropTypes.bool, } PasswordValidation.defaultProps = { - formName: undefined, - formLabel: undefined, + formName: '', + formLabel: '', submitFailed: false, - minLength: undefined, - atLeastOneDigit: undefined, - atLeastOneUppercase: undefined, - atLeastOneLowerrcase: undefined, - atLeastOnePunctuation: undefined, + minLength: false, + atLeastOneDigit: false, + atLeastOneUppercase: false, + atLeastOneLowerrcase: false, + atLeastOnePunctuation: false, } export default compose( diff --git a/packages/component-faraday-ui/src/PersonInfo.js b/packages/component-faraday-ui/src/PersonInfo.js index 7d9ce203b0be1271292ab8bbdff4f35d4fbd3e7e..bca7e16d14205d77df66a82a8d41ed490821f4a1 100644 --- a/packages/component-faraday-ui/src/PersonInfo.js +++ b/packages/component-faraday-ui/src/PersonInfo.js @@ -1,19 +1,10 @@ import React from 'react' -import PropTypes from 'prop-types' import { withCountries } from 'pubsweet-component-faraday-ui' - +import PropTypes from 'prop-types' import { Text, Row, Label, Item } from './' -const defaultPerson = { - email: '', - firstName: '', - lastName: '', - affiliation: '', - country: '', -} - const PersonInfo = ({ - person: { email, firstName, lastName, affiliation, country } = defaultPerson, + person: { email, firstName, lastName, affiliation, country }, countryLabel, }) => ( <Row> @@ -39,8 +30,8 @@ const PersonInfo = ({ </Item> </Row> ) - -PersonInfo.proTypes = { +PersonInfo.propTypes = { + /** Person with information */ person: PropTypes.shape({ email: PropTypes.string, firstName: PropTypes.string, @@ -50,4 +41,14 @@ PersonInfo.proTypes = { }), } +PersonInfo.defaultProps = { + person: { + email: '', + firstName: '', + lastName: '', + affiliation: '', + country: '', + }, +} + export default withCountries(PersonInfo) diff --git a/packages/component-faraday-ui/src/PersonInvitation.js b/packages/component-faraday-ui/src/PersonInvitation.js index fca2998caba3cec54b5c9657952cc42b23b24c94..941dfc6107ed7f79888958114537b17d8162483a 100644 --- a/packages/component-faraday-ui/src/PersonInvitation.js +++ b/packages/component-faraday-ui/src/PersonInvitation.js @@ -1,5 +1,6 @@ -import React, { Fragment } from 'react' +import PropTypes from 'prop-types' import styled from 'styled-components' +import React, { Fragment } from 'react' import { compose, withHandlers, defaultProps, setDisplayName } from 'recompose' import { Text, OpenModal, IconButton, marginHelper, withFetching } from './' @@ -84,6 +85,44 @@ const PersonInvitation = ({ </Root> ) +PersonInvitation.propTypes = { + /** Id of invitation. */ + id: PropTypes.string, + /** Type of invitation. */ + type: PropTypes.string, + /** Role of user. */ + role: PropTypes.string, + /** Reason written for review. */ + reason: PropTypes.string, + /** Id of user. */ + userId: PropTypes.string, + /** If user has left an answer or not. */ + hasAnswer: PropTypes.bool, + /** Date of invite. */ + invitedOn: PropTypes.number, + /** If user was accepted or not. */ + isAccepted: PropTypes.bool, + /** Date of user response. */ + respondedOn: PropTypes.number, + /** Details of person. */ + person: PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + }), +} +PersonInvitation.defaultProps = { + id: '', + role: '', + type: '', + reason: '', + userId: '', + hasAnswer: false, + invitedOn: Date.now(), + isAccepted: false, + respondedOn: Date.now(), + person: {}, +} + export default compose( defaultProps({ person: { diff --git a/packages/component-faraday-ui/src/PublonsTable.js b/packages/component-faraday-ui/src/PublonsTable.js index ce9f549473a84b3e60bda962f46054e93cefd1ef..c77945960d0e45eb9fa65c3bb1616ebfda4859bb 100644 --- a/packages/component-faraday-ui/src/PublonsTable.js +++ b/packages/component-faraday-ui/src/PublonsTable.js @@ -4,7 +4,7 @@ import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { Button, Spinner } from '@pubsweet/ui' import { compose, withHandlers, withProps } from 'recompose' - +import PropTypes from 'prop-types' import { Label, OpenModal, Text, withFetching, ActionLink } from '../' const TableView = ({ @@ -100,6 +100,17 @@ export default compose( }), )(PublonsTable) +TableView.propTypes = { + reviewers: PropTypes.arrayOf(PropTypes.object), + /** Sends an invitation to the reviewer. */ + onInviteReviewer: PropTypes.func, +} + +TableView.defaultProps = { + reviewers: [], + onInviteReviewer: () => {}, +} + // #region styles const Table = styled.table` border-collapse: collapse; diff --git a/packages/component-faraday-ui/src/PublonsTable.md b/packages/component-faraday-ui/src/PublonsTable.md index f692c2e4740672589b4ff386c06e1f13c180315e..bf7301a2e05b4e794ce16a8664bbd5095e5e009e 100644 --- a/packages/component-faraday-ui/src/PublonsTable.md +++ b/packages/component-faraday-ui/src/PublonsTable.md @@ -3,37 +3,26 @@ A list of publon reviewers. ```js const reviewers = [ { - id: 0, - email: 'email1@email.com', - publishingName: 'Name1', - recentOrganizations: { - name: 'Org1' - }, - numVerifiedReviews: '100' + name: 'Ursachi Anca', + email: 'anca@thinslices.com', + profileUrl: '', + affiliation: 'ts', + reviews: 10, }, { - id: 1, - email: 'email2@email.com', - publishingName: 'Name2', - recentOrganizations: { - name: 'Org2' - }, - numVerifiedReviews: '200' + name: 'Josh', + email: 'josh@thinslices.com', + profileUrl: '', + affiliation: 'ts', + reviews: 8, }, - { - id: 2, - email: 'email3@email.com', - publishingName: 'Name3', - recentOrganizations: { - name: 'Org3' - }, - numVerifiedReviews: '300' - }, -]; +] +;<PublonsTable + reviewers={reviewers} + onInviteReviwer={(reviewer, modalProps) => { + console.log('the reviewer', reviewer) -<PublonsTable reviewers={reviewers} onInviteReviwer={(reviewer, modalProps) => { - console.log('the reviewer', reviewer) - - modalProps.setModalError('avem eroare boss') -}}/> + modalProps.setModalError('avem eroare boss') + }} +/> ``` diff --git a/packages/component-faraday-ui/src/RadioWithComments.js b/packages/component-faraday-ui/src/RadioWithComments.js index 785149e94c2ca25bd7bc8b0ee30f21eb5e9b286f..d81a9cdc37c9bdb9a34c1714d3c49a86435c8e3d 100644 --- a/packages/component-faraday-ui/src/RadioWithComments.js +++ b/packages/component-faraday-ui/src/RadioWithComments.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { get } from 'lodash' import { Field } from 'redux-form' import styled from 'styled-components' @@ -75,6 +76,32 @@ const RadioWithComments = ({ </Root> ) +RadioWithComments.propTypes = { + /** Defines if a fragment is required or not. */ + required: PropTypes.bool, + /** Values taken by form. */ + formValues: PropTypes.object, //eslint-disable-line + /** Name of field selected after using radio buttons. */ + radioFieldName: PropTypes.string, + /** Name of comments field after radio buttons choice. */ + commentsFieldName: PropTypes.string, + /** Name of field that was commented on. */ + commentsOn: PropTypes.string, + /** Label name of the field that was commented on. */ + commentsLabel: PropTypes.string, + /** Name of radio label field on witch it was commented. */ + radioLabel: PropTypes.string, +} +RadioWithComments.defaultProps = { + required: false, + formValues: {}, + radioFieldName: '', + commentsFieldName: '', + commentsOn: '', + commentsLabel: '', + radioLabel: '', +} + export default RadioWithComments // #region styles diff --git a/packages/component-faraday-ui/src/RemoteOpener.js b/packages/component-faraday-ui/src/RemoteOpener.js index 44bcb785bdb7be2d1db3e3a9bab8f951c4e002c2..6681f273f4deb13d8e53cef076ce9a3f04e32461 100644 --- a/packages/component-faraday-ui/src/RemoteOpener.js +++ b/packages/component-faraday-ui/src/RemoteOpener.js @@ -1,3 +1,4 @@ +import PropTypes from 'prop-types' import { withStateHandlers } from 'recompose' const RemoteOpener = ({ expanded, toggle, children }) => @@ -11,3 +12,15 @@ export default withStateHandlers( }), }, )(RemoteOpener) + +RemoteOpener.propTypes = { + /** Prop used together with toggle. */ + expanded: PropTypes.bool, + /** Callback function used to control the state of the component. + * To be used together with the `expanded` prop. + */ toggle: PropTypes.func, +} +RemoteOpener.defaultProps = { + expanded: false, + toggle: () => {}, +} diff --git a/packages/component-faraday-ui/src/ReviewerBreakdown.js b/packages/component-faraday-ui/src/ReviewerBreakdown.js index 7d257102a24dc7f39217f22b6c0529d800026247..8e51446107a345ca5776fe3558849127755ad2b9 100644 --- a/packages/component-faraday-ui/src/ReviewerBreakdown.js +++ b/packages/component-faraday-ui/src/ReviewerBreakdown.js @@ -1,11 +1,8 @@ import React from 'react' -import { get } from 'lodash' -import { compose, withHandlers, withProps } from 'recompose' +import PropTypes from 'prop-types' import { Text, Row } from './' -const ReviewerBreakdown = ({ getReportBreakdown }) => getReportBreakdown() - const roleFilter = role => i => i.role === role const submittedFilter = r => r.review && r.review.submittedOn const acceptedFilter = i => i.hasAnswer && i.isAccepted @@ -17,48 +14,58 @@ const reviewerReduce = (acc, r) => ({ submitted: submittedFilter(r) ? acc.submitted + 1 : acc.submitted, }) -export default compose( - withProps(({ fragment }) => ({ - invitations: get(fragment, 'invitations', []), - recommendations: get(fragment, 'recommendations', []), - })), - withHandlers({ - getReportBreakdown: ({ invitations, recommendations, ...rest }) => () => { - const reviewerInvitations = invitations.filter(roleFilter('reviewer')) - const invitationsWithRecommendations = reviewerInvitations.map(r => ({ - ...r, - review: recommendations.find(rec => rec.userId === r.userId), - })) - const report = invitationsWithRecommendations.reduce(reviewerReduce, { - accepted: 0, - declined: 0, - submitted: 0, - }) - return reviewerInvitations.length ? ( - <Row fitContent justify="flex-end" {...rest}> - <Text customId mr={1 / 2}> - {reviewerInvitations.length} - </Text> - <Text mr={1 / 2}> invited,</Text> +const ReviewerBreakdown = ({ + fragment: { invitations = [], recommendations = [] }, + ...rest +}) => { + const reviewerInvitations = invitations.filter(roleFilter('reviewer')) + const invitationsWithRecommendations = reviewerInvitations.map(r => ({ + ...r, + review: recommendations.find(rec => rec.userId === r.userId), + })) + const report = invitationsWithRecommendations.reduce(reviewerReduce, { + accepted: 0, + declined: 0, + submitted: 0, + }) + return reviewerInvitations.length ? ( + <Row fitContent justify="flex-end" {...rest}> + <Text customId mr={1 / 2}> + {reviewerInvitations.length} + </Text> + <Text mr={1 / 2}> invited,</Text> + + <Text customId mr={1 / 2}> + {report.accepted} + </Text> + <Text mr={1 / 2}> agreed,</Text> - <Text customId mr={1 / 2}> - {report.accepted} - </Text> - <Text mr={1 / 2}> agreed,</Text> + <Text customId mr={1 / 2}> + {report.declined} + </Text> + <Text mr={1 / 2}> declined,</Text> - <Text customId mr={1 / 2}> - {report.declined} - </Text> - <Text mr={1 / 2}> declined,</Text> + <Text customId mr={1 / 2}> + {report.submitted} + </Text> + <Text mr={1 / 2}> submitted</Text> + </Row> + ) : ( + <Text mr={1}>{`${reviewerInvitations.length} invited`}</Text> + ) +} - <Text customId mr={1 / 2}> - {report.submitted} - </Text> - <Text mr={1 / 2}> submitted</Text> - </Row> - ) : ( - <Text mr={1}>{`${reviewerInvitations.length} invited`}</Text> - ) - }, +ReviewerBreakdown.propTypes = { + fragment: PropTypes.shape({ + invitations: PropTypes.arrayOf(PropTypes.object), + recommendations: PropTypes.arrayOf(PropTypes.object), }), -)(ReviewerBreakdown) +} +ReviewerBreakdown.defaultProps = { + fragment: { + invitations: [], + recommendations: [], + }, +} + +export default ReviewerBreakdown diff --git a/packages/component-faraday-ui/src/ReviewerReport.js b/packages/component-faraday-ui/src/ReviewerReport.js index 36c67144b3e092102fe16e27a26c2228c0809402..ab0359a208c8e5b743bc97ebc29c0ffc74e1c3ba 100644 --- a/packages/component-faraday-ui/src/ReviewerReport.js +++ b/packages/component-faraday-ui/src/ReviewerReport.js @@ -1,13 +1,16 @@ import React, { Fragment } from 'react' import { get } from 'lodash' +import PropTypes from 'prop-types' import { withProps } from 'recompose' import styled from 'styled-components' -import { th } from '@pubsweet/ui-toolkit' import { DateParser } from '@pubsweet/ui' +import { th } from '@pubsweet/ui-toolkit' import { Label, Item, FileItem, Row, Text } from './' const ReviewerReport = ({ + journal, + showOwner, onPreview, onDownload, reportFile, @@ -17,7 +20,6 @@ const ReviewerReport = ({ reviewerName, reviewerNumber, recommendation, - showOwner = false, report: { submittedOn }, }) => ( <Root> @@ -92,6 +94,39 @@ export default withProps( }), )(ReviewerReport) +ReviewerReport.propTypes = { + /** True when you want to show reviewer name. */ + showOwner: PropTypes.bool, + /** Pass object with informations about the report. */ + report: PropTypes.shape({ + /** Unique id for report. */ + id: PropTypes.string, + /** Unique id for user. */ + userId: PropTypes.string, + /** Comments by reviewers. */ + comments: PropTypes.arrayOf(PropTypes.object), + /** When the comment was created. */ + createdOn: PropTypes.number, + /** When the comment was updated. */ + updatedOn: PropTypes.number, + /** When the comment was submited. */ + submittedOn: PropTypes.number, + /** The recommendation given by reviewer. */ + recommendation: PropTypes.string, + /** Type of recommendation. */ + recommendationType: PropTypes.string, + }), + /** Pass object with informations about recommendation. */ + journal: PropTypes.shape({ + recommendations: PropTypes.arrayOf(PropTypes.object), + }), +} + +ReviewerReport.defaultProps = { + showOwner: false, + report: {}, + journal: { recommendation: [] }, +} // #region styles const Root = styled.div` background-color: ${th('colorBackgroundHue')}; diff --git a/packages/component-faraday-ui/src/ReviewerReport.md b/packages/component-faraday-ui/src/ReviewerReport.md index 440b6a882e447344287e5db1a6383fd9de82e775..515b6e4651c6304a51ef780dce202c860497a98a 100644 --- a/packages/component-faraday-ui/src/ReviewerReport.md +++ b/packages/component-faraday-ui/src/ReviewerReport.md @@ -29,6 +29,7 @@ const report = { submittedOn: 1538053600624, recommendation: 'publish', recommendationType: 'review', + reviewerIndex: 1 } const journal = { diff --git a/packages/component-faraday-ui/src/ReviewerReportAuthor.js b/packages/component-faraday-ui/src/ReviewerReportAuthor.js index b921052a43f28c03404f823a5244fd301cbb19dc..c29d5e60c5df76bbe0d37288022508aa001033c0 100644 --- a/packages/component-faraday-ui/src/ReviewerReportAuthor.js +++ b/packages/component-faraday-ui/src/ReviewerReportAuthor.js @@ -1,21 +1,24 @@ import React, { Fragment } from 'react' import { get } from 'lodash' -import { withProps, compose } from 'recompose' +import PropTypes from 'prop-types' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { DateParser } from '@pubsweet/ui' +import { withProps, compose } from 'recompose' import { - Label, - Item, - FileItem, Row, Text, + Item, + Label, + FileItem, withFilePreview, withFileDownload, } from './' const ReviewerReportAuthor = ({ + journal, + showOwner, reviewFile, previewFile, downloadFile, @@ -23,7 +26,6 @@ const ReviewerReportAuthor = ({ reviewerName, reviewerNumber, recommendation, - showOwner = false, report: { submittedOn }, }) => ( <Root> @@ -82,6 +84,40 @@ export default compose( })), )(ReviewerReportAuthor) +ReviewerReportAuthor.propTypes = { + /** True when you want to show reviewer name. */ + showOwner: PropTypes.bool, + /** Pass object with informations about the report. */ + report: PropTypes.shape({ + /** Unique id for report. */ + id: PropTypes.string, + /** Unique id for user. */ + userId: PropTypes.string, + /** Comments by reviewers. */ + comments: PropTypes.arrayOf(PropTypes.object), + /** When the comment was created. */ + createdOn: PropTypes.number, + /** When the comment was updated. */ + updatedOn: PropTypes.number, + /** When the comment was submited. */ + submittedOn: PropTypes.number, + /** The recommendation given by reviewer. */ + recommendation: PropTypes.string, + /** Type of recommendation. */ + recommendationType: PropTypes.string, + }), + /** Pass object with informations about recommendation. */ + journal: PropTypes.shape({ + recommendations: PropTypes.arrayOf(PropTypes.object), + }), +} + +ReviewerReportAuthor.defaultProps = { + showOwner: false, + report: {}, + journal: { recommendation: [] }, +} + // #region styles const Root = styled.div` background-color: ${th('colorBackgroundHue')}; diff --git a/packages/component-faraday-ui/src/ReviewersTable.js b/packages/component-faraday-ui/src/ReviewersTable.js index e2197d20c406eeff827b6b4051f48062d7e7493e..f9ba6708bc73a0ebbbced263fc9bc85176a3b279 100644 --- a/packages/component-faraday-ui/src/ReviewersTable.js +++ b/packages/component-faraday-ui/src/ReviewersTable.js @@ -1,3 +1,4 @@ +import PropTypes from 'prop-types' import React, { Fragment } from 'react' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' @@ -5,10 +6,10 @@ import { DateParser } from '@pubsweet/ui' import { get, isEqual, orderBy } from 'lodash' import { compose, shouldUpdate, withHandlers, withProps } from 'recompose' -import { Label, PersonInvitation, Text } from '../' +import { Label, PersonInvitation, Text } from './' const ReviewersTable = ({ - invitations, + invitations = [], getInvitationStatus, renderAcceptedLabel, onResendReviewerInvite, @@ -94,6 +95,34 @@ const orderInvitations = i => { return 1 } +ReviewersTable.propTypes = { + /** Passes properties for invited reviewwers. */ + invitations: PropTypes.arrayOf( + PropTypes.shape({ + /** Reviewers unique id. */ + id: PropTypes.string, + /** Reviewers role. */ + role: PropTypes.string, + /** Type of invitation. */ + type: PropTypes.string, + /** Users unique id. */ + userId: PropTypes.string, + /** Reviewer has responded. */ + hasAnswer: PropTypes.bool, + /** Date of invite. */ + invitedOn: PropTypes.number, + /** Reviewer has accepted. */ + isAccepted: PropTypes.bool, + /** Date of the response. */ + respondedOn: PropTypes.number, + }), + ), +} + +ReviewersTable.defaultProps = { + invitations: [], +} + export default compose( shouldUpdate( ({ invitations }, { invitations: nextInvitations }) => diff --git a/packages/component-faraday-ui/src/Tabs.js b/packages/component-faraday-ui/src/Tabs.js index a7d90025dcd5eb9ce1d48215b0da37319fe9dffa..0e7ebbb3387a529091414f7e288ad22e851456e1 100644 --- a/packages/component-faraday-ui/src/Tabs.js +++ b/packages/component-faraday-ui/src/Tabs.js @@ -1,8 +1,21 @@ +import PropTypes from 'prop-types' import { compose, withStateHandlers } from 'recompose' -const Tabs = ({ items, selectedTab, changeTab, children }) => +const Tabs = ({ items, selectedTab = 2, changeTab, children }) => children({ selectedTab, changeTab }) +Tabs.propTypes = { + /** The selected tab. */ + selectedTab: PropTypes.number, + /** Handler to change the tab. */ + changeTab: PropTypes.func, +} + +Tabs.defaultProps = { + selectedTab: 0, + changeTab: () => {}, +} + export default compose( withStateHandlers(({ selectedTab = 0 }) => ({ selectedTab }), { changeTab: () => selectedTab => ({ diff --git a/packages/component-faraday-ui/src/Tag.js b/packages/component-faraday-ui/src/Tag.js index fd6ce0316577b29f1ca95619cdd180a860209c54..a37711bc72e4b111633e26248693206ed87b530e 100644 --- a/packages/component-faraday-ui/src/Tag.js +++ b/packages/component-faraday-ui/src/Tag.js @@ -1,11 +1,12 @@ -import { has } from 'lodash' +import { get } from 'lodash' +import PropTypes from 'prop-types' import { th } from '@pubsweet/ui-toolkit' import styled, { css } from 'styled-components' import { marginHelper } from './styledHelpers' const tagCSS = props => { - if (has(props, 'oldStatus')) { + if (get(props, 'oldStatus')) { return css` background-color: ${th('colorFurnitureHue')}; height: calc(${th('gridUnit')} * 3) @@ -15,7 +16,7 @@ const tagCSS = props => { ` } - if (has(props, `status`)) { + if (get(props, `status`)) { return css` background-color: ${th('tag.statusBackgroundColor')}; padding: calc(${th('gridUnit')} / 4) ${th('gridUnit')}; @@ -35,7 +36,7 @@ const tagCSS = props => { } /** @component */ -export default styled.div` +const Tag = styled.div` border-radius: ${th('tag.borderRadius') ? th('tag.borderRadius') : th('borderRadius')}; @@ -52,3 +53,17 @@ export default styled.div` ${tagCSS}; ${marginHelper}; ` + +Tag.propTypes = { + /** Old status of the corresponding user. */ + oldStatus: PropTypes.bool, + /** New status of the corresponding user. */ + status: PropTypes.bool, +} + +Tag.defaultProps = { + oldStatus: false, + status: false, +} + +export default Tag diff --git a/packages/component-faraday-ui/src/Text.js b/packages/component-faraday-ui/src/Text.js index d8092434a6dc7f35fa449cd1ad801d5344e0ea26..5a21b6b2e540bc4d977e0d33729800b563624196 100644 --- a/packages/component-faraday-ui/src/Text.js +++ b/packages/component-faraday-ui/src/Text.js @@ -1,30 +1,31 @@ import React from 'react' -import { has, get } from 'lodash' +import { get } from 'lodash' +import PropTypes from 'prop-types' import { th } from '@pubsweet/ui-toolkit' import styled, { css } from 'styled-components' import { paddingHelper, marginHelper } from './styledHelpers' const textHelper = props => { - if (has(props, 'secondary')) { + if (get(props, 'secondary')) { return css` color: ${th('colorSecondary')}; font-family: ${th('fontReading')}; ` } - if (has(props, 'error')) { + if (get(props, 'error')) { return css` color: ${th('colorError')}; font-family: ${th('fontReading')}; ` } - if (has(props, 'customId')) { + if (get(props, 'customId')) { return css` color: ${th('colorPrimary')}; font-family: ${th('fontInterface')}; ` } - if (has(props, 'labelLine')) { + if (get(props, 'labelLine')) { return css` color: ${th('colorFurnitureHue')}; font-family: ${th('fontInterface')}; @@ -38,7 +39,7 @@ const textHelper = props => { } ` } - if (has(props, 'journal')) { + if (get(props, 'journal')) { return css` color: ${th('colorSecondary')}; font-family: ${th('fontReading')}; @@ -88,7 +89,7 @@ const Root = styled.div` display: flex; ` -export default ({ bullet, children, ...rest }) => +const Text = ({ bullet, children, ...rest }) => bullet ? ( <Root> <Bullet>{'\u2022'}</Bullet> @@ -97,3 +98,29 @@ export default ({ bullet, children, ...rest }) => ) : ( <StyledText {...rest}>{children}</StyledText> ) + +Text.propTypes = { + /** Default color for non-primary actions. */ + secondary: PropTypes.bool, + /** Default color for error actions. */ + error: PropTypes.bool, + /** Default style for the customId text. */ + customId: PropTypes.bool, + /** Default style for text used as a label Line. */ + labelLine: PropTypes.bool, + /** Default style used for journal text. */ + journal: PropTypes.bool, + /** Default style used for small text. */ + small: PropTypes.bool, +} + +Text.defaultProps = { + secondary: false, + error: false, + customId: false, + labelLine: false, + journal: false, + small: false, +} + +export default Text diff --git a/packages/component-faraday-ui/src/Text.md b/packages/component-faraday-ui/src/Text.md index a99cff36c791742b9c407ace98d9b794b34edf6c..18d57021692c02150f753822defcf8c3083d3f64 100644 --- a/packages/component-faraday-ui/src/Text.md +++ b/packages/component-faraday-ui/src/Text.md @@ -19,12 +19,24 @@ A secondary text. (Body 2) <Text secondary>my boy is amazing</Text> ``` +Error text. + +```js +<Text error>why error?</Text> +``` + A text used for manuscript custom IDs. ```js <Text customId>ID 444222</Text> ``` +A text used for journal. + +```js +<Text journal>text for journal</Text> +``` + A small text. ```js diff --git a/packages/component-faraday-ui/src/TextTooltip.js b/packages/component-faraday-ui/src/TextTooltip.js index 8bcd4cc0352c3754f269295dab914b7c3ed089aa..2c43317ee93a8e6ed19b25a9ae36113c3d2d0350 100644 --- a/packages/component-faraday-ui/src/TextTooltip.js +++ b/packages/component-faraday-ui/src/TextTooltip.js @@ -1,6 +1,7 @@ -import React, { Fragment } from 'react' +import PropTypes from 'prop-types' import 'react-tippy/dist/tippy.css' import { Tooltip } from 'react-tippy' +import React, { Fragment } from 'react' import { Text, Row } from 'pubsweet-component-faraday-ui' import { ThemeProvider, withTheme } from 'styled-components' @@ -25,4 +26,13 @@ const TextTooltip = ({ theme = {}, children, ...rest }) => ( </Tooltip> ) +TextTooltip.propTypes = { + /** User can hover over an item, without clicking it, and a new window will appear with a new title */ + title: PropTypes.string, +} +TextTooltip.defaultProps = { + title: + 'β-Carboline Silver Compound Binding Studies with Human Serum Albumin: A Comprehensive Multispectroscopic Analysis and Molecular Modeling Study', +} + export default withTheme(TextTooltip) diff --git a/packages/component-faraday-ui/src/Textarea.js b/packages/component-faraday-ui/src/Textarea.js index 8013357da8409d4356a9da67367b7719a41c1d39..91fac36c2976228cb22b6c18c5db3ba91d40b9c5 100644 --- a/packages/component-faraday-ui/src/Textarea.js +++ b/packages/component-faraday-ui/src/Textarea.js @@ -1,4 +1,5 @@ import { get } from 'lodash' +import PropTypes from 'prop-types' import { th } from '@pubsweet/ui-toolkit' import styled, { css } from 'styled-components' @@ -33,6 +34,14 @@ const Textarea = styled.textarea` background-color: ${th('colorBackgroundHue')}; } ` +Textarea.propTypes = { + /** The minimum height that the text box should have */ + minHeight: PropTypes.number, +} + +Textarea.defaultProps = { + minHeight: 10, +} /** @component */ export default Textarea diff --git a/packages/component-faraday-ui/src/UserProfile.js b/packages/component-faraday-ui/src/UserProfile.js index 71592b198a12df5444b2d2446a3eb91a91b614d8..7c59dda1bef5d1d2c9f17c011966e9ca87666ca1 100644 --- a/packages/component-faraday-ui/src/UserProfile.js +++ b/packages/component-faraday-ui/src/UserProfile.js @@ -1,13 +1,14 @@ /* eslint-disable handle-callback-err */ -import React, { Fragment } from 'react' import { get } from 'lodash' +import PropTypes from 'prop-types' import styled from 'styled-components' import { reduxForm } from 'redux-form' +import React, { Fragment } from 'react' import { th } from '@pubsweet/ui-toolkit' +import { withCountries } from 'pubsweet-component-faraday-ui' import { required as requiredValidator } from 'xpub-validators' import { compose, withStateHandlers, withProps } from 'recompose' import { H3, Spinner, ValidatedField, TextField, Menu } from '@pubsweet/ui' -import { withCountries, MenuCountry } from 'pubsweet-component-faraday-ui' import { Row, @@ -181,9 +182,7 @@ const EditUserProfile = compose( <Item ml={1} vertical> <Label required>Country</Label> <ValidatedField - component={input => ( - <MenuCountry {...input} placeholder="Please select" /> - )} + component={input => <Menu {...input} options={countries} />} name="country" validate={[requiredValidator]} /> @@ -240,6 +239,72 @@ const UserProfile = ({ /> ) +UserProfile.propTypes = { + /** Passes journals label and value which will appear in the signature. */ + journal: PropTypes.shape({ + title: PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.string, + value: PropTypes.string, + }), + ), + }), + /** Passes properties for the users profile */ + user: PropTypes.shape({ + /** Users unique id. */ + id: PropTypes.string, + /** Type of created account. */ + type: PropTypes.string, + /** Determine if account is admin ot not. */ + admin: PropTypes.bool, + /** Email used for user authentification. */ + email: PropTypes.string, + /** */ + teams: PropTypes.array, + /** Title of account userd. */ + title: PropTypes.string, + /** */ + agreeTC: PropTypes.bool, + /** Country of account user. */ + contry: PropTypes.string, + /** Status of account. */ + isActive: PropTypes.bool, + /** Last Name of accounts user. */ + lastName: PropTypes.string, + /** First name of accounts user. */ + username: PropTypes.string, + /** Account user first name. */ + firstName: PropTypes.string, + /** */ + fragments: PropTypes.array, + /** Accounts user affiliation. */ + affiliation: PropTypes.string, + /** */ + collection: PropTypes.array, + /** Determine if account is confirmed or not. */ + isConfirmed: PropTypes.bool, + /** Determine if account is editor in chief or not. */ + editorInChief: PropTypes.bool, + /** */ + notifications: PropTypes.shape({ + email: PropTypes.shape({ + user: PropTypes.bool, + system: PropTypes.bool, + }), + }), + + /** Determine if account is hendling editor or not. */ + handlingEditor: PropTypes.bool, + /** Users unique token */ + token: PropTypes.string, + }), +} + +UserProfile.defaultProps = { + journal: {}, + user: {}, +} + export default compose( withCountries, withStateHandlers( diff --git a/packages/component-faraday-ui/src/WizardAuthors.js b/packages/component-faraday-ui/src/WizardAuthors.js index 4b490d3efa1115683c9bc6b5f63b73e1e65ea524..6739fd1c16731963438485fe3b25bdfe8cf90f7b 100644 --- a/packages/component-faraday-ui/src/WizardAuthors.js +++ b/packages/component-faraday-ui/src/WizardAuthors.js @@ -1,5 +1,6 @@ -import React, { Fragment } from 'react' +import PropTypes from 'prop-types' import styled from 'styled-components' +import React, { Fragment } from 'react' import { th } from '@pubsweet/ui-toolkit' import { omit, isBoolean, get } from 'lodash' import { compose, withState, withHandlers } from 'recompose' @@ -223,6 +224,36 @@ export default compose( }), )(WizardAuthors) +WizardAuthors.propTypes = { + /** List of authors. */ + authors: PropTypes.arrayOf(PropTypes.object), + /** Function used for draging authors. */ + moveAuthor: PropTypes.func, + /** Funtion used for adding new authors. */ + addNewAuthor: PropTypes.func, + /** Function used for deleting authors. */ + deleteAuthor: PropTypes.func, + /** Function used for selecting authors for edit. */ + setAuthorEdit: PropTypes.func, + /** Function used for saving new authors. */ + saveNewAuthor: PropTypes.func, + /** Function used for editing authors. */ + editExistingAuthor: PropTypes.func, + /** Function used for submiting authors. */ + authorEditorSubmit: PropTypes.func, +} + +WizardAuthors.defaultProps = { + authors: [], + moveAuthor: () => {}, + addNewAuthor: () => {}, + deleteAuthor: () => {}, + setAuthorEdit: () => {}, + saveNewAuthor: () => {}, + editExistingAuthor: () => {}, + authorEditorSubmit: () => {}, +} + // #region styles const SortableContainer = styled.div` background-color: ${th('colorBackground')}; diff --git a/packages/component-faraday-ui/src/WizardFiles.js b/packages/component-faraday-ui/src/WizardFiles.js index 9bd0591a7ff21c8ca020583682a8130d7b9da290..d93ddfe81f76b809d52d828a3dc03bc5952ecca0 100644 --- a/packages/component-faraday-ui/src/WizardFiles.js +++ b/packages/component-faraday-ui/src/WizardFiles.js @@ -1,4 +1,5 @@ import React, { Fragment } from 'react' +import PropTypes from 'prop-types' import { get } from 'lodash' import { compose, withState, withHandlers } from 'recompose' @@ -18,6 +19,9 @@ const WizardFiles = ({ changeList, previewFile, downloadFile, + manuscripts, + coverLetter, + supplementary, }) => ( <Fragment> <FileSection @@ -75,6 +79,47 @@ const initialFiles = { supplementary: [], } +WizardFiles.propTypes = { + /** Fragments manuscript file. */ + manuscripts: PropTypes.arrayOf( + PropTypes.shape({ + /** Id of added manuscript file. */ + id: PropTypes.string, + /** Name of added manuscript file. */ + name: PropTypes.string, + /** Size of added manusript file. */ + size: PropTypes.number, + }), + ), + /** Fragments cover letter file. */ + coverLetter: PropTypes.arrayOf( + PropTypes.shape({ + /** Id of added cover letter file. */ + id: PropTypes.string, + /** Name of added cover letter file. */ + name: PropTypes.string, + /** Size of added cover letter file. */ + size: PropTypes.number, + }), + ), + /** Fragments supplementary file. */ + supplementary: PropTypes.arrayOf( + PropTypes.shape({ + /** Id of added cover letter file. */ + id: PropTypes.string, + /** Name of added cover letter file. */ + name: PropTypes.string, + /** Size of added cover letter file. */ + size: PropTypes.number, + }), + ), +} +WizardFiles.defaultProps = { + manuscripts: [], + coverLetter: [], + supplementary: [], +} + export default compose( withFilePreview, withFileDownload, diff --git a/packages/component-faraday-ui/src/contextualBoxes/AssignHE.js b/packages/component-faraday-ui/src/contextualBoxes/AssignHE.js index caae4f78f6415c5a7e5c76da2b1636074a2a878c..decb41c06ba7d32b0a7e2202024d63a8901e55a6 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/AssignHE.js +++ b/packages/component-faraday-ui/src/contextualBoxes/AssignHE.js @@ -1,4 +1,5 @@ import React, { Fragment } from 'react' +import PropTypes from 'prop-types' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { Button, TextField } from '@pubsweet/ui' @@ -49,7 +50,7 @@ const AssignHE = ({ </TextContainer> {handlingEditors.length > 0 && ( <Fragment> - <Row alignItems="center" height={4} pl={1}> + <Row alignItems="center" height="4" pl={1}> <Item flex={1}> <Label>Name</Label> </Item> @@ -62,7 +63,7 @@ const AssignHE = ({ <CustomRow alignItems="center" data-test-id={`manuscript-assign-he-invite-${he.id}`} - height={4} + height="4" isFirst={index === 0} key={he.id} pl={1} @@ -96,6 +97,27 @@ const AssignHE = ({ </Root> ) +AssignHE.propTypes = { + /** Changes the search value to lowercase letters. */ + changeSearch: PropTypes.func, + /** The value of the search input box. */ + searchValue: PropTypes.string, + /** Clears the value of the search input box. */ + clearSearch: PropTypes.func, + /** The list of available handling editors. */ + handlingEditors: PropTypes.arrayOf(PropTypes.object), + /** Invites the selected handling editor. */ + inviteHandlingEditor: PropTypes.func, +} + +AssignHE.defaultProps = { + changeSearch: () => {}, + searchValue: '', + clearSearch: () => {}, + handlingEditors: [], + inviteHandlingEditor: () => {}, +} + export default compose( defaultProps({ inviteHandlingEditor: he => {}, @@ -134,7 +156,6 @@ export default compose( // #region styles const Root = styled.div` background-color: ${th('colorBackgroundHue2')}; - ${paddingHelper}; ` diff --git a/packages/component-faraday-ui/src/contextualBoxes/AssignHE.md b/packages/component-faraday-ui/src/contextualBoxes/AssignHE.md index afb5179bdb3cc399ebf0e287c177d7a8ed4fc620..7e25e7c077d80db952c67ded04d8063a479563b9 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/AssignHE.md +++ b/packages/component-faraday-ui/src/contextualBoxes/AssignHE.md @@ -2,12 +2,22 @@ Assign Handling Editor contextual box. ```js const handlingEditors = [ - { id: '1', name: 'Handling Edi', email: 'handling@edi.com' }, - { id: '2', name: 'Aurel Vlaicu', email: 'aurel@vlaicu.com' }, - { id: '3', name: 'Gheorghe Hagi', email: 'gica@hagi.com' }, -]; + { + id: '1', + firstName: 'Handling', + lastName: 'Edi', + email: 'handling@edi.com', + }, + { + id: '2', + firstName: 'Aurel', + lastName: 'Vlaicu', + email: 'aurel@vlaicu.com', + }, + { id: '3', firstName: 'Gheorghe', lastName: 'Hagi', email: 'gica@hagi.com' }, +] -<ContextualBox label="Assign Handling Editor"> +;<ContextualBox label="Assign Handling Editor"> <AssignHE handlingEditors={handlingEditors} inviteHandlingEditor={he => console.log('inviting: ', he)} diff --git a/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js b/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js index 696e8a4e405ca71b5e6844cfedf81994863060a2..aed0b39d26e55a8bcffc0b8b600db616a0038ea5 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js +++ b/packages/component-faraday-ui/src/contextualBoxes/AuthorReviews.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { withProps, compose } from 'recompose' import { get } from 'lodash' @@ -51,6 +52,24 @@ const AuthorReviews = ({ </ContextualBox> ) +AuthorReviews.propTypes = { + /** The list of available reports. */ + reports: PropTypes.arrayOf(PropTypes.object), + /** Returns the url of the selected file. */ + getSignedUrl: PropTypes.func, + /** Object containing the list of recommendations. */ + journal: PropTypes.object, //eslint-disable-line + /** Contains the token of the currently logged user. */ + token: PropTypes.string, +} + +AuthorReviews.defaultProps = { + reports: [], + getSignedUrl: () => {}, + journal: {}, + token: '', +} + export default compose( withProps( ({ diff --git a/packages/component-faraday-ui/src/contextualBoxes/HERecommendation.js b/packages/component-faraday-ui/src/contextualBoxes/HERecommendation.js index 3eb14eb32d1a156f67e545557886f1366d14b0cf..79593cc08ad553f86c18a4b8ab0e76850212d598 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/HERecommendation.js +++ b/packages/component-faraday-ui/src/contextualBoxes/HERecommendation.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { get, tail } from 'lodash' import { reduxForm } from 'redux-form' import styled from 'styled-components' @@ -107,7 +108,6 @@ const HERecommendation = ({ /> </ItemOverrideAlert> </Row> - {get(formValues, 'recommendation') === 'minor' || get(formValues, 'recommendation') === 'major' ? ( <Row mt={2}> @@ -147,7 +147,6 @@ const HERecommendation = ({ </ResponsiveItem> </ResponsiveRow> )} - <Row justify="flex-end" mt={2}> <Button data-test-id="button-editorial-recommendation-submit" @@ -166,6 +165,24 @@ const HERecommendation = ({ </ContextualBox> ) +HERecommendation.propTypes = { + /* Contains the values of the form inputs */ + formValues: PropTypes.object, //eslint-disable-line + /* Handles the submission of the recommendation */ + handleSubmit: PropTypes.func, + /* Specifies if the fragment has reviewer reports */ + hasReviewerReports: PropTypes.bool, + /* Specifies if the contextual box should be highlighted */ + highlight: PropTypes.bool, +} + +HERecommendation.defaultProps = { + formValues: {}, + handleSubmit: () => {}, + hasReviewerReports: false, + highlight: false, +} + export default compose( withFetching, withModal(({ isFetching }) => ({ diff --git a/packages/component-faraday-ui/src/contextualBoxes/HERecommendation.md b/packages/component-faraday-ui/src/contextualBoxes/HERecommendation.md index 8d00e6a5fd7d66796ff780a4ddbc1d9adb172546..45874db4a4e567de25d688c774c6db4e596fc1ca 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/HERecommendation.md +++ b/packages/component-faraday-ui/src/contextualBoxes/HERecommendation.md @@ -2,10 +2,37 @@ HE recommendation. ```js const formValues = { - recommendation: 'minor-revision', + recommendation: 'minor', } +const options = [ + { + value: 'publish', + label: 'Publish', + message: 'Recommend Manuscript for Publishing', + button: 'Submit Recommendation', + }, + { + value: 'reject', + label: 'Reject', + message: 'Recommend Manuscript for Rejection', + button: 'Submit Recommendation', + }, + { + value: 'minor', + label: 'Request Minor Revision', + message: 'Request Minor Revision', + button: 'Request Revision', + }, + { + value: 'major', + label: 'Request Major Revision', + message: 'Request Major Revision', + button: 'Request Revision', + }, +] ;<HERecommendation formValues={formValues} + options={options} modalKey="heRecommendation" onRecommendationSubmit={(values, props) => { props.setFetching(true) diff --git a/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js index cdb6ed72a1c30a89e4da9bb466549eec443ce1bd..9c74c2c383b25b3807ec72f3b2c2d55dcd821698 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js +++ b/packages/component-faraday-ui/src/contextualBoxes/ResponseToRevisionRequest.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { compose } from 'recompose' import { @@ -33,6 +34,22 @@ const ResponseToRevisionRequest = ({ </ContextualBox> ) +ResponseToRevisionRequest.propTypes = { + /** Object containing the selected fragment. */ + fragment: PropTypes.object, //eslint-disable-line + /** Callback function used to control the state of the component. + * To be used together with the `expanded` prop. + */ + toggle: PropTypes.func, + /** Prop used together with toggle. */ + expanded: PropTypes.bool, +} +ResponseToRevisionRequest.defaultProps = { + fragment: {}, + toggle: () => {}, + expanded: false, +} + export default compose(withFilePreview, withFileDownload)( ResponseToRevisionRequest, ) diff --git a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js index 987aa4a775f7eed363cfcfe0793c5e4baeb1468c..d8c5df524a74c5de294c3d9bb7611b4cc2875e95 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js +++ b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js @@ -1,5 +1,6 @@ import React, { Fragment } from 'react' import { get } from 'lodash' +import PropTypes from 'prop-types' import { H4 } from '@pubsweet/ui' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' @@ -139,6 +140,67 @@ const ReviewerDetails = ({ </ContextualBox> ) +ReviewerDetails.propTypes = { + /** Object containing the list of recommendations. */ + journal: PropTypes.object, //eslint-disable-line + /** Object containing the selected fragment. */ + fragment: PropTypes.object, //eslint-disable-line + /** Specifies how many reviewers have been invited. */ + invitations: PropTypes.array, //eslint-disable-line + /** Array that contains publon reviewers. */ + publonReviewers: PropTypes.array, //eslint-disable-line + /** View content of the uploaded file. */ + previewFile: PropTypes.func, + /** Downloads the file from the server. */ + downloadFile: PropTypes.func, + /** Sends an invitation to the reviewer. */ + onInviteReviewer: PropTypes.func, + /** Reviewers reports. */ + reports: PropTypes.array, //eslint-disable-line + /** Sends an invitation to a Publon reviewer. */ + onInvitePublonReviewer: PropTypes.func, + /** Resends an invitation to an already invited. */ + onResendReviewerInvite: PropTypes.func, + /** Cancels an invitation to an invited reviewer. */ + onRevokeReviewerInvite: PropTypes.func, + /** Callback function used to control the state of the component. + * To be used together with the `expanded` prop. + */ + toggle: PropTypes.func, + /** Prop used together with toggle. */ + expanded: PropTypes.bool, + /* Specifies if the contextual box should be highlighted */ + highlight: PropTypes.bool, + /** Specifies if manuscript is at the latest version. */ + isLatestVersion: PropTypes.bool, + /** Specifies if we can invite reviewers on the current version. */ + canInviteReviewers: PropTypes.bool, + /** Specifies if we can view reviewers details on the current version. */ + canViewReviewersDetails: PropTypes.bool, + /** Specifies if the author can view reports details on the current version. */ + authorCanViewReportsDetails: PropTypes.func, +} +ReviewerDetails.defaultProps = { + journal: {}, + reports: [], + fragment: {}, + invitations: [], + publonReviewers: [], + previewFile: () => {}, + downloadFile: () => {}, + onInviteReviewer: () => {}, + onInvitePublonReviewer: () => {}, + onResendReviewerInvite: () => {}, + onRevokeReviewerInvite: () => {}, + toggle: () => {}, + expanded: false, + highlight: false, + canInviteReviewers: false, + canViewReviewersDetails: false, + authorCanViewReportsDetails: () => {}, + isLatestVersion: false, +} + export default compose( withFilePreview, withFileDownload, diff --git a/packages/component-faraday-ui/src/gridItems/Item.js b/packages/component-faraday-ui/src/gridItems/Item.js index 060846c5310beecc5fb598646589fcfeff966b47..a784d8561d2aaa1ee4e87ab87559efbeb79d650c 100644 --- a/packages/component-faraday-ui/src/gridItems/Item.js +++ b/packages/component-faraday-ui/src/gridItems/Item.js @@ -1,12 +1,13 @@ import { isNumber } from 'lodash' +import PropTypes from 'prop-types' import styled from 'styled-components' import { marginHelper, paddingHelper } from 'pubsweet-component-faraday-ui' /** @component */ -export default styled.div.attrs(props => ({ - 'data-test-id': props['data-test-id'] || 'item', -}))` +const Item = styled.div.attrs({ + 'data-test-id': props => props['data-test-id'] || 'item', +})` align-items: ${({ alignItems }) => alignItems || 'initial'}; display: flex; flex: ${({ flex }) => (isNumber(flex) ? flex : 1)}; @@ -17,3 +18,26 @@ export default styled.div.attrs(props => ({ ${marginHelper}; ${paddingHelper}; ` + +Item.propTypes = { + /** Defines how flex items are laid out along the secondary axis. */ + alignItems: PropTypes.string, + /** How much space should this item take relative to the other items. */ + flex: PropTypes.number, + /** Sets the flex direction. If true items are layed out in a column. */ + vertical: PropTypes.bool, + /** Sets whether flex items are forced onto one line or can wrap on multiple ones. */ + flexWrap: PropTypes.string, + /** Specifies alignment along the main axis. */ + justify: PropTypes.string, +} + +Item.defaultProps = { + alignItems: 'initial', + flex: 1, + vertical: false, + flexWrap: 'initial', + justify: 'initial', +} + +export default Item diff --git a/packages/component-faraday-ui/src/gridItems/Item.md b/packages/component-faraday-ui/src/gridItems/Item.md index f6f91b4d33f93f53be7c1257d2786a38dadc315b..60aa616a3d7c01496c47fb5f353bf9f529ef062a 100644 --- a/packages/component-faraday-ui/src/gridItems/Item.md +++ b/packages/component-faraday-ui/src/gridItems/Item.md @@ -7,6 +7,14 @@ An item. By default the content is displayed in a row. </Item> ``` +All items are wrapped into a flex container + +```js +<Item flex={1}> + <div>i m the only flex container</div> +</Item> +``` + Displayed in a column. ```js @@ -15,3 +23,33 @@ Displayed in a column. <span>I am at the bottom</span> </Item> ``` + +Items are aligned in their containing block + +```js +<Item alignItems="center" vertical> + <div>I m the first item</div> + <div>I m the second item</div> + <div>I m the third item</div> +</Item> +``` + +Long items wrap on the next row + +```js +<Item flexWrap="wrap"> + <div>wrap us together please, i m first, and i will be the longest to prove my point</div> + <div>wrap us together please, i m second</div> + <div>wrap us together please, i m last</div> +</Item> +``` + +Adds spaces between items + +```js +<Item justify="space-between"> + <div>group us from the left, i m first</div> + <div>group us from the left, i m second</div> + <div>group us from the left, i m last</div> +</Item> +``` diff --git a/packages/component-faraday-ui/src/gridItems/Row.js b/packages/component-faraday-ui/src/gridItems/Row.js index facd07a3a394b4a7fe79be1a3c88bb1b2dec9fe0..9885c26aa20d875994268925273dd173167d28a0 100644 --- a/packages/component-faraday-ui/src/gridItems/Row.js +++ b/packages/component-faraday-ui/src/gridItems/Row.js @@ -1,22 +1,43 @@ import { get } from 'lodash' +import PropTypes from 'prop-types' import styled from 'styled-components' import { heightHelper, marginHelper, paddingHelper } from '../styledHelpers' /** @component */ -export default styled.div.attrs(props => ({ - 'data-test-id': props['data-test-id'] || 'row', -}))` +const Row = styled.div.attrs({ + 'data-test-id': props => props['data-test-id'] || 'row', +})` align-items: ${props => get(props, 'alignItems', 'flex-start')}; background-color: ${props => props.bgColor || 'transparent'}; display: flex; flex-wrap: ${props => get(props, 'flexWrap', 'initial')}; justify-content: ${props => get(props, 'justify', 'space-evenly')}; - height: ${props => get(props, 'height', 'auto')}; - width: ${props => (props.fitContent ? 'fit-content' : '100%')}; + height: ${props => get(props, 'height', 'autp')}; ${heightHelper}; ${marginHelper}; ${paddingHelper}; ` + +Row.propTypes = { + /** Defines how flex items are laid out along the seconday axis. */ + alignItems: PropTypes.string, + /** Defines the background color. */ + bgColor: PropTypes.string, + /** Sets whether flex items are forced onto one line or can wrap on multiple ones. */ + flexWrap: PropTypes.string, + /** Specifies alignment along the main axis. */ + justifyContent: PropTypes.string, +} + +Row.defaultProps = { + alignItems: 'flex-start', + bgColor: 'transparent', + flexWrap: 'initial', + justifyContent: 'space-evenly', + height: '100%', +} + +export default Row diff --git a/packages/component-faraday-ui/src/gridItems/Row.md b/packages/component-faraday-ui/src/gridItems/Row.md index 77bcd1717adfaab12885fe3178df888070346276..c397c36e451ca563392a6b28bd5f87eeb13a39cd 100644 --- a/packages/component-faraday-ui/src/gridItems/Row.md +++ b/packages/component-faraday-ui/src/gridItems/Row.md @@ -2,8 +2,57 @@ A row of items. ```js <Row> - <Item>Item 1</Item> - <Item>Item 2</Item> - <div>Item 3</div> + <Item>Item 1</Item> + <Item>Item 2</Item> + <Item>Item 3</Item> </Row> -``` \ No newline at end of file +``` + +Items are aligned in their containing block + +```js +<Row alignItems="flex-start" vertical> + <Item>I m the first item</Item> + <Item>I m the second item</Item> + <Item>I m the third item</Item> +</Row> +``` + +Long items wrap on the next row + +```js +<Row flexWrap="wrap"> + <Item> + wrap us together please, i m first, and i will be the longest to prove my + point + </Item> + <Item>wrap us together please, i m second</Item> + <Item>wrap us together please, i m last</Item> +</Row> +``` + +Adds spaces between items + +```js +<Row justifyContent="space-evenly"> + <Item>group us from the left, i m first</Item> + <Item>group us from the left, i m second</Item> + <Item>group us from the left, i m last</Item> +</Row> +``` + +The height of an item is specified + +```js +<Row height="100%"> + <Item>this is an item</Item> +</Row> +``` + +Adds color to the row + +```js +<Row bgColor="aqua"> + <Item>this is an item</Item> +</Row> +``` diff --git a/packages/component-faraday-ui/src/helpers/README.md b/packages/component-faraday-ui/src/helpers/README.md new file mode 100644 index 0000000000000000000000000000000000000000..588a016a342b676e6bb207f4a2f87fe92da8e694 --- /dev/null +++ b/packages/component-faraday-ui/src/helpers/README.md @@ -0,0 +1,320 @@ +## Hindawi Helpers + +_Utility HOCs_ + +* [withCountries](#withcountries) +* [withFetching](#withfetching) +* [withFileDownload](#withfiledownload) +* [withFilePreview](#withfilepreview) +* [withPagination](#withpagination) +* [withRoles](#withroles) +* [withZipDownload](#withzipdownload) + +_HOCs used for files drag and drop_ + +* [withFileSectionDrop](#withfilesectiondrop) +* [withNativeFileDrop](#withnativefiledrop) + +_Utility functions_ + +* [handleError](#handleerror) + +# Utility HOCs + +## withCountries + +Injects `countries` and `countryLabel` as props. + +### withCountries props + +| Name | Type | Description | +| :----------- | :--------------------------------- | :-------------------------------------------------- | +| countries | `[{value: string, label: string}]` | the list of countries | +| countryLabel | `(code: string) => string` | get the name of the country with the specified code | + +```js +import { Menu } from '@pubsweet/ui' +import { withCountries } from 'pubsweet-component-faraday-ui' + +const Wrapped = ({ countries, countryLabel }) => ( + <div> + <Menu options={countries} placeholder="Select a country" /> + + <span>Selected country: {countryLabel('RO')}</span> + </div> +) + +export default withCountries(Wrapped) +``` + +## withFetching + +Injects `isFetching`, `fetchingError`, `setFetching`, `toggleFetching`, `setError` and `clearError` as props. + +### withFetching props + +| Name | Type | Description | +| :------------- | :----------------------- | :---------------------------------------------------------- | +| isFetching | `bool` | Pending async operation sattus | +| fetchingError | `fetchingError` | Value representing the error | +| setFetching | `(value: bool) => any` | Function for setting the `isFetching` value | +| toggleFetching | `(value: bool) => any` | Function that toggles the current value of `isFetching` | +| setError | `(error: string) => any` | Function that sets `fetchingError` | +| clearError | `() => any` | Function that resets `fetchingError` to it's original value | + +```js +import { withFetching } from 'pubsweet-component-faraday-ui' + +const Wrapped = ({ isFetching, fetchingError, setFetching, toggleFetching }) => ( + <div> + {isFetching && <span>I am fetching</span>} + <span>{`The error: ${fetchingError}`</span> + <button onClick={() => setFetching(true)}>Set fetching true</button> + <button onClick={() => setFetching(false)}>Set fetching false</button> + <button onClick={toggleFetching}>Toggle fetching</button> + </div> +) + +export default withFetching(Wrapped) +``` + +## withFileDownload + +Injects `downloadFile` as a prop. + +### withFileDownload props + +| Name | Type | Description | +| :----------- | :------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| downloadFile | `(file: {id: string, name: string}) => any` | Downloads the file specified as a parameter. The wrapped component should have the authentication token in a prop called `token` in order for this to work. | + +```js +import { FileItem, withFileDownload } from 'pubsweet-component-faraday-ui' + +const file = { + id: 'myfile', + name: 'myfile.pdf', + size: 100231, +} + +const Wrapped = ({ downloadFile }) => ( + <div> + <FileItem item={file} onDownload={downloadfile} /> + </div> +) + +export default withFileDownload(Wrapped) +``` + +## withFilePreview + +Generate a securized file URL and preview it in a new tab. Injects `previewFile` as a prop. + +This HOC assumes the following props are present on the wrapped component: + +| Name | Type | Description | +| :----------- | :--------------------------------------------- | :------------------------------------------------ | +| getSignedURL | `(id: string) => Promise({signedURL: string})` | Async call that returns the securized S3 file url | + +### withFilePreviewProps + +| Name | Type | Description | +| :---------- | :--------------------------------- | :--------------------------------------------------------------------------- | +| previewFile | `(file: {id: string, ...}) => any` | Opens the file preview in a new tab (only possible for PDF files and images) | + +```javascript +import { withProps } from 'recompose' +import { FileItem, withFilePreview Wrapped} from 'pubsweet-component-faraday-ui' + +const file = { + id: 'myfile', + name: 'myfile.pdf', + size: 100231, +} + +const Wrapped = ({ previewFile }) => ( + <div> + <FileItem item={file} onPreview={previewFile} /> + </div> +) + +export default withFilePreview(Wrapped) +``` + +## withPagination + +Injects `page`, `itemsPerPage`, `toFirst`, `nextPage`, `toLast`, `prevPage`, `changeItemsPerPage`, `hasMore`, `maxItems` and `paginatedItems` as props. + +### withPagination props + +| Name | Type | Description | +| :----------------- | :---------------------------------------------------------- | :------------------------------------ | +| page | `number` | Current page. | +| itemsPerPage | `number` | Number of items to be shown per page. | +| maxItems | `number` | Total number of items. | +| maxItems | `number` | Total number of items. | +| hasMore | `bool` | If we're not at the last page yet. | +| paginatedItems | `[any]` | Slice of the original items. | +| toFirst | `() => { page: number }` | Go to the first page. | +| toLast | `() => { page: number }` | Go to the last page. | +| nextPage | `() => { page: number }` | Move to the next page. | +| prevPage | `() => { page: number }` | Move to the previous page. | +| changeItemsPerPage | `e: HTMLInputEvent => {page: number, itemsPerPage: number}` | Change the number of items per page. | + +```js +import { withPagination } from 'pubsweet-component-faraday-ui' + +const Wrapped = ({ page, nextPage, prevPage, paginatedItems, changeItemsPerPage }) => ( + <div> + <span>Page {page}</span> + <button onClick={prevPage}>Prev page</button> + <button onClick={nextPage}>Next page</button> + <input type="text" onChange={changeItemsPerPage} /> + <div> + { + paginatedItems.map(p => <span>{p}<span>) + } + </div> + </div> +) + +export default withPagination(Wrapped) +``` + +## withRoles + +Injects the `roles` array as a prop. The roles are parsed from the journal config files. + +### withRoles props + +| Name | Type | Description | +| :---- | :--------------------------------- | :---------------------- | +| roles | `[{value: string, label: string}]` | An array of user roles. | + +```js +import { Menu } from '@pubsweet/ui' +import { withRoles } from 'pubsweet-component-faraday-ui' + +const Wrapped = ({ roles }) => <Menu options={roles} /> + +export default withRoles(Wrapped) +``` + +## withZipDownload + +Downloads all the files of a fragment as a zip archive. Injects the `downloadFiles` function as a prop. + +This HOCs assumes the following props are present on the wrapped component: + +| Name | Type | Description | +| :---------- | :--------------------- | :----------------------------------------------------- | +| token | `string` | Authentication token (used to authorize this request). | +| isReviewer | `bool` | If the user is reviewer. | +| fragmentId | `string` | Id of the fragment whose files we want to download. | +| setFetching | `(value: bool) => any` | Callback to set a fetching status. | +| archiveName | `string` | Name of the outputted archive file. | + +### withZipDownload props + +| Name | Type | Description | +| :------------ | :---------------- | :----------------------------------------- | +| downloadFiles | `strin() => anyg` | Download all the fragment's file as a zip. | + +# Files drag and drop + +## withFileSectionDrop + +HOC used to provide drop functionality to the `FileSection` component. It's main purpose is to change a file from one list to another. This is usually done in a callback called `changeList` that should be provided to the wrapped component. + +This HOC assumes the wrapped component has the following props: + +| Name | Type | Description | +| :-------------------- | :-------------------------------------------------------------- | :------------------------------------------------- | +| files | `[{id: string, ...}]` | List of files passed to the wrapped component. | +| setError | `(error: string) => any` | Error setting callback. | +| listId | `string` | Current list id. | +| allowedFileExtensions | `[string]` | Allowed file types. | +| maxFiles | `number` | Maximum number of files allowed. | +| changeList | `(fromListId: string, toListId: string: fileId: string) => any` | Callback fired when moving the file to a new list. | + +```js +import { compose, withHandler, withProps } from 'recompose' +import { FileSection, withFileSectionDrop } from 'pubsweet-component-faraday-ui' + +const Wrapped = compose( + withProps({ + files: [...], + listId: 'CoverLetter', + maxFiles: 3, + allowedFileExtensions: ['pdf'], + }), + withHandlers({ + changeList: () => (fromListId, toListId, fileId) => { + // do the actual change here + } + }), + withFileSectionDrop, +)(FileSection) + +export default Wrapped +``` + +## withNativeFileDrop + +HOC used to provide native file drop functionality to the `FileSection` component. It's purpose is to do something when dragging files from the computer's hard drive into the app. _This HOC allows only single items! Dragging multiple items into the wrapped component will only handle the first item!_ + +This HOC assumes the wrapped component has the following props: + +| Name | Type | Description | +| :-------------------- | :----------------------- | :--------------------------------------------- | +| files | `[{id: string, ...}]` | List of files passed to the wrapped component. | +| setError | `(error: string) => any` | Error setting callback. | +| allowedFileExtensions | `[string]` | Allowed file types. | +| maxFiles | `number` | Maximum number of files allowed. | +| onFileDrop | `(file: File) => any` | Callback fired when a valid file is dropped. | + +```js +import { compose, withHandler, withProps } from 'recompose' +import { FileSection, withNativeFileDrop } from 'pubsweet-component-faraday-ui' + +const Wrapped = compose( + withProps({ + files: [...], + listId: 'CoverLetter', + maxFiles: 3, + allowedFileExtensions: ['pdf'], + }), + withHandlers({ + onFileDrop: () => file => { + // do something with the dropped file + } + }), + withNativeFileDrop, +)(FileSection) + +export default Wrapped +``` + +# Utility functions + +## handleError + +Function that parses the server error. Calls the passed function with the parsed error. + +Has the following signature: +`(callbackFn: (parsedError) => any) => (e: Error) => any` + +```js +const customErrorLogger = parsedError => + console.error(`This is very handled: ${parsedError}`) + +// point free notation +anAsyncOperation().catch(handleError(customErrorLogger)) + +// can be used besides other function calls + +anAsyncOperation().catch(err => { + setFetching(false) + handleError(customErrorLogger)(err) +}) +``` diff --git a/packages/component-faraday-ui/src/manuscriptDetails/DeleteManuscriptModal.js b/packages/component-faraday-ui/src/manuscriptDetails/DeleteManuscriptModal.js index 3984b15d1748df5b39ddf06ffed006f36a68ddef..7dfb480b56dae130a6d08012d9e8ec74808d2681 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/DeleteManuscriptModal.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/DeleteManuscriptModal.js @@ -67,9 +67,9 @@ const DeleteManuscriptModal = props => ( onClick={showModal} paddingBottom={2} paddingRight={0} - size={1.6} + size={1.65} > - DELETE + Delete </DeleteIcon> )} </OpenModal> diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptAssignHE.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptAssignHE.js index ed9e04dfc0e67bd3844c512eee5a6a49f9b7a0ce..59d3714ce59fd66775c0cf57ba1c30ffc0355174 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptAssignHE.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptAssignHE.js @@ -1,5 +1,6 @@ import React from 'react' import { ContextualBox, AssignHE } from 'pubsweet-component-faraday-ui' +import PropTypes from 'prop-types' const ManuscriptAssignHE = ({ toggle, @@ -8,6 +9,7 @@ const ManuscriptAssignHE = ({ isFetching, currentUser: { permissions: { canAssignHE = false } }, handlingEditors = [], + inviteHandlingEditor, }) => canAssignHE ? ( <ContextualBox @@ -25,4 +27,15 @@ const ManuscriptAssignHE = ({ </ContextualBox> ) : null +ManuscriptAssignHE.propTypes = { + /** Handling editors you want to be displayed. */ + handlingEditors: PropTypes.arrayOf(PropTypes.object), + /** Callback function fired when the handling editor is invited. */ + inviteHandlingEditor: PropTypes.func, +} + +ManuscriptAssignHE.defaultProps = { + handlingEditors: [], + inviteHandlingEditor: () => {}, +} export default ManuscriptAssignHE diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptAssignHE.md b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptAssignHE.md index 7787e62799867bccde289c719eaad3ece654ea85..29309b5e1745bec9febe83ab91addd1a5c210a46 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptAssignHE.md +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptAssignHE.md @@ -32,7 +32,7 @@ const currentUser = { {(expanded, toggle) => ( <ManuscriptAssignHE toggle={toggle} - expanded={expanded} + expanded currentUser={currentUser} handlingEditors={handlingEditors} assignHE={he => console.log('assigning...', he)} diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.js index fc084c8e5d6dfbb36b1028a4b88fabf3779ed348..ce835848092518c4831fcc9b34da41c8e5592db7 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.js @@ -2,6 +2,7 @@ import React from 'react' import { get } from 'lodash' import { DateParser } from '@pubsweet/ui' import { compose, withHandlers } from 'recompose' +import PropTypes from 'prop-types' import { Row, @@ -20,8 +21,8 @@ const ManuscriptDetailsTop = ({ goToEdit, getSignedUrl, goToTechnicalCheck, - fragment = {}, - collection = {}, + fragment, + collection, currentUser: { isReviewer, token, @@ -119,3 +120,30 @@ export default compose( }, }), )(ManuscriptDetailsTop) + +ManuscriptDetailsTop.propTypes = { + /** Object containing the selected fragment. */ + fragment: PropTypes.object, //eslint-disable-line + /** Object containing the selected collection. */ + collection: PropTypes.object, //eslint-disable-line + /** Object with versions of manuscript. */ + versions: PropTypes.array, //eslint-disable-line + /** An async call that returns the securized S3 file url. */ + getSignedUrl: PropTypes.func, + /** An async call that takes you to edit. */ + goToEdit: PropTypes.func, + /** An async call that takes you to thchnical check. */ + goToTechnicalCheck: PropTypes.func, + /** Object containing token for current user. */ + currentUser: PropTypes.object, //eslint-disable-line +} + +ManuscriptDetailsTop.defaultProps = { + fragment: {}, + collection: {}, + versions: [], + getSignedUrl: () => {}, + goToEdit: () => {}, + goToTechnicalCheck: () => {}, + currentUser: {}, +} diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.md b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.md index f4b7fc2d8524c16945c715d88db44f52824025ab..f08d36e626c777e5ff28541097100a0f1cc39991 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.md +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.md @@ -1,11 +1,61 @@ Manuscript Details top section ```js +const authors = [ + { + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + }, + { + email: 'michael.felps@gmail.com', + firstName: 'Michael', + lastName: 'Felps', + isSubmitting: true, + isCorresponding: true, + }, + { + email: 'barrack.obama@gmail.com', + firstName: 'Barrack', + lastName: 'Obama', + }, + { + email: 'barrack.obama@gmail1.com', + firstName: 'Barrack 1', + lastName: 'Obama', + }, + { + email: 'barrack.obama@gmail2.com', + firstName: 'Barrack 2', + lastName: 'Obama', + }, +] + +const collection = { + customId: '55113358', + visibleStatus: 'Pending Approval', + handlingEditor: { + id: 'he-1', + name: 'Handlington Ignashevici', + }, + invitations: [], +} + +const fragment = { + authors, + created: Date.now(), + submitted: Date.now(), + metadata: { + journal: 'Awesomeness', + title: 'A very ok title with many authors', + type: 'research', + }, +} const history = { push: () => alert('go back') }; -const fragment={}; -const collection={}; + const currentUser = { isReviewer: true, token: 'abc-123', diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptEicDecision.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptEicDecision.js index 07fcac0087453c6943265160174beb18b23f95f0..3224fd577be60109705e15411ac235687d859470 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptEicDecision.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptEicDecision.js @@ -6,6 +6,7 @@ import { reduxForm } from 'redux-form' import { th } from '@pubsweet/ui-toolkit' import { required } from 'xpub-validators' import { Button, Menu, ValidatedField } from '@pubsweet/ui' +import PropTypes from 'prop-types' import { withModal } from 'pubsweet-component-modal/src/components' import { @@ -59,7 +60,8 @@ const ManuscriptEicDecision = ({ isFetching, handleSubmit, messagesLabel, - collection = {}, + collection, + submitDecision, ...rest }) => ( <ContextualBox @@ -149,6 +151,23 @@ export default compose( }), )(ManuscriptEicDecision) +ManuscriptEicDecision.propTypes = { + /** Object with details about collection. */ + collection: PropTypes.object, //eslint-disable-line + /** Label of the decision of EIC. */ + messagesLabel: PropTypes.object, //eslint-disable-line + /** Callback function fired when the handling editor submit his decision. */ + submitDecision: PropTypes.func, + /** Values taken by form. */ + formValues: PropTypes.object, //eslint-disable-line +} +ManuscriptEicDecision.defaultProps = { + collection: {}, + messagesLabel: {}, + submitDecision: () => {}, + formValues: {}, +} + // #region styles const Root = styled.div` display: flex; diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptFileList.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptFileList.js index 4f4c2ea781867330911b163f54a2b395a2cfdade..901ebc1a2b66466f0dc45b5bddad781e5dbdc1bf 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptFileList.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptFileList.js @@ -1,6 +1,6 @@ +import PropTypes from 'prop-types' import React, { Fragment } from 'react' import { ManuscriptFileSection } from 'pubsweet-component-faraday-ui' - import { withFilePreview, withFileDownload } from '../helpers' const ManuscriptFileList = ({ @@ -35,5 +35,26 @@ const ManuscriptFileList = ({ /> </Fragment> ) +ManuscriptFileList.propTypes = { + /** Files that are uploaded by author. */ + files: PropTypes.shape({ + coverLetter: PropTypes.arrayOf(PropTypes.object), + manuscripts: PropTypes.arrayOf(PropTypes.object), + supplementary: PropTypes.arrayOf(PropTypes.object), + }), + /** Callback function fired when delete icon is pressed. */ + onDelete: PropTypes.func, + /** Callback function fired when download icon is pressed. */ + onDownload: PropTypes.func, + /** Callback function fired when preview icon is pressed. */ + onPreview: PropTypes.func, +} + +ManuscriptFileList.defaultProps = { + files: {}, + onDelete: () => {}, + onDownload: () => {}, + onPreview: () => {}, +} export default withFilePreview(withFileDownload(ManuscriptFileList)) diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptFileSection.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptFileSection.js index c2a6867e2577f2a943a4b61c7290caa68c0f619f..e4fef65e9a5e47432f311ec5f51087a6542b2aae 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptFileSection.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptFileSection.js @@ -1,7 +1,8 @@ import React, { Fragment } from 'react' import { Text, FileItem, Item, Row } from 'pubsweet-component-faraday-ui' +import PropTypes from 'prop-types' -const ManuscriptFileSection = ({ list = [], label = '', ...rest }) => ( +const ManuscriptFileSection = ({ list, label, ...rest }) => ( <Fragment> {!!list.length && ( <Fragment> @@ -28,4 +29,22 @@ const ManuscriptFileSection = ({ list = [], label = '', ...rest }) => ( </Fragment> ) +ManuscriptFileSection.propTypes = { + /** List of uploaded files */ + list: PropTypes.arrayOf(PropTypes.object), + /** Category name of uploaded files. */ + label: PropTypes.string, + /** Callback function fired when download icon is pressed. */ + onDownload: PropTypes.func, + /** Callback function fired when preview icon is pressed. */ + onPreview: PropTypes.func, +} + +ManuscriptFileSection.defaultProps = { + list: [], + label: '', + onDownload: () => {}, + onPreview: () => {}, +} + export default ManuscriptFileSection diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js index 296bebafcfc99f9f765f677a90d97d74f630b3e1..e3925e13ff39142a13dd6a91b92578fce453f48a 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.js @@ -1,5 +1,6 @@ import React, { Fragment } from 'react' import { get, chain, isEmpty } from 'lodash' +import PropTypes from 'prop-types' import { H2, H4, DateParser, Button } from '@pubsweet/ui' import { compose, @@ -83,6 +84,29 @@ const ManuscriptHeader = ({ ) } +ManuscriptHeader.propTypes = { + /** Component that takes a func that returns a react elem and calls it instead of implementing its own rander. */ + renderHE: PropTypes.func, + /** Object containing the selected fragment. */ + fragment: PropTypes.object, //eslint-disable-line + /** Manuscript types that you can chose from. */ + manuscriptType: PropTypes.object, //eslint-disable-line + /** Status for editor in chief. */ + editorInChief: PropTypes.string, + /** Object containing the selected collection. */ + collection: PropTypes.object, //eslint-disable-line + /** Specifies if manuscript is at the latest version. */ + isLatestVersion: PropTypes.bool, +} +ManuscriptHeader.defaultProps = { + renderHE: () => {}, + fragment: {}, + manuscriptType: {}, + editorInChief: 'Unassigned', + collection: {}, + isLatestVersion: false, +} + export default compose( defaultProps({ inviteHE: () => {}, diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.md b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.md index 86ddd80a766067f270313f5e663095f18c6cb126..e8d4243ea27d655c5d98b001eaed06afa1907828 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.md +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptHeader.md @@ -2,33 +2,65 @@ Manuscript header without a HE assigned. ```js const authors = [ - { + { + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ecbafc48fe', email: 'john.doe@gmail.com', firstName: 'John', lastName: 'Doe', isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'michael.felps@gmail.com', - firstName: 'Michael', - lastName: 'Felps', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ecsdfc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', isSubmitting: true, isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail.com', - firstName: 'Barrack', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ec56fc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail1.com', - firstName: 'Barrack 1', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-144cbafc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail2.com', - firstName: 'Barrack 2', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ec33fc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, ] @@ -54,7 +86,9 @@ const fragment = { } const currentUser = { - canAssignHE: true, + permissions: { + canAssignHE: true, + }, } const journal = { @@ -75,7 +109,6 @@ const journal = { }, ], } - ;<ManuscriptHeader collection={collection} fragment={fragment} @@ -92,33 +125,65 @@ Manuscript header with a pending HE invitation. ```js const authors = [ - { + { + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ecbafc48fe', email: 'john.doe@gmail.com', firstName: 'John', lastName: 'Doe', isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'michael.felps@gmail.com', - firstName: 'Michael', - lastName: 'Felps', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ecsdfc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', isSubmitting: true, isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail.com', - firstName: 'Barrack', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ec56fc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail1.com', - firstName: 'Barrack 1', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-144cbafc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail2.com', - firstName: 'Barrack 2', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ec33fc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, ] @@ -143,12 +208,14 @@ const collection = { ], } -const handlingEditors=[{ +const handlingEditors = [ + { id: 'he-1', firstName: 'Handlington', lastName: 'Ignashevici', name: 'Handlington Ignashevici', -}] + }, +] const fragment = { authors, @@ -162,7 +229,9 @@ const fragment = { } const currentUser = { - canAssignHE: true, + permissions: { + canAssignHE: true, + }, } const journal = { @@ -183,7 +252,6 @@ const journal = { }, ], } - ;<ManuscriptHeader collection={collection} fragment={fragment} @@ -201,32 +269,64 @@ Manuscript header with a pending HE invitation. ```js const authors = [ { + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ecbafc48fe', email: 'john.doe@gmail.com', firstName: 'John', lastName: 'Doe', isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'michael.felps@gmail.com', - firstName: 'Michael', - lastName: 'Felps', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ecsdfc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', isSubmitting: true, isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail.com', - firstName: 'Barrack', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ec56fc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail1.com', - firstName: 'Barrack 1', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-144cbafc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, { - email: 'barrack.obama@gmail2.com', - firstName: 'Barrack 2', - lastName: 'Obama', + affiliation: 'TSD', + affiliationNumber: 1, + country: 'AX', + id: '5001955e-cc18-42d4-b0ca-15ec33fc48fe', + email: 'john.doe@gmail.com', + firstName: 'John', + lastName: 'Doe', + isSubmitting: true, + isCorresponding: true, + title: 'mr', }, ] @@ -263,7 +363,11 @@ const fragment = { }, } -const currentUser = {} +const currentUser = { + permissions: { + canAssignHE: false, + }, +} const journal = { manuscriptTypes: [ @@ -283,7 +387,6 @@ const journal = { }, ], } - ;<ManuscriptHeader collection={collection} fragment={fragment} diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptMetadata.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptMetadata.js index 8e7fa1ded80839cdbcb214631d082a944846b8ee..12d737abb56a3d36951d68884c3aae4b0e375d2a 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptMetadata.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptMetadata.js @@ -1,6 +1,7 @@ -import React, { Fragment } from 'react' -import { isEmpty, get } from 'lodash' +import PropTypes from 'prop-types' import { withProps } from 'recompose' +import { isEmpty, get } from 'lodash' +import React, { Fragment } from 'react' import { Text, @@ -79,6 +80,23 @@ const ManuscriptMetadata = ({ </Fragment> ) +ManuscriptMetadata.propTypes = { + /** Files Label of the contextual box. */ + filesLabel: PropTypes.string, + /** An async call that returns the securized S3 file url. */ + getSignedUrl: PropTypes.func, + /** Object containing token for current user. */ + currentUser: PropTypes.object, //eslint-disable-line + /** Object containing the selected fragment. */ + fragment: PropTypes.object, //eslint-disable-line +} +ManuscriptMetadata.defaultProps = { + filesLabel: '', + getSignedUrl: () => {}, + currentUser: {}, + fragment: {}, +} + export default withProps(({ fragment: { files } }) => ({ filesLabel: `Files (${get(files, 'manuscripts', []).length + get(files, 'coverLetter', []).length + diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptVersion.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptVersion.js index 2f7473750f267ef12771024e3480984dd06f82f9..423a35f0248d42c12f62fbfe37563f9b54a959ac 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptVersion.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptVersion.js @@ -1,10 +1,11 @@ import React from 'react' import { get } from 'lodash' +import PropTypes from 'prop-types' import { Menu } from '@pubsweet/ui' const ManuscriptVersion = ({ history, - versions, + versions = [], fragment = {}, collection = {}, }) => @@ -20,4 +21,18 @@ const ManuscriptVersion = ({ /> ) +ManuscriptVersion.propTypes = { + /** Object with versions of manuscript. */ + versions: PropTypes.array, //eslint-disable-line + /** Object containing the selected fragment. */ + fragment: PropTypes.object, //eslint-disable-line + /** Object containing the selected collection. */ + collection: PropTypes.object, //eslint-disable-line +} + +ManuscriptVersion.defaultProps = { + versions: [], + fragment: {}, + collection: {}, +} export default ManuscriptVersion diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptVersion.md b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptVersion.md index 00e12ce334886136eb8308dd2c6b5fdc7a018e68..cee73787f78450a832987131c913cf7274943267 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptVersion.md +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptVersion.md @@ -1,19 +1,22 @@ Manuscript version component ```js - const history = { - push: v => console.log('go to version -> ', v) -}; - -const fragment={}; -const collection={ - fragments: ['1','2'], -}; + push: v => console.log('go to version -> ', v), +} -<ManuscriptVersion +const fragment = {} +const collection = { + fragments: ['1', '2'], +} +const versions = [ + { label: 'Version 1', value: '10d28459-6f8e-4f6c-a57e-65979e5f8d2' }, + { label: 'Version 2', value: '10d28459-6f8e-4f6c-a57e-65979e5f854' }, +] +;<ManuscriptVersion collection={collection} history={history} fragment={fragment} - /> + versions={versions} +/> ``` diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ResponseToInvitation.js b/packages/component-faraday-ui/src/manuscriptDetails/ResponseToInvitation.js index a638617e4a1adb041b45b48c310df51e95be1c29..27165b3c104800a7444733910499cc5a9700565d 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ResponseToInvitation.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ResponseToInvitation.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { reduxForm } from 'redux-form' import { required } from 'xpub-validators' import { get, has, capitalize } from 'lodash' @@ -86,6 +87,32 @@ const ResponseToInvitation = ({ </ContextualBox> ) +ResponseToInvitation.propTypes = { + /** Label of the contextual box. */ + label: PropTypes.string, + /** Title that will be showed on the card. */ + title: PropTypes.string, + /** Expands a message for collapse or expand. */ + expanded: PropTypes.bool, + /** Method used to toggle a message on click. */ + toggle: PropTypes.func, + /* Handles the submission of the recommendation. */ + handleSubmit: PropTypes.func, + /** Specifies if it will show comments on the current version. */ + shouldShowComments: PropTypes.bool, + /** Specifies the Label name for the respond to invitation button. */ + buttonLabel: PropTypes.string, +} +ResponseToInvitation.defaultProps = { + label: '', + title: '', + toggle: () => {}, + expanded: false, + handleSubmit: () => {}, + shouldShowComments: false, + buttonLabel: 'RESPOND TO INVITATION', +} + export default compose( withFetching, withModal(({ isFetching, modalKey }) => ({ diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ResponseToInvitation.md b/packages/component-faraday-ui/src/manuscriptDetails/ResponseToInvitation.md index e7f3a21c9d5f65814365bd1e87054d925a0fb775..588a77de8ffc3b45d90266d6d0ef94629240c262 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ResponseToInvitation.md +++ b/packages/component-faraday-ui/src/manuscriptDetails/ResponseToInvitation.md @@ -5,10 +5,9 @@ const formValues = { decision: 'accept', } ;<RemoteOpener> - {({ toggle, expanded }) => ( + {({ toggle }) => ( <ResponseToInvitation commentsOn="decline" - expanded={expanded} label="Do you agree to be the handling editor for this manuscript?" formValues={formValues} onResponse={(values, { setFetching }) => { @@ -26,9 +25,8 @@ A Reviewer response to an invitation. ```js <RemoteOpener> - {({ toggle, expanded }) => ( + {({ toggle }) => ( <ResponseToInvitation - expanded={expanded} label="Do you agree to review this manuscript?" onResponse={(values, { setFetching }) => { console.log('on response: ', values) diff --git a/packages/component-faraday-ui/src/modals/MultiAction.js b/packages/component-faraday-ui/src/modals/MultiAction.js index 3748de9af6df5a4fef6b920d16d8202bbd2f550b..3d40da665ac17e088e9f2f154b9621f35aabcef8 100644 --- a/packages/component-faraday-ui/src/modals/MultiAction.js +++ b/packages/component-faraday-ui/src/modals/MultiAction.js @@ -3,19 +3,22 @@ import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { H2, Button, Spinner } from '@pubsweet/ui' import { compose, setDisplayName, withHandlers } from 'recompose' +import PropTypes from 'prop-types' import { IconButton, Text, Row } from '../' const MultiAction = ({ title, + content, onClose, + onCancel, subtitle, onConfirm, modalError, isFetching, renderContent, - confirmText = 'OK', - cancelText = 'Cancel', + confirmText, + cancelText, }) => ( <Root> <IconButton icon="x" onClick={onClose} right={5} secondary top={5} /> @@ -36,7 +39,7 @@ const MultiAction = ({ <Spinner size={3} /> ) : ( <Fragment> - <Button data-test-id="modal-cancel" onClick={onClose}> + <Button data-test-id="modal-cancel" onClick={onCancel}> {cancelText} </Button> <Button data-test-id="modal-confirm" onClick={onConfirm} primary> @@ -48,6 +51,38 @@ const MultiAction = ({ </Root> ) +MultiAction.propTypes = { + /** Title that will be showed on the card. */ + title: PropTypes.string, + /** Subtitle that will be showed on the card. */ + subtitle: PropTypes.string, + /** The text you want to see on the button when someone submit the report. */ + confirmText: PropTypes.string, + /** The text you want to see on the button when someone cancel the report. */ + cancelText: PropTypes.string, + /** Callback function fired when cancel confirmation card. */ + onCancel: PropTypes.func, + /** Callback function fired when confirm confirmation card. */ + onConfirm: PropTypes.func, + /** When is true will show a spinner. */ + onClose: PropTypes.func, + /** Callback function fired when you want to close the card. */ + isFetching: PropTypes.bool, + /** The component you want to show on the card. */ + content: PropTypes.func, +} +MultiAction.defaultProps = { + title: undefined, + subtitle: undefined, + confirmText: 'OK', + cancelText: 'Cancel', + onCancel: undefined, + onConfirm: undefined, + onClose: undefined, + isFetching: undefined, + content: undefined, +} + export default compose( withHandlers({ onConfirm: ({ onConfirm, ...props }) => () => { diff --git a/packages/component-faraday-ui/src/modals/OpenModal.js b/packages/component-faraday-ui/src/modals/OpenModal.js index 923053d3c1842c6eb939583843676f579adb310f..d575f9a6ad599ae1512a35d76d59f8f511030ec9 100644 --- a/packages/component-faraday-ui/src/modals/OpenModal.js +++ b/packages/component-faraday-ui/src/modals/OpenModal.js @@ -1,10 +1,22 @@ +import React from 'react' import { compose, withHandlers, withProps } from 'recompose' import { withModal } from 'pubsweet-component-modal/src/components' - +import PropTypes from 'prop-types' import { MultiAction, SingleActionModal } from './' -const OpenModal = ({ showModal, children }) => children(showModal) - +const OpenModal = ({ + showModal, + title, + subtitle, + confirmText, + cancelText, + children, + onConfirm, + onCancel, + onClose, + content, + modalKey, +}) => <div>{children(showModal)}</div> const selectModalComponent = props => { if (props.component) { return { @@ -21,6 +33,38 @@ const selectModalComponent = props => { } } +OpenModal.propTypes = { + /** Title that will be showed on the card. */ + title: PropTypes.string, + /** Subtitle that will be showed on the card. */ + subtitle: PropTypes.string, + /** The text you want to see on the button when someone submit the report. */ + confirmText: PropTypes.string, + /** The text you want to see on the button when someone cancel the report. */ + cancelText: PropTypes.string, + /** Callback function fired when cancel confirmation card. */ + onCancel: PropTypes.func, + /** Callback function fired when confirm confirmation card. */ + onConfirm: PropTypes.func, + /** When is true will show a spinner. */ + onClose: PropTypes.func, + /** The text you want to show on the card. */ + content: PropTypes.func, + /** Unique key for modal box. */ + modalKey: PropTypes.string, +} +OpenModal.defaultProps = { + title: undefined, + subtitle: undefined, + confirmText: 'OK', + cancelText: 'Cancel', + onCancel: undefined, + onConfirm: undefined, + onClose: undefined, + content: undefined, + modalKey: undefined, +} + export default compose( withProps(selectModalComponent), withModal(({ isFetching, modalKey, modalComponent }) => ({ diff --git a/packages/component-faraday-ui/src/modals/OpenModal.md b/packages/component-faraday-ui/src/modals/OpenModal.md index 617fcdf2544de263f0b7c2bfd0931b089b455f5b..ae38b6151b4272e841489d08572fa3d9d58cad13 100644 --- a/packages/component-faraday-ui/src/modals/OpenModal.md +++ b/packages/component-faraday-ui/src/modals/OpenModal.md @@ -19,9 +19,8 @@ Open a confirmation modal by clicking on an element Pass a custon component as the modal content. ```js -const Custom = () => <div>inside the modal</div>; - -<OpenModal +const Custom = `<div>inside the modal</div>` +;<OpenModal onConfirm={props => console.log('confirm', props)} onCancel={props => console.log('cancel', props)} title="Are you sure?" @@ -37,7 +36,7 @@ Open a single action modal. ```js <OpenModal - onConfirm={console.log} + onConfirm={props => console.log('confirm', props)} title="Are you sure?" confirmText="I am pretty sure" modalKey="1234" diff --git a/packages/component-faraday-ui/src/modals/SingleActionModal.js b/packages/component-faraday-ui/src/modals/SingleActionModal.js index d6c60a80872ada93dc21cb0c3f67bf599f34d706..ebccf5ee584f076aa9ddc454ef5ef4a0857e0ccf 100644 --- a/packages/component-faraday-ui/src/modals/SingleActionModal.js +++ b/packages/component-faraday-ui/src/modals/SingleActionModal.js @@ -3,6 +3,7 @@ import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { Button, H2 } from '@pubsweet/ui' import { compose, setDisplayName, withHandlers } from 'recompose' +import PropTypes from 'prop-types' import { IconButton, Text } from '../' @@ -12,7 +13,8 @@ const SingleActionModal = ({ content, onClick, subtitle, - confirmText = 'OK', + confirmText, + onConfirm, }) => ( <Root> <IconButton icon="x" onClick={onClick} right={5} secondary top={5} /> @@ -66,4 +68,25 @@ const Root = styled.div` margin-top: ${th('gridUnit')}; } ` + +SingleActionModal.propTypes = { + /** Title that will be showed on the card. */ + title: PropTypes.string, + /** Subtitle that will be showed on the card. */ + subtitle: PropTypes.string, + /** Callback function fired when confirm confirmation card. */ + onConfirm: PropTypes.func, + /** The text you want to see on the button when someone submit the report. */ + confirmText: PropTypes.string, + /** If true success icon is replaced with error icon. */ + error: PropTypes.bool, +} + +SingleActionModal.defaultProps = { + title: undefined, + subtitle: undefined, + onConfirm: undefined, + confirmText: 'OK', + error: undefined, +} // #endregion diff --git a/packages/component-faraday-ui/src/pending/ControlledAccordion.js b/packages/component-faraday-ui/src/pending/ControlledAccordion.js index e4f9b30f9df252bf1070d0d561ac527f9a55fc69..84374ee3c1941ae6a7b04b29f39036a3a53e11af 100644 --- a/packages/component-faraday-ui/src/pending/ControlledAccordion.js +++ b/packages/component-faraday-ui/src/pending/ControlledAccordion.js @@ -24,8 +24,8 @@ class ControlledAccordion extends React.Component { const shouldScroll = !prevProps.expanded && this.props.expanded if (this.props.scrollIntoView && shouldScroll) { - const appBarHeight = 70 // TODO -- take height from constants - const appBarMargin = 16 // TODO -- take margin from constants + const appBarHeight = 70 + const appBarMargin = 16 this.scroller.scrollTop = this._accordion.offsetTop - appBarHeight - appBarMargin } diff --git a/packages/component-faraday-ui/src/submissionRevision/DetailsAndAuthors.js b/packages/component-faraday-ui/src/submissionRevision/DetailsAndAuthors.js index 351585752d1ff1f4f61873070293ece08fd8987e..31076120157ede92ae8ba51fe682e81938e71047 100644 --- a/packages/component-faraday-ui/src/submissionRevision/DetailsAndAuthors.js +++ b/packages/component-faraday-ui/src/submissionRevision/DetailsAndAuthors.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { get, has } from 'lodash' import { Field } from 'redux-form' import styled from 'styled-components' @@ -107,4 +108,149 @@ const Root = styled.div` padding-left: calc(${th('gridUnit')} * 1); ` +DetailsAndAuthors.propTypes = { + /** Deprecated object containing manuscript types. */ + journal: PropTypes.string, + /** Object containing the selected fragment */ + fragment: PropTypes.PropTypes.shape({ + id: PropTypes.string, + type: PropTypes.string, + files: PropTypes.shape({ + coverLetter: PropTypes.array, + manuscripts: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + size: PropTypes.number, + originalName: PropTypes.string, + }), + ), + supplementary: PropTypes.array, + }), + owners: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string, + username: PropTypes.string, + }), + ), + authors: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string, + email: PropTypes.string, + country: PropTypes.string, + lastName: PropTypes.string, + firstName: PropTypes.string, + affiliation: PropTypes.string, + isSubmitting: PropTypes.bool, + isCorresponding: PropTypes.bool, + }), + ), + created: PropTypes.string, + version: PropTypes.number, + metadata: PropTypes.shape({ + type: PropTypes.string, + title: PropTypes.string, + journal: PropTypes.string, + abstract: PropTypes.string, + }), + conflicts: PropTypes.shape({ + hasFunding: PropTypes.string, + hasConflicts: PropTypes.string, + hasDataAvailability: PropTypes.string, + }), + submitted: PropTypes.number, + collectionId: PropTypes.string, + declarations: PropTypes.shape({ + agree: PropTypes.bool, + }), + fragmentType: PropTypes.string, + recomandations: PropTypes.array, + }), + /** Object containing the selected collection. */ + collection: PropTypes.shape({ + id: PropTypes.string, + type: PropTypes.string, + owners: PropTypes.array, + status: PropTypes.string, + created: PropTypes.number, + customId: PropTypes.string, + fragments: PropTypes.arrayOf(PropTypes.string), + technicalChecks: PropTypes.object, + CurrentVersion: PropTypes.shape({ + id: PropTypes.string, + type: PropTypes.string, + files: PropTypes.shape({ + coverLetter: PropTypes.array, + manuscripts: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + size: PropTypes.number, + originalName: PropTypes.string, + }), + ), + supplementary: PropTypes.array, + }), + owners: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string, + username: PropTypes.string, + }), + ), + authors: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string, + email: PropTypes.string, + country: PropTypes.string, + lastName: PropTypes.string, + firstName: PropTypes.string, + affiliation: PropTypes.string, + isSubmitting: PropTypes.bool, + isCorresponding: PropTypes.bool, + }), + ), + created: PropTypes.string, + version: PropTypes.number, + metadata: PropTypes.shape({ + type: PropTypes.string, + title: PropTypes.string, + journal: PropTypes.string, + abstract: PropTypes.string, + }), + conflicts: PropTypes.shape({ + hasFunding: PropTypes.string, + hasConflicts: PropTypes.string, + hasDataAvailability: PropTypes.string, + }), + submitted: PropTypes.number, + collectionId: PropTypes.string, + declarations: PropTypes.shape({ + agree: PropTypes.bool, + }), + fragmentType: PropTypes.string, + recomandations: PropTypes.array, + }), + visibleStatus: PropTypes.string, + }), + /** Chages the form to allow editing of the selected author and returns his index. */ + onAuthorEdit: PropTypes.func, + /** Manuscript types that you can chose from. */ + manuscriptTypes: PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.string, + value: PropTypes.string, + author: PropTypes.bool, + peerReview: PropTypes.bool, + abstractRequired: PropTypes.bool, + }), + ), +} +DetailsAndAuthors.defaultProps = { + journal: '', + fragment: {}, + collection: {}, + onAuthorEdit: () => {}, + manuscriptTypes: [], +} + export default DetailsAndAuthors diff --git a/packages/component-faraday-ui/src/submissionRevision/ManuscriptFiles.js b/packages/component-faraday-ui/src/submissionRevision/ManuscriptFiles.js index fb28460c7be1b02da1fa789118e48b0056b357c6..9c1c1f2bf7e638b65f324f17beaca920bb53afa5 100644 --- a/packages/component-faraday-ui/src/submissionRevision/ManuscriptFiles.js +++ b/packages/component-faraday-ui/src/submissionRevision/ManuscriptFiles.js @@ -1,6 +1,7 @@ import React from 'react' import { get, has } from 'lodash' import { Field } from 'redux-form' +import PropTypes from 'prop-types' import { Icon } from '@pubsweet/ui' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' @@ -57,6 +58,42 @@ const ManuscriptFiles = ({ </ContextualBox> ) +ManuscriptFiles.propTypes = { + /** Contains the token of the currently logged user. */ + token: PropTypes.string, + /** Object containing the selected fragment. */ + fragment: PropTypes.object, //eslint-disable-line + /** Object containing the selected collection. */ + collection: PropTypes.object, //eslint-disable-line + /** Name of added form. */ + formName: PropTypes.func, + /** Change added form. */ + changeForm: PropTypes.func, + /** Removes the file from the server. */ + deleteFile: PropTypes.func, + /** Uploads the file to the server. */ + uploadFile: PropTypes.func, + /** View content of the uploaded file. */ + previewFile: PropTypes.func, + /** An async call that returns the securized S3 file url. */ + getSignedUrl: PropTypes.func, + /** Value representing if the form has any errors. */ + formErrors: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), +} + +ManuscriptFiles.defaultProps = { + token: '', + fragment: {}, + collection: {}, + formName: () => {}, + changeForm: () => {}, + deleteFile: () => {}, + uploadFile: () => {}, + previewFile: () => {}, + getSignedUrl: () => {}, + formErrors: {}, +} + export default ManuscriptFiles // #region styled-components diff --git a/packages/component-faraday-ui/src/submissionRevision/ManuscriptFiles.md b/packages/component-faraday-ui/src/submissionRevision/ManuscriptFiles.md index 42a8e212005461b35ce3cedc2926dc0ffff6b7a2..5129d1d5a62f8cc632451b7b3eba4be8b0e69006 100644 --- a/packages/component-faraday-ui/src/submissionRevision/ManuscriptFiles.md +++ b/packages/component-faraday-ui/src/submissionRevision/ManuscriptFiles.md @@ -14,8 +14,6 @@ const Wrapper = compose( reduxForm({ form: 'styleguide', }), -)(( props ) => ( - <ManuscriptFiles {...props} /> -)) +)(props => <ManuscriptFiles {...props} />) ;<Wrapper /> -``` \ No newline at end of file +``` diff --git a/packages/component-faraday-ui/src/submissionRevision/ResponseToReviewer.js b/packages/component-faraday-ui/src/submissionRevision/ResponseToReviewer.js index 790f2143d69a8cb7aa52c0edeff6ffd67b5387b2..d1f8bfdeba643f8e049e32328f231d4fa979023c 100644 --- a/packages/component-faraday-ui/src/submissionRevision/ResponseToReviewer.js +++ b/packages/component-faraday-ui/src/submissionRevision/ResponseToReviewer.js @@ -1,5 +1,6 @@ import React from 'react' import { isEmpty } from 'lodash' +import PropTypes from 'prop-types' import styled from 'styled-components' import { th } from '@pubsweet/ui-toolkit' import { FilePicker, Spinner, ValidatedField } from '@pubsweet/ui' @@ -20,6 +21,7 @@ import { const allowedFileExtensions = ['pdf', 'doc', 'docx', 'txt', 'rdf', 'odt'] const ResponseToReviewer = ({ file, + token, onDelete, onUpload, isFetching, @@ -74,6 +76,23 @@ const ResponseToReviewer = ({ </ContextualBox> ) +ResponseToReviewer.propTypes = { + /** Deletes the file from the server then updates the form. */ + onDelete: PropTypes.func, + /** Uploads the file then updates the form. */ + onUpload: PropTypes.func, + /** View content of the uploaded file. */ + previewFile: PropTypes.func, + /** Downloads the file from the server. */ + downloadFile: PropTypes.func, +} +ResponseToReviewer.defaultProps = { + onDelete: () => {}, + onUpload: () => {}, + previewFile: () => {}, + downloadFile: () => {}, +} + const Root = styled.div` border-left: ${th('borderWidth')} ${th('borderStyle')} ${th('colorBorder')}; padding-left: calc(${th('gridUnit')} * 1); diff --git a/packages/component-faraday-ui/src/submissionRevision/ResponseToReviewer.md b/packages/component-faraday-ui/src/submissionRevision/ResponseToReviewer.md index e9264445b46902365f4a0d50608d13bd67fde690..903a52a7079d90ebd8749503990df5bba2460577 100644 --- a/packages/component-faraday-ui/src/submissionRevision/ResponseToReviewer.md +++ b/packages/component-faraday-ui/src/submissionRevision/ResponseToReviewer.md @@ -1,7 +1,24 @@ ```js +const { reduxForm, getFormValues, change } = require('redux-form') +const { compose } = require('recompose') +const { connect } = require('react-redux') + const allowedFileExtensions = ['pdf', 'doc', 'docx'] -const onUpload = (f) => {console.log('Upload', f)} +const onUpload = file => console.log('Upload', file) -<ResponseToReviewer onUpload={onUpload} allowedFileExtensions={allowedFileExtensions}/> +const Wrapper = compose( + connect(state => ({ + formValues: getFormValues('Response to reviewer')(state), + })), + reduxForm({ + form: 'Response to reviewer', + }), +)(props => ( + <ResponseToReviewer + onUpload={onUpload} + allowedFileExtensions={allowedFileExtensions} + /> +)) +;<Wrapper /> ``` diff --git a/packages/component-faraday-ui/src/submissionRevision/SubmitRevision.js b/packages/component-faraday-ui/src/submissionRevision/SubmitRevision.js index ace1a76edeca379d7beb733515e56ae95d00e23a..aec7021b003dc65598b05a433a0d4db559d70641 100644 --- a/packages/component-faraday-ui/src/submissionRevision/SubmitRevision.js +++ b/packages/component-faraday-ui/src/submissionRevision/SubmitRevision.js @@ -1,4 +1,5 @@ import React from 'react' +import PropTypes from 'prop-types' import { Button } from '@pubsweet/ui' import styled from 'styled-components' import { reduxForm } from 'redux-form' @@ -30,6 +31,7 @@ const SubmitRevision = ({ onAuthorEdit, isEditingAuthor, formErrors, + formName, }) => ( <ContextualBox highlight label="Submit Revision" mb={2}> <Root> @@ -51,7 +53,7 @@ const SubmitRevision = ({ deleteFile={deleteFile} downloadFile={downloadFile} formErrors={formErrors} - formName="revision" + formName={formName} fragment={fragment} getSignedUrl={getSignedUrl} previewFile={previewFile} @@ -85,6 +87,65 @@ const SubmitRevision = ({ </ContextualBox> ) +SubmitRevision.propTypes = { + /** Object containing the list of recommendations. */ + journal: PropTypes.object, //eslint-disable-line + /** Uploads the file to the server. */ + addFile: PropTypes.func, + /** Object containing the selected fragment. */ + fragment: PropTypes.object, //eslint-disable-line + /** An async call to add an author to the manuscript. */ + addAuthor: PropTypes.func, + /** Removes the file from the server. */ + deleteFile: PropTypes.func, + /** Object containing the selected collection. */ + collection: PropTypes.object, //eslint-disable-line + /** Change added form. */ + changeForm: PropTypes.func, + /** Object containing token for current user. */ + currentUser: PropTypes.object, //eslint-disable-line + /** View content of the uploaded file. */ + previewFile: PropTypes.func, + /** Value representing if the form has any errors. */ + hasFormError: PropTypes.bool, + /** An async call to remove an existing author from the manuscript. */ + deleteAuthor: PropTypes.func, + /** An async call that returns the securized S3 file url. */ + getSignedUrl: PropTypes.func, + /** Value containing the revision's file for the reviewer's response. */ + responseFile: PropTypes.object, //eslint-disable-line + /** Downloads the file from the server. */ + downloadFile: PropTypes.func, + /** Uploads the file then updates the form. */ + addResponseFile: PropTypes.func, + /** Deletes the file from the server then updates the form. */ + deleteResponseFile: PropTypes.func, + /** Chages the form to allow editing of the selected author and returns his index */ + onAuthorEdit: PropTypes.func, + /** Value representing if the form has any errors */ + formErrors: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), +} +SubmitRevision.defaultProps = { + journal: {}, + addFile: () => {}, + fragment: {}, + addAuthor: () => {}, + deleteFile: () => {}, + collection: {}, + changeForm: () => {}, + currentUser: {}, + previewFile: () => {}, + hasFormError: false, + deleteAuthor: () => {}, + getSignedUrl: () => {}, + responseFile: {}, + downloadFile: () => {}, + addResponseFile: () => {}, + deleteResponseFile: () => {}, + onAuthorEdit: () => {}, + formErrors: {}, +} + const Root = styled.div` background-color: ${th('colorBackgroundHue2')}; padding: calc(${th('gridUnit')} * 2); diff --git a/packages/component-faraday-ui/src/submissionRevision/SubmitRevision.md b/packages/component-faraday-ui/src/submissionRevision/SubmitRevision.md index 6c9a0bde8927225e69c55be3fa2ee2cf2f78938c..a6768429d7e80c0e4ca23a917b4db015add55d20 100644 --- a/packages/component-faraday-ui/src/submissionRevision/SubmitRevision.md +++ b/packages/component-faraday-ui/src/submissionRevision/SubmitRevision.md @@ -1,5 +1,8 @@ ```js const props = { + currentUser: { + token: 'hashmancasalaamdanam', + }, fragment: { id: 'a9dc38fe-5524-4728-b97f-9495a2eb4bee', type: 'fragment', diff --git a/packages/component-manuscript/src/components/ManuscriptVersion.js b/packages/component-manuscript/src/components/ManuscriptVersion.js deleted file mode 100644 index b198686d019f28f5db818cf7c71312896ec7b1e9..0000000000000000000000000000000000000000 --- a/packages/component-manuscript/src/components/ManuscriptVersion.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react' -import { get } from 'lodash' -import { Menu } from '@pubsweet/ui' -import { withRouter } from 'react-router-dom' - -import { parseVersionOptions } from './utils' - -const ManuscriptVersion = ({ - history, - version = {}, - project = { fragments: [] }, -}) => { - const fragments = get(project, 'fragments') - return ( - !!fragments.length && ( - <Menu - inline - onChange={v => - history.push(`/projects/${project.id}/versions/${v}/details`) - } - options={parseVersionOptions(fragments)} - placeholder="Please select" - value={get(version, 'id')} - /> - ) - ) -} - -export default withRouter(ManuscriptVersion) diff --git a/packages/component-manuscript/src/components/index.js b/packages/component-manuscript/src/components/index.js index 1afadcd39c73e96ab282ac07a1ca105b73d5e575..246c1ba34418e61bbbb41a0ee9bf64e62bcd3f8b 100644 --- a/packages/component-manuscript/src/components/index.js +++ b/packages/component-manuscript/src/components/index.js @@ -2,11 +2,12 @@ export { default as Authors } from './Authors' export { default as ShowMore } from './ShowMore' export { default as SideBarRoles } from './SideBarRoles' export { default as ManuscriptPage } from './ManuscriptPage' -export { default as SubmitRevision } from './SubmitRevision' export { default as EditorialComment } from './EditorialComment' export { default as ReviewReportCard } from './ReviewReportCard' export { default as ManuscriptLayout } from './ManuscriptLayout' -export { default as ManuscriptVersion } from './ManuscriptVersion' +export { + default as ManuscriptVersion, +} from '../../../component-faraday-ui/src/manuscriptDetails/ManuscriptVersion' export { default as EditorialComments } from './EditorialComments' export { default as ReviewReportsList } from './ReviewReportsList' export { default as ReviewerReportForm } from './ReviewerReportForm' diff --git a/packages/component-manuscript/src/handleRecommendation/README.md b/packages/component-manuscript/src/handleRecommendation/README.md new file mode 100644 index 0000000000000000000000000000000000000000..81084d76afa0df06f8e584c720ec638558a4b753 --- /dev/null +++ b/packages/component-manuscript/src/handleRecommendation/README.md @@ -0,0 +1,57 @@ +## Hindawi Handling Recommendation HOC. + +Injects `createRecommendation` and `onEditorialRecommendation` handlers as props. + +### withHandleRecommendation props + +`recommendationHandler` namespace contains the following fields: + +| Name | Type | Description | +| :------------------------ | :------------------------------------- | :-------------------------------------------- | +| createRecommendation | `(reduxFormValues, modalProps) => any` | creates a recommendation for the manuscript | +| onEditorialRecommendation | `(reduxFormValues, modalProps) => any` | handles the recommendation for the manuscript | + +_Note: The functions must be used withing a modal._ + +```javascript +const HERecommendationPanel = ({ createRecommendation }) => ( + <Modal> + <span>Recommend the manuscript for:</span> + <select> + <option>Approve</option> + <option>Reject</option> + <option>Minor revision</option> + <option>Major revision</option> + </select> + <button + onClick={() => + createRecommendation(reduxFormValues, { ...modalProps, setFetching }) + } + > + Submit + </button> + </Modal> +) + +const EICDecisionPanel = ({ onEditorialRecommendation }) => ( + <Modal> + <span>Take decision to:</span> + <select> + <option>Approve</option> + <option>Reject</option> + <option>Minor revision</option> + <option>Major revision</option> + </select> + <button + onClick={() => + onEditorialRecommendation(reduxFormValues, { + ...modalProps, + setFetching, + }) + } + > + Submit + </button> + </Modal> +) +``` diff --git a/packages/component-manuscript/src/inviteHandlingEditor/README.md b/packages/component-manuscript/src/inviteHandlingEditor/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9badc8fff6048f76569b7df6f30afaf868e7b119 --- /dev/null +++ b/packages/component-manuscript/src/inviteHandlingEditor/README.md @@ -0,0 +1,51 @@ +## Hindawi Handling Editor Invite HOC. + +Injects `assignHE`, `revokeHE` and `onHEResponse` handlers as props. + +### withInviteHandlingEditor props + +`inviteHandlingEditor` namespace contains the following fields: + +| Name | Type | Description | +| :----------- | :------------------------------------- | :----------------------------------------------- | +| assignHE | `(email, modalProps) => any` | sends an invitation to the handling editor | +| revokeHE | `(invitationId, modalProps) => any` | revokes a sent invitation to the handling editor | +| onHEResponse | `(reduxFormValues, modalProps) => any` | handles the handling editor's response | + +_Note: The functions must be used withing a modal._ + +```javascript +const EditorInChiefPanel = ({ assignHE, revokeHE }) => ( + <Modal> + <span>Handlin d'Editor</span> + <button onClick={() => assignHE(email, { ...modalProps, setFetching })}> + Resend Invitation + </button> + <button + onClick={() => revokeHE(invitationId, { ...modalProps, setFetching })} + > + Cancel Invitation + </button> + </Modal> +) + +const HandlingEditorPanel = ({ onHeResponse }) => ( + <Modal> + <span>Accept invitation?</span> + <button + onClick={() => + onHeResponse(reduxFormValues, { ...modalProps, setFetching }) + } + > + Yes + </button> + <button + onClick={() => + onHeResponse(reduxFormValues, { ...modalProps, setFetching }) + } + > + No + </button> + </Modal> +) +``` diff --git a/packages/component-manuscript/src/inviteReviewer/README.md b/packages/component-manuscript/src/inviteReviewer/README.md new file mode 100644 index 0000000000000000000000000000000000000000..74f050b225d985e666212a0909088bcb0c223c25 --- /dev/null +++ b/packages/component-manuscript/src/inviteReviewer/README.md @@ -0,0 +1,85 @@ +## Hindawi Reviewer Invite HOC. + +Injects `onInviteReviewer`, `onInvitePublonReviewer`, `onResendInviteReviewer`, `onRevokeInviteReviewer` and `onReviewerResponse` handlers as props. + +### withInviteReviewer props + +`inviteReviewer` namespace contains the following fields: + +| Name | Type | Description | +| :--------------------- | :------------------------------------- | :--------------------------------------------------- | +| onInviteReviewer | `(reduxFormValues, modalProps) => any` | sends an invitation to the reviewer | +| onInvitePublonReviewer | `(reduxFormValues, modalProps) => any` | sends an invitation to a Publon reviewer | +| onResendInviteReviewer | `(email, modalProps) => any` | resends an invitation to an already invited reviewer | +| onRevokeInviteReviewer | `(invitationId, modalProps) => any` | cancels an invitation to an invited reviewer | +| onReviewerResponse | `(reduxFormValues, modalProps) => any` | handles the reviewer response to the invitation | + +_Note: The functions must be used withing a modal_ + +```javascript +const InviteReviewer = ({ + onInviteReviewer, + onInvitePublonReviewer, + onResendInviteReviewer, + onRevokeInviteReviewer, +}) => ( + <Modal> + <span>Reviewers list</span> + <div> + <span>Revi Ewerin</span> + <button + onClick={() => onInviteReviewer(values, { ...modalProps, setFetching })} + > + Invite + </button> + </div> + <div> + <span>Publonus re' Vyewer</span> + <button + onClick={() => + onInvitePublonReviewer(reviewerData, { ...modalProps, setFetching }) + } + > + Invite + </button> + </div> + <div> + <span>Rev d'Iewer</span> + <button + onClick={() => + onResendInviteReviewer(email, { ...modalProps, setFetching }) + } + > + Resend invitation + </button> + <button + onClick={() => + onRevokeInviteReviewer(invitationId, { ...modalProps, setFetching }) + } + > + Cancel invitation + </button> + </div> + </Modal> +) + +const Invitation = ({ onReviewerResponse }) => ( + <Modal> + <span>Accept invitation?</span> + <button + onClick={() => + onReviewerResponse(reduxFormValues, { ...modalProps, setFetching }) + } + > + Yes + </button> + <button + onClick={() => + onReviewerResponse(reduxFormValues, { ...modalProps, setFetching }) + } + > + No + </button> + </Modal> +) +``` diff --git a/packages/component-manuscript/src/submitRevision/README.md b/packages/component-manuscript/src/submitRevision/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0ba42dd4bd5aaaf5cb96a90894f54442e4075967 --- /dev/null +++ b/packages/component-manuscript/src/submitRevision/README.md @@ -0,0 +1,81 @@ +## Hindawi Submit Revision HOC. + +The `withSubmitRevision` HOC contains the logic for submitting a manuscript version. It contains the following utility HOCs: + +* `withFetching` +* `withFilePreview` +* `withFileDownload` +* `withModal` + +..as well as other `recompose` HOCs. + +### withSubmitRevision props + +`submitRevision` namespace contains the following fields: +Name|Type|Description +---|---|--- +collection|`object`|Object containing the selected collection +fragment|`object`|Object containing the selected fragment +journal|`object`|Deprecated object containing manuscript types +currentUser|`object`|Object containing the currently logged user +initialValues|`{...fragment}`| Object containing the initial state of the fragment +isEditingAuthor|`bool`|Value representing if the current user is the editing author +canSubmit|`bool`|Value representing if the form doesn't have errors and can be submitted +hasFormError|`bool`|Value representing if the form has any errors +formErrors|`bool`|Value representing if the form has any errors +responseFile|`file`|Value containing the revision's file for the reviewer's response +addAuthor|`({ author, collectionId: string, fragmentId: string }) => any`|An async call to add an author to the manuscript +deleteAuthor|`({ authorId, fragmentId, collectionId }) => any`|An async call to remove an existing author from the manuscript +onAuthorEdit|`index => authorEditIndex: number`|Chages the form to allow editing of the selected author and returns his index +addFile|`({ file: object, type: string, fragment: object }) => any`|Uploads the file to the server +deleteFile|`({ fileId: string, type: string }) => any`|Removes the file from the server +getSignedUrl|`(id: string) => Promise({signedURL: string})`|An async call that returns the securized S3 file url +addResponseFile|`file => any`|Uploads the file then updates the form +deleteResponseFile|`file => any`|Deletes the file from the server then updates the form +onChange|`(reduxFormValues, dispatch, { collection, fragment }) => any`|Used to autosave new fragment when fields change +validate|`({ editAuthors: , files: array, responseToReviewers: object }) => errors: object`|Checks the form for required fields and returns the errors +onSubmit|`(reduxFormValues, dispatch, { history, fragment, collection, showModal, setFetching, canSubmit })`|Handles the submission of a new manuscript version + +```javascript +const ManuscriptLayout = ({submitRevision}) =>( + <SubmitRevision {...submitRevision} /> +) + +const SubmitRevision = ({...}) => ( + <Root> + <DetailsAndAuthors + addAuthor={addAuthor} + changeForm={changeForm} + collection={collection} + deleteAuthor={deleteAuthor} + formErrors={formErrors} + fragment={fragment} + isAuthorEdit={isEditingAuthor} + manuscriptTypes={journal.manuscriptTypes} + onAuthorEdit={onAuthorEdit} + /> + + <ManuscriptFiles + changeForm={changeForm} + collection={collection} + deleteFile={deleteFile} + downloadFile={downloadFile} + formErrors={formErrors} + formName="revision" + fragment={fragment} + getSignedUrl={getSignedUrl} + previewFile={previewFile} + token={currentUser.token} + uploadFile={addFile} + /> + + <ResponseToReviewer + file={responseFile} + getSignedUrl={getSignedUrl} + isFetching={isFetching} + onDelete={deleteResponseFile} + onUpload={addResponseFile} + token={currentUser.token} + /> + </Root> +```