Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • mynameissmeall/xpub-faraday
1 result
Show changes
Commits on Source (76)
Showing
with 361 additions and 36 deletions
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) {
......
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">
......
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')};
`
......
......@@ -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"
/>
)
......
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({
......
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')}
......
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 }) => ({
......
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
......
......@@ -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;
......
......@@ -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',
......
......@@ -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;
......
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',
......
*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>
......
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,
......
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
......
......@@ -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')};
......
......@@ -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,
}
......
......@@ -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({
......
......@@ -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)
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 }) => ({
......