diff --git a/packages/component-wizard/package.json b/packages/component-wizard/package.json index 36a5fc943c597269167a49556af5c480397dca86..8cbb986ae5f5e758a739340a19022cef2427f1f4 100644 --- a/packages/component-wizard/package.json +++ b/packages/component-wizard/package.json @@ -2,22 +2,31 @@ "name": "pubsweet-component-wizard", "version": "0.0.1", "main": "src", + "author": "Collaborative Knowledge Foundation", "license": "MIT", + "files": [ + "src", + "dist" + ], "dependencies": { "@pubsweet/ui": "^0.1.1", "moment": "^2.20.1", - "prop-types": "^15.5.10", - "react": "^15.6.1", "react-dnd": "^2.5.4", "react-dnd-html5-backend": "^2.5.4", "react-dom": "^15.6.1", "react-router-dom": "^4.2.2", - "recompose": "^0.26.0", "redux": "^3.6.0", - "redux-form": "^7.0.3" + "redux-form": "^7.0.3", + "recompose": "^0.26.0", + "xpub-validators": "^0.0.2", + "xpub-connect": "^0.0.2", + "xpub-journal": "^0.0.2", + "xpub-selectors": "^0.0.2", + "styled-components": "^3.1.6" }, "peerDependencies": { "prop-types": "^15.5.10", + "pubsweet-client": "^1.0.0-beta.8", "react": "^15.6.1", "react-dom": "^15.6.1", "react-redux": "^5.0.2", diff --git a/packages/component-wizard/src/components/AutosaveIndicator.js b/packages/component-wizard/src/components/AutosaveIndicator.js index a8f9574b334a56821c58cfb2678186c7e6f82ac1..da53bd8beef27b530b6021b7ded6ebf9cfb83303 100644 --- a/packages/component-wizard/src/components/AutosaveIndicator.js +++ b/packages/component-wizard/src/components/AutosaveIndicator.js @@ -1,15 +1,15 @@ import React from 'react' import moment from 'moment' import { connect } from 'react-redux' -import classnames from 'classnames' import { compose, withProps } from 'recompose' +// import { Icon, Spinner } from '@pubsweet/ui' import { Icon } from '@pubsweet/ui' +import styled from 'styled-components' import { getFormValues } from 'redux-form' +import Spinner from 'pubsweet-components-faraday/src/components/UIComponents/Spinner' import { getAutosave } from '../redux/autosave' -import classes from './AutosaveIndicator.local.scss' - const durationParser = lastUpdate => { const today = moment() const last = moment(lastUpdate) @@ -19,42 +19,43 @@ const durationParser = lastUpdate => { const Indicator = ({ isVisibile, + progressText = 'Saving changes...', + errorText = 'Changes not saved', + successText, autosave: { isFetching, error, lastUpdate }, }) => isVisibile ? ( - <div className={classnames(classes.container)}> + <Root> {isFetching && ( - <div className={classnames(classes['icon-container'])}> - <div className={classnames(classes.rotate, classes.icon)}> - <Icon size={16}>loader</Icon> - </div> - <span>Saving changes...</span> - </div> + <AutoSaveContainer> + <Spinner icon="loader" size={16} /> + <Info>{progressText}</Info> + </AutoSaveContainer> )} {!isFetching && lastUpdate && ( - <div className={classnames(classes['icon-container'])}> - <div className={classnames(classes.icon)}> + <AutoSaveContainer> + <IconContainer> <Icon size={16}>check-circle</Icon> - </div> - <span>{durationParser(lastUpdate)}</span> - </div> + </IconContainer> + <Info>{successText || durationParser(lastUpdate)}</Info> + </AutoSaveContainer> )} {!isFetching && error && ( - <div className={classnames(classes['icon-container'])}> - <div className={classnames(classes.icon)}> - <Icon color="red" size={16}> + <AutoSaveContainer> + <IconContainer> + <Icon color="var(--color-danger)" size={16}> alert-triangle </Icon> - </div> - <span className={classnames(classes['error-text'])} title={error}> - Changes not saved - </span> - </div> + </IconContainer> + <Info error="var(--color-danger)" title={error}> + {errorText} + </Info> + </AutoSaveContainer> )} - </div> + </Root> ) : null export default compose( @@ -66,3 +67,24 @@ export default compose( isVisibile: form && Boolean(isFetching || lastUpdate || error), })), )(Indicator) + +const Root = styled.div` + align-items: center; + display: flex; + justify-content: flex-end; +` +const AutoSaveContainer = styled.div` + align-items: center; + display: flex; + padding: 5px; +` +const IconContainer = styled.div` + align-items: center; + display: flex; + justify-content: center; +` +const Info = styled.span` + font-size: 12px; + margin-left: 5px; + color: ${({ error }) => error || ''}; +` diff --git a/packages/component-wizard/src/components/AutosaveIndicator.local.scss b/packages/component-wizard/src/components/AutosaveIndicator.local.scss deleted file mode 100644 index 5392f64ad863d4691dbfadbccd3ca401003e8cea..0000000000000000000000000000000000000000 --- a/packages/component-wizard/src/components/AutosaveIndicator.local.scss +++ /dev/null @@ -1,66 +0,0 @@ -.container { - align-items: center; - display: flex; - justify-content: flex-end; -} - -@keyframes rotating { - from { - -o-transform: rotate(0deg); - -ms-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - to { - -o-transform: rotate(360deg); - -ms-transform: rotate(360deg); - -moz-transform: rotate(360deg); - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -@-webkit-keyframes rotating { - from { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - to { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } -} - -.rotate { - -webkit-animation: rotating 1.2s linear infinite; - -moz-animation: rotating 1.2s linear infinite; - -ms-animation: rotating 1.2s linear infinite; - -o-animation: rotating 1.2s linear infinite; - animation: rotating 1.2s linear infinite; -} - -.icon-container { - align-items: center; - display: flex; - padding: 5px; - - .icon { - align-items: center; - display: flex; - justify-content: center; - margin: 0 5px 0 0; - } - - span { - font-size: 12px; - } -} - -.error-text { - color: red; - font-size: 12px; - font-weight: 400; -} diff --git a/packages/component-wizard/src/components/AutosaveIndicator.md b/packages/component-wizard/src/components/AutosaveIndicator.md new file mode 100644 index 0000000000000000000000000000000000000000..86af657d2746b4e2a355c9c061675f13083eadd7 --- /dev/null +++ b/packages/component-wizard/src/components/AutosaveIndicator.md @@ -0,0 +1,21 @@ +# AutoSave indicator + +Display the status of the form (Saving in progress, Saved or Error while saving) + +## Props + +| Prop | Description | Required | Default | Type | +| :---: | :--------------------------------------------------------------------------: | :------: | :------: | :----: | +| formName | Redux Form name | false | 'wizard' | string | +| progressText | Text to show while API returns | false | 'Saving changes... ' | string | +| errorText | Text to show on error | false | 'Changes not saved ' | string | +| successText | Text to show on success | false | 'Progress saved ${duration.humanize()} ago.' | string | +## Examples + +```js +<AutosaveIndicator /> +``` + +```js +<AutosaveIndicator formName="authors" progressText='Saving...' successText='Saved' errorText='Something went wrong!' /> +``` \ No newline at end of file diff --git a/packages/component-wizard/src/components/Wizard.js b/packages/component-wizard/src/components/Wizard.js index e1745a30b55ec279815cf9463fc74476db1c229a..97edfa95a1bf67e3482a73e392454823e1b8a821 100644 --- a/packages/component-wizard/src/components/Wizard.js +++ b/packages/component-wizard/src/components/Wizard.js @@ -1,8 +1,8 @@ import React from 'react' -import classnames from 'classnames' +import styled from 'styled-components' import { Steps } from 'pubsweet-components-faraday/src/components' +// import { Steps } from '@pubsweet/ui' -import classes from './Wizard.local.scss' import WizardFormStep from './WizardFormStep' export default ({ @@ -12,7 +12,7 @@ export default ({ prevStep, step, }) => ( - <div className={classnames(classes.container)}> + <Root> {showProgress && ( <Steps currentStep={step} margin="0 20px 60px 0"> {getSteps().map((step, index) => ( @@ -21,5 +21,12 @@ export default ({ </Steps> )} <WizardFormStep {...steps[step]} nextStep={nextStep} prevStep={prevStep} /> - </div> + </Root> ) + +const Root = styled.div` + align-items: center; + display: flex; + flex-direction: column; + margin: 0 auto; +` diff --git a/packages/component-wizard/src/components/Wizard.local.scss b/packages/component-wizard/src/components/Wizard.local.scss deleted file mode 100644 index 77e5cd336c2d3bbf7f6b870aff8fb1bf32c5d4b1..0000000000000000000000000000000000000000 --- a/packages/component-wizard/src/components/Wizard.local.scss +++ /dev/null @@ -1,8 +0,0 @@ -.container { - align-items: center; - display: flex; - flex-direction: column; - margin: 0 auto; - width: 900px; -} - diff --git a/packages/component-wizard/src/components/WizardStep.js b/packages/component-wizard/src/components/WizardStep.js index ff5bdc3b9f3ba264388d94a8e9ca4f0054f84017..02baab3128538093680bcf22164b75c9227a67bf 100644 --- a/packages/component-wizard/src/components/WizardStep.js +++ b/packages/component-wizard/src/components/WizardStep.js @@ -1,9 +1,8 @@ import React from 'react' import { get } from 'lodash' -import classnames from 'classnames' +import styled from 'styled-components' import { ValidatedField, Button } from '@pubsweet/ui' -import classes from './WizardStep.local.scss' import AutosaveIndicator from './AutosaveIndicator' export default ({ @@ -25,12 +24,11 @@ export default ({ wizard: { confirmationModal: ConfirmationModal }, ...rest }) => ( - <div className={classnames(classes.step)}> - <form className={classnames(classes.form)} onSubmit={handleSubmit}> - <h3 className={classnames(classes.title)}>{title}</h3> + <Root width="700px"> + <FormContainer onSubmit={handleSubmit}> + <Title>{title}</Title> {subtitle && ( - <div - className={classnames(classes.subtitle)} + <Subtitle dangerouslySetInnerHTML={{ __html: subtitle }} // eslint-disable-line /> )} @@ -65,7 +63,7 @@ export default ({ ) }, )} - <div className={classnames(classes.buttons)}> + <ButtonContainer> <Button onClick={isFirst ? () => history.push('/') : prevStep}> {isFirst ? `${wizard.cancelText || 'Cancel'}` @@ -76,13 +74,57 @@ export default ({ ? `${wizard.submitText || 'Submit Manuscript'}` : `${wizard.nextText || 'Next'}`} </Button> - </div> + </ButtonContainer> {confirmation && ( - <div className={classnames(classes.modal)}> + <ModalContainer> <ConfirmationModal toggleConfirming={toggleConfirmation} /> - </div> + </ModalContainer> )} - </form> + </FormContainer> <AutosaveIndicator /> - </div> + </Root> ) + +const Root = styled.div` + align-items: stretch; + border: 1px solid var(--color-pending); + display: flex; + flex-direction: column; + justify-content: flex-start; + padding: 0 20px; + width: ${({ width }) => width || '700px'}; +` + +const FormContainer = styled.form` + display: flex; + flex-direction: column; +` +const Title = styled.h3` + align-self: center; +` + +const Subtitle = styled.div` + align-self: center; + margin-bottom: 25px; +` + +const ButtonContainer = styled.div` + align-items: center; + align-self: center; + display: flex; + justify-content: space-around; + margin: 15px 0; + width: ${({ width }) => width || '400px'}; +` + +const ModalContainer = styled.div` + align-items: center; + background: rgba(255, 255, 255, 0.95); + bottom: 0; + display: flex; + justify-content: center; + left: 0; + position: fixed; + right: 0; + top: 0; +` diff --git a/packages/component-wizard/src/components/WizardStep.local.scss b/packages/component-wizard/src/components/WizardStep.local.scss deleted file mode 100644 index 8918f2a9853afac723a5d68b6a5e0e8bc22190ca..0000000000000000000000000000000000000000 --- a/packages/component-wizard/src/components/WizardStep.local.scss +++ /dev/null @@ -1,44 +0,0 @@ -.step { - align-items: stretch; - border: 1px solid #222; - display: flex; - flex-direction: column; - justify-content: flex-start; - padding: 0 20px; - width: 700px; - - .title { - align-self: center; - } - - .subtitle { - align-self: center; - margin-bottom: 25px; - } -} - -.form { - display: flex; - flex-direction: column; -} - -.buttons { - align-items: center; - align-self: center; - display: flex; - justify-content: space-around; - margin: 15px 0; - width: 400px; -} - -.modal { - align-items: center; - background: rgba(255, 255, 255, 0.95); - bottom: 0; - display: flex; - justify-content: center; - left: 0; - position: fixed; - right: 0; - top: 0; -} diff --git a/packages/components-faraday/src/components/Admin/Admin.js b/packages/components-faraday/src/components/Admin/Admin.js index 8bb2efb4763a63d6895a9e2eb109a9b8c88655b7..10a21ca47871a8863218d5d62faa879851571543 100644 --- a/packages/components-faraday/src/components/Admin/Admin.js +++ b/packages/components-faraday/src/components/Admin/Admin.js @@ -1,21 +1,24 @@ import React from 'react' -import PropTypes from 'prop-types' +import styled from 'styled-components' -import classes from './Admin.local.scss' - -const Admin = ({ users }) => ( - <div className={classes.root}> +const Admin = ({ users = [] }) => ( + <Root> <h2>Admin</h2> <ul> {users.map((u, i) => ( - <li key={i}> + <li key={u.id}> {u.username} - {u.email} </li> ))} </ul> - </div> + </Root> ) -Admin.propTypes = {} - export default Admin + +const Root = styled.div` + display: flex; + flex-direction: column; + margin: auto; + max-width: 60em; +` diff --git a/packages/components-faraday/src/components/Admin/Admin.local.scss b/packages/components-faraday/src/components/Admin/Admin.local.scss deleted file mode 100644 index 6ea81ade44fa58f18373e06c91eed42c61da4037..0000000000000000000000000000000000000000 --- a/packages/components-faraday/src/components/Admin/Admin.local.scss +++ /dev/null @@ -1,6 +0,0 @@ -.root { - display: flex; - flex-direction: column; - margin: auto; - max-width: 60em; -} diff --git a/packages/components-faraday/src/components/Admin/AdminPage.js b/packages/components-faraday/src/components/Admin/AdminPage.js index 40a751d36ae83c6d0e7dde55ce75ef8c08ce2539..684f7df5ddd552914641e4961163e89fbc134b9e 100644 --- a/packages/components-faraday/src/components/Admin/AdminPage.js +++ b/packages/components-faraday/src/components/Admin/AdminPage.js @@ -1,5 +1,4 @@ import { get } from 'lodash' -import PropTypes from 'prop-types' import { compose } from 'recompose' import { connect } from 'react-redux' import { actions } from 'pubsweet-client'